summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
authorHappy <markaizer@gmail.com>2014-08-21 04:50:46 +0800
committerHappy <markaizer@gmail.com>2014-08-21 04:50:46 +0800
commitf52e1007fe08c67003c0bc4c78231904dd3fd5cc (patch)
tree99907d827264e501774e58ab4630e41fa7103c02 /src/map
parent2410110dece79b4598c12f1c953219f1d0d1904a (diff)
parent769b1d05aa5cfa8cddfe7d21b35d5c5e4da3bbd6 (diff)
downloadhercules-f52e1007fe08c67003c0bc4c78231904dd3fd5cc.tar.gz
hercules-f52e1007fe08c67003c0bc4c78231904dd3fd5cc.tar.bz2
hercules-f52e1007fe08c67003c0bc4c78231904dd3fd5cc.tar.xz
hercules-f52e1007fe08c67003c0bc4c78231904dd3fd5cc.zip
Merge pull request #1 from HerculesWS/master
Update from original
Diffstat (limited to 'src/map')
-rw-r--r--src/map/CMakeLists.txt12
-rw-r--r--src/map/HPMmap.c215
-rw-r--r--src/map/HPMmap.h29
-rw-r--r--src/map/Makefile.in157
-rw-r--r--src/map/atcommand.c3983
-rw-r--r--src/map/atcommand.h49
-rw-r--r--src/map/battle.c3434
-rw-r--r--src/map/battle.h181
-rw-r--r--src/map/battleground.c590
-rw-r--r--src/map/battleground.h78
-rw-r--r--src/map/buyingstore.c105
-rw-r--r--src/map/buyingstore.h48
-rw-r--r--src/map/chat.c316
-rw-r--r--src/map/chat.h58
-rw-r--r--src/map/chrif.c1328
-rw-r--r--src/map/chrif.h190
-rw-r--r--src/map/clif.c5642
-rw-r--r--src/map/clif.h300
-rw-r--r--src/map/date.c15
-rw-r--r--src/map/date.h14
-rw-r--r--src/map/duel.c137
-rw-r--r--src/map/duel.h60
-rw-r--r--src/map/elemental.c450
-rw-r--r--src/map/elemental.h114
-rw-r--r--src/map/guild.c780
-rw-r--r--src/map/guild.h95
-rw-r--r--src/map/homunculus.c227
-rw-r--r--src/map/homunculus.h49
-rw-r--r--src/map/instance.c519
-rw-r--r--src/map/instance.h42
-rw-r--r--src/map/intif.c1567
-rw-r--r--src/map/intif.h287
-rw-r--r--src/map/irc-bot.c313
-rw-r--r--src/map/irc-bot.h29
-rw-r--r--src/map/itemdb.c2381
-rw-r--r--src/map/itemdb.h679
-rw-r--r--src/map/log.c170
-rw-r--r--src/map/log.h69
-rw-r--r--src/map/mail.c31
-rw-r--r--src/map/mail.h14
-rw-r--r--src/map/map.c5314
-rw-r--r--src/map/map.h406
-rw-r--r--src/map/mapreg.h56
-rw-r--r--src/map/mapreg_sql.c393
-rw-r--r--src/map/mercenary.c288
-rw-r--r--src/map/mercenary.h89
-rw-r--r--src/map/mob.c2030
-rw-r--r--src/map/mob.h226
-rw-r--r--src/map/npc.c3302
-rw-r--r--src/map/npc.h333
-rw-r--r--src/map/npc_chat.c238
-rw-r--r--src/map/packets.h791
-rw-r--r--src/map/packets_struct.h595
-rw-r--r--src/map/party.c576
-rw-r--r--src/map/party.h92
-rw-r--r--src/map/path.c532
-rw-r--r--src/map/path.h53
-rw-r--r--src/map/pc.c5753
-rw-r--r--src/map/pc.h566
-rw-r--r--src/map/pc_groups.c467
-rw-r--r--src/map/pc_groups.h122
-rw-r--r--src/map/pet.c771
-rw-r--r--src/map/pet.h109
-rw-r--r--src/map/quest.c528
-rw-r--r--src/map/quest.h61
-rw-r--r--src/map/script.c14083
-rw-r--r--src/map/script.h762
-rw-r--r--src/map/searchstore.c46
-rw-r--r--src/map/searchstore.h49
-rw-r--r--src/map/skill.c8745
-rw-r--r--src/map/skill.h411
-rw-r--r--src/map/sql/CMakeLists.txt116
-rw-r--r--src/map/status.c10093
-rw-r--r--src/map/status.h2183
-rw-r--r--src/map/storage.c276
-rw-r--r--src/map/storage.h92
-rw-r--r--src/map/trade.c157
-rw-r--r--src/map/trade.h19
-rw-r--r--src/map/unit.c1331
-rw-r--r--src/map/unit.h154
-rw-r--r--src/map/vending.c55
-rw-r--r--src/map/vending.h17
82 files changed, 50084 insertions, 36953 deletions
diff --git a/src/map/CMakeLists.txt b/src/map/CMakeLists.txt
deleted file mode 100644
index 51c3538ef..000000000
--- a/src/map/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-
-#
-# setup
-#
-set( MAP_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "" )
-set( SQL_MAP_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "" )
-
-
-#
-# targets
-#
-add_subdirectory( sql )
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c
new file mode 100644
index 000000000..cb8c979c6
--- /dev/null
+++ b/src/map/HPMmap.c
@@ -0,0 +1,215 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#define HERCULES_CORE
+
+#include "HPMmap.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "atcommand.h"
+#include "battle.h"
+#include "battleground.h"
+#include "chat.h"
+#include "chrif.h"
+#include "clif.h"
+#include "date.h"
+#include "duel.h"
+#include "elemental.h"
+#include "guild.h"
+#include "homunculus.h"
+#include "instance.h"
+#include "intif.h"
+#include "irc-bot.h"
+#include "itemdb.h"
+#include "log.h"
+#include "mail.h"
+#include "map.h"
+#include "mapreg.h"
+#include "mercenary.h"
+#include "mob.h"
+#include "npc.h"
+#include "party.h"
+#include "path.h"
+#include "pc.h"
+#include "pc_groups.h"
+#include "pet.h"
+#include "quest.h"
+#include "script.h"
+#include "searchstore.h"
+#include "skill.h"
+#include "status.h"
+#include "storage.h"
+#include "trade.h"
+#include "unit.h"
+#include "vending.h"
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/db.h"
+#include "../common/des.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/mapindex.h"
+#include "../common/mmo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/sysinfo.h"
+
+#include "../common/HPMDataCheck.h"
+
+struct HPM_atcommand_list {
+ //tracking currently not enabled
+ // - requires modifying how plugins calls atcommand creation
+ // - needs load/unload during runtime support
+ //unsigned int pID;/* plugin id */
+ char name[ATCOMMAND_LENGTH];
+ AtCommandFunc func;
+};
+
+struct HPM_atcommand_list *atcommand_list = NULL;
+unsigned int atcommand_list_items = 0;
+
+/**
+ * (char*) data name -> (unsigned int) HPMDataCheck[] index
+ **/
+DBMap *datacheck_db;
+
+bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) {
+ /* record address */
+ switch( type ) {
+ case HPDT_MSD:
+ ret->HPDataSRCPtr = (void**)(&((struct map_session_data *)ptr)->hdata);
+ ret->hdatac = &((struct map_session_data *)ptr)->hdatac;
+ break;
+ case HPDT_NPCD:
+ ret->HPDataSRCPtr = (void**)(&((struct npc_data *)ptr)->hdata);
+ ret->hdatac = &((struct npc_data *)ptr)->hdatac;
+ break;
+ case HPDT_MAP:
+ ret->HPDataSRCPtr = (void**)(&((struct map_data *)ptr)->hdata);
+ ret->hdatac = &((struct map_data *)ptr)->hdatac;
+ break;
+ case HPDT_PARTY:
+ ret->HPDataSRCPtr = (void**)(&((struct party_data *)ptr)->hdata);
+ ret->hdatac = &((struct party_data *)ptr)->hdatac;
+ break;
+ case HPDT_GUILD:
+ ret->HPDataSRCPtr = (void**)(&((struct guild *)ptr)->hdata);
+ ret->hdatac = &((struct guild *)ptr)->hdatac;
+ break;
+ case HPDT_INSTANCE:
+ ret->HPDataSRCPtr = (void**)(&((struct instance_data *)ptr)->hdata);
+ ret->hdatac = &((struct instance_data *)ptr)->hdatac;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+void HPM_map_plugin_load_sub(struct hplugin *plugin) {
+ plugin->hpi->addCommand = HPM->import_symbol("addCommand",plugin->idx);
+ plugin->hpi->addScript = HPM->import_symbol("addScript",plugin->idx);
+ plugin->hpi->addPCGPermission = HPM->import_symbol("addGroupPermission",plugin->idx);
+}
+
+bool HPM_map_add_atcommand(char *name, AtCommandFunc func) {
+ unsigned int i = 0;
+
+ for(i = 0; i < atcommand_list_items; i++) {
+ if( !strcmpi(atcommand_list[i].name,name) ) {
+ ShowDebug("HPM_map_add_atcommand: duplicate command '%s', skipping...\n", name);
+ return false;
+ }
+ }
+
+ i = atcommand_list_items;
+
+ RECREATE(atcommand_list, struct HPM_atcommand_list , ++atcommand_list_items);
+
+ safestrncpy(atcommand_list[i].name, name, sizeof(atcommand_list[i].name));
+ atcommand_list[i].func = func;
+
+ return true;
+}
+
+void HPM_map_atcommands(void) {
+ unsigned int i;
+
+ for(i = 0; i < atcommand_list_items; i++) {
+ atcommand->add(atcommand_list[i].name,atcommand_list[i].func,true);
+ }
+}
+
+/**
+ * Called by HPM->DataCheck on a plugins incoming data, ensures data structs in use are matching!
+ **/
+bool HPM_map_DataCheck (struct s_HPMDataCheck *src, unsigned int size, char *name) {
+ unsigned int i, j;
+
+ for(i = 0; i < size; i++) {
+
+ if( !strdb_exists(datacheck_db, src[i].name) ) {
+ ShowError("HPMDataCheck:%s: '%s' was not found\n",name,src[i].name);
+ return false;
+ } else {
+ j = strdb_uiget(datacheck_db, src[i].name);/* not double lookup; exists sets cache to found data */
+ if( src[i].size != HPMDataCheck[j].size ) {
+ ShowWarning("HPMDataCheck:%s: '%s' size mismatch %u != %u\n",name,src[i].name,src[i].size,HPMDataCheck[j].size);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Adds a new group permission to the HPM-provided list
+ **/
+void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned int *mask) {
+ unsigned char index = pcg->HPMpermissions_count;
+
+ RECREATE(pcg->HPMpermissions, struct pc_groups_new_permission, ++pcg->HPMpermissions_count);
+
+ pcg->HPMpermissions[index].pID = pluginID;
+ pcg->HPMpermissions[index].name = aStrdup(name);
+ pcg->HPMpermissions[index].mask = mask;
+}
+
+void HPM_map_do_init(void) {
+ unsigned int i;
+
+ /**
+ * Populates datacheck_db for easy lookup later on
+ **/
+ datacheck_db = strdb_alloc(DB_OPT_BASE,0);
+
+ for(i = 0; i < HPMDataCheckLen; i++) {
+ strdb_uiput(datacheck_db, HPMDataCheck[i].name, i);
+ }
+
+}
+
+void HPM_map_do_final(void) {
+ unsigned char i;
+
+ if( atcommand_list )
+ aFree(atcommand_list);
+ /**
+ * why is pcg->HPM being cleared here? because PCG's do_final is not final,
+ * is used on reload, and would thus cause plugin-provided permissions to go away
+ **/
+ for( i = 0; i < pcg->HPMpermissions_count; i++ ) {
+ aFree(pcg->HPMpermissions[i].name);
+ }
+ if( pcg->HPMpermissions )
+ aFree(pcg->HPMpermissions);
+
+ db_destroy(datacheck_db);
+}
diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h
new file mode 100644
index 000000000..99c4224ff
--- /dev/null
+++ b/src/map/HPMmap.h
@@ -0,0 +1,29 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#ifndef MAP_HPMMAP_H
+#define MAP_HPMMAP_H
+
+#include "../common/cbasetypes.h"
+#include "../map/atcommand.h"
+#include "../common/HPM.h"
+
+struct hplugin;
+struct map_session_data;
+
+bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
+
+bool HPM_map_add_atcommand(char *name, AtCommandFunc func);
+void HPM_map_atcommands(void);
+
+void HPM_map_plugin_load_sub(struct hplugin *plugin);
+
+void HPM_map_do_final(void);
+
+void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned int *mask);
+
+bool HPM_map_DataCheck(struct s_HPMDataCheck *src, unsigned int size, char *name);
+
+void HPM_map_do_init(void);
+
+#endif /* MAP_HPMMAP_H */
diff --git a/src/map/Makefile.in b/src/map/Makefile.in
index bb99b6a05..fc58c9d70 100644
--- a/src/map/Makefile.in
+++ b/src/map/Makefile.in
@@ -1,43 +1,47 @@
-
-COMMON_H = $(shell ls ../common/*.h)
-
-MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o
-MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h
-MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar
-
-LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \
- ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o
-LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \
- ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \
- ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h
-LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig
-
-MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \
- npc_chat.o chat.o path.o itemdb.o mob.o script.o \
- storage.o skill.o atcommand.o battle.o battleground.o \
- intif.o trade.o party.o vending.o guild.o pet.o \
- log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \
- buyingstore.o searchstore.o duel.o pc_groups.o elemental.o irc-bot.o
-MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \
- obj_sql/mapreg_sql.o
-MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \
- chat.h itemdb.h mob.h script.h path.h \
- storage.h skill.h atcommand.h battle.h battleground.h \
- intif.h trade.h party.h vending.h guild.h pet.h \
- log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h \
- buyingstore.h searchstore.h duel.h pc_groups.h \
- ../config/core.h ../config/renewal.h ../config/secure.h ../config/const.h \
- ../config/classes/general.h elemental.h packets.h packets_struct.h irc-bot.h
+# Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+# See the LICENSE file
+
+# @configure_input@
+
+CONFIG_D = ../config
+CONFIG_H = $(wildcard $(CONFIG_D)/*.h) $(wildcard $(CONFIG_D)/*/*.h)
+
+COMMON_D = ../common
+COMMON_H = $(wildcard $(COMMON_D)/*.h)
+SYSINFO_INC = $(COMMON_D)/sysinfo.inc
+
+LIBCONFIG_D = ../../3rdparty/libconfig
+LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \
+ scanner.o strbuf.o)
+LIBCONFIG_H = $(addprefix $(LIBCONFIG_D)/, libconfig.h grammar.h parsectx.h \
+ scanctx.h scanner.h strbuf.h wincompat.h)
+LIBCONFIG_INCLUDE = -I$(LIBCONFIG_D)
+
+MT19937AR_D = ../../3rdparty/mt19937ar
+MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
+MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
+MT19937AR_INCLUDE = -I$(MT19937AR_D)
+
+MAP_C = atcommand.c battle.c battleground.c buyingstore.c chat.c chrif.c \
+ clif.c date.c duel.c elemental.c guild.c homunculus.c HPMmap.c \
+ instance.c intif.c irc-bot.c itemdb.c log.c mail.c map.c mapreg_sql.c \
+ mercenary.c mob.c npc.c npc_chat.c party.c path.c pc.c pc_groups.c \
+ pet.c quest.c script.c searchstore.c skill.c status.c storage.c \
+ trade.c unit.c vending.c
+MAP_OBJ = $(addprefix obj_sql/, $(patsubst %c,%o,$(MAP_C)))
+MAP_H = atcommand.h battle.h battleground.h buyingstore.h chat.h chrif.h \
+ clif.h date.h duel.h elemental.h guild.h homunculus.h HPMmap.h \
+ instance.h intif.h irc-bot.h itemdb.h log.h mail.h map.h mapreg.h \
+ mercenary.h mob.h npc.h packets.h packets_struct.h party.h path.h \
+ pc.h pc_groups.h pet.h quest.h script.h searchstore.h skill.h \
+ status.h storage.h trade.h unit.h vending.h
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
- ALL_DEPENDS=txt sql
- SQL_DEPENDS=map-server
+ MAP_SERVER_SQL_DEPENDS=$(MAP_OBJ) $(COMMON_D)/obj_sql/common_sql.a $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ $(SYSINFO_INC))
else
- ALL_TARGET=txt
- SQL_DEPENDS=needs_mysql
+ MAP_SERVER_SQL_DEPENDS=needs_mysql
endif
-TXT_DEPENDS=map-server
HAVE_PCRE=@HAVE_PCRE@
ifeq ($(HAVE_PCRE),yes)
@@ -48,41 +52,47 @@ endif
@SET_MAKE@
+CC = @CC@
+export CC
+
#####################################################################
-.PHONY : all txt sql clean help
+.PHONY: all sql map-server clean buildclean help
-all: $(ALL_DEPENDS)
+all: sql
-txt: $(TXT_DEPENDS)
+sql: map-server
-sql: $(SQL_DEPENDS)
+buildclean:
+ @echo " CLEAN map (build temp files)"
+ @rm -rf *.o obj_sql
-clean:
+clean: buildclean
@echo " CLEAN map"
- @rm -rf *.o obj_txt obj_sql ../../map-server@EXEEXT@ ../../map-server@EXEEXT@
+ @rm -rf ../../map-server@EXEEXT@
help:
-ifeq ($(HAVE_MYSQL),yes)
- @echo "possible targets are 'sql' 'txt' 'all' 'clean' 'help'"
- @echo "'sql' - map server (SQL version)"
-else
- @echo "possible targets are 'txt' 'all' 'clean' 'help'"
-endif
- @echo "'txt' - map server (TXT version)"
- @echo "'all' - builds all above targets"
- @echo "'clean' - cleans builds and objects"
- @echo "'help' - outputs this message"
+ @echo "possible targets are 'map-server' 'all' 'clean' 'help'"
+ @echo "'map-server' - map server"
+ @echo "'all' - builds all above targets"
+ @echo "'clean' - cleans builds and objects"
+ @echo "'buildclean' - cleans build temporary (object) files, without deleting the"
+ @echo " executables"
+ @echo "'help' - outputs this message"
#####################################################################
+Makefile: Makefile.in
+ @$(MAKE) -C ../.. src/map/Makefile
+
+$(SYSINFO_INC): $(MAP_C) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H)
+ @echo " MAKE $@"
+ @$(MAKE) -C ../.. sysinfo
+
needs_mysql:
@echo "MySQL not found or disabled by the configure script"
@exit 1
# object directories
-obj_txt:
- @echo " MKDIR obj_txt"
- @-mkdir obj_txt
obj_sql:
@echo " MKDIR obj_sql"
@@ -90,25 +100,32 @@ obj_sql:
# executables
-map-server: obj_sql $(MAP_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a
- @echo " LD $@"
- @@CC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@
+map-server: ../../map-server@EXEEXT@
+
+../../map-server@EXEEXT@: $(MAP_SERVER_SQL_DEPENDS) Makefile
+ @echo " LD $(notdir $@)"
+ @$(CC) @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_OBJ) $(COMMON_D)/obj_sql/common_sql.a \
+ $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@
# map object files
-obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H)
+obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_sql
@echo " CC $<"
- @@CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+ @$(CC) @CFLAGS@ @DEFS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
# missing object files
-../common/obj_all/common.a:
- @$(MAKE) -C ../common sql
-
-../common/obj_sql/common_sql.a:
- @$(MAKE) -C ../common sql
-
-MT19937AR_OBJ:
- @$(MAKE) -C ../../3rdparty/mt19937ar
-
-LIBCONFIG_OBJ:
- @$(MAKE) -C ../../3rdparty/libconfig
+$(COMMON_D)/obj_all/common.a:
+ @echo " MAKE $@"
+ @$(MAKE) -C $(COMMON_D) sql
+
+$(COMMON_D)/obj_sql/common_sql.a:
+ @echo " MAKE $@"
+ @$(MAKE) -C $(COMMON_D) sql
+
+$(MT19937AR_OBJ):
+ @echo " MAKE $@"
+ @$(MAKE) -C $(MT19937AR_D)
+
+$(LIBCONFIG_OBJ):
+ @echo " MAKE $@"
+ @$(MAKE) -C $(LIBCONFIG_D)
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index b6a9e42ee..b5e8fa797 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -2,64 +2,65 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/mmo.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/core.h"
-#include "../common/showmsg.h"
-#include "../common/malloc.h"
-#include "../common/random.h"
-#include "../common/socket.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
-#include "../common/conf.h"
+#define HERCULES_CORE
+#include "../config/core.h" // AUTOLOOTITEM_SIZE, AUTOTRADE_PERSISTENCY, MAX_SUGGESTIONS, MOB_FLEE(), MOB_HIT(), RENEWAL, RENEWAL_DROP, RENEWAL_EXP
#include "atcommand.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "HPMmap.h"
#include "battle.h"
#include "chat.h"
-#include "clif.h"
#include "chrif.h"
+#include "clif.h"
#include "duel.h"
+#include "elemental.h"
+#include "guild.h"
+#include "homunculus.h"
#include "intif.h"
#include "itemdb.h"
#include "log.h"
+#include "mail.h"
#include "map.h"
-#include "pc.h"
-#include "pc_groups.h" // groupid2name
-#include "status.h"
-#include "skill.h"
+#include "mapreg.h"
+#include "mercenary.h"
#include "mob.h"
#include "npc.h"
-#include "pet.h"
-#include "homunculus.h"
-#include "mail.h"
-#include "mercenary.h"
-#include "elemental.h"
#include "party.h"
-#include "guild.h"
+#include "pc.h"
+#include "pc_groups.h" // groupid2name
+#include "pet.h"
+#include "quest.h"
#include "script.h"
+#include "searchstore.h"
+#include "skill.h"
+#include "status.h"
#include "storage.h"
#include "trade.h"
#include "unit.h"
-#include "mapreg.h"
-#include "quest.h"
-#include "searchstore.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/core.h"
+#include "../common/malloc.h"
+#include "../common/mmo.h" // MAX_CARTS
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/sysinfo.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-static char* msg_table[MAX_MSG]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
+struct atcommand_interface atcommand_s;
static char atcmd_output[CHAT_SIZE_MAX];
static char atcmd_player_name[NAME_LENGTH];
-static AtCommandInfo* get_atcommandinfo_byname(const char *name); // @help
-static const char* atcommand_checkalias(const char *aliasname); // @help
-static void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool atcommand); // @help
-
// @commands (script-based)
struct atcmd_binding_data* get_atcommandbind_byname(const char* name) {
int i = 0;
@@ -67,7 +68,7 @@ struct atcmd_binding_data* get_atcommandbind_byname(const char* name) {
if( *name == atcommand->at_symbol || *name == atcommand->char_symbol )
name++; // for backwards compatibility
- ARR_FIND( 0, atcommand->binding_count, i, strcmp(atcommand->binding[i]->command, name) == 0 );
+ ARR_FIND( 0, atcommand->binding_count, i, strcmpi(atcommand->binding[i]->command, name) == 0 );
return ( i < atcommand->binding_count ) ? atcommand->binding[i] : NULL;
}
@@ -75,58 +76,64 @@ struct atcmd_binding_data* get_atcommandbind_byname(const char* name) {
//-----------------------------------------------------------
// Return the message string of the specified number by [Yor]
//-----------------------------------------------------------
-const char* msg_txt(int msg_number)
-{
+const char* atcommand_msg(int msg_number) {
if (msg_number >= 0 && msg_number < MAX_MSG &&
- msg_table[msg_number] != NULL && msg_table[msg_number][0] != '\0')
- return msg_table[msg_number];
+ atcommand->msg_table[msg_number] != NULL && atcommand->msg_table[msg_number][0] != '\0')
+ return atcommand->msg_table[msg_number];
return "??";
}
-/*==========================================
- * Read Message Data
- *------------------------------------------*/
-int msg_config_read(const char* cfgName)
-{
+/**
+ * Reads Message Data
+ *
+ * @param[in] cfg_name configuration filename to read.
+ * @param[in] allow_override whether to allow duplicate message IDs to override the original value.
+ * @return success state.
+ */
+bool msg_config_read(const char *cfg_name, bool allow_override) {
int msg_number;
char line[1024], w1[1024], w2[1024];
FILE *fp;
static int called = 1;
- if ((fp = fopen(cfgName, "r")) == NULL) {
- ShowError("Messages file not found: %s\n", cfgName);
- return 1;
+ if ((fp = fopen(cfg_name, "r")) == NULL) {
+ ShowError("Messages file not found: %s\n", cfg_name);
+ return false;
}
if ((--called) == 0)
- memset(msg_table, 0, sizeof(msg_table[0]) * MAX_MSG);
+ memset(atcommand->msg_table, 0, sizeof(atcommand->msg_table[0]) * MAX_MSG);
- while(fgets(line, sizeof(line), fp))
- {
+ while(fgets(line, sizeof(line), fp)) {
if (line[0] == '/' && line[1] == '/')
continue;
- if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2)
+ if (sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2) != 2)
continue;
- if (strcmpi(w1, "import") == 0)
- msg_config_read(w2);
- else
- {
+ if (strcmpi(w1, "import") == 0) {
+ msg_config_read(w2, true);
+ } else {
msg_number = atoi(w1);
- if (msg_number >= 0 && msg_number < MAX_MSG)
- {
- if (msg_table[msg_number] != NULL)
- aFree(msg_table[msg_number]);
- msg_table[msg_number] = (char *)aMalloc((strlen(w2) + 1)*sizeof (char));
- strcpy(msg_table[msg_number],w2);
+ if (msg_number >= 0 && msg_number < MAX_MSG) {
+ if (atcommand->msg_table[msg_number] != NULL) {
+ if (!allow_override) {
+ ShowError("Duplicate message: ID '%d' was already used for '%s'. Message '%s' will be ignored.\n",
+ msg_number, w2, atcommand->msg_table[msg_number]);
+ continue;
+ }
+ aFree(atcommand->msg_table[msg_number]);
+ }
+ /* this could easily become consecutive memory like get_str() and save the malloc overhead for over 1k calls [Ind] */
+ atcommand->msg_table[msg_number] = (char *)aMalloc((strlen(w2) + 1)*sizeof (char));
+ strcpy(atcommand->msg_table[msg_number],w2);
}
}
}
fclose(fp);
- return 0;
+ return true;
}
/*==========================================
@@ -136,7 +143,7 @@ void do_final_msg(void)
{
int i;
for (i = 0; i < MAX_MSG; i++)
- aFree(msg_table[i]);
+ aFree(atcommand->msg_table[i]);
}
/**
@@ -159,45 +166,39 @@ ACMD(send)
// read message type as hex number (without the 0x)
if(!message || !*message ||
!((sscanf(message, "len %x", &type)==1 && (len=1))
- || sscanf(message, "%x", &type)==1) )
- {
- int i;
- for (i = 900; i <= 903; ++i)
- clif->message(fd, msg_txt(i));
- return false;
- }
-
-#define PARSE_ERROR(error,p) \
-{\
-clif->message(fd, (error));\
-sprintf(atcmd_output, ">%s", (p));\
-clif->message(fd, atcmd_output);\
-}
- //define PARSE_ERROR
-
-#define CHECK_EOS(p) \
-if(*(p) == 0){\
-clif->message(fd, "Unexpected end of string");\
-return false;\
-}
- //define CHECK_EOS
-
-#define SKIP_VALUE(p) \
-{\
-while(*(p) && !ISSPACE(*(p))) ++(p); /* non-space */\
-while(*(p) && ISSPACE(*(p))) ++(p); /* space */\
-}
- //define SKIP_VALUE
-
-#define GET_VALUE(p,num) \
-{\
-if(sscanf((p), "x%lx", &(num)) < 1 && sscanf((p), "%ld ", &(num)) < 1){\
-PARSE_ERROR("Invalid number in:",(p));\
-return false;\
-}\
-}
- //define GET_VALUE
-
+ || sscanf(message, "%x", &type)==1) ) {
+ clif->message(fd, msg_txt(900)); // Usage:
+ clif->message(fd, msg_txt(901)); // @send len <packet hex number>
+ clif->message(fd, msg_txt(902)); // @send <packet hex number> {<value>}*
+ clif->message(fd, msg_txt(903)); // Value: <type=B(default),W,L><number> or S<length>"<string>"
+ return false;
+ }
+
+#define PARSE_ERROR(error,p) do {\
+ clif->message(fd, (error));\
+ sprintf(atcmd_output, ">%s", (p));\
+ clif->message(fd, atcmd_output);\
+} while(0) //define PARSE_ERROR
+
+#define CHECK_EOS(p) do { \
+ if(*(p) == 0){ \
+ clif->message(fd, "Unexpected end of string");\
+ return false;\
+ } \
+} while(0) //define CHECK_EOS
+
+#define SKIP_VALUE(p) do { \
+ while(*(p) && !ISSPACE(*(p))) ++(p); /* non-space */\
+ while(*(p) && ISSPACE(*(p))) ++(p); /* space */\
+} while(0) //define SKIP_VALUE
+
+#define GET_VALUE(p,num) do { \
+ if(sscanf((p), "x%lx", &(num)) < 1 && sscanf((p), "%ld ", &(num)) < 1){\
+ PARSE_ERROR("Invalid number in:",(p));\
+ return false;\
+ }\
+} while(0) //define GET_VALUE
+
if (type > 0 && type < MAX_PACKET_DB) {
if(len)
@@ -219,8 +220,8 @@ return false;\
len=SHRT_MAX-4; // maximum length
off=4;
}
- WFIFOHEAD(fd, len);
- WFIFOW(fd,0)=TOW(type);
+ WFIFOHEAD(sd->fd, len);
+ WFIFOW(sd->fd,0)=TOW(type);
// parse packet contents
SKIP_VALUE(message);
@@ -228,25 +229,25 @@ return false;\
if(ISDIGIT(*message) || *message == '-' || *message == '+')
{// default (byte)
GET_VALUE(message,num);
- WFIFOB(fd,off)=TOB(num);
+ WFIFOB(sd->fd,off)=TOB(num);
++off;
} else if(TOUPPER(*message) == 'B')
{// byte
++message;
GET_VALUE(message,num);
- WFIFOB(fd,off)=TOB(num);
+ WFIFOB(sd->fd,off)=TOB(num);
++off;
} else if(TOUPPER(*message) == 'W')
{// word (2 bytes)
++message;
GET_VALUE(message,num);
- WFIFOW(fd,off)=TOW(num);
+ WFIFOW(sd->fd,off)=TOW(num);
off+=2;
} else if(TOUPPER(*message) == 'L')
{// long word (4 bytes)
++message;
GET_VALUE(message,num);
- WFIFOL(fd,off)=TOL(num);
+ WFIFOL(sd->fd,off)=TOL(num);
off+=4;
} else if(TOUPPER(*message) == 'S')
{// string - escapes are valid
@@ -299,7 +300,7 @@ return false;\
num<<=8;
num+=(ISDIGIT(*message)?*message-'0':TOLOWER(*message)-'a'+10);
}
- WFIFOB(fd,off)=TOB(num);
+ WFIFOB(sd->fd,off)=TOB(num);
++message;
CHECK_EOS(message);
continue;
@@ -328,13 +329,13 @@ return false;\
CHECK_EOS(message);
}
}
- WFIFOB(fd,off)=TOB(num);
+ WFIFOB(sd->fd,off)=TOB(num);
continue;
}
}
} else
num=*message;
- WFIFOB(fd,off)=TOB(num);
+ WFIFOB(sd->fd,off)=TOB(num);
++message;
CHECK_EOS(message);
}//for
@@ -347,7 +348,7 @@ return false;\
// terminate the string
if(off < end)
{// fill the rest with 0's
- memset(WFIFOP(fd,off),0,end-off);
+ memset(WFIFOP(sd->fd,off),0,end-off);
off=end;
}
} else
@@ -359,12 +360,12 @@ return false;\
}
if(packet_db[type].len == -1) {// send dynamic packet
- WFIFOW(fd,2)=TOW(off);
- WFIFOSET(fd,off);
+ WFIFOW(sd->fd,2)=TOW(off);
+ WFIFOSET(sd->fd,off);
} else {// send static packet
if(off < len)
- memset(WFIFOP(fd,off),0,len-off);
- WFIFOSET(fd,len);
+ memset(WFIFOP(sd->fd,off),0,len-off);
+ WFIFOSET(sd->fd,len);
}
} else {
clif->message(fd, msg_txt(259)); // Invalid packet
@@ -382,15 +383,12 @@ return false;\
/*==========================================
* @rura, @warp, @mapmove
*------------------------------------------*/
-ACMD(mapmove)
-{
+ACMD(mapmove) {
char map_name[MAP_NAME_LENGTH_EXT];
- unsigned short mapindex;
+ unsigned short map_index;
short x = 0, y = 0;
int16 m = -1;
-
- nullpo_retr(-1, sd);
-
+
memset(map_name, '\0', sizeof(map_name));
if (!message || !*message ||
@@ -401,30 +399,35 @@ ACMD(mapmove)
return false;
}
- mapindex = mapindex_name2id(map_name);
- if (mapindex)
- m = iMap->mapindex2mapid(mapindex);
+ map_index = mapindex->name2id(map_name);
+ if (map_index)
+ m = map->mapindex2mapid(map_index);
- if (!mapindex) { // m < 0 means on different server! [Kevin]
+ if (!map_index || m < 0) { // m < 0 means on different server or that map is disabled! [Kevin]
clif->message(fd, msg_txt(1)); // Map not found.
return false;
}
+
+ if( sd->bl.m == m && sd->bl.x == x && sd->bl.y == y ) {
+ clif->message(fd, msg_txt(253)); // You already are at your destination!
+ return false;
+ }
- if ((x || y) && iMap->getcell(m, x, y, CELL_CHKNOPASS) && pc->get_group_level(sd) < battle_config.gm_ignore_warpable_area)
- { //This is to prevent the pc->setpos call from printing an error.
+ if ((x || y) && map->getcell(m, x, y, CELL_CHKNOPASS) && pc_get_group_level(sd) < battle_config.gm_ignore_warpable_area) {
+ //This is to prevent the pc->setpos call from printing an error.
clif->message(fd, msg_txt(2));
- if (!iMap->search_freecell(NULL, m, &x, &y, 10, 10, 1))
+ if (!map->search_freecell(NULL, m, &x, &y, 10, 10, 1))
x = y = 0; //Invalid cell, use random spot.
}
- if (map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ if (map->list[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(247));
return false;
}
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(248));
return false;
}
- if (pc->setpos(sd, mapindex, x, y, CLR_TELEPORT) != 0) {
+ if (pc->setpos(sd, map_index, x, y, CLR_TELEPORT) != 0) {
clif->message(fd, msg_txt(1)); // Map not found.
return false;
}
@@ -436,11 +439,9 @@ ACMD(mapmove)
/*==========================================
* Displays where a character is. Corrected version by Silent. [Skotlex]
*------------------------------------------*/
-ACMD(where)
-{
+ACMD(where) {
struct map_session_data* pl_sd;
- nullpo_retr(-1, sd);
memset(atcmd_player_name, '\0', sizeof atcmd_player_name);
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
@@ -448,10 +449,10 @@ ACMD(where)
return false;
}
- pl_sd = iMap->nick2sd(atcmd_player_name);
+ pl_sd = map->nick2sd(atcmd_player_name);
if (pl_sd == NULL ||
strncmp(pl_sd->status.name, atcmd_player_name, NAME_LENGTH) != 0 ||
- (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc->get_group_level(pl_sd) > pc->get_group_level(sd) && !pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID))
+ (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > pc_get_group_level(sd) && !pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID))
) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
@@ -466,45 +467,43 @@ ACMD(where)
/*==========================================
*
*------------------------------------------*/
-ACMD(jumpto)
-{
+ACMD(jumpto) {
struct map_session_data *pl_sd = NULL;
-
- nullpo_retr(-1, sd);
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(911)); // Please enter a player name (usage: @jumpto/@warpto/@goto <char name/ID>).
return false;
}
-
- if((pl_sd=iMap->nick2sd((char *)message)) == NULL && (pl_sd=iMap->charid2sd(atoi(message))) == NULL)
- {
- clif->message(fd, msg_txt(3)); // Character not found.
+
+ if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map.
return false;
}
-
- if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
- {
- clif->message(fd, msg_txt(247)); // You are not authorized to warp to this map.
+
+ if( pc_isdead(sd) ) {
+ clif->message(fd, msg_txt(864)); // "You cannot use this command when dead."
return false;
}
-
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
- {
- clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map.
+
+ if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
+ clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
- if( pc_isdead(sd) )
- {
- clif->message(fd, msg_txt(664));
+ if (pl_sd->bl.m >= 0 && map->list[pl_sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ clif->message(fd, msg_txt(247)); // You are not authorized to warp to this map.
return false;
}
-
+
+ if( pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y ) {
+ clif->message(fd, msg_txt(253)); // You already are at your destination!
+ return false;
+ }
+
pc->setpos(sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT);
sprintf(atcmd_output, msg_txt(4), pl_sd->status.name); // Jumped to %s
- clif->message(fd, atcmd_output);
-
+ clif->message(fd, atcmd_output);
+
return true;
}
@@ -514,30 +513,32 @@ ACMD(jumpto)
ACMD(jump)
{
short x = 0, y = 0;
-
- nullpo_retr(-1, sd);
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
sscanf(message, "%hd %hd", &x, &y);
- if (map[sd->bl.m].flag.noteleport && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map.
+ if (map->list[sd->bl.m].flag.noteleport && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map.
return false;
}
- if( pc_isdead(sd) )
- {
- clif->message(fd, msg_txt(664));
+ if( pc_isdead(sd) ) {
+ clif->message(fd, msg_txt(864)); // "You cannot use this command when dead."
return false;
}
- if ((x || y) && iMap->getcell(sd->bl.m, x, y, CELL_CHKNOPASS))
- { //This is to prevent the pc->setpos call from printing an error.
+ if ((x || y) && map->getcell(sd->bl.m, x, y, CELL_CHKNOPASS)) {
+ //This is to prevent the pc->setpos call from printing an error.
clif->message(fd, msg_txt(2));
- if (!iMap->search_freecell(NULL, sd->bl.m, &x, &y, 10, 10, 1))
+ if (!map->search_freecell(NULL, sd->bl.m, &x, &y, 10, 10, 1))
x = y = 0; //Invalid cell, use random spot.
}
+
+ if( x && y && sd->bl.x == x && sd->bl.y == y ) {
+ clif->message(fd, msg_txt(253)); // You already are at your destination!
+ return false;
+ }
pc->setpos(sd, sd->mapindex, x, y, CLR_TELEPORT);
sprintf(atcmd_output, msg_txt(5), sd->bl.x, sd->bl.y); // Jumped to %d %d
@@ -549,8 +550,7 @@ ACMD(jump)
* Display list of online characters with
* various info.
*------------------------------------------*/
-ACMD(who)
-{
+ACMD(who) {
struct map_session_data *pl_sd = NULL;
struct s_mapiterator *iter = NULL;
char map_name[MAP_NAME_LENGTH_EXT] = "";
@@ -565,27 +565,25 @@ ACMD(who)
*/
int display_type = 1;
int map_id = -1;
-
- nullpo_retr(-1, sd);
-
- if (strstr(command, "map") != NULL) {
- if (sscanf(message, "%15s %23s", map_name, player_name) < 1 || (map_id = iMap->mapname2mapid(map_name)) < 0)
+
+ if (stristr(info->command, "map") != NULL) {
+ if (sscanf(message, "%15s %23s", map_name, player_name) < 1 || (map_id = map->mapname2mapid(map_name)) < 0)
map_id = sd->bl.m;
} else {
sscanf(message, "%23s", player_name);
}
- if (strstr(command, "2") != NULL)
+ if (stristr(info->command, "2") != NULL)
display_type = 2;
- else if (strstr(command, "3") != NULL)
+ else if (stristr(info->command, "3") != NULL)
display_type = 3;
- level = pc->get_group_level(sd);
+ level = pc_get_group_level(sd);
StrBuf->Init(&buf);
iter = mapit_getallusers();
for (pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter)) {
- if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pc->get_group_level(pl_sd) > level)) { // you can look only lower or same level
+ if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pc_get_group_level(pl_sd) > level)) { // you can look only lower or same level
if (stristr(pl_sd->status.name, player_name) == NULL // search with no case sensitive
|| (map_id >= 0 && pl_sd->bl.m != map_id))
continue;
@@ -593,7 +591,7 @@ ACMD(who)
case 2: {
StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s "
if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
- StrBuf->Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) "
+ StrBuf->Printf(&buf, msg_txt(344), pcg->get_name(pl_sd->group)); // "(%s) "
StrBuf->Printf(&buf, msg_txt(347), pl_sd->status.base_level, pl_sd->status.job_level,
pc->job_name(pl_sd->status.class_)); // "| Lv:%d/%d | Job: %s"
break;
@@ -603,7 +601,7 @@ ACMD(who)
StrBuf->Printf(&buf, msg_txt(912), pl_sd->status.char_id, pl_sd->status.account_id); // "(CID:%d/AID:%d) "
StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s "
if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
- StrBuf->Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) "
+ StrBuf->Printf(&buf, msg_txt(344), pcg->get_name(pl_sd->group)); // "(%s) "
StrBuf->Printf(&buf, msg_txt(348), mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); // "| Location: %s %d %d"
break;
}
@@ -613,7 +611,7 @@ ACMD(who)
StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s "
if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
- StrBuf->Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) "
+ StrBuf->Printf(&buf, msg_txt(344), pcg->get_name(pl_sd->group)); // "(%s) "
if (p != NULL)
StrBuf->Printf(&buf, msg_txt(345), p->party.name); // " | Party: '%s'"
if (g != NULL)
@@ -637,11 +635,11 @@ ACMD(who)
StrBuf->Printf(&buf, msg_txt(30), count); // %d players found.
} else {
if (count == 0)
- StrBuf->Printf(&buf, msg_txt(54), map[map_id].name); // No player found in map '%s'.
+ StrBuf->Printf(&buf, msg_txt(54), map->list[map_id].name); // No player found in map '%s'.
else if (count == 1)
- StrBuf->Printf(&buf, msg_txt(55), map[map_id].name); // 1 player found in map '%s'.
+ StrBuf->Printf(&buf, msg_txt(55), map->list[map_id].name); // 1 player found in map '%s'.
else
- StrBuf->Printf(&buf, msg_txt(56), count, map[map_id].name); // %d players found in map '%s'.
+ StrBuf->Printf(&buf, msg_txt(56), count, map->list[map_id].name); // %d players found in map '%s'.
}
clif->message(fd, StrBuf->Value(&buf));
StrBuf->Destroy(&buf);
@@ -661,9 +659,7 @@ ACMD(whogm)
char player_name[NAME_LENGTH];
struct guild *g;
struct party_data *p;
-
- nullpo_retr(-1, sd);
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(match_text, '\0', sizeof(match_text));
memset(player_name, '\0', sizeof(player_name));
@@ -674,12 +670,12 @@ ACMD(whogm)
match_text[j] = TOLOWER(match_text[j]);
count = 0;
- level = pc->get_group_level(sd);
+ level = pc_get_group_level(sd);
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
- pl_level = pc->get_group_level(pl_sd);
+ pl_level = pc_get_group_level(pl_sd);
if (!pl_level)
continue;
@@ -737,15 +733,13 @@ ACMD(whogm)
/*==========================================
*
*------------------------------------------*/
-ACMD(save)
-{
- nullpo_retr(-1, sd);
+ACMD(save) {
pc->setsavepoint(sd, sd->mapindex, sd->bl.x, sd->bl.y);
if (sd->status.pet_id > 0 && sd->pd)
- intif_save_petdata(sd->status.account_id, &sd->pd->pet);
+ intif->save_petdata(sd->status.account_id, &sd->pd->pet);
- chrif_save(sd,0);
+ chrif->save(sd,0);
clif->message(fd, msg_txt(6)); // Your save point has been changed.
@@ -755,19 +749,16 @@ ACMD(save)
/*==========================================
*
*------------------------------------------*/
-ACMD(load)
-{
+ACMD(load) {
int16 m;
-
- nullpo_retr(-1, sd);
-
- m = iMap->mapindex2mapid(sd->status.save_point.map);
- if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_txt(249)); // You are not authorized to warp to your save map.
+
+ m = map->mapindex2mapid(sd->status.save_point.map);
+ if (m >= 0 && map->list[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ clif->message(fd, msg_txt(249)); // You are not authorized to warp to your save map.
return false;
}
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map.
+ if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map.
return false;
}
@@ -783,9 +774,7 @@ ACMD(load)
ACMD(speed)
{
int speed;
-
- nullpo_retr(-1, sd);
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message || sscanf(message, "%d", &speed) < 1) {
@@ -794,15 +783,21 @@ ACMD(speed)
return false;
}
- if (speed < 0) {
+ sd->state.permanent_speed = 0;
+
+ if (speed < 0)
sd->base_status.speed = DEFAULT_WALK_SPEED;
- sd->state.permanent_speed = 0; // Remove lock when set back to default speed.
- } else {
+ else
sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED);
+
+ if( sd->base_status.speed != DEFAULT_WALK_SPEED ) {
sd->state.permanent_speed = 1; // Set lock when set to non-default speed.
- }
+ clif->message(fd, msg_txt(8)); // Speed changed.
+ } else
+ clif->message(fd, msg_txt(172)); //Speed returned to normal.
+
status_calc_bl(&sd->bl, SCB_SPEED);
- clif->message(fd, msg_txt(8)); // Speed changed.
+
return true;
}
@@ -811,13 +806,10 @@ ACMD(speed)
*------------------------------------------*/
ACMD(storage)
{
- nullpo_retr(-1, sd);
-
if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag)
return false;
- if (storage_storageopen(sd) == 1)
- { //Already open.
+ if (storage->open(sd) == 1) { //Already open.
clif->message(fd, msg_txt(250));
return false;
}
@@ -833,8 +825,6 @@ ACMD(storage)
*------------------------------------------*/
ACMD(guildstorage)
{
- nullpo_retr(-1, sd);
-
if (!sd->status.guild_id) {
clif->message(fd, msg_txt(252));
return false;
@@ -853,7 +843,11 @@ ACMD(guildstorage)
return false;
}
- storage_guild_storageopen(sd);
+ if( gstorage->open(sd) ) {
+ clif->message(fd, msg_txt(1201)); // Your guild's storage has already been opened by another member, try again later.
+ return false;
+ }
+
clif->message(fd, msg_txt(920)); // Guild storage opened.
return true;
}
@@ -864,7 +858,6 @@ ACMD(guildstorage)
ACMD(option)
{
int param1 = 0, param2 = 0, param3 = 0;
- nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d %d %d", &param1, &param2, &param3) < 1 || param1 < 0 || param2 < 0 || param3 < 0)
{// failed to match the parameters so inform the user of the options
@@ -895,37 +888,35 @@ ACMD(option)
/*==========================================
*
*------------------------------------------*/
-ACMD(hide)
-{
- nullpo_retr(-1, sd);
+ACMD(hide) {
if (sd->sc.option & OPTION_INVISIBLE) {
sd->sc.option &= ~OPTION_INVISIBLE;
if (sd->disguise != -1 )
- status_set_viewdata(&sd->bl, sd->disguise);
+ status->set_viewdata(&sd->bl, sd->disguise);
else
- status_set_viewdata(&sd->bl, sd->status.class_);
+ status->set_viewdata(&sd->bl, sd->status.class_);
clif->message(fd, msg_txt(10)); // Invisible: Off
// increment the number of pvp players on the map
- map[sd->bl.m].users_pvp++;
+ map->list[sd->bl.m].users_pvp++;
- if( map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank )
- {// register the player for ranking calculations
- sd->pvp_timer = iTimer->add_timer( iTimer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0 );
+ if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank ) {
+ // register the player for ranking calculations
+ sd->pvp_timer = timer->add( timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0 );
}
//bugreport:2266
- iMap->foreachinmovearea(clif->insight, &sd->bl, AREA_SIZE, sd->bl.x, sd->bl.y, BL_ALL, &sd->bl);
+ map->foreachinmovearea(clif->insight, &sd->bl, AREA_SIZE, sd->bl.x, sd->bl.y, BL_ALL, &sd->bl);
} else {
sd->sc.option |= OPTION_INVISIBLE;
sd->vd.class_ = INVISIBLE_CLASS;
clif->message(fd, msg_txt(11)); // Invisible: On
// decrement the number of pvp players on the map
- map[sd->bl.m].users_pvp--;
+ map->list[sd->bl.m].users_pvp--;
- if( map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER )
- {// unregister the player for ranking
- iTimer->delete_timer( sd->pvp_timer, pc->calc_pvprank_timer );
+ if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ) {
+ // unregister the player for ranking
+ timer->delete( sd->pvp_timer, pc->calc_pvprank_timer );
sd->pvp_timer = INVALID_TIMER;
}
}
@@ -937,51 +928,52 @@ ACMD(hide)
/*==========================================
* Changes a character's class
*------------------------------------------*/
-ACMD(jobchange)
-{
+ACMD(jobchange) {
int job = 0, upper = 0;
const char* text;
- nullpo_retr(-1, sd);
- if (!message || !*message || sscanf(message, "%d %d", &job, &upper) < 1) {
- int i;
- bool found = false;
-
+ if (!message || !*message || sscanf(message, "%d %d", &job, &upper) < 1) {
upper = 0;
-
- // Normal Jobs
- for( i = JOB_NOVICE; i < JOB_MAX_BASIC && !found; i++ ){
- if (strncmpi(message, pc->job_name(i), 16) == 0) {
- job = i;
- found = true;
+
+ if( message ) {
+ int i;
+ bool found = false;
+
+ // Normal Jobs
+ for( i = JOB_NOVICE; i < JOB_MAX_BASIC && !found; i++ ) {
+ if (strncmpi(message, pc->job_name(i), 16) == 0) {
+ job = i;
+ found = true;
+ }
}
- }
-
- // High Jobs, Babys and Third
- for( i = JOB_NOVICE_HIGH; i < JOB_MAX && !found; i++ ){
- if (strncmpi(message, pc->job_name(i), 16) == 0) {
- job = i;
- found = true;
+
+ // High Jobs, Babies and Third
+ for( i = JOB_NOVICE_HIGH; i < JOB_MAX && !found; i++ ){
+ if (strncmpi(message, pc->job_name(i), 16) == 0) {
+ job = i;
+ found = true;
+ }
+ }
+
+ if (!found) {
+ text = atcommand_help_string(info);
+ if (text)
+ clif->messageln(fd, text);
+ return false;
}
- }
-
- if (!found) {
- text = atcommand_help_string(info);
- if (text)
- clif->messageln(fd, text);
- return false;
}
}
-
+ /* WHY DO WE LIST THEM THEN? */
+ // Deny direct transformation into dummy jobs
if (job == JOB_KNIGHT2 || job == JOB_CRUSADER2 || job == JOB_WEDDING || job == JOB_XMAS || job == JOB_SUMMER
|| job == JOB_LORD_KNIGHT2 || job == JOB_PALADIN2 || job == JOB_BABY_KNIGHT2 || job == JOB_BABY_CRUSADER2 || job == JOB_STAR_GLADIATOR2
|| (job >= JOB_RUNE_KNIGHT2 && job <= JOB_MECHANIC_T2) || (job >= JOB_BABY_RUNE2 && job <= JOB_BABY_MECHANIC2)
- ) // Deny direct transformation into dummy jobs
- {clif->message(fd, msg_txt(923)); //"You can not change to this job by command."
- return true;}
+ ) {
+ clif->message(fd, msg_txt(923)); //"You can not change to this job by command."
+ return true;
+ }
- if (pcdb_checkid(job))
- {
+ if (pcdb_checkid(job)) {
if (pc->jobchange(sd, job, upper) == 0)
clif->message(fd, msg_txt(12)); // Your job has been changed.
else {
@@ -1003,7 +995,6 @@ ACMD(jobchange)
*------------------------------------------*/
ACMD(kill)
{
- nullpo_retr(-1, sd);
status_kill(&sd->bl);
clif->message(sd->fd, msg_txt(13)); // A pity! You've died.
if (fd != sd->fd)
@@ -1016,10 +1007,8 @@ ACMD(kill)
*------------------------------------------*/
ACMD(alive)
{
- nullpo_retr(-1, sd);
- if (!status_revive(&sd->bl, 100, 100))
- {
- clif->message(fd, msg_txt(667));
+ if (!status->revive(&sd->bl, 100, 100)) {
+ clif->message(fd, msg_txt(867)); // "You're not dead."
return false;
}
clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1);
@@ -1032,24 +1021,23 @@ ACMD(alive)
*------------------------------------------*/
ACMD(kami)
{
- unsigned long color=0;
- nullpo_retr(-1, sd);
+ unsigned int color=0;
memset(atcmd_output, '\0', sizeof(atcmd_output));
- if(*(command + 5) != 'c' && *(command + 5) != 'C') {
+ if(*(info->command + 4) != 'c' && *(info->command + 4) != 'C') {
if (!message || !*message) {
clif->message(fd, msg_txt(980)); // Please enter a message (usage: @kami <message>).
return false;
}
sscanf(message, "%199[^\n]", atcmd_output);
- if (strstr(command, "l") != NULL)
- clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP);
+ if (stristr(info->command, "l") != NULL)
+ clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
else
- intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(command + 5) == 'b' || *(command + 5) == 'B') ? 0x10 : 0);
+ intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(info->command + 4) == 'b' || *(info->command + 4) == 'B') ? BC_BLUE : BC_YELLOW);
} else {
- if(!message || !*message || (sscanf(message, "%lx %199[^\n]", &color, atcmd_output) < 2)) {
+ if(!message || !*message || (sscanf(message, "%u %199[^\n]", &color, atcmd_output) < 2)) {
clif->message(fd, msg_txt(981)); // Please enter color and message (usage: @kamic <color> <message>).
return false;
}
@@ -1058,7 +1046,7 @@ ACMD(kami)
clif->message(fd, msg_txt(982)); // Invalid color.
return false;
}
- intif_broadcast2(atcmd_output, strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0);
+ intif->broadcast2(atcmd_output, strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0);
}
return true;
}
@@ -1069,7 +1057,6 @@ ACMD(kami)
ACMD(heal)
{
int hp = 0, sp = 0; // [Valaris] thanks to fov
- nullpo_retr(-1, sd);
sscanf(message, "%d %d", &hp, &sp);
@@ -1086,7 +1073,7 @@ ACMD(heal)
}
if ( hp > 0 && sp >= 0 ) {
- if(!status_heal(&sd->bl, hp, sp, 0))
+ if(!status->heal(&sd->bl, hp, sp, 0))
clif->message(fd, msg_txt(157)); // HP and SP are already with the good value.
else
clif->message(fd, msg_txt(17)); // HP, SP recovered.
@@ -1094,8 +1081,8 @@ ACMD(heal)
}
if ( hp < 0 && sp <= 0 ) {
- status_damage(NULL, &sd->bl, -hp, -sp, 0, 0);
- clif->damage(&sd->bl,&sd->bl, iTimer->gettick(), 0, 0, -hp, 0, 4, 0);
+ status->damage(NULL, &sd->bl, -hp, -sp, 0, 0);
+ clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, 4, 0);
clif->message(fd, msg_txt(156)); // HP or/and SP modified.
return true;
}
@@ -1103,18 +1090,18 @@ ACMD(heal)
//Opposing signs.
if ( hp ) {
if (hp > 0)
- status_heal(&sd->bl, hp, 0, 0);
+ status->heal(&sd->bl, hp, 0, 0);
else {
- status_damage(NULL, &sd->bl, -hp, 0, 0, 0);
- clif->damage(&sd->bl,&sd->bl, iTimer->gettick(), 0, 0, -hp, 0, 4, 0);
+ status->damage(NULL, &sd->bl, -hp, 0, 0, 0);
+ clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, 4, 0);
}
}
if ( sp ) {
if (sp > 0)
- status_heal(&sd->bl, 0, sp, 0);
+ status->heal(&sd->bl, 0, sp, 0);
else
- status_damage(NULL, &sd->bl, 0, -sp, 0, 0);
+ status->damage(NULL, &sd->bl, 0, -sp, 0, 0);
}
clif->message(fd, msg_txt(156)); // HP or/and SP modified.
@@ -1123,48 +1110,84 @@ ACMD(heal)
/*==========================================
* @item command (usage: @item <name/id_of_item> <quantity>) (modified by [Yor] for pet_egg)
+ * @itembound command (usage: @itembound <name/id_of_item> <quantity> <bound type>) (revised by [Mhalicot])
*------------------------------------------*/
ACMD(item)
{
char item_name[100];
- int number = 0, item_id, flag = 0;
+ int number = 0, item_id, flag = 0, bound = 0;
struct item item_tmp;
struct item_data *item_data;
int get_count, i;
- nullpo_retr(-1, sd);
memset(item_name, '\0', sizeof(item_name));
-
- if (!message || !*message || (
- sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 &&
- sscanf(message, "%99s %d", item_name, &number) < 1
- )) {
- clif->message(fd, msg_txt(983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>).
+
+ if (!strcmpi(info->command,"itembound") && (!message || !*message || (
+ sscanf(message, "\"%99[^\"]\" %d %d", item_name, &number, &bound) < 2 &&
+ sscanf(message, "%99s %d %d", item_name, &number, &bound) < 2
+ ))) {
+ clif->message(fd, msg_txt(295)); // Please enter an item name or ID (usage: @itembound <item name/ID> <quantity> <bound_type>).
+ return false;
+ } else if (!message || !*message || (
+ sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 &&
+ sscanf(message, "%99s %d", item_name, &number) < 1 ))
+ {
+ clif->message(fd, msg_txt(983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>).
return false;
}
if (number <= 0)
number = 1;
- if ((item_data = itemdb_searchname(item_name)) == NULL &&
- (item_data = itemdb_exists(atoi(item_name))) == NULL)
+ if ((item_data = itemdb->search_name(item_name)) == NULL &&
+ (item_data = itemdb->exists(atoi(item_name))) == NULL)
{
clif->message(fd, msg_txt(19)); // Invalid item ID or name.
return false;
}
+ if(!strcmpi(info->command,"itembound") ) {
+ if( !(bound >= IBT_MIN && bound <= IBT_MAX) ) {
+ clif->message(fd, msg_txt(298)); // Invalid bound type
+ return false;
+ }
+ switch( (enum e_item_bound_type)bound ) {
+ case IBT_CHARACTER:
+ case IBT_ACCOUNT:
+ break; /* no restrictions */
+ case IBT_PARTY:
+ if( !sd->status.party_id ) {
+ clif->message(fd, msg_txt(1498)); //You can't add a party bound item to a character without party!
+ return false;
+ }
+ break;
+ case IBT_GUILD:
+ if( !sd->status.guild_id ) {
+ clif->message(fd, msg_txt(1499)); //You can't add a guild bound item to a character without guild!
+ return false;
+ }
+ break;
+ }
+ }
+
item_id = item_data->nameid;
get_count = number;
//Check if it's stackable.
- if (!itemdb_isstackable2(item_data))
- get_count = 1;
+ if (!itemdb->isstackable2(item_data)) {
+ if( bound && (item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR) ) {
+ clif->message(fd, msg_txt(498)); // Cannot create bounded pet eggs or pet armors.
+ return false;
+ }
+ get_count = 1;
+ }
for (i = 0; i < number; i += get_count) {
// if not pet egg
- if (!pet_create_egg(sd, item_id)) {
+ if (!pet->create_egg(sd, item_id)) {
memset(&item_tmp, 0, sizeof(item_tmp));
item_tmp.nameid = item_id;
item_tmp.identify = 1;
+ item_tmp.bound = (unsigned char)bound;
if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND)))
clif->additem(sd, 0, 0, flag);
@@ -1177,22 +1200,27 @@ ACMD(item)
}
/*==========================================
- *
+ * @item2 and @itembound2 command (revised by [Mhalicot])
*------------------------------------------*/
ACMD(item2)
{
struct item item_tmp;
struct item_data *item_data;
char item_name[100];
- int item_id, number = 0;
+ int item_id, number = 0, bound = 0;
int identify = 0, refine = 0, attr = 0;
int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
- nullpo_retr(-1, sd);
memset(item_name, '\0', sizeof(item_name));
- if (!message || !*message || (
- sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 &&
+ if (!strcmpi(info->command,"itembound2") && (!message || !*message || (
+ sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 &&
+ sscanf(message, "%99s %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 ))) {
+ clif->message(fd, msg_txt(296)); // Please enter all parameters (usage: @itembound2 <item name/ID> <quantity>
+ clif->message(fd, msg_txt(297)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4> <bound_type>).
+ return false;
+ } else if ( !message || !*message || (
+ sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 &&
sscanf(message, "%99s %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9
)) {
clif->message(fd, msg_txt(984)); // Please enter all parameters (usage: @item2 <item name/ID> <quantity>
@@ -1202,10 +1230,15 @@ ACMD(item2)
if (number <= 0)
number = 1;
-
+
+ if( !strcmpi(info->command,"itembound2") && !(bound >= IBT_MIN && bound <= IBT_MAX) ) {
+ clif->message(fd, msg_txt(298)); // Invalid bound type
+ return false;
+ }
+
item_id = 0;
- if ((item_data = itemdb_searchname(item_name)) != NULL ||
- (item_data = itemdb_exists(atoi(item_name))) != NULL)
+ if ((item_data = itemdb->search_name(item_name)) != NULL ||
+ (item_data = itemdb->exists(atoi(item_name))) != NULL)
item_id = item_data->nameid;
if (item_id > 500) {
@@ -1213,9 +1246,14 @@ ACMD(item2)
int loop, get_count, i;
loop = 1;
get_count = number;
- if (item_data->type == IT_WEAPON || item_data->type == IT_ARMOR ||
- item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR) {
- loop = number;
+ if( !strcmpi(info->command,"itembound2") )
+ bound = 1;
+ if( !itemdb->isstackable2(item_data) ) {
+ if( bound && (item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR) ) {
+ clif->message(fd, msg_txt(498)); // Cannot create bounded pet eggs or pet armors.
+ return false;
+ }
+ loop = number;
get_count = 1;
if (item_data->type == IT_PETEGG) {
identify = 1;
@@ -1235,10 +1273,12 @@ ACMD(item2)
item_tmp.identify = identify;
item_tmp.refine = refine;
item_tmp.attribute = attr;
+ item_tmp.bound = (unsigned char)bound;
item_tmp.card[0] = c1;
item_tmp.card[1] = c2;
item_tmp.card[2] = c3;
item_tmp.card[3] = c4;
+
if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND)))
clif->additem(sd, 0, 0, flag);
}
@@ -1259,7 +1299,6 @@ ACMD(item2)
ACMD(itemreset)
{
int i;
- nullpo_retr(-1, sd);
for (i = 0; i < MAX_INVENTORY; i++) {
if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == 0) {
@@ -1277,7 +1316,7 @@ ACMD(itemreset)
ACMD(baselevelup)
{
int level=0, i=0, status_point=0;
- nullpo_retr(-1, sd);
+
level = atoi(message);
if (!message || !*message || !level) {
@@ -1290,13 +1329,14 @@ ACMD(baselevelup)
clif->message(fd, msg_txt(47)); // Base level can't go any higher.
return false;
} // End Addition
- if ((unsigned int)level > pc->maxbaselv(sd) || (unsigned int)level > pc->maxbaselv(sd) - sd->status.base_level) // fix positiv overflow
+ if ((unsigned int)level > pc->maxbaselv(sd) || (unsigned int)level > pc->maxbaselv(sd) - sd->status.base_level) // fix positive overflow
level = pc->maxbaselv(sd) - sd->status.base_level;
for (i = 0; i < level; i++)
status_point += pc->gets_status_point(sd->status.base_level + i);
sd->status.status_point += status_point;
sd->status.base_level += (unsigned int)level;
+ status_calc_pc(sd, SCO_FORCE);
status_percent_heal(&sd->bl, 100, 100);
clif->misceffect(&sd->bl, 0);
clif->message(fd, msg_txt(21)); // Base level raised.
@@ -1318,13 +1358,13 @@ ACMD(baselevelup)
sd->status.status_point -= status_point;
sd->status.base_level -= (unsigned int)level;
clif->message(fd, msg_txt(22)); // Base level lowered.
+ status_calc_pc(sd, SCO_FORCE);
}
sd->status.base_exp = 0;
clif->updatestatus(sd, SP_STATUSPOINT);
clif->updatestatus(sd, SP_BASELEVEL);
clif->updatestatus(sd, SP_BASEEXP);
clif->updatestatus(sd, SP_NEXTBASEEXP);
- status_calc_pc(sd, 0);
pc->baselevelchanged(sd);
if(sd->status.party_id)
party->send_levelup(sd);
@@ -1337,7 +1377,6 @@ ACMD(baselevelup)
ACMD(joblevelup)
{
int level=0;
- nullpo_retr(-1, sd);
level = atoi(message);
@@ -1350,7 +1389,7 @@ ACMD(joblevelup)
clif->message(fd, msg_txt(23)); // Job level can't go any higher.
return false;
}
- if ((unsigned int)level > pc->maxjoblv(sd) || (unsigned int)level > pc->maxjoblv(sd) - sd->status.job_level) // fix positiv overflow
+ if ((unsigned int)level > pc->maxjoblv(sd) || (unsigned int)level > pc->maxjoblv(sd) - sd->status.job_level) // fix positive overflow
level = pc->maxjoblv(sd) - sd->status.job_level;
sd->status.job_level += (unsigned int)level;
sd->status.skill_point += level;
@@ -1362,11 +1401,11 @@ ACMD(joblevelup)
return false;
}
level *=-1;
- if ((unsigned int)level >= sd->status.job_level) // fix negativ overflow
+ if ((unsigned int)level >= sd->status.job_level) // fix negative overflow
level = sd->status.job_level-1;
sd->status.job_level -= (unsigned int)level;
if (sd->status.skill_point < level)
- pc->resetskill(sd,0); //Reset skills since we need to substract more points.
+ pc->resetskill(sd,0); //Reset skills since we need to subtract more points.
if (sd->status.skill_point < level)
sd->status.skill_point = 0;
else
@@ -1378,7 +1417,7 @@ ACMD(joblevelup)
clif->updatestatus(sd, SP_JOBEXP);
clif->updatestatus(sd, SP_NEXTJOBEXP);
clif->updatestatus(sd, SP_SKILLPOINT);
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
return true;
}
@@ -1390,30 +1429,28 @@ ACMD(help) {
const char *command_name = NULL;
char *default_command = "help";
AtCommandInfo *tinfo = NULL;
-
- nullpo_retr(-1, sd);
-
+
if (!message || !*message) {
command_name = default_command; // If no command_name specified, display help for @help.
} else {
if (*message == atcommand->at_symbol || *message == atcommand->char_symbol)
++message;
- command_name = atcommand_checkalias(message);
+ command_name = atcommand->check_alias(message);
}
if (!atcommand->can_use2(sd, command_name, COMMAND_ATCOMMAND)) {
sprintf(atcmd_output, msg_txt(153), message); // "%s is Unknown Command"
clif->message(fd, atcmd_output);
- atcommand_get_suggestions(sd, command_name, true);
+ atcommand->get_suggestions(sd, command_name, true);
return false;
}
- tinfo = get_atcommandinfo_byname(atcommand_checkalias(command_name));
+ tinfo = atcommand->get_info_byname(atcommand->check_alias(command_name));
if ( !tinfo || tinfo->help == NULL ) {
sprintf(atcmd_output, msg_txt(988), atcommand->at_symbol, command_name); // There is no help for %c%s.
clif->message(fd, atcmd_output);
- atcommand_get_suggestions(sd, command_name, true);
+ atcommand->get_suggestions(sd, command_name, true);
return false;
}
@@ -1429,7 +1466,7 @@ ACMD(help) {
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, msg_txt(990)); // Available aliases:
- command_info = get_atcommandinfo_byname(command_name);
+ command_info = atcommand->get_info_byname(command_name);
iter = db_iterator(atcommand->alias_db);
for (alias_info = dbi_first(iter); dbi_exists(iter); alias_info = dbi_next(iter)) {
if (alias_info->command == command_info) {
@@ -1450,13 +1487,13 @@ ACMD(help) {
// helper function, used in foreach calls to stop auto-attack timers
// parameter: '0' - everyone, 'id' - only those attacking someone with that id
-static int atcommand_stopattack(struct block_list *bl,va_list ap)
+int atcommand_stopattack(struct block_list *bl,va_list ap)
{
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
int id = va_arg(ap, int);
if (ud && ud->attacktimer != INVALID_TIMER && (!id || id == ud->target))
{
- unit_stop_attack(bl);
+ unit->stop_attack(bl);
return 1;
}
return 0;
@@ -1464,35 +1501,33 @@ static int atcommand_stopattack(struct block_list *bl,va_list ap)
/*==========================================
*
*------------------------------------------*/
-static int atcommand_pvpoff_sub(struct block_list *bl,va_list ap)
+int atcommand_pvpoff_sub(struct block_list *bl,va_list ap)
{
TBL_PC* sd = (TBL_PC*)bl;
clif->pvpset(sd, 0, 0, 2);
if (sd->pvp_timer != INVALID_TIMER) {
- iTimer->delete_timer(sd->pvp_timer, pc->calc_pvprank_timer);
+ timer->delete(sd->pvp_timer, pc->calc_pvprank_timer);
sd->pvp_timer = INVALID_TIMER;
}
return 0;
}
-ACMD(pvpoff)
-{
- nullpo_retr(-1, sd);
+ACMD(pvpoff) {
- if (!map[sd->bl.m].flag.pvp) {
+ if (!map->list[sd->bl.m].flag.pvp) {
clif->message(fd, msg_txt(160)); // PvP is already Off.
return false;
}
- iMap->zone_change2(sd->bl.m,map[sd->bl.m].prev_zone);
- map[sd->bl.m].flag.pvp = 0;
+ map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
+ map->list[sd->bl.m].flag.pvp = 0;
if (!battle_config.pk_mode) {
clif->map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING);
clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP);
}
- iMap->foreachinmap(atcommand_pvpoff_sub,sd->bl.m, BL_PC);
- iMap->foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0);
+ map->foreachinmap(atcommand->pvpoff_sub,sd->bl.m, BL_PC);
+ map->foreachinmap(atcommand->stopattack,sd->bl.m, BL_CHAR, 0);
clif->message(fd, msg_txt(31)); // PvP: Off.
return true;
}
@@ -1500,11 +1535,11 @@ ACMD(pvpoff)
/*==========================================
*
*------------------------------------------*/
-static int atcommand_pvpon_sub(struct block_list *bl,va_list ap)
+int atcommand_pvpon_sub(struct block_list *bl,va_list ap)
{
TBL_PC* sd = (TBL_PC*)bl;
if (sd->pvp_timer == INVALID_TIMER) {
- sd->pvp_timer = iTimer->add_timer(iTimer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
+ sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
sd->pvp_rank = 0;
sd->pvp_lastusers = 0;
sd->pvp_point = 5;
@@ -1514,22 +1549,20 @@ static int atcommand_pvpon_sub(struct block_list *bl,va_list ap)
return 0;
}
-ACMD(pvpon)
-{
- nullpo_retr(-1, sd);
+ACMD(pvpon) {
- if (map[sd->bl.m].flag.pvp) {
+ if (map->list[sd->bl.m].flag.pvp) {
clif->message(fd, msg_txt(161)); // PvP is already On.
return false;
}
- iMap->zone_change2(sd->bl.m,strdb_get(zone_db, MAP_ZONE_PVP_NAME));
- map[sd->bl.m].flag.pvp = 1;
+ map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_PVP_NAME));
+ map->list[sd->bl.m].flag.pvp = 1;
if (!battle_config.pk_mode) {// display pvp circle and rank
clif->map_property_mapall(sd->bl.m, MAPPROPERTY_FREEPVPZONE);
clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP);
- iMap->foreachinmap(atcommand_pvpon_sub,sd->bl.m, BL_PC);
+ map->foreachinmap(atcommand->pvpon_sub,sd->bl.m, BL_PC);
}
clif->message(fd, msg_txt(32)); // PvP: On.
@@ -1540,20 +1573,18 @@ ACMD(pvpon)
/*==========================================
*
*------------------------------------------*/
-ACMD(gvgoff)
-{
- nullpo_retr(-1, sd);
+ACMD(gvgoff) {
- if (!map[sd->bl.m].flag.gvg) {
+ if (!map->list[sd->bl.m].flag.gvg) {
clif->message(fd, msg_txt(162)); // GvG is already Off.
return false;
}
- iMap->zone_change2(sd->bl.m,map[sd->bl.m].prev_zone);
- map[sd->bl.m].flag.gvg = 0;
+ map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
+ map->list[sd->bl.m].flag.gvg = 0;
clif->map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING);
clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP);
- iMap->foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0);
+ map->foreachinmap(atcommand->stopattack,sd->bl.m, BL_CHAR, 0);
clif->message(fd, msg_txt(33)); // GvG: Off.
return true;
@@ -1562,17 +1593,15 @@ ACMD(gvgoff)
/*==========================================
*
*------------------------------------------*/
-ACMD(gvgon)
-{
- nullpo_retr(-1, sd);
+ACMD(gvgon) {
- if (map[sd->bl.m].flag.gvg) {
+ if (map->list[sd->bl.m].flag.gvg) {
clif->message(fd, msg_txt(163)); // GvG is already On.
return false;
}
- iMap->zone_change2(sd->bl.m,strdb_get(zone_db, MAP_ZONE_GVG_NAME));
- map[sd->bl.m].flag.gvg = 1;
+ map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_GVG_NAME));
+ map->list[sd->bl.m].flag.gvg = 1;
clif->map_property_mapall(sd->bl.m, MAPPROPERTY_AGITZONE);
clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP);
clif->message(fd, msg_txt(34)); // GvG: On.
@@ -1586,7 +1615,6 @@ ACMD(gvgon)
ACMD(model)
{
int hair_style = 0, hair_color = 0, cloth_color = 0;
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
@@ -1603,7 +1631,7 @@ ACMD(model)
pc->changelook(sd, LOOK_HAIR, hair_style);
pc->changelook(sd, LOOK_HAIR_COLOR, hair_color);
pc->changelook(sd, LOOK_CLOTHES_COLOR, cloth_color);
- clif->message(fd, msg_txt(36)); // Appearence changed.
+ clif->message(fd, msg_txt(36)); // Appearance changed.
} else {
clif->message(fd, msg_txt(37)); // An invalid number was specified.
return false;
@@ -1618,7 +1646,6 @@ ACMD(model)
ACMD(dye)
{
int cloth_color = 0;
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
@@ -1630,7 +1657,7 @@ ACMD(dye)
if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) {
pc->changelook(sd, LOOK_CLOTHES_COLOR, cloth_color);
- clif->message(fd, msg_txt(36)); // Appearence changed.
+ clif->message(fd, msg_txt(36)); // Appearance changed.
} else {
clif->message(fd, msg_txt(37)); // An invalid number was specified.
return false;
@@ -1645,7 +1672,6 @@ ACMD(dye)
ACMD(hair_style)
{
int hair_style = 0;
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
@@ -1657,7 +1683,7 @@ ACMD(hair_style)
if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE) {
pc->changelook(sd, LOOK_HAIR, hair_style);
- clif->message(fd, msg_txt(36)); // Appearence changed.
+ clif->message(fd, msg_txt(36)); // Appearance changed.
} else {
clif->message(fd, msg_txt(37)); // An invalid number was specified.
return false;
@@ -1672,7 +1698,6 @@ ACMD(hair_style)
ACMD(hair_color)
{
int hair_color = 0;
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
@@ -1684,7 +1709,7 @@ ACMD(hair_color)
if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR) {
pc->changelook(sd, LOOK_HAIR_COLOR, hair_color);
- clif->message(fd, msg_txt(36)); // Appearence changed.
+ clif->message(fd, msg_txt(36)); // Appearance changed.
} else {
clif->message(fd, msg_txt(37)); // An invalid number was specified.
return false;
@@ -1696,69 +1721,63 @@ ACMD(hair_color)
/*==========================================
* @go [city_number or city_name] - Updated by Harbin
*------------------------------------------*/
-ACMD(go)
-{
+ACMD(go) {
int i;
- int town;
+ int town = INT_MAX; // Initialized to INT_MAX instead of -1 to avoid conflicts with those who map [-3:-1] to @memo locations.
char map_name[MAP_NAME_LENGTH];
- int16 m;
const struct {
char map[MAP_NAME_LENGTH];
int x, y;
+ int min_match; ///< Minimum string length to match
} data[] = {
- { MAP_PRONTERA, 156, 191 }, // 0=Prontera
- { MAP_MORROC, 156, 93 }, // 1=Morroc
- { MAP_GEFFEN, 119, 59 }, // 2=Geffen
- { MAP_PAYON, 162, 233 }, // 3=Payon
- { MAP_ALBERTA, 192, 147 }, // 4=Alberta
+ { MAP_PRONTERA, 156, 191, 3 }, // 0 = Prontera
+ { MAP_MORROC, 156, 93, 4 }, // 1 = Morroc
+ { MAP_GEFFEN, 119, 59, 3 }, // 2 = Geffen
+ { MAP_PAYON, 162, 233, 3 }, // 3 = Payon
+ { MAP_ALBERTA, 192, 147, 3 }, // 4 = Alberta
#ifdef RENEWAL
- { MAP_IZLUDE, 128, 146 }, // 5=Izlude (Renewal)
+ { MAP_IZLUDE, 128, 146, 3 }, // 5 = Izlude (Renewal)
#else
- { MAP_IZLUDE, 128, 114 }, // 5=Izlude
+ { MAP_IZLUDE, 128, 114, 3 }, // 5 = Izlude
#endif
- { MAP_ALDEBARAN, 140, 131 }, // 6=Al de Baran
- { MAP_LUTIE, 147, 134 }, // 7=Lutie
- { MAP_COMODO, 209, 143 }, // 8=Comodo
- { MAP_YUNO, 157, 51 }, // 9=Yuno
- { MAP_AMATSU, 198, 84 }, // 10=Amatsu
- { MAP_GONRYUN, 160, 120 }, // 11=Gonryun
- { MAP_UMBALA, 89, 157 }, // 12=Umbala
- { MAP_NIFLHEIM, 21, 153 }, // 13=Niflheim
- { MAP_LOUYANG, 217, 40 }, // 14=Louyang
- { MAP_NOVICE, 53, 111 }, // 15=Training Grounds
- { MAP_JAIL, 23, 61 }, // 16=Prison
- { MAP_JAWAII, 249, 127 }, // 17=Jawaii
- { MAP_AYOTHAYA, 151, 117 }, // 18=Ayothaya
- { MAP_EINBROCH, 64, 200 }, // 19=Einbroch
- { MAP_LIGHTHALZEN, 158, 92 }, // 20=Lighthalzen
- { MAP_EINBECH, 70, 95 }, // 21=Einbech
- { MAP_HUGEL, 96, 145 }, // 22=Hugel
- { MAP_RACHEL, 130, 110 }, // 23=Rachel
- { MAP_VEINS, 216, 123 }, // 24=Veins
- { MAP_MOSCOVIA, 223, 184 }, // 25=Moscovia
- { MAP_MIDCAMP, 180, 240 }, // 26=Midgard Camp
- { MAP_MANUK, 282, 138 }, // 27=Manuk
- { MAP_SPLENDIDE, 197, 176 }, // 28=Splendide
- { MAP_BRASILIS, 182, 239 }, // 29=Brasilis
- { MAP_DICASTES, 198, 187 }, // 30=El Dicastes
- { MAP_MORA, 44, 151 }, // 31=Mora
- { MAP_DEWATA, 200, 180 }, // 32=Dewata
- { MAP_MALANGDO, 140, 114 }, // 33=Malangdo Island
- { MAP_MALAYA, 242, 211 }, // 34=Malaya Port
- { MAP_ECLAGE, 110, 39 }, // 35=Eclage
+ { MAP_ALDEBARAN, 140, 131, 3 }, // 6 = Aldebaran
+ { MAP_LUTIE, 147, 134, 3 }, // 7 = Lutie
+ { MAP_COMODO, 209, 143, 3 }, // 8 = Comodo
+ { MAP_YUNO, 157, 51, 3 }, // 9 = Juno
+ { MAP_AMATSU, 198, 84, 3 }, // 10 = Amatsu
+ { MAP_GONRYUN, 160, 120, 3 }, // 11 = Kunlun
+ { MAP_UMBALA, 89, 157, 3 }, // 12 = Umbala
+ { MAP_NIFLHEIM, 21, 153, 3 }, // 13 = Niflheim
+ { MAP_LOUYANG, 217, 40, 3 }, // 14 = Luoyang
+ { MAP_NOVICE, 53, 111, 3 }, // 15 = Training Grounds
+ { MAP_JAIL, 23, 61, 3 }, // 16 = Prison
+ { MAP_JAWAII, 249, 127, 3 }, // 17 = Jawaii
+ { MAP_AYOTHAYA, 151, 117, 3 }, // 18 = Ayothaya
+ { MAP_EINBROCH, 64, 200, 5 }, // 19 = Einbroch
+ { MAP_LIGHTHALZEN, 158, 92, 3 }, // 20 = Lighthalzen
+ { MAP_EINBECH, 70, 95, 5 }, // 21 = Einbech
+ { MAP_HUGEL, 96, 145, 3 }, // 22 = Hugel
+ { MAP_RACHEL, 130, 110, 3 }, // 23 = Rachel
+ { MAP_VEINS, 216, 123, 3 }, // 24 = Veins
+ { MAP_MOSCOVIA, 223, 184, 3 }, // 25 = Moscovia
+ { MAP_MIDCAMP, 180, 240, 3 }, // 26 = Midgard Camp
+ { MAP_MANUK, 282, 138, 3 }, // 27 = Manuk
+ { MAP_SPLENDIDE, 197, 176, 3 }, // 28 = Splendide
+ { MAP_BRASILIS, 182, 239, 3 }, // 29 = Brasilis
+ { MAP_DICASTES, 198, 187, 3 }, // 30 = El Dicastes
+ { MAP_MORA, 44, 151, 4 }, // 31 = Mora
+ { MAP_DEWATA, 200, 180, 3 }, // 32 = Dewata
+ { MAP_MALANGDO, 140, 114, 5 }, // 33 = Malangdo Island
+ { MAP_MALAYA, 242, 211, 5 }, // 34 = Malaya Port
+ { MAP_ECLAGE, 110, 39, 3 }, // 35 = Eclage
};
-
- nullpo_retr(-1, sd);
-
+
memset(map_name, '\0', sizeof(map_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
- // get the number
- town = atoi(message);
-
- if (!message || !*message || sscanf(message, "%11s", map_name) < 1 || town < 0 || town >= ARRAYLENGTH(data))
- {// no value matched so send the list of locations
+ if (!message || !*message || sscanf(message, "%11s", map_name) < 1) {
+ // no value matched so send the list of locations
const char* text;
// attempt to find the text help string
@@ -1772,114 +1791,64 @@ ACMD(go)
return false;
}
-
- // get possible name of the city
- map_name[MAP_NAME_LENGTH-1] = '\0';
- for (i = 0; map_name[i]; i++)
- map_name[i] = TOLOWER(map_name[i]);
- // try to identify the map name
- if (strncmp(map_name, "prontera", 3) == 0) {
- town = 0;
- } else if (strncmp(map_name, "morocc", 4) == 0 ||
- strncmp(map_name, "morroc", 4) == 0) {
- town = 1;
- } else if (strncmp(map_name, "geffen", 3) == 0) {
- town = 2;
- } else if (strncmp(map_name, "payon", 3) == 0) {
- town = 3;
- } else if (strncmp(map_name, "alberta", 3) == 0) {
- town = 4;
- } else if (strncmp(map_name, "izlude", 3) == 0) {
- town = 5;
- } else if (strncmp(map_name, "aldebaran", 3) == 0) {
- town = 6;
- } else if (strncmp(map_name, "lutie", 3) == 0 ||
- strcmp(map_name, "christmas") == 0 ||
- strncmp(map_name, "xmas", 3) == 0 ||
- strncmp(map_name, "x-mas", 3) == 0) {
- town = 7;
- } else if (strncmp(map_name, "comodo", 3) == 0) {
- town = 8;
- } else if (strncmp(map_name, "juno", 3) == 0 ||
- strncmp(map_name, "yuno", 3) == 0) {
- town = 9;
- } else if (strncmp(map_name, "amatsu", 3) == 0) {
- town = 10;
- } else if (strncmp(map_name, "kunlun", 3) == 0 ||
- strncmp(map_name, "gonryun", 3) == 0) {
- town = 11;
- } else if (strncmp(map_name, "umbala", 3) == 0) {
- town = 12;
- } else if (strncmp(map_name, "niflheim", 3) == 0) {
- town = 13;
- } else if (strncmp(map_name, "louyang", 3) == 0) {
- town = 14;
- } else if (strncmp(map_name, "new_1-1", 3) == 0 ||
- strncmp(map_name, "startpoint", 3) == 0 ||
- strncmp(map_name, "beginning", 3) == 0) {
- town = 15;
- } else if (strncmp(map_name, "sec_pri", 3) == 0 ||
- strncmp(map_name, "prison", 3) == 0 ||
- strncmp(map_name, "jail", 3) == 0) {
- town = 16;
- } else if (strncmp(map_name, "jawaii", 3) == 0) {
- town = 17;
- } else if (strncmp(map_name, "ayothaya", 3) == 0) {
- town = 18;
- } else if (strncmp(map_name, "einbroch", 5) == 0) {
- town = 19;
- } else if (strncmp(map_name, "lighthalzen", 3) == 0) {
- town = 20;
- } else if (strncmp(map_name, "einbech", 5) == 0) {
- town = 21;
- } else if (strncmp(map_name, "hugel", 3) == 0) {
- town = 22;
- } else if (strncmp(map_name, "rachel", 3) == 0) {
- town = 23;
- } else if (strncmp(map_name, "veins", 3) == 0) {
- town = 24;
- } else if (strncmp(map_name, "moscovia", 3) == 0) {
- town = 25;
- } else if (strncmp(map_name, "mid_camp", 3) == 0) {
- town = 26;
- } else if (strncmp(map_name, "manuk", 3) == 0) {
- town = 27;
- } else if (strncmp(map_name, "splendide", 3) == 0) {
- town = 28;
- } else if (strncmp(map_name, "brasilis", 3) == 0) {
- town = 29;
- } else if (strncmp(map_name, "dicastes01", 3) == 0) {
- town = 30;
- } else if (strcmp(map_name, "mora") == 0) {
- town = 31;
- } else if (strncmp(map_name, "dewata", 3) == 0) {
- town = 32;
- } else if (strncmp(map_name, "malangdo", 5) == 0) {
- town = 33;
- } else if (strncmp(map_name, "malaya", 5) == 0) {
- town = 34;
- } else if (strncmp(map_name, "eclage", 3) == 0) {
- town = 35;
- }
-
- if (town >= 0 && town < ARRAYLENGTH(data))
- {
- m = iMap->mapname2mapid(data[town].map);
- if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+
+ // Numeric entry
+ if (ISDIGIT(*message) || (message[0] == '-' && ISDIGIT(message[1]))) {
+ town = atoi(message);
+ }
+
+ if (town < 0 || town >= ARRAYLENGTH(data)) {
+ map_name[MAP_NAME_LENGTH-1] = '\0';
+
+ // Match maps on the list
+ for (i = 0; i < ARRAYLENGTH(data); i++) {
+ if (strncmpi(map_name, data[i].map, data[i].min_match) == 0) {
+ town = i;
+ break;
+ }
+ }
+ }
+
+ if (town < 0 || town >= ARRAYLENGTH(data)) {
+ // Alternate spellings
+ if (strncmpi(map_name, "morroc", 4) == 0) { // Correct town name for 'morocc'
+ town = 1;
+ } else if (strncmpi(map_name, "lutie", 3) == 0) { // Correct town name for 'xmas'
+ town = 7;
+ } else if (strncmpi(map_name, "juno", 3) == 0) { // Correct town name for 'yuno'
+ town = 9;
+ } else if (strncmpi(map_name, "kunlun", 3) == 0) { // Original town name for 'gonryun'
+ town = 11;
+ } else if (strncmpi(map_name, "luoyang", 3) == 0) { // Original town name for 'louyang'
+ town = 14;
+ } else if (strncmpi(map_name, "startpoint", 3) == 0 // Easy to remember alternatives to 'new_1-1'
+ || strncmpi(map_name, "beginning", 3) == 0) {
+ town = 15;
+ } else if (strncmpi(map_name, "prison", 3) == 0 // Easy to remember alternatives to 'sec_pri'
+ || strncmpi(map_name, "jail", 3) == 0) {
+ town = 16;
+ } else if (strncmpi(map_name, "rael", 3) == 0) { // Original town name for 'rachel'
+ town = 23;
+ }
+ }
+
+ if (town >= 0 && town < ARRAYLENGTH(data)) {
+ int16 m = map->mapname2mapid(data[town].map);
+ if (m >= 0 && map->list[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(247));
return false;
}
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(248));
return false;
}
- if (pc->setpos(sd, mapindex_name2id(data[town].map), data[town].x, data[town].y, CLR_TELEPORT) == 0) {
+ if (pc->setpos(sd, mapindex->name2id(data[town].map), data[town].x, data[town].y, CLR_TELEPORT) == 0) {
clif->message(fd, msg_txt(0)); // Warped.
} else {
clif->message(fd, msg_txt(1)); // Map not found.
return false;
}
- } else { // if you arrive here, you have an error in town variable when reading of names
+ } else {
clif->message(fd, msg_txt(38)); // Invalid location number or name.
return false;
}
@@ -1901,14 +1870,13 @@ ACMD(monster)
int i, k, range;
short mx, my;
unsigned int size;
- nullpo_retr(-1, sd);
memset(name, '\0', sizeof(name));
memset(monster, '\0', sizeof(monster));
memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message) {
- clif->message(fd, msg_txt(80)); // Give the display name or monster name/id please.
+ clif->message(fd, msg_txt(80)); // Please specify a display name or monster name/id.
return false;
}
if (sscanf(message, "\"%23[^\"]\" %23s %d", name, monster, &number) > 1 ||
@@ -1928,19 +1896,14 @@ ACMD(monster)
return false;
}
- if ((mob_id = mobdb_searchname(monster)) == 0) // check name first (to avoid possible name begining by a number)
- mob_id = mobdb_checkid(atoi(monster));
+ if ((mob_id = mob->db_searchname(monster)) == 0) // check name first (to avoid possible name beginning by a number)
+ mob_id = mob->db_checkid(atoi(monster));
if (mob_id == 0) {
clif->message(fd, msg_txt(40)); // Invalid monster ID or name.
return false;
}
-
- if (mob_id == MOBID_EMPERIUM) {
- clif->message(fd, msg_txt(83)); // Monster 'Emperium' cannot be spawned.
- return false;
- }
-
+
if (number <= 0)
number = 1;
@@ -1951,12 +1914,12 @@ ACMD(monster)
if (battle_config.atc_spawn_quantity_limit && number > battle_config.atc_spawn_quantity_limit)
number = battle_config.atc_spawn_quantity_limit;
- if (strcmp(command+1, "monstersmall") == 0)
- size = SZ_MEDIUM; // This is just gorgeous [mkbu95]
- else if (strcmp(command+1, "monsterbig") == 0)
+ if (strcmpi(info->command, "monstersmall") == 0)
+ size = SZ_SMALL;
+ else if (strcmpi(info->command, "monsterbig") == 0)
size = SZ_BIG;
else
- size = SZ_SMALL;
+ size = SZ_MEDIUM;
if (battle_config.etc_log)
ShowInfo("%s monster='%s' name='%s' id=%d count=%d (%d,%d)\n", command, monster, name, mob_id, number, sd->bl.x, sd->bl.y);
@@ -1964,8 +1927,8 @@ ACMD(monster)
count = 0;
range = (int)sqrt((float)number) +2; // calculation of an odd number (+ 4 area around)
for (i = 0; i < number; i++) {
- iMap->search_freecell(&sd->bl, 0, &mx, &my, range, range, 0);
- k = mob_once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, eventname, size, AI_NONE);
+ map->search_freecell(&sd->bl, 0, &mx, &my, range, range, 0);
+ k = mob->once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, eventname, size, AI_NONE|(mob_id == MOBID_EMPERIUM?0x200:0x0));
count += (k != 0) ? 1 : 0;
}
@@ -1987,7 +1950,7 @@ ACMD(monster)
/*==========================================
*
*------------------------------------------*/
-static int atkillmonster_sub(struct block_list *bl, va_list ap)
+int atkillmonster_sub(struct block_list *bl, va_list ap)
{
struct mob_data *md;
int flag;
@@ -2005,24 +1968,22 @@ static int atkillmonster_sub(struct block_list *bl, va_list ap)
return 1;
}
-ACMD(killmonster)
-{
+ACMD(killmonster) {
int map_id, drop_flag;
char map_name[MAP_NAME_LENGTH_EXT];
- nullpo_retr(-1, sd);
memset(map_name, '\0', sizeof(map_name));
if (!message || !*message || sscanf(message, "%15s", map_name) < 1)
map_id = sd->bl.m;
else {
- if ((map_id = iMap->mapname2mapid(map_name)) < 0)
+ if ((map_id = map->mapname2mapid(map_name)) < 0)
map_id = sd->bl.m;
}
- drop_flag = strcmp(command+1, "killmonster2");
+ drop_flag = strcmpi(info->command, "killmonster2");
- iMap->foreachinmap(atkillmonster_sub, map_id, BL_MOB, -drop_flag);
+ map->foreachinmap(atcommand->atkillmonster_sub, map_id, BL_MOB, -drop_flag);
clif->message(fd, msg_txt(165)); // All monsters killed!
@@ -2036,7 +1997,6 @@ ACMD(refine)
{
int i,j, position = 0, refine = 0, current_position, final_refine;
int count;
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
@@ -2068,9 +2028,10 @@ ACMD(refine)
refine = cap_value(refine, -MAX_REFINE, MAX_REFINE);
count = 0;
- for (j = 0; j < EQI_MAX-1; j++) {
+ for (j = 0; j < EQI_MAX; j++) {
if ((i = sd->equip_index[j]) < 0)
continue;
+ if(j == EQI_AMMO) continue; /* can't equip ammo */
if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == i)
continue;
if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == i)
@@ -2116,7 +2077,6 @@ ACMD(produce)
int item_id, attribute = 0, star = 0;
struct item_data *item_data;
struct item tmp_item;
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(item_name, '\0', sizeof(item_name));
@@ -2129,15 +2089,15 @@ ACMD(produce)
return false;
}
- if ( (item_data = itemdb_searchname(item_name)) == NULL &&
- (item_data = itemdb_exists(atoi(item_name))) == NULL ) {
+ if ( (item_data = itemdb->search_name(item_name)) == NULL &&
+ (item_data = itemdb->exists(atoi(item_name))) == NULL ) {
clif->message(fd, msg_txt(170)); //This item is not an equipment.
return false;
}
item_id = item_data->nameid;
- if (itemdb_isequip2(item_data)) {
+ if (itemdb->isequip2(item_data)) {
int flag = 0;
if (attribute < MIN_ATTRIBUTE || attribute > MAX_ATTRIBUTE)
attribute = ATTRIBUTE_NORMAL;
@@ -2172,14 +2132,13 @@ ACMD(produce)
ACMD(memo)
{
int position = 0;
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
if( !message || !*message || sscanf(message, "%d", &position) < 1 )
{
int i;
- clif->message(sd->fd, msg_txt(668));
+ clif->message(sd->fd, msg_txt(868)); // "Your current memo positions are:"
for( i = 0; i < MAX_MEMOPOINTS; i++ )
{
if( sd->status.memo_point[i].map )
@@ -2205,21 +2164,19 @@ ACMD(memo)
/*==========================================
*
*------------------------------------------*/
-ACMD(gat)
-{
+ACMD(gat) {
int y;
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
for (y = 2; y >= -2; y--) {
sprintf(atcmd_output, "%s (x= %d, y= %d) %02X %02X %02X %02X %02X",
- map[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y,
- iMap->getcell(sd->bl.m, sd->bl.x - 2, sd->bl.y + y, CELL_GETTYPE),
- iMap->getcell(sd->bl.m, sd->bl.x - 1, sd->bl.y + y, CELL_GETTYPE),
- iMap->getcell(sd->bl.m, sd->bl.x, sd->bl.y + y, CELL_GETTYPE),
- iMap->getcell(sd->bl.m, sd->bl.x + 1, sd->bl.y + y, CELL_GETTYPE),
- iMap->getcell(sd->bl.m, sd->bl.x + 2, sd->bl.y + y, CELL_GETTYPE));
+ map->list[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y,
+ map->getcell(sd->bl.m, sd->bl.x - 2, sd->bl.y + y, CELL_GETTYPE),
+ map->getcell(sd->bl.m, sd->bl.x - 1, sd->bl.y + y, CELL_GETTYPE),
+ map->getcell(sd->bl.m, sd->bl.x, sd->bl.y + y, CELL_GETTYPE),
+ map->getcell(sd->bl.m, sd->bl.x + 1, sd->bl.y + y, CELL_GETTYPE),
+ map->getcell(sd->bl.m, sd->bl.x + 2, sd->bl.y + y, CELL_GETTYPE));
clif->message(fd, atcmd_output);
}
@@ -2233,7 +2190,6 @@ ACMD(gat)
ACMD(displaystatus)
{
int i, type, flag, tick, val1 = 0, val2 = 0, val3 = 0;
- nullpo_retr(-1, sd);
if (!message || !*message || (i = sscanf(message, "%d %d %d %d %d %d", &type, &flag, &tick, &val1, &val2, &val3)) < 1) {
clif->message(fd, msg_txt(1009)); // Please enter a status type/flag (usage: @displaystatus <status type> <flag> <tick> {<val1> {<val2> {<val3>}}}).
@@ -2305,7 +2261,6 @@ ACMD(skillpoint)
{
int point;
unsigned int new_skill_point;
- nullpo_retr(-1, sd);
if (!message || !*message || (point = atoi(message)) == 0) {
clif->message(fd, msg_txt(1011)); // Please enter a number (usage: @skpoint <number of points>).
@@ -2353,7 +2308,6 @@ ACMD(skillpoint)
ACMD(zeny)
{
int zeny=0, ret=-1;
- nullpo_retr(-1, sd);
if (!message || !*message || (zeny = atoi(message)) == 0) {
clif->message(fd, msg_txt(1012)); // Please enter an amount (usage: @zeny <amount>).
@@ -2369,20 +2323,22 @@ ACMD(zeny)
if((ret=pc->payzeny(sd,-zeny,LOG_TYPE_COMMAND,NULL)) == 1)
clif->message(fd, msg_txt(41)); // Unable to decrease the number/value.
}
- if(!ret) clif->message(fd, msg_txt(176)); //ret=0 mean cmd success
+
+ if( ret ) //ret != 0 means cmd failure
+ return false;
+
+ clif->message(fd, msg_txt(176));
return true;
}
/*==========================================
*
*------------------------------------------*/
-ACMD(param)
-{
+ACMD(param) {
int i, value = 0, new_value, max;
const char* param[] = { "str", "agi", "vit", "int", "dex", "luk" };
- short* status[6];
+ short* stats[6];
//we don't use direct initialization because it isn't part of the c standard.
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
@@ -2391,38 +2347,38 @@ ACMD(param)
return false;
}
- ARR_FIND( 0, ARRAYLENGTH(param), i, strcmpi(command+1, param[i]) == 0 );
+ ARR_FIND( 0, ARRAYLENGTH(param), i, strcmpi(info->command, param[i]) == 0 );
if( i == ARRAYLENGTH(param) || i > MAX_STATUS_TYPE) { // normally impossible...
clif->message(fd, msg_txt(1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>).
return false;
}
- status[0] = &sd->status.str;
- status[1] = &sd->status.agi;
- status[2] = &sd->status.vit;
- status[3] = &sd->status.int_;
- status[4] = &sd->status.dex;
- status[5] = &sd->status.luk;
+ stats[0] = &sd->status.str;
+ stats[1] = &sd->status.agi;
+ stats[2] = &sd->status.vit;
+ stats[3] = &sd->status.int_;
+ stats[4] = &sd->status.dex;
+ stats[5] = &sd->status.luk;
if( battle_config.atcommand_max_stat_bypass )
max = SHRT_MAX;
else
max = pc_maxparameter(sd);
- if(value < 0 && *status[i] <= -value) {
+ if(value < 0 && *stats[i] <= -value) {
new_value = 1;
- } else if(max - *status[i] < value) {
+ } else if(max - *stats[i] < value) {
new_value = max;
} else {
- new_value = *status[i] + value;
+ new_value = *stats[i] + value;
}
- if (new_value != *status[i]) {
- *status[i] = new_value;
+ if (new_value != *stats[i]) {
+ *stats[i] = new_value;
clif->updatestatus(sd, SP_STR + i);
clif->updatestatus(sd, SP_USTR + i);
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
clif->message(fd, msg_txt(42)); // Stat changed.
} else {
if (value < 0)
@@ -2438,19 +2394,17 @@ ACMD(param)
/*==========================================
* Stat all by fritz (rewritten by [Yor])
*------------------------------------------*/
-ACMD(stat_all)
-{
+ACMD(stat_all) {
int index, count, value, max, new_value;
- short* status[6];
+ short* stats[6];
//we don't use direct initialization because it isn't part of the c standard.
- nullpo_retr(-1, sd);
- status[0] = &sd->status.str;
- status[1] = &sd->status.agi;
- status[2] = &sd->status.vit;
- status[3] = &sd->status.int_;
- status[4] = &sd->status.dex;
- status[5] = &sd->status.luk;
+ stats[0] = &sd->status.str;
+ stats[1] = &sd->status.agi;
+ stats[2] = &sd->status.vit;
+ stats[3] = &sd->status.int_;
+ stats[4] = &sd->status.dex;
+ stats[5] = &sd->status.luk;
if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) {
value = pc_maxparameter(sd);
@@ -2463,17 +2417,17 @@ ACMD(stat_all)
}
count = 0;
- for (index = 0; index < ARRAYLENGTH(status); index++) {
+ for (index = 0; index < ARRAYLENGTH(stats); index++) {
- if (value > 0 && *status[index] > max - value)
+ if (value > 0 && *stats[index] > max - value)
new_value = max;
- else if (value < 0 && *status[index] <= -value)
+ else if (value < 0 && *stats[index] <= -value)
new_value = 1;
else
- new_value = *status[index] +value;
+ new_value = *stats[index] +value;
- if (new_value != (int)*status[index]) {
- *status[index] = new_value;
+ if (new_value != (int)*stats[index]) {
+ *stats[index] = new_value;
clif->updatestatus(sd, SP_STR + index);
clif->updatestatus(sd, SP_USTR + index);
count++;
@@ -2481,7 +2435,7 @@ ACMD(stat_all)
}
if (count > 0) { // if at least 1 stat modified
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
clif->message(fd, msg_txt(84)); // All stats changed!
} else {
if (value < 0)
@@ -2497,12 +2451,10 @@ ACMD(stat_all)
/*==========================================
*
*------------------------------------------*/
-ACMD(guildlevelup)
-{
+ACMD(guildlevelup) {
int level = 0;
- short added_level;
+ int16 added_level;
struct guild *guild_info;
- nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d", &level) < 1 || level == 0) {
clif->message(fd, msg_txt(1014)); // Please enter a valid level (usage: @guildlvup/@guildlvlup <# of levels>).
@@ -2513,19 +2465,21 @@ ACMD(guildlevelup)
clif->message(fd, msg_txt(43)); // You're not in a guild.
return false;
}
- //if (strcmp(sd->status.name, guild_info->master) != 0) {
- // clif->message(fd, msg_txt(44)); // You're not the master of your guild.
- // return false;
- //}
+#if 0 // By enabling this, only the guild leader can use this command
+ if (strcmp(sd->status.name, guild_info->master) != 0) {
+ clif->message(fd, msg_txt(44)); // You're not the master of your guild.
+ return false;
+ }
+#endif // 0
- added_level = (short)level;
- if (level > 0 && (level > MAX_GUILDLEVEL || added_level > ((short)MAX_GUILDLEVEL - guild_info->guild_lv))) // fix positiv overflow
- added_level = (short)MAX_GUILDLEVEL - guild_info->guild_lv;
- else if (level < 0 && (level < -MAX_GUILDLEVEL || added_level < (1 - guild_info->guild_lv))) // fix negativ overflow
- added_level = 1 - guild_info->guild_lv;
+ if (level > INT16_MAX || (level > 0 && level > MAX_GUILDLEVEL - guild_info->guild_lv)) // fix positive overflow
+ level = MAX_GUILDLEVEL - guild_info->guild_lv;
+ else if (level < INT16_MIN || (level < 0 && level < 1 - guild_info->guild_lv)) // fix negative overflow
+ level = 1 - guild_info->guild_lv;
+ added_level = (int16)level;
if (added_level != 0) {
- intif_guild_change_basicinfo(guild_info->guild_id, GBI_GUILDLV, &added_level, sizeof(added_level));
+ intif->guild_change_basicinfo(guild_info->guild_id, GBI_GUILDLV, &added_level, sizeof(added_level));
clif->message(fd, msg_txt(179)); // Guild level changed.
} else {
clif->message(fd, msg_txt(45)); // Guild level change failed.
@@ -2542,31 +2496,30 @@ ACMD(makeegg)
{
struct item_data *item_data;
int id, pet_id;
- nullpo_retr(-1, sd);
if (!message || !*message) {
clif->message(fd, msg_txt(1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>).
return false;
}
- if ((item_data = itemdb_searchname(message)) != NULL) // for egg name
+ if ((item_data = itemdb->search_name(message)) != NULL) // for egg name
id = item_data->nameid;
else
- if ((id = mobdb_searchname(message)) != 0) // for monster name
+ if ((id = mob->db_searchname(message)) != 0) // for monster name
;
else
id = atoi(message);
- pet_id = search_petDB_index(id, PET_CLASS);
+ pet_id = pet->search_petDB_index(id, PET_CLASS);
if (pet_id < 0)
- pet_id = search_petDB_index(id, PET_EGG);
+ pet_id = pet->search_petDB_index(id, PET_EGG);
if (pet_id >= 0) {
- sd->catch_target_class = pet_db[pet_id].class_;
- intif_create_pet(
+ sd->catch_target_class = pet->db[pet_id].class_;
+ intif->create_pet(
sd->status.account_id, sd->status.char_id,
- (short)pet_db[pet_id].class_, (short)mob_db(pet_db[pet_id].class_)->lv,
- (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate,
- 100, 0, 1, pet_db[pet_id].jname);
+ (short)pet->db[pet_id].class_, (short)mob->db(pet->db[pet_id].class_)->lv,
+ (short)pet->db[pet_id].EggID, 0, (short)pet->db[pet_id].intimate,
+ 100, 0, 1, pet->db[pet_id].jname);
} else {
clif->message(fd, msg_txt(180)); // The monster/egg name/id doesn't exist.
return false;
@@ -2580,7 +2533,6 @@ ACMD(makeegg)
*------------------------------------------*/
ACMD(hatch)
{
- nullpo_retr(-1, sd);
if (sd->status.pet_id <= 0)
clif->sendegg(sd);
else {
@@ -2598,7 +2550,6 @@ ACMD(petfriendly)
{
int friendly;
struct pet_data *pd;
- nullpo_retr(-1, sd);
if (!message || !*message || (friendly = atoi(message)) < 0) {
clif->message(fd, msg_txt(1016)); // Please enter a valid value (usage: @petfriendly <0-1000>).
@@ -2622,7 +2573,7 @@ ACMD(petfriendly)
return false;
}
- pet_set_intimate(pd, friendly);
+ pet->set_intimate(pd, friendly);
clif->send_petstatus(sd);
clif->message(fd, msg_txt(182)); // Pet intimacy changed.
return true;
@@ -2635,7 +2586,6 @@ ACMD(pethungry)
{
int hungry;
struct pet_data *pd;
- nullpo_retr(-1, sd);
if (!message || !*message || (hungry = atoi(message)) < 0) {
clif->message(fd, msg_txt(1017)); // Please enter a valid number (usage: @pethungry <0-100>).
@@ -2669,7 +2619,6 @@ ACMD(pethungry)
ACMD(petrename)
{
struct pet_data *pd;
- nullpo_retr(-1, sd);
if (!sd->status.pet_id || !sd->pd) {
clif->message(fd, msg_txt(184)); // Sorry, but you have no pet.
return false;
@@ -2681,7 +2630,7 @@ ACMD(petrename)
}
pd->pet.rename_flag = 0;
- intif_save_petdata(sd->status.account_id, &pd->pet);
+ intif->save_petdata(sd->status.account_id, &pd->pet);
clif->send_petstatus(sd);
clif->message(fd, msg_txt(187)); // You can now rename your pet.
@@ -2694,30 +2643,28 @@ ACMD(petrename)
ACMD(recall) {
struct map_session_data *pl_sd = NULL;
- nullpo_retr(-1, sd);
if (!message || !*message) {
clif->message(fd, msg_txt(1018)); // Please enter a player name (usage: @recall <char name/ID>).
return false;
}
- if((pl_sd=iMap->nick2sd((char *)message)) == NULL && (pl_sd=iMap->charid2sd(atoi(message))) == NULL)
- {
+ if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
- if ( pc->get_group_level(sd) < pc->get_group_level(pl_sd) )
+ if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) )
{
clif->message(fd, msg_txt(81)); // Your GM level doesn't authorize you to preform this action on the specified player.
return false;
}
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(1019)); // You are not authorized to warp someone to this map.
return false;
}
- if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ if (pl_sd->bl.m >= 0 && map->list[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(1020)); // You are not authorized to warp this player from their map.
return false;
}
@@ -2737,16 +2684,15 @@ ACMD(recall) {
*------------------------------------------*/
ACMD(char_block)
{
- nullpo_retr(-1, sd);
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
- clif->message(fd, msg_txt(1021)); // Please enter a player name (usage: @charblock/@block <char name>).
+ clif->message(fd, msg_txt(1021)); // Please enter a player name (usage: @block <char name>).
return false;
}
- chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block
+ chrif->char_ask_name(sd->status.account_id, atcmd_player_name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block
clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it.
return true;
@@ -2765,7 +2711,7 @@ ACMD(char_block)
* mn: minute
* s: second
* <example> @ban +1m-2mn1s-6y test_player
- * this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
+ * this example adds 1 month and 1 second, and subtracts 2 minutes and 6 years at the same time.
*------------------------------------------*/
ACMD(char_ban)
{
@@ -2773,13 +2719,12 @@ ACMD(char_ban)
int year, month, day, hour, minute, second, value;
time_t timestamp;
struct tm *tmtime;
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
if (!message || !*message || sscanf(message, "%255s %23[^\n]", atcmd_output, atcmd_player_name) < 2) {
- clif->message(fd, msg_txt(1022)); // Please enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <char name>).
+ clif->message(fd, msg_txt(1022)); // Please enter ban time and a player name (usage: @ban <time> <char name>).
return false;
}
@@ -2843,7 +2788,7 @@ ACMD(char_ban)
return false;
}
- chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 2, year, month, day, hour, minute, second); // type: 2 - ban
+ chrif->char_ask_name(sd->status.account_id, atcmd_player_name, !strcmpi(info->command,"charban") ? 6 : 2, year, month, day, hour, minute, second); // type: 2 - ban; 6 - charban
clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it.
return true;
@@ -2854,17 +2799,16 @@ ACMD(char_ban)
*------------------------------------------*/
ACMD(char_unblock)
{
- nullpo_retr(-1, sd);
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
- clif->message(fd, msg_txt(1024)); // Please enter a player name (usage: @charunblock <char name>).
+ clif->message(fd, msg_txt(1024)); // Please enter a player name (usage: @unblock <char name>).
return false;
}
// send answer to login server via char-server
- chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 3, 0, 0, 0, 0, 0, 0); // type: 3 - unblock
+ chrif->char_ask_name(sd->status.account_id, atcmd_player_name, 3, 0, 0, 0, 0, 0, 0); // type: 3 - unblock
clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it.
return true;
@@ -2875,17 +2819,16 @@ ACMD(char_unblock)
*------------------------------------------*/
ACMD(char_unban)
{
- nullpo_retr(-1, sd);
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
- clif->message(fd, msg_txt(1025)); // Please enter a player name (usage: @charunban <char name>).
+ clif->message(fd, msg_txt(1025)); // Please enter a player name (usage: @unban <char name>).
return false;
}
// send answer to login server via char-server
- chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban
+ chrif->char_ask_name(sd->status.account_id, atcmd_player_name, !strcmpi(info->command,"charunban") ? 7 : 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban account; type 7 - unban character
clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it.
return true;
@@ -2894,11 +2837,9 @@ ACMD(char_unban)
/*==========================================
*
*------------------------------------------*/
-ACMD(night)
-{
- nullpo_retr(-1, sd);
+ACMD(night) {
- if (iMap->night_flag != 1) {
+ if (map->night_flag != 1) {
pc->map_night_timer(pc->night_timer_tid, 0, 0, 1);
} else {
clif->message(fd, msg_txt(89)); // Night mode is already enabled.
@@ -2911,11 +2852,9 @@ ACMD(night)
/*==========================================
*
*------------------------------------------*/
-ACMD(day)
-{
- nullpo_retr(-1, sd);
+ACMD(day) {
- if (iMap->night_flag != 0) {
+ if (map->night_flag != 0) {
pc->map_day_timer(pc->day_timer_tid, 0, 0, 1);
} else {
clif->message(fd, msg_txt(90)); // Day mode is already enabled.
@@ -2932,22 +2871,20 @@ ACMD(doom)
{
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
-
- nullpo_retr(-1, sd);
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
- if (pl_sd->fd != fd && pc->get_group_level(sd) >= pc->get_group_level(pl_sd))
+ if (pl_sd->fd != fd && pc_get_group_level(sd) >= pc_get_group_level(pl_sd))
{
status_kill(&pl_sd->bl);
clif->specialeffect(&pl_sd->bl,450,AREA);
- clif->message(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement.
+ clif->message(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgment.
}
}
mapit->free(iter);
- clif->message(fd, msg_txt(62)); // Judgement was made.
+ clif->message(fd, msg_txt(62)); // Judgment was made.
return true;
}
@@ -2959,22 +2896,20 @@ ACMD(doommap)
{
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
-
- nullpo_retr(-1, sd);
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
- if (pl_sd->fd != fd && sd->bl.m == pl_sd->bl.m && pc->get_group_level(sd) >= pc->get_group_level(pl_sd))
+ if (pl_sd->fd != fd && sd->bl.m == pl_sd->bl.m && pc_get_group_level(sd) >= pc_get_group_level(pl_sd))
{
status_kill(&pl_sd->bl);
clif->specialeffect(&pl_sd->bl,450,AREA);
- clif->message(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement.
+ clif->message(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgment.
}
}
mapit->free(iter);
- clif->message(fd, msg_txt(62)); // Judgement was made.
+ clif->message(fd, msg_txt(62)); // Judgment was made.
return true;
}
@@ -2982,9 +2917,9 @@ ACMD(doommap)
/*==========================================
*
*------------------------------------------*/
-static void atcommand_raise_sub(struct map_session_data* sd) {
+void atcommand_raise_sub(struct map_session_data* sd) {
- status_revive(&sd->bl, 100, 100);
+ status->revive(&sd->bl, 100, 100);
clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1);
clif->message(sd->fd, msg_txt(63)); // Mercy has been shown.
@@ -2997,13 +2932,11 @@ ACMD(raise)
{
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
-
- nullpo_retr(-1, sd);
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
if( pc_isdead(pl_sd) )
- atcommand_raise_sub(pl_sd);
+ atcommand->raise_sub(pl_sd);
mapit->free(iter);
clif->message(fd, msg_txt(64)); // Mercy has been granted.
@@ -3018,13 +2951,11 @@ ACMD(raisemap)
{
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
-
- nullpo_retr(-1, sd);
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
if (sd->bl.m == pl_sd->bl.m && pc_isdead(pl_sd) )
- atcommand_raise_sub(pl_sd);
+ atcommand->raise_sub(pl_sd);
mapit->free(iter);
clif->message(fd, msg_txt(64)); // Mercy has been granted.
@@ -3038,7 +2969,6 @@ ACMD(raisemap)
ACMD(kick)
{
struct map_session_data *pl_sd;
- nullpo_retr(-1, sd);
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
@@ -3047,15 +2977,14 @@ ACMD(kick)
return false;
}
- if((pl_sd=iMap->nick2sd((char *)message)) == NULL && (pl_sd=iMap->charid2sd(atoi(message))) == NULL)
- {
+ if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
- if ( pc->get_group_level(sd) < pc->get_group_level(pl_sd) )
+ if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) )
{
- clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
+ clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
return false;
}
@@ -3071,12 +3000,11 @@ ACMD(kickall)
{
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
- nullpo_retr(-1, sd);
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
- if (pc->get_group_level(sd) >= pc->get_group_level(pl_sd)) { // you can kick only lower or same gm level
+ if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kick only lower or same gm level
if (sd->status.account_id != pl_sd->status.account_id)
clif->GM_kick(NULL, pl_sd);
}
@@ -3093,7 +3021,6 @@ ACMD(kickall)
*------------------------------------------*/
ACMD(allskill)
{
- nullpo_retr(-1, sd);
pc->allskillup(sd); // all skills
sd->status.skill_point = 0; // 0 skill points
clif->updatestatus(sd, SP_SKILLPOINT); // update
@@ -3108,7 +3035,6 @@ ACMD(allskill)
ACMD(questskill)
{
uint16 skill_id, index;
- nullpo_retr(-1, sd);
if (!message || !*message || (skill_id = atoi(message)) <= 0)
{// also send a list of skills applicable to this command
@@ -3151,7 +3077,6 @@ ACMD(questskill)
ACMD(lostskill)
{
uint16 skill_id, index;
- nullpo_retr(-1, sd);
if (!message || !*message || (skill_id = atoi(message)) <= 0)
{// also send a list of skills applicable to this command
@@ -3197,14 +3122,13 @@ ACMD(spiritball)
{
int max_spiritballs;
int number;
- nullpo_retr(-1, sd);
max_spiritballs = min(ARRAYLENGTH(sd->spirit_timer), 0x7FFF);
if( !message || !*message || (number = atoi(message)) < 0 || number > max_spiritballs )
{
char msg[CHAT_SIZE_MAX];
- safesnprintf(msg, sizeof(msg), msg_txt(1028), max_spiritballs); // Please enter a party name (usage: @party <party_name>).
+ safesnprintf(msg, sizeof(msg), msg_txt(1028), max_spiritballs); // Please enter an amount (usage: @spiritball <number: 0-%d>).
clif->message(fd, msg);
return false;
}
@@ -3224,7 +3148,6 @@ ACMD(spiritball)
ACMD(party)
{
char party_name[NAME_LENGTH];
- nullpo_retr(-1, sd);
memset(party_name, '\0', sizeof(party_name));
@@ -3245,7 +3168,6 @@ ACMD(guild)
{
char guild_name[NAME_LENGTH];
int prev;
- nullpo_retr(-1, sd);
memset(guild_name, '\0', sizeof(guild_name));
@@ -3264,7 +3186,6 @@ ACMD(guild)
ACMD(breakguild)
{
- nullpo_retr(-1, sd);
if (sd->status.guild_id) { // Check if the player has a guild
struct guild *g;
@@ -3296,15 +3217,13 @@ ACMD(breakguild)
/*==========================================
*
*------------------------------------------*/
-ACMD(agitstart)
-{
- nullpo_retr(-1, sd);
- if (iMap->agit_flag == 1) {
+ACMD(agitstart) {
+ if (map->agit_flag == 1) {
clif->message(fd, msg_txt(73)); // War of Emperium is currently in progress.
return false;
}
- iMap->agit_flag = 1;
+ map->agit_flag = 1;
guild->agit_start();
clif->message(fd, msg_txt(72)); // War of Emperium has been initiated.
@@ -3314,15 +3233,13 @@ ACMD(agitstart)
/*==========================================
*
*------------------------------------------*/
-ACMD(agitstart2)
-{
- nullpo_retr(-1, sd);
- if (iMap->agit2_flag == 1) {
+ACMD(agitstart2) {
+ if (map->agit2_flag == 1) {
clif->message(fd, msg_txt(404)); // "War of Emperium SE is currently in progress."
return false;
}
- iMap->agit2_flag = 1;
+ map->agit2_flag = 1;
guild->agit2_start();
clif->message(fd, msg_txt(403)); // "War of Emperium SE has been initiated."
@@ -3332,15 +3249,13 @@ ACMD(agitstart2)
/*==========================================
*
*------------------------------------------*/
-ACMD(agitend)
-{
- nullpo_retr(-1, sd);
- if (iMap->agit_flag == 0) {
+ACMD(agitend) {
+ if (map->agit_flag == 0) {
clif->message(fd, msg_txt(75)); // War of Emperium is currently not in progress.
return false;
}
- iMap->agit_flag = 0;
+ map->agit_flag = 0;
guild->agit_end();
clif->message(fd, msg_txt(74)); // War of Emperium has been ended.
@@ -3350,15 +3265,13 @@ ACMD(agitend)
/*==========================================
*
*------------------------------------------*/
-ACMD(agitend2)
-{
- nullpo_retr(-1, sd);
- if (iMap->agit2_flag == 0) {
+ACMD(agitend2) {
+ if (map->agit2_flag == 0) {
clif->message(fd, msg_txt(406)); // "War of Emperium SE is currently not in progress."
return false;
}
- iMap->agit2_flag = 0;
+ map->agit2_flag = 0;
guild->agit2_end();
clif->message(fd, msg_txt(405)); // "War of Emperium SE has been ended."
@@ -3368,23 +3281,19 @@ ACMD(agitend2)
/*==========================================
* @mapexit - shuts down the map server
*------------------------------------------*/
-ACMD(mapexit)
-{
- nullpo_retr(-1, sd);
-
- iMap->do_shutdown();
+ACMD(mapexit) {
+ map->do_shutdown();
return true;
}
/*==========================================
- * idsearch <part_of_name>: revrited by [Yor]
+ * idsearch <part_of_name>: rewrite by [Yor]
*------------------------------------------*/
ACMD(idsearch)
{
char item_name[100];
unsigned int i, match;
struct item_data *item_array[MAX_SEARCH];
- nullpo_retr(-1, sd);
memset(item_name, '\0', sizeof(item_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
@@ -3394,9 +3303,9 @@ ACMD(idsearch)
return false;
}
- sprintf(atcmd_output, msg_txt(77), item_name); // The reference result of '%s' (name: id):
+ sprintf(atcmd_output, msg_txt(77), item_name); // Search results for '%s' (name: id):
clif->message(fd, atcmd_output);
- match = itemdb_searchname_array(item_array, MAX_SEARCH, item_name);
+ match = itemdb->search_name_array(item_array, MAX_SEARCH, item_name, 0);
if (match > MAX_SEARCH) {
sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, match);
clif->message(fd, atcmd_output);
@@ -3406,7 +3315,7 @@ ACMD(idsearch)
sprintf(atcmd_output, msg_txt(78), item_array[i]->jname, item_array[i]->nameid); // %s: %d
clif->message(fd, atcmd_output);
}
- sprintf(atcmd_output, msg_txt(79), match); // It is %d affair above.
+ sprintf(atcmd_output, msg_txt(79), match); // %d results found.
clif->message(fd, atcmd_output);
return true;
@@ -3420,24 +3329,21 @@ ACMD(recallall)
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
int count;
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map.
+ if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ clif->message(fd, msg_txt(1032)); // You are not authorized to warp someone to your current map.
return false;
}
count = 0;
iter = mapit_getallusers();
- for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
- {
- if (sd->status.account_id != pl_sd->status.account_id && pc->get_group_level(sd) >= pc->get_group_level(pl_sd))
- {
+ for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) {
+ if (sd->status.account_id != pl_sd->status.account_id && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) {
if (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y)
continue; // Don't waste time warping the character to the same place.
- if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
+ if (pl_sd->bl.m >= 0 && map->list[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
count++;
else {
if (pc_isdead(pl_sd)) { //Wake them up
@@ -3469,7 +3375,6 @@ ACMD(guildrecall)
int count;
char guild_name[NAME_LENGTH];
struct guild *g;
- nullpo_retr(-1, sd);
memset(guild_name, '\0', sizeof(guild_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
@@ -3479,8 +3384,8 @@ ACMD(guildrecall)
return false;
}
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map.
+ if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ clif->message(fd, msg_txt(1032)); // You are not authorized to warp someone to your current map.
return false;
}
@@ -3496,11 +3401,10 @@ ACMD(guildrecall)
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
- if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.guild_id == g->guild_id)
- {
- if (pc->get_group_level(pl_sd) > pc->get_group_level(sd) || (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y))
+ if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.guild_id == g->guild_id) {
+ if (pc_get_group_level(pl_sd) > pc_get_group_level(sd) || (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y))
continue; // Skip GMs greater than you... or chars already on the cell
- if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
+ if (pl_sd->bl.m >= 0 && map->list[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
count++;
else
pc->setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN);
@@ -3528,7 +3432,6 @@ ACMD(partyrecall)
char party_name[NAME_LENGTH];
struct party_data *p;
int count;
- nullpo_retr(-1, sd);
memset(party_name, '\0', sizeof(party_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
@@ -3538,8 +3441,8 @@ ACMD(partyrecall)
return false;
}
- if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map.
+ if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
+ clif->message(fd, msg_txt(1032)); // You are not authorized to warp someone to your current map.
return false;
}
@@ -3553,13 +3456,11 @@ ACMD(partyrecall)
count = 0;
iter = mapit_getallusers();
- for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
- {
- if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.party_id == p->party.party_id)
- {
- if (pc->get_group_level(pl_sd) > pc->get_group_level(sd) || (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y))
+ for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) {
+ if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.party_id == p->party.party_id) {
+ if (pc_get_group_level(pl_sd) > pc_get_group_level(sd) || (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y))
continue; // Skip GMs greater than you... or chars already on the cell
- if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
+ if (pl_sd->bl.m >= 0 && map->list[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE))
count++;
else
pc->setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN);
@@ -3582,8 +3483,7 @@ ACMD(partyrecall)
*------------------------------------------*/
ACMD(reloaditemdb)
{
- nullpo_retr(-1, sd);
- itemdb_reload();
+ itemdb->reload();
clif->message(fd, msg_txt(97)); // Item database has been reloaded.
return true;
@@ -3593,13 +3493,12 @@ ACMD(reloaditemdb)
*
*------------------------------------------*/
ACMD(reloadmobdb) {
- nullpo_retr(-1, sd);
- mob_reload();
- read_petdb();
+ mob->reload();
+ pet->read_db();
homun->reload();
- read_mercenarydb();
- read_mercenary_skilldb();
- reload_elementaldb();
+ mercenary->read_db();
+ mercenary->read_skilldb();
+ elemental->reload_db();
clif->message(fd, msg_txt(98)); // Monster database has been reloaded.
return true;
@@ -3610,11 +3509,10 @@ ACMD(reloadmobdb) {
*------------------------------------------*/
ACMD(reloadskilldb)
{
- nullpo_retr(-1, sd);
skill->reload();
homun->reload_skill();
- reload_elemental_skilldb();
- read_mercenary_skilldb();
+ elemental->reload_skilldb();
+ mercenary->read_skilldb();
clif->message(fd, msg_txt(99)); // Skill database has been reloaded.
return true;
@@ -3623,26 +3521,25 @@ ACMD(reloadskilldb)
/*==========================================
* @reloadatcommand - reloads conf/atcommand.conf conf/groups.conf
*------------------------------------------*/
-void atcommand_doload();
ACMD(reloadatcommand) {
config_t run_test;
- if (conf_read_file(&run_test, "conf/groups.conf")) {
+ if (libconfig->read_file(&run_test, "conf/groups.conf")) {
clif->message(fd, msg_txt(1036)); // Error reading groups.conf, reload failed.
return false;
}
- config_destroy(&run_test);
+ libconfig->destroy(&run_test);
- if (conf_read_file(&run_test, iMap->ATCOMMAND_CONF_FILENAME)) {
+ if (libconfig->read_file(&run_test, map->ATCOMMAND_CONF_FILENAME)) {
clif->message(fd, msg_txt(1037)); // Error reading atcommand.conf, reload failed.
return false;
}
- config_destroy(&run_test);
+ libconfig->destroy(&run_test);
- atcommand_doload();
- pc_groups_reload();
+ atcommand->doload();
+ pcg->reload();
clif->message(fd, msg_txt(254));
return true;
}
@@ -3654,7 +3551,7 @@ ACMD(reloadbattleconf)
struct Battle_Config prev_config;
memcpy(&prev_config, &battle_config, sizeof(prev_config));
- battle->config_read(iMap->BATTLE_CONF_FILENAME);
+ battle->config_read(map->BATTLE_CONF_FILENAME);
if( prev_config.item_rate_mvp != battle_config.item_rate_mvp
|| prev_config.item_rate_common != battle_config.item_rate_common
@@ -3688,8 +3585,8 @@ ACMD(reloadbattleconf)
|| prev_config.job_exp_rate != battle_config.job_exp_rate
)
{ // Exp or Drop rates changed.
- mob_reload(); //Needed as well so rate changes take effect.
- chrif_ragsrvinfo(battle_config.base_exp_rate, battle_config.job_exp_rate, battle_config.item_rate_common);
+ mob->reload(); //Needed as well so rate changes take effect.
+ chrif->ragsrvinfo(battle_config.base_exp_rate, battle_config.job_exp_rate, battle_config.item_rate_common);
}
clif->message(fd, msg_txt(255));
return true;
@@ -3697,9 +3594,8 @@ ACMD(reloadbattleconf)
/*==========================================
* @reloadstatusdb - reloads job_db1.txt job_db2.txt job_db2-2.txt refine_db.txt size_fix.txt
*------------------------------------------*/
-ACMD(reloadstatusdb)
-{
- status_readdb();
+ACMD(reloadstatusdb) {
+ status->readdb();
clif->message(fd, msg_txt(256));
return true;
}
@@ -3716,12 +3612,10 @@ ACMD(reloadpcdb)
/*==========================================
* @reloadscript - reloads all scripts (npcs, warps, mob spawns, ...)
*------------------------------------------*/
-ACMD(reloadscript)
-{
+ACMD(reloadscript) {
struct s_mapiterator* iter;
struct map_session_data* pl_sd;
- nullpo_retr(-1, sd);
//atcommand_broadcast( fd, sd, "@broadcast", "Server is reloading scripts..." );
//atcommand_broadcast( fd, sd, "@broadcast", "You will feel a bit of lag at this point !" );
@@ -3746,9 +3640,9 @@ ACMD(reloadscript)
mapit->free(iter);
flush_fifos();
- iMap->reloadnpc(true); // reload config files seeking for npcs
- script_reload();
- npc_reload();
+ map->reloadnpc(true, NULL, 0); // reload config files seeking for npcs
+ script->reload();
+ npc->reload();
clif->message(fd, msg_txt(100)); // Scripts have been reloaded.
@@ -3773,9 +3667,7 @@ ACMD(mapinfo) {
int i, m_id, chat_num = 0, list = 0, vend_num = 0;
unsigned short m_index;
char mapname[24];
-
- nullpo_retr(-1, sd);
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(mapname, '\0', sizeof(mapname));
memset(direction, '\0', sizeof(direction));
@@ -3789,16 +3681,16 @@ ACMD(mapinfo) {
if (mapname[0] == '\0') {
safestrncpy(mapname, mapindex_id2name(sd->mapindex), MAP_NAME_LENGTH);
- m_id = iMap->mapindex2mapid(sd->mapindex);
+ m_id = map->mapindex2mapid(sd->mapindex);
} else {
- m_id = iMap->mapname2mapid(mapname);
+ m_id = map->mapname2mapid(mapname);
}
if (m_id < 0) {
clif->message(fd, msg_txt(1)); // Map not found.
return false;
}
- m_index = mapindex_name2id(mapname); //This one shouldn't fail since the previous seek did not.
+ m_index = mapindex->name2id(mapname); //This one shouldn't fail since the previous seek did not.
clif->message(fd, msg_txt(1039)); // ------ Map Info ------
@@ -3809,135 +3701,135 @@ ACMD(mapinfo) {
if( pl_sd->mapindex == m_index ) {
if( pl_sd->state.vending )
vend_num++;
- else if( (cd = (struct chat_data*)iMap->id2bl(pl_sd->chatID)) != NULL && cd->usersd[0] == pl_sd )
+ else if( (cd = (struct chat_data*)map->id2bl(pl_sd->chatID)) != NULL && cd->usersd[0] == pl_sd )
chat_num++;
}
}
mapit->free(iter);
- sprintf(atcmd_output, msg_txt(1040), mapname, map[m_id].zone->name, map[m_id].users, map[m_id].npc_num, chat_num, vend_num); // Map: %s (Zone:%s) | Players: %d | NPCs: %d | Chats: %d | Vendings: %d
+ sprintf(atcmd_output, msg_txt(1040), mapname, map->list[m_id].zone->name, map->list[m_id].users, map->list[m_id].npc_num, chat_num, vend_num); // Map: %s (Zone:%s) | Players: %d | NPCs: %d | Chats: %d | Vendings: %d
clif->message(fd, atcmd_output);
clif->message(fd, msg_txt(1041)); // ------ Map Flags ------
- if (map[m_id].flag.town)
+ if (map->list[m_id].flag.town)
clif->message(fd, msg_txt(1042)); // Town Map
- if (battle_config.autotrade_mapflag == map[m_id].flag.autotrade)
+ if (battle_config.autotrade_mapflag == map->list[m_id].flag.autotrade)
clif->message(fd, msg_txt(1043)); // Autotrade Enabled
else
clif->message(fd, msg_txt(1044)); // Autotrade Disabled
- if (map[m_id].flag.battleground)
+ if (map->list[m_id].flag.battleground)
clif->message(fd, msg_txt(1045)); // Battlegrounds ON
strcpy(atcmd_output,msg_txt(1046)); // PvP Flags:
- if (map[m_id].flag.pvp)
+ if (map->list[m_id].flag.pvp)
strcat(atcmd_output, msg_txt(1047)); // Pvp ON |
- if (map[m_id].flag.pvp_noguild)
+ if (map->list[m_id].flag.pvp_noguild)
strcat(atcmd_output, msg_txt(1048)); // NoGuild |
- if (map[m_id].flag.pvp_noparty)
+ if (map->list[m_id].flag.pvp_noparty)
strcat(atcmd_output, msg_txt(1049)); // NoParty |
- if (map[m_id].flag.pvp_nightmaredrop)
+ if (map->list[m_id].flag.pvp_nightmaredrop)
strcat(atcmd_output, msg_txt(1050)); // NightmareDrop |
- if (map[m_id].flag.pvp_nocalcrank)
+ if (map->list[m_id].flag.pvp_nocalcrank)
strcat(atcmd_output, msg_txt(1051)); // NoCalcRank |
clif->message(fd, atcmd_output);
strcpy(atcmd_output,msg_txt(1052)); // GvG Flags:
- if (map[m_id].flag.gvg)
+ if (map->list[m_id].flag.gvg)
strcat(atcmd_output, msg_txt(1053)); // GvG ON |
- if (map[m_id].flag.gvg_dungeon)
+ if (map->list[m_id].flag.gvg_dungeon)
strcat(atcmd_output, msg_txt(1054)); // GvG Dungeon |
- if (map[m_id].flag.gvg_castle)
+ if (map->list[m_id].flag.gvg_castle)
strcat(atcmd_output, msg_txt(1055)); // GvG Castle |
- if (map[m_id].flag.gvg_noparty)
+ if (map->list[m_id].flag.gvg_noparty)
strcat(atcmd_output, msg_txt(1056)); // NoParty |
clif->message(fd, atcmd_output);
strcpy(atcmd_output,msg_txt(1057)); // Teleport Flags:
- if (map[m_id].flag.noteleport)
+ if (map->list[m_id].flag.noteleport)
strcat(atcmd_output, msg_txt(1058)); // NoTeleport |
- if (map[m_id].flag.monster_noteleport)
+ if (map->list[m_id].flag.monster_noteleport)
strcat(atcmd_output, msg_txt(1059)); // Monster NoTeleport |
- if (map[m_id].flag.nowarp)
+ if (map->list[m_id].flag.nowarp)
strcat(atcmd_output, msg_txt(1060)); // NoWarp |
- if (map[m_id].flag.nowarpto)
+ if (map->list[m_id].flag.nowarpto)
strcat(atcmd_output, msg_txt(1061)); // NoWarpTo |
- if (map[m_id].flag.noreturn)
+ if (map->list[m_id].flag.noreturn)
strcat(atcmd_output, msg_txt(1062)); // NoReturn |
- if (map[m_id].flag.nomemo)
+ if (map->list[m_id].flag.nomemo)
strcat(atcmd_output, msg_txt(1064)); // NoMemo |
clif->message(fd, atcmd_output);
sprintf(atcmd_output, msg_txt(1065), // No Exp Penalty: %s | No Zeny Penalty: %s
- (map[m_id].flag.noexppenalty) ? msg_txt(1066) : msg_txt(1067), (map[m_id].flag.nozenypenalty) ? msg_txt(1066) : msg_txt(1067)); // On / Off
+ (map->list[m_id].flag.noexppenalty) ? msg_txt(1066) : msg_txt(1067),
+ (map->list[m_id].flag.nozenypenalty) ? msg_txt(1066) : msg_txt(1067)); // On / Off
clif->message(fd, atcmd_output);
- if (map[m_id].flag.nosave) {
- if (!map[m_id].save.map)
+ if (map->list[m_id].flag.nosave) {
+ if (!map->list[m_id].save.map)
clif->message(fd, msg_txt(1068)); // No Save (Return to last Save Point)
- else if (map[m_id].save.x == -1 || map[m_id].save.y == -1 ) {
- sprintf(atcmd_output, msg_txt(1069), mapindex_id2name(map[m_id].save.map)); // No Save, Save Point: %s,Random
+ else if (map->list[m_id].save.x == -1 || map->list[m_id].save.y == -1 ) {
+ sprintf(atcmd_output, msg_txt(1069), mapindex_id2name(map->list[m_id].save.map)); // No Save, Save Point: %s,Random
clif->message(fd, atcmd_output);
- }
- else {
+ } else {
sprintf(atcmd_output, msg_txt(1070), // No Save, Save Point: %s,%d,%d
- mapindex_id2name(map[m_id].save.map),map[m_id].save.x,map[m_id].save.y);
+ mapindex_id2name(map->list[m_id].save.map),map->list[m_id].save.x,map->list[m_id].save.y);
clif->message(fd, atcmd_output);
}
}
strcpy(atcmd_output,msg_txt(1071)); // Weather Flags:
- if (map[m_id].flag.snow)
+ if (map->list[m_id].flag.snow)
strcat(atcmd_output, msg_txt(1072)); // Snow |
- if (map[m_id].flag.fog)
+ if (map->list[m_id].flag.fog)
strcat(atcmd_output, msg_txt(1073)); // Fog |
- if (map[m_id].flag.sakura)
+ if (map->list[m_id].flag.sakura)
strcat(atcmd_output, msg_txt(1074)); // Sakura |
- if (map[m_id].flag.clouds)
+ if (map->list[m_id].flag.clouds)
strcat(atcmd_output, msg_txt(1075)); // Clouds |
- if (map[m_id].flag.clouds2)
+ if (map->list[m_id].flag.clouds2)
strcat(atcmd_output, msg_txt(1076)); // Clouds2 |
- if (map[m_id].flag.fireworks)
+ if (map->list[m_id].flag.fireworks)
strcat(atcmd_output, msg_txt(1077)); // Fireworks |
- if (map[m_id].flag.leaves)
+ if (map->list[m_id].flag.leaves)
strcat(atcmd_output, msg_txt(1078)); // Leaves |
- if (map[m_id].flag.nightenabled)
+ if (map->list[m_id].flag.nightenabled)
strcat(atcmd_output, msg_txt(1080)); // Displays Night |
clif->message(fd, atcmd_output);
strcpy(atcmd_output,msg_txt(1081)); // Other Flags:
- if (map[m_id].flag.nobranch)
+ if (map->list[m_id].flag.nobranch)
strcat(atcmd_output, msg_txt(1082)); // NoBranch |
- if (map[m_id].flag.notrade)
+ if (map->list[m_id].flag.notrade)
strcat(atcmd_output, msg_txt(1083)); // NoTrade |
- if (map[m_id].flag.novending)
+ if (map->list[m_id].flag.novending)
strcat(atcmd_output, msg_txt(1084)); // NoVending |
- if (map[m_id].flag.nodrop)
+ if (map->list[m_id].flag.nodrop)
strcat(atcmd_output, msg_txt(1085)); // NoDrop |
- if (map[m_id].flag.noskill)
+ if (map->list[m_id].flag.noskill)
strcat(atcmd_output, msg_txt(1086)); // NoSkill |
- if (map[m_id].flag.noicewall)
+ if (map->list[m_id].flag.noicewall)
strcat(atcmd_output, msg_txt(1087)); // NoIcewall |
- if (map[m_id].flag.allowks)
+ if (map->list[m_id].flag.allowks)
strcat(atcmd_output, msg_txt(1088)); // AllowKS |
- if (map[m_id].flag.reset)
+ if (map->list[m_id].flag.reset)
strcat(atcmd_output, msg_txt(1089)); // Reset |
clif->message(fd, atcmd_output);
strcpy(atcmd_output,msg_txt(1090)); // Other Flags:
- if (map[m_id].nocommand)
+ if (map->list[m_id].nocommand)
strcat(atcmd_output, msg_txt(1091)); // NoCommand |
- if (map[m_id].flag.nobaseexp)
+ if (map->list[m_id].flag.nobaseexp)
strcat(atcmd_output, msg_txt(1092)); // NoBaseEXP |
- if (map[m_id].flag.nojobexp)
+ if (map->list[m_id].flag.nojobexp)
strcat(atcmd_output, msg_txt(1093)); // NoJobEXP |
- if (map[m_id].flag.nomobloot)
+ if (map->list[m_id].flag.nomobloot)
strcat(atcmd_output, msg_txt(1094)); // NoMobLoot |
- if (map[m_id].flag.nomvploot)
+ if (map->list[m_id].flag.nomvploot)
strcat(atcmd_output, msg_txt(1095)); // NoMVPLoot |
- if (map[m_id].flag.partylock)
+ if (map->list[m_id].flag.partylock)
strcat(atcmd_output, msg_txt(1096)); // PartyLock |
- if (map[m_id].flag.guildlock)
+ if (map->list[m_id].flag.guildlock)
strcat(atcmd_output, msg_txt(1097)); // GuildLock |
clif->message(fd, atcmd_output);
@@ -3960,9 +3852,8 @@ ACMD(mapinfo) {
break;
case 2:
clif->message(fd, msg_txt(1100)); // ----- NPCs in Map -----
- for (i = 0; i < map[m_id].npc_num;)
- {
- nd = map[m_id].npc[i];
+ for (i = 0; i < map->list[m_id].npc_num;) {
+ nd = map->list[m_id].npc[i];
switch(nd->dir) {
case 0: strcpy(direction, msg_txt(1101)); break; // North
case 1: strcpy(direction, msg_txt(1102)); break; // North West
@@ -3989,7 +3880,7 @@ ACMD(mapinfo) {
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
- if ((cd = (struct chat_data*)iMap->id2bl(pl_sd->chatID)) != NULL &&
+ if ((cd = (struct chat_data*)map->id2bl(pl_sd->chatID)) != NULL &&
pl_sd->mapindex == m_index &&
cd->usersd[0] == pl_sd)
{
@@ -4006,7 +3897,6 @@ ACMD(mapinfo) {
default: // normally impossible to arrive here
clif->message(fd, msg_txt(1118)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>).
return false;
- break;
}
return true;
@@ -4017,14 +3907,22 @@ ACMD(mapinfo) {
*------------------------------------------*/
ACMD(mount_peco)
{
- nullpo_retr(-1, sd);
-
if (sd->disguise != -1) {
clif->message(fd, msg_txt(212)); // Cannot mount while in disguise.
return false;
}
- if( (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT && pc->checkskill(sd,RK_DRAGONTRAINING) > 0 ) {
+ if( sd->sc.data[SC_ALL_RIDING] ) {
+ clif->message(fd, msg_txt(1476)); // You are already mounting something else
+ return false;
+ }
+
+ if( (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT ) {
+ if( !pc->checkskill(sd,RK_DRAGONTRAINING) ) {
+ sprintf(atcmd_output, msg_txt(213), skill->get_desc(RK_DRAGONTRAINING)); // You need %s to mount!
+ clif->message(fd, atcmd_output);
+ return false;
+ }
if( !(sd->sc.option&OPTION_DRAGON1) ) {
clif->message(sd->fd,msg_txt(1119)); // You have mounted your Dragon.
pc->setoption(sd, sd->sc.option|OPTION_DRAGON1);
@@ -4034,7 +3932,12 @@ ACMD(mount_peco)
}
return true;
}
- if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER && pc->checkskill(sd,RA_WUGRIDER) > 0 ) {
+ if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) {
+ if( !pc->checkskill(sd,RA_WUGRIDER) ) {
+ sprintf(atcmd_output, msg_txt(213), skill->get_desc(RA_WUGRIDER)); // You need %s to mount!
+ clif->message(fd, atcmd_output);
+ return false;
+ }
if( !pc_isridingwug(sd) ) {
clif->message(sd->fd,msg_txt(1121)); // You have mounted your Warg.
pc->setoption(sd, sd->sc.option|OPTION_WUGRIDER);
@@ -4054,36 +3957,36 @@ ACMD(mount_peco)
}
return true;
}
- if (!pc_isriding(sd)) { // if actually no peco
-
- if (!pc->checkskill(sd, KN_RIDING)) {
- clif->message(fd, msg_txt(213)); // You can not mount a Peco Peco with your current job.
- return false;
+ if( sd->class_&MAPID_SWORDMAN && sd->class_&JOBL_2 ) {
+ if( !pc_isriding(sd) ) { // if actually no peco
+ if (!pc->checkskill(sd, KN_RIDING)) {
+ sprintf(atcmd_output, msg_txt(213), skill->get_desc(KN_RIDING)); // You need %s to mount!
+ clif->message(fd, atcmd_output);
+ return false;
+ }
+ pc->setoption(sd, sd->sc.option | OPTION_RIDING);
+ clif->message(fd, msg_txt(102)); // You have mounted a Peco Peco.
+ } else {//Dismount
+ pc->setoption(sd, sd->sc.option & ~OPTION_RIDING);
+ clif->message(fd, msg_txt(214)); // You have released your Peco Peco.
}
-
- pc->setoption(sd, sd->sc.option | OPTION_RIDING);
- clif->message(fd, msg_txt(102)); // You have mounted a Peco Peco.
- } else {//Dismount
- pc->setoption(sd, sd->sc.option & ~OPTION_RIDING);
- clif->message(fd, msg_txt(214)); // You have released your Peco Peco.
+ return true;
}
-
- return true;
+ clif->message(fd, msg_txt(215)); // Your class can't mount!
+ return false;
}
/*==========================================
*Spy Commands by Syrus22
*------------------------------------------*/
-ACMD(guildspy)
-{
+ACMD(guildspy) {
char guild_name[NAME_LENGTH];
struct guild *g;
- nullpo_retr(-1, sd);
memset(guild_name, '\0', sizeof(guild_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
- if (!iMap->enable_spy)
+ if (!map->enable_spy)
{
clif->message(fd, msg_txt(1125)); // The mapserver has spy command support disabled.
return false;
@@ -4115,16 +4018,14 @@ ACMD(guildspy)
/*==========================================
*
*------------------------------------------*/
-ACMD(partyspy)
-{
+ACMD(partyspy) {
char party_name[NAME_LENGTH];
struct party_data *p;
- nullpo_retr(-1, sd);
memset(party_name, '\0', sizeof(party_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
- if (!iMap->enable_spy)
+ if (!map->enable_spy)
{
clif->message(fd, msg_txt(1125)); // The mapserver has spy command support disabled.
return false;
@@ -4160,7 +4061,6 @@ ACMD(partyspy)
ACMD(repairall)
{
int count, i;
- nullpo_retr(-1, sd);
count = 0;
for (i = 0; i < MAX_INVENTORY; i++) {
@@ -4186,10 +4086,8 @@ ACMD(repairall)
/*==========================================
* @nuke [Valaris]
*------------------------------------------*/
-ACMD(nuke)
-{
+ACMD(nuke) {
struct map_session_data *pl_sd;
- nullpo_retr(-1, sd);
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
@@ -4198,12 +4096,12 @@ ACMD(nuke)
return false;
}
- if ((pl_sd = iMap->nick2sd(atcmd_player_name)) != NULL) {
- if (pc->get_group_level(sd) >= pc->get_group_level(pl_sd)) { // you can kill only lower or same GM level
- skill->castend_nodamage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, iTimer->gettick(), 0);
+ if ((pl_sd = map->nick2sd(atcmd_player_name)) != NULL) {
+ if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kill only lower or same GM level
+ skill->castend_nodamage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, timer->gettick(), 0);
clif->message(fd, msg_txt(109)); // Player has been nuked!
} else {
- clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
+ clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
return false;
}
} else {
@@ -4217,13 +4115,10 @@ ACMD(nuke)
/*==========================================
* @tonpc
*------------------------------------------*/
-ACMD(tonpc)
-{
+ACMD(tonpc) {
char npcname[NAME_LENGTH+1];
struct npc_data *nd;
-
- nullpo_retr(-1, sd);
-
+
memset(npcname, 0, sizeof(npcname));
if (!message || !*message || sscanf(message, "%23[^\n]", npcname) < 1) {
@@ -4231,8 +4126,8 @@ ACMD(tonpc)
return false;
}
- if ((nd = npc_name2id(npcname)) != NULL) {
- if (pc->setpos(sd, map_id2index(nd->bl.m), nd->bl.x, nd->bl.y, CLR_TELEPORT) == 0)
+ if ((nd = npc->name2id(npcname)) != NULL) {
+ if (nd->bl.m != -1 && pc->setpos(sd, map_id2index(nd->bl.m), nd->bl.x, nd->bl.y, CLR_TELEPORT) == 0)
clif->message(fd, msg_txt(0)); // Warped.
else
return false;
@@ -4250,7 +4145,6 @@ ACMD(tonpc)
ACMD(shownpc)
{
char NPCname[NAME_LENGTH+1];
- nullpo_retr(-1, sd);
memset(NPCname, '\0', sizeof(NPCname));
@@ -4259,8 +4153,8 @@ ACMD(shownpc)
return false;
}
- if (npc_name2id(NPCname) != NULL) {
- npc_enable(NPCname, 1);
+ if (npc->name2id(NPCname) != NULL) {
+ npc->enable(NPCname, 1);
clif->message(fd, msg_txt(110)); // Npc Enabled.
} else {
clif->message(fd, msg_txt(111)); // This NPC doesn't exist.
@@ -4276,7 +4170,6 @@ ACMD(shownpc)
ACMD(hidenpc)
{
char NPCname[NAME_LENGTH+1];
- nullpo_retr(-1, sd);
memset(NPCname, '\0', sizeof(NPCname));
@@ -4285,12 +4178,12 @@ ACMD(hidenpc)
return false;
}
- if (npc_name2id(NPCname) == NULL) {
+ if (npc->name2id(NPCname) == NULL) {
clif->message(fd, msg_txt(111)); // This NPC doesn't exist.
return false;
}
- npc_enable(NPCname, 0);
+ npc->enable(NPCname, 0);
clif->message(fd, msg_txt(112)); // Npc Disabled.
return true;
}
@@ -4312,9 +4205,9 @@ ACMD(loadnpc)
fclose(fp);
// add to list of script sources and run it
- npc_addsrcfile(message);
- npc_parsesrcfile(message,true);
- npc_read_event_script();
+ npc->addsrcfile(message);
+ npc->parsesrcfile(message,true);
+ npc->read_event_script();
clif->message(fd, msg_txt(262));
@@ -4325,7 +4218,6 @@ ACMD(unloadnpc)
{
struct npc_data *nd;
char NPCname[NAME_LENGTH+1];
- nullpo_retr(-1, sd);
memset(NPCname, '\0', sizeof(NPCname));
@@ -4334,14 +4226,14 @@ ACMD(unloadnpc)
return false;
}
- if ((nd = npc_name2id(NPCname)) == NULL) {
+ if ((nd = npc->name2id(NPCname)) == NULL) {
clif->message(fd, msg_txt(111)); // This NPC doesn't exist.
return false;
}
- npc_unload_duplicates(nd);
- npc_unload(nd,true);
- npc_read_event_script();
+ npc->unload_duplicates(nd);
+ npc->unload(nd,true);
+ npc->read_event_script();
clif->message(fd, msg_txt(112)); // Npc Disabled.
return true;
}
@@ -4352,10 +4244,9 @@ ACMD(unloadnpc)
char* txt_time(unsigned int duration)
{
int days, hours, minutes, seconds;
- char temp[CHAT_SIZE_MAX];
static char temp1[CHAT_SIZE_MAX];
+ int tlen = 0;
- memset(temp, '\0', sizeof(temp));
memset(temp1, '\0', sizeof(temp1));
days = duration / (60 * 60 * 24);
@@ -4366,22 +4257,22 @@ char* txt_time(unsigned int duration)
seconds = duration - (60 * minutes);
if (days == 1)
- sprintf(temp, msg_txt(219), days); // %d day
+ tlen += sprintf(tlen + temp1, msg_txt(219), days); // %d day
else if (days > 1)
- sprintf(temp, msg_txt(220), days); // %d days
+ tlen += sprintf(tlen + temp1, msg_txt(220), days); // %d days
if (hours == 1)
- sprintf(temp1, msg_txt(221), temp, hours); // %s %d hour
+ tlen += sprintf(tlen + temp1, msg_txt(221), hours); // %d hour
else if (hours > 1)
- sprintf(temp1, msg_txt(222), temp, hours); // %s %d hours
+ tlen += sprintf(tlen + temp1, msg_txt(222), hours); // %d hours
if (minutes < 2)
- sprintf(temp, msg_txt(223), temp1, minutes); // %s %d minute
+ tlen += sprintf(tlen + temp1, msg_txt(223), minutes); // %d minute
else
- sprintf(temp, msg_txt(224), temp1, minutes); // %s %d minutes
+ tlen += sprintf(tlen + temp1, msg_txt(224), minutes); // %d minutes
if (seconds == 1)
- sprintf(temp1, msg_txt(225), temp, seconds); // %s and %d second
+ sprintf(tlen + temp1, msg_txt(225), seconds); // and %d second
else if (seconds > 1)
- sprintf(temp1, msg_txt(226), temp, seconds); // %s and %d seconds
-
+ sprintf(tlen + temp1, msg_txt(226), seconds); // and %d seconds
+
return temp1;
}
@@ -4389,14 +4280,10 @@ char* txt_time(unsigned int duration)
* @time/@date/@serverdate/@servertime: Display the date/time of the server (by [Yor]
* Calculation management of GM modification (@day/@night GM commands) is done
*------------------------------------------*/
-ACMD(servertime)
-{
- const struct TimerData * timer_data;
- const struct TimerData * timer_data2;
+ACMD(servertime) {
time_t time_server; // variable for number of seconds (used with time() function)
struct tm *datetime; // variable for time in structure ->tm_mday, ->tm_sec, ...
char temp[CHAT_SIZE_MAX];
- nullpo_retr(-1, sd);
memset(temp, '\0', sizeof(temp));
@@ -4406,62 +4293,49 @@ ACMD(servertime)
strftime(temp, sizeof(temp)-1, msg_txt(230), datetime); // Server time (normal time): %A, %B %d %Y %X.
clif->message(fd, temp);
- if (battle_config.night_duration == 0 && battle_config.day_duration == 0) {
- if (iMap->night_flag == 0)
+ if (pc->day_timer_tid != INVALID_TIMER && pc->night_timer_tid != INVALID_TIMER) {
+ const struct TimerData * timer_data = timer->get(pc->night_timer_tid);
+ const struct TimerData * timer_data2 = timer->get(pc->day_timer_tid);
+
+ if (map->night_flag == 0) {
+ sprintf(temp, msg_txt(235), // Game time: The game is actually in daylight for %s.
+ txt_time((unsigned int)(DIFF_TICK(timer_data->tick,timer->gettick())/1000)));
+ clif->message(fd, temp);
+ if (DIFF_TICK(timer_data->tick, timer_data2->tick) > 0)
+ sprintf(temp, msg_txt(237), // Game time: After, the game will be in night for %s.
+ txt_time((unsigned int)(DIFF_TICK(timer_data->interval,DIFF_TICK(timer_data->tick,timer_data2->tick)) / 1000)));
+ else
+ sprintf(temp, msg_txt(237), // Game time: After, the game will be in night for %s.
+ txt_time((unsigned int)(DIFF_TICK(timer_data2->tick,timer_data->tick)/1000)));
+ clif->message(fd, temp);
+ } else {
+ sprintf(temp, msg_txt(233), // Game time: The game is actually in night for %s.
+ txt_time((unsigned int)(DIFF_TICK(timer_data2->tick,timer->gettick()) / 1000)));
+ clif->message(fd, temp);
+ if (DIFF_TICK(timer_data2->tick,timer_data->tick) > 0)
+ sprintf(temp, msg_txt(239), // Game time: After, the game will be in daylight for %s.
+ txt_time((unsigned int)((timer_data2->interval - DIFF_TICK(timer_data2->tick, timer_data->tick)) / 1000)));
+ else
+ sprintf(temp, msg_txt(239), // Game time: After, the game will be in daylight for %s.
+ txt_time((unsigned int)(DIFF_TICK(timer_data->tick, timer_data2->tick) / 1000)));
+ clif->message(fd, temp);
+ }
+ sprintf(temp, msg_txt(238), txt_time(timer_data2->interval / 1000)); // Game time: A day cycle has a normal duration of %s.
+ clif->message(fd, temp);
+ } else {
+ if (map->night_flag == 0)
clif->message(fd, msg_txt(231)); // Game time: The game is in permanent daylight.
else
clif->message(fd, msg_txt(232)); // Game time: The game is in permanent night.
- } else if (battle_config.night_duration == 0)
- if (iMap->night_flag == 1) { // we start with night
- timer_data = iTimer->get_timer(pc->day_timer_tid);
- sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,iTimer->gettick())/1000)); // Game time: The game is actualy in night for %s.
- clif->message(fd, temp);
- clif->message(fd, msg_txt(234)); // Game time: After, the game will be in permanent daylight.
- } else
- clif->message(fd, msg_txt(231)); // Game time: The game is in permanent daylight.
- else if (battle_config.day_duration == 0)
- if (iMap->night_flag == 0) { // we start with day
- timer_data = iTimer->get_timer(pc->night_timer_tid);
- sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,iTimer->gettick())/1000)); // Game time: The game is actualy in daylight for %s.
- clif->message(fd, temp);
- clif->message(fd, msg_txt(236)); // Game time: After, the game will be in permanent night.
- } else
- clif->message(fd, msg_txt(232)); // Game time: The game is in permanent night.
- else {
- if (iMap->night_flag == 0) {
- timer_data = iTimer->get_timer(pc->night_timer_tid);
- timer_data2 = iTimer->get_timer(pc->day_timer_tid);
- sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,iTimer->gettick())/1000)); // Game time: The game is actualy in daylight for %s.
- clif->message(fd, temp);
- if (DIFF_TICK(timer_data->tick, timer_data2->tick) > 0)
- sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data->interval,DIFF_TICK(timer_data->tick,timer_data2->tick)) / 1000)); // Game time: After, the game will be in night for %s.
- else
- sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data2->tick,timer_data->tick)/1000)); // Game time: After, the game will be in night for %s.
- clif->message(fd, temp);
- sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s.
- clif->message(fd, temp);
- } else {
- timer_data = iTimer->get_timer(pc->day_timer_tid);
- timer_data2 = iTimer->get_timer(pc->night_timer_tid);
- sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,iTimer->gettick()) / 1000)); // Game time: The game is actualy in night for %s.
- clif->message(fd, temp);
- if (DIFF_TICK(timer_data->tick,timer_data2->tick) > 0)
- sprintf(temp, msg_txt(239), txt_time((timer_data->interval - DIFF_TICK(timer_data->tick, timer_data2->tick)) / 1000)); // Game time: After, the game will be in daylight for %s.
- else
- sprintf(temp, msg_txt(239), txt_time(DIFF_TICK(timer_data2->tick, timer_data->tick) / 1000)); // Game time: After, the game will be in daylight for %s.
- clif->message(fd, temp);
- sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s.
- clif->message(fd, temp);
- }
- }
+ }
return true;
}
//Added by Coltaro
-//We're using this function here instead of using time_t so that it only counts player's jail time when he/she's online (and since the idea is to reduce the amount of minutes one by one in status_change_timer...).
+//We're using this function here instead of using time_t so that it only counts player's jail time when he/she's online (and since the idea is to reduce the amount of minutes one by one in status->change_timer...).
//Well, using time_t could still work but for some reason that looks like more coding x_x
-static void get_jail_time(int jailtime, int* year, int* month, int* day, int* hour, int* minute)
+void get_jail_time(int jailtime, int* year, int* month, int* day, int* hour, int* minute)
{
const int factor_year = 518400; //12*30*24*60 = 518400
const int factor_month = 43200; //30*24*60 = 43200
@@ -4490,12 +4364,10 @@ static void get_jail_time(int jailtime, int* year, int* month, int* day, int* ho
* @jail <char_name> by [Yor]
* Special warp! No check with nowarp and nowarpto flag
*------------------------------------------*/
-ACMD(jail)
-{
+ACMD(jail) {
struct map_session_data *pl_sd;
int x, y;
unsigned short m_index;
- nullpo_retr(-1, sd);
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
@@ -4504,14 +4376,14 @@ ACMD(jail)
return false;
}
- if ((pl_sd = iMap->nick2sd(atcmd_player_name)) == NULL) {
+ if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
- if (pc->get_group_level(sd) < pc->get_group_level(pl_sd))
+ if (pc_get_group_level(sd) < pc_get_group_level(pl_sd))
{ // you can jail only lower or same GM
- clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
+ clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
return false;
}
@@ -4523,20 +4395,20 @@ ACMD(jail)
switch(rnd() % 2) { //Jail Locations
case 0:
- m_index = mapindex_name2id(MAP_JAIL);
+ m_index = mapindex->name2id(MAP_JAIL);
x = 24;
y = 75;
break;
default:
- m_index = mapindex_name2id(MAP_JAIL);
+ m_index = mapindex->name2id(MAP_JAIL);
x = 49;
y = 75;
break;
}
//Duration of INT_MAX to specify infinity.
- sc_start4(&pl_sd->bl,SC_JAILED,100,INT_MAX,m_index,x,y,1000);
- clif->message(pl_sd->fd, msg_txt(117)); // GM has send you in jails.
+ sc_start4(NULL,&pl_sd->bl,SC_JAILED,100,INT_MAX,m_index,x,y,1000);
+ clif->message(pl_sd->fd, msg_txt(117)); // You have been jailed by a GM.
clif->message(fd, msg_txt(118)); // Player warped in jails.
return true;
}
@@ -4545,8 +4417,7 @@ ACMD(jail)
* @unjail/@discharge <char_name> by [Yor]
* Special warp! No check with nowarp and nowarpto flag
*------------------------------------------*/
-ACMD(unjail)
-{
+ACMD(unjail) {
struct map_session_data *pl_sd;
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
@@ -4556,14 +4427,14 @@ ACMD(unjail)
return false;
}
- if ((pl_sd = iMap->nick2sd(atcmd_player_name)) == NULL) {
+ if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
- if (pc->get_group_level(sd) < pc->get_group_level(pl_sd)) { // you can jail only lower or same GM
+ if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { // you can jail only lower or same GM
- clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
+ clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
return false;
}
@@ -4574,20 +4445,18 @@ ACMD(unjail)
}
//Reset jail time to 1 sec.
- sc_start(&pl_sd->bl,SC_JAILED,100,1,1000);
+ sc_start(NULL,&pl_sd->bl,SC_JAILED,100,1,1000);
clif->message(pl_sd->fd, msg_txt(120)); // A GM has discharged you from jail.
clif->message(fd, msg_txt(121)); // Player unjailed.
return true;
}
-ACMD(jailfor)
-{
+ACMD(jailfor) {
struct map_session_data *pl_sd = NULL;
int year, month, day, hour, minute, value;
char * modif_p;
int jailtime = 0,x,y;
short m_index = 0;
- nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%255s %23[^\n]",atcmd_output,atcmd_player_name) < 2) {
clif->message(fd, msg_txt(400)); //Usage: @jailfor <time> <character name>
@@ -4636,13 +4505,13 @@ ACMD(jailfor)
return false;
}
- if ((pl_sd = iMap->nick2sd(atcmd_player_name)) == NULL) {
+ if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
- if (pc->get_group_level(pl_sd) > pc->get_group_level(sd)) {
- clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
+ if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) {
+ clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
return false;
}
@@ -4663,7 +4532,7 @@ ACMD(jailfor)
clif->message(pl_sd->fd, msg_txt(120)); // GM has discharge you.
clif->message(fd, msg_txt(121)); // Player unjailed
} else {
- get_jail_time(jailtime,&year,&month,&day,&hour,&minute);
+ atcommand->get_jail_time(jailtime,&year,&month,&day,&hour,&minute);
sprintf(atcmd_output,msg_txt(402),msg_txt(1137),year,month,day,hour,minute); //%s in jail for %d years, %d months, %d days, %d hours and %d minutes
clif->message(pl_sd->fd, atcmd_output);
sprintf(atcmd_output,msg_txt(402),msg_txt(1138),year,month,day,hour,minute); //This player is now in jail for %d years, %d months, %d days, %d hours and %d minutes
@@ -4678,16 +4547,16 @@ ACMD(jailfor)
switch(rnd()%2)
{
case 1: //Jail #1
- m_index = mapindex_name2id(MAP_JAIL);
+ m_index = mapindex->name2id(MAP_JAIL);
x = 49; y = 75;
break;
default: //Default Jail
- m_index = mapindex_name2id(MAP_JAIL);
+ m_index = mapindex->name2id(MAP_JAIL);
x = 24; y = 75;
break;
}
- sc_start4(&pl_sd->bl,SC_JAILED,100,jailtime,m_index,x,y,jailtime?60000:1000); //jailtime = 0: Time was reset to 0. Wait 1 second to warp player out (since it's done in status_change_timer).
+ sc_start4(NULL,&pl_sd->bl,SC_JAILED,100,jailtime,m_index,x,y,jailtime?60000:1000); //jailtime = 0: Time was reset to 0. Wait 1 second to warp player out (since it's done in status->change_timer).
return true;
}
@@ -4697,8 +4566,6 @@ ACMD(jailtime)
{
int year, month, day, hour, minute;
- nullpo_retr(-1, sd);
-
if (!sd->sc.data[SC_JAILED]) {
clif->message(fd, msg_txt(1139)); // You are not in jail.
return false;
@@ -4715,7 +4582,7 @@ ACMD(jailtime)
}
//Get remaining jail time
- get_jail_time(sd->sc.data[SC_JAILED]->val1,&year,&month,&day,&hour,&minute);
+ atcommand->get_jail_time(sd->sc.data[SC_JAILED]->val1,&year,&month,&day,&hour,&minute);
sprintf(atcmd_output,msg_txt(402),msg_txt(1142),year,month,day,hour,minute); // You will remain in jail for %d years, %d months, %d days, %d hours and %d minutes
clif->message(fd, atcmd_output);
@@ -4729,7 +4596,6 @@ ACMD(jailtime)
ACMD(disguise)
{
int id = 0;
- nullpo_retr(-1, sd);
if (!message || !*message) {
clif->message(fd, msg_txt(1143)); // Please enter a Monster/NPC name/ID (usage: @disguise <name/ID>).
@@ -4738,12 +4604,12 @@ ACMD(disguise)
if ((id = atoi(message)) > 0)
{ //Acquired an ID
- if (!mobdb_checkid(id) && !npcdb_checkid(id))
+ if (!mob->db_checkid(id) && !npcdb_checkid(id))
id = 0; //Invalid id for either mobs or npcs.
} else { //Acquired a Name
- if ((id = mobdb_searchname(message)) == 0)
+ if ((id = mob->db_searchname(message)) == 0)
{
- struct npc_data* nd = npc_name2id(message);
+ struct npc_data* nd = npc->name2id(message);
if (nd != NULL)
id = nd->class_;
}
@@ -4760,7 +4626,13 @@ ACMD(disguise)
clif->message(fd, msg_txt(1144)); // Character cannot be disguised while mounted.
return false;
}
-
+
+ if(sd->sc.data[SC_MONSTER_TRANSFORM])
+ {
+ clif->message(fd, msg_txt(1487)); // Character cannot be disguised while in monster form.
+ return false;
+ }
+
pc->disguise(sd, id);
clif->message(fd, msg_txt(122)); // Disguise applied.
@@ -4775,17 +4647,16 @@ ACMD(disguiseall)
int mob_id=0;
struct map_session_data *pl_sd;
struct s_mapiterator* iter;
- nullpo_retr(-1, sd);
if (!message || !*message) {
clif->message(fd, msg_txt(1145)); // Please enter a Monster/NPC name/ID (usage: @disguiseall <name/ID>).
return false;
}
- if ((mob_id = mobdb_searchname(message)) == 0) // check name first (to avoid possible name begining by a number)
+ if ((mob_id = mob->db_searchname(message)) == 0) // check name first (to avoid possible name begining by a number)
mob_id = atoi(message);
- if (!mobdb_checkid(mob_id) && !npcdb_checkid(mob_id)) { //if mob or npc...
+ if (!mob->db_checkid(mob_id) && !npcdb_checkid(mob_id)) { //if mob or npc...
clif->message(fd, msg_txt(123)); // Monster/NPC name/id not found.
return false;
}
@@ -4818,11 +4689,11 @@ ACMD(disguiseguild)
}
if( (id = atoi(monster)) > 0 ) {
- if( !mobdb_checkid(id) && !npcdb_checkid(id) )
+ if( !mob->db_checkid(id) && !npcdb_checkid(id) )
id = 0;
} else {
- if( (id = mobdb_searchname(monster)) == 0 ) {
- struct npc_data* nd = npc_name2id(monster);
+ if( (id = mob->db_searchname(monster)) == 0 ) {
+ struct npc_data* nd = npc->name2id(monster);
if( nd != NULL )
id = nd->class_;
}
@@ -4852,10 +4723,9 @@ ACMD(disguiseguild)
*------------------------------------------*/
ACMD(undisguise)
{
- nullpo_retr(-1, sd);
if (sd->disguise != -1) {
pc->disguise(sd, -1);
- clif->message(fd, msg_txt(124)); // Undisguise applied.
+ clif->message(fd, msg_txt(124)); // Disguise removed.
} else {
clif->message(fd, msg_txt(125)); // You're not disguised.
return false;
@@ -4870,7 +4740,6 @@ ACMD(undisguise)
ACMD(undisguiseall) {
struct map_session_data *pl_sd;
struct s_mapiterator* iter;
- nullpo_retr(-1, sd);
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
@@ -4878,7 +4747,7 @@ ACMD(undisguiseall) {
pc->disguise(pl_sd, -1);
mapit->free(iter);
- clif->message(fd, msg_txt(124)); // Undisguise applied.
+ clif->message(fd, msg_txt(124)); // Disguise removed.
return true;
}
@@ -4892,7 +4761,6 @@ ACMD(undisguiseguild)
struct map_session_data *pl_sd;
struct guild *g;
int i;
- nullpo_retr(-1, sd);
memset(guild_name, '\0', sizeof(guild_name));
@@ -4910,7 +4778,7 @@ ACMD(undisguiseguild)
if( (pl_sd = g->member[i].sd) && pl_sd->disguise != -1 )
pc->disguise(pl_sd, -1);
- clif->message(fd, msg_txt(124)); // Undisguise applied.
+ clif->message(fd, msg_txt(124)); // Disguise removed.
return true;
}
@@ -4922,7 +4790,7 @@ ACMD(exp)
{
char output[CHAT_SIZE_MAX];
double nextb, nextj;
- nullpo_retr(-1, sd);
+
memset(output, '\0', sizeof(output));
nextb = pc->nextbaseexp(sd);
@@ -4944,7 +4812,6 @@ ACMD(exp)
*------------------------------------------*/
ACMD(broadcast)
{
- nullpo_retr(-1, sd);
memset(atcmd_output, '\0', sizeof(atcmd_output));
@@ -4954,7 +4821,7 @@ ACMD(broadcast)
}
sprintf(atcmd_output, "%s: %s", sd->status.name, message);
- intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, 0);
+ intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT);
return true;
}
@@ -4964,8 +4831,6 @@ ACMD(broadcast)
*------------------------------------------*/
ACMD(localbroadcast)
{
- nullpo_retr(-1, sd);
-
memset(atcmd_output, '\0', sizeof(atcmd_output));
if (!message || !*message) {
@@ -4975,7 +4840,7 @@ ACMD(localbroadcast)
sprintf(atcmd_output, "%s: %s", sd->status.name, message);
- clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP);
+ clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
return true;
}
@@ -4987,31 +4852,30 @@ ACMD(email)
{
char actual_email[100];
char new_email[100];
- nullpo_retr(-1, sd);
memset(actual_email, '\0', sizeof(actual_email));
memset(new_email, '\0', sizeof(new_email));
if (!message || !*message || sscanf(message, "%99s %99s", actual_email, new_email) < 2) {
- clif->message(fd, msg_txt(1151)); // Please enter 2 emails (usage: @email <actual@email> <new@email>).
+ clif->message(fd, msg_txt(1151)); // Please enter two e-mail addresses (usage: @email <current@email> <new@email>).
return false;
}
if (e_mail_check(actual_email) == 0) {
- clif->message(fd, msg_txt(144)); // Invalid actual email. If you have default e-mail, give a@a.com.
+ clif->message(fd, msg_txt(144)); // Invalid e-mail. If your email hasn't been set, use a@a.com.
return false;
} else if (e_mail_check(new_email) == 0) {
- clif->message(fd, msg_txt(145)); // Invalid new email. Please enter a real e-mail.
+ clif->message(fd, msg_txt(145)); // Invalid new email. Please enter a real e-mail address.
return false;
} else if (strcmpi(new_email, "a@a.com") == 0) {
- clif->message(fd, msg_txt(146)); // New email must be a real e-mail.
+ clif->message(fd, msg_txt(146)); // New email must be a real e-mail address.
return false;
} else if (strcmpi(actual_email, new_email) == 0) {
- clif->message(fd, msg_txt(147)); // New email must be different of the actual e-mail.
+ clif->message(fd, msg_txt(147)); // New e-mail must be different from the current e-mail address.
return false;
}
- chrif_changeemail(sd->status.account_id, actual_email, new_email);
+ chrif->changeemail(sd->status.account_id, actual_email, new_email);
clif->message(fd, msg_txt(148)); // Information sended to login-server via char-server.
return true;
}
@@ -5022,7 +4886,6 @@ ACMD(email)
ACMD(effect)
{
int type = 0, flag = 0;
- nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d", &type) < 1) {
clif->message(fd, msg_txt(1152)); // Please enter an effect number (usage: @effect <effect number>).
@@ -5040,7 +4903,6 @@ ACMD(effect)
*------------------------------------------*/
ACMD(killer)
{
- nullpo_retr(-1, sd);
sd->state.killer = !sd->state.killer;
if(sd->state.killer)
@@ -5056,16 +4918,14 @@ ACMD(killer)
* @killable by MouseJstr
* enable other people killing you
*------------------------------------------*/
-ACMD(killable)
-{
- nullpo_retr(-1, sd);
+ACMD(killable) {
sd->state.killable = !sd->state.killable;
if(sd->state.killable)
clif->message(fd, msg_txt(242));
else {
clif->message(fd, msg_txt(288));
- iMap->foreachinrange(atcommand_stopattack,&sd->bl, AREA_SIZE, BL_CHAR, sd->bl.id);
+ map->foreachinrange(atcommand->stopattack,&sd->bl, AREA_SIZE, BL_CHAR, sd->bl.id);
}
return true;
}
@@ -5074,10 +4934,8 @@ ACMD(killable)
* @skillon by MouseJstr
* turn skills on for the map
*------------------------------------------*/
-ACMD(skillon)
-{
- nullpo_retr(-1, sd);
- map[sd->bl.m].flag.noskill = 0;
+ACMD(skillon) {
+ map->list[sd->bl.m].flag.noskill = 0;
clif->message(fd, msg_txt(244));
return true;
}
@@ -5086,10 +4944,8 @@ ACMD(skillon)
* @skilloff by MouseJstr
* Turn skills off on the map
*------------------------------------------*/
-ACMD(skilloff)
-{
- nullpo_retr(-1, sd);
- map[sd->bl.m].flag.noskill = 1;
+ACMD(skilloff) {
+ map->list[sd->bl.m].flag.noskill = 1;
clif->message(fd, msg_txt(243));
return true;
}
@@ -5098,11 +4954,10 @@ ACMD(skilloff)
* @npcmove by MouseJstr
* move a npc
*------------------------------------------*/
-ACMD(npcmove)
-{
+ACMD(npcmove) {
int x = 0, y = 0, m;
struct npc_data *nd = 0;
- nullpo_retr(-1, sd);
+
memset(atcmd_player_name, '\0', sizeof atcmd_player_name);
if (!message || !*message || sscanf(message, "%d %d %23[^\n]", &x, &y, atcmd_player_name) < 3) {
@@ -5110,23 +4965,21 @@ ACMD(npcmove)
return false;
}
- if ((nd = npc_name2id(atcmd_player_name)) == NULL)
- {
+ if ((nd = npc->name2id(atcmd_player_name)) == NULL) {
clif->message(fd, msg_txt(111)); // This NPC doesn't exist.
return false;
}
- if ((m=nd->bl.m) < 0 || nd->bl.prev == NULL)
- {
- clif->message(fd, msg_txt(1154)); // NPC is not on this map.
+ if ((m=nd->bl.m) < 0 || nd->bl.prev == NULL) {
+ clif->message(fd, msg_txt(1154)); // NPC is not in this map.
return false; //Not on a map.
}
- x = cap_value(x, 0, map[m].xs-1);
- y = cap_value(y, 0, map[m].ys-1);
- iMap->foreachinrange(clif->outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl);
- iMap->moveblock(&nd->bl, x, y, iTimer->gettick());
- iMap->foreachinrange(clif->insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl);
+ x = cap_value(x, 0, map->list[m].xs-1);
+ y = cap_value(y, 0, map->list[m].ys-1);
+ map->foreachinrange(clif->outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl);
+ map->moveblock(&nd->bl, x, y, timer->gettick());
+ map->foreachinrange(clif->insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl);
clif->message(fd, msg_txt(1155)); // NPC moved.
return true;
@@ -5143,7 +4996,6 @@ ACMD(addwarp)
unsigned short m;
struct npc_data* nd;
- nullpo_retr(-1, sd);
memset(warpname, '\0', sizeof(warpname));
if (!message || !*message || sscanf(message, "%31s %d %d %23[^\n]", mapname, &x, &y, warpname) < 4) {
@@ -5151,7 +5003,7 @@ ACMD(addwarp)
return false;
}
- m = mapindex_name2id(mapname);
+ m = mapindex->name2id(mapname);
if( m == 0 )
{
sprintf(atcmd_output, msg_txt(1157), mapname); // Unknown map '%s'.
@@ -5159,7 +5011,7 @@ ACMD(addwarp)
return false;
}
- nd = npc_add_warp(warpname, sd->bl.m, sd->bl.x, sd->bl.y, 2, 2, m, x, y);
+ nd = npc->add_warp(warpname, sd->bl.m, sd->bl.x, sd->bl.y, 2, 2, m, x, y);
if( nd == NULL )
return false;
@@ -5172,10 +5024,8 @@ ACMD(addwarp)
* @follow by [MouseJstr]
* Follow a player .. staying no more then 5 spaces away
*------------------------------------------*/
-ACMD(follow)
-{
+ACMD(follow) {
struct map_session_data *pl_sd = NULL;
- nullpo_retr(-1, sd);
if (!message || !*message) {
if (sd->followtarget == -1)
@@ -5186,7 +5036,7 @@ ACMD(follow)
return true;
}
- if ( (pl_sd = iMap->nick2sd((char *)message)) == NULL )
+ if ( (pl_sd = map->nick2sd((char *)message)) == NULL )
{
clif->message(fd, msg_txt(3)); // Character not found.
return false;
@@ -5211,7 +5061,7 @@ ACMD(follow)
ACMD(dropall)
{
int i;
- nullpo_retr(-1, sd);
+
for (i = 0; i < MAX_INVENTORY; i++) {
if (sd->status.inventory[i].amount) {
if(sd->status.inventory[i].equip != 0)
@@ -5229,11 +5079,10 @@ ACMD(dropall)
ACMD(storeall)
{
int i;
- nullpo_retr(-1, sd);
if (sd->state.storage_flag != 1)
{ //Open storage.
- if( storage_storageopen(sd) == 1 ) {
+ if( storage->open(sd) == 1 ) {
clif->message(fd, msg_txt(1161)); // You currently cannot open your storage.
return false;
}
@@ -5243,10 +5092,10 @@ ACMD(storeall)
if (sd->status.inventory[i].amount) {
if(sd->status.inventory[i].equip != 0)
pc->unequipitem(sd, i, 3);
- storage_storageadd(sd, i, sd->status.inventory[i].amount);
+ storage->add(sd, i, sd->status.inventory[i].amount);
}
}
- storage_storageclose(sd);
+ storage->close(sd);
clif->message(fd, msg_txt(1162)); // All items stored.
return true;
@@ -5255,7 +5104,6 @@ ACMD(storeall)
ACMD(clearstorage)
{
int i, j;
- nullpo_retr(-1, sd);
if (sd->state.storage_flag == 1) {
clif->message(fd, msg_txt(250));
@@ -5264,9 +5112,9 @@ ACMD(clearstorage)
j = sd->status.storage.storage_amount;
for (i = 0; i < j; ++i) {
- storage_delitem(sd, i, sd->status.storage.items[i].amount);
+ storage->delitem(sd, i, sd->status.storage.items[i].amount);
}
- storage_storageclose(sd);
+ storage->close(sd);
clif->message(fd, msg_txt(1394)); // Your storage was cleaned.
return true;
@@ -5276,8 +5124,7 @@ ACMD(cleargstorage)
{
int i, j;
struct guild *g;
- struct guild_storage *gstorage;
- nullpo_retr(-1, sd);
+ struct guild_storage *guild_storage;
g = sd->guild;
@@ -5296,18 +5143,18 @@ ACMD(cleargstorage)
return false;
}
- gstorage = guild2storage2(sd->status.guild_id);
- if (gstorage == NULL) {// Doesn't have opened @gstorage yet, so we skip the deletion since *shouldn't* have any item there.
+ guild_storage = gstorage->id2storage2(sd->status.guild_id);
+ if (guild_storage == NULL) {// Doesn't have opened @gstorage yet, so we skip the deletion since *shouldn't* have any item there.
return false;
}
- j = gstorage->storage_amount;
- gstorage->lock = 1; // Lock @gstorage: do not allow any item to be retrieved or stored from any guild member
+ j = guild_storage->storage_amount;
+ guild_storage->lock = 1; // Lock @gstorage: do not allow any item to be retrieved or stored from any guild member
for (i = 0; i < j; ++i) {
- guild_storage_delitem(sd, gstorage, i, gstorage->items[i].amount);
+ gstorage->delitem(sd, guild_storage, i, guild_storage->items[i].amount);
}
- storage_guild_storageclose(sd);
- gstorage->lock = 0; // Cleaning done, release lock
+ gstorage->close(sd);
+ guild_storage->lock = 0; // Cleaning done, release lock
clif->message(fd, msg_txt(1395)); // Your guild storage was cleaned.
return true;
@@ -5316,16 +5163,16 @@ ACMD(cleargstorage)
ACMD(clearcart)
{
int i;
- nullpo_retr(-1, sd);
if (pc_iscarton(sd) == 0) {
clif->message(fd, msg_txt(1396)); // You do not have a cart to be cleaned.
return false;
}
- if (sd->state.vending == 1) { //Somehow...
- return false;
- }
+ if( sd->state.vending == 1 ) {
+ clif->message(fd, msg_txt(548)); // You can't clean a cart while vending!
+ return false;
+ }
for( i = 0; i < MAX_CART; i++ )
if(sd->status.cart[i].nameid > 0)
@@ -5345,14 +5192,13 @@ ACMD(clearcart)
#define MAX_SKILLID_PARTIAL_RESULTS 5
#define MAX_SKILLID_PARTIAL_RESULTS_LEN 74 /* "skill " (6) + "%d:" (up to 5) + "%s" (up to 30) + " (%s)" (up to 33) */
ACMD(skillid) {
- int skillen, idx, i, found = 0;
+ int idx, i, found = 0;
+ size_t skillen;
DBIterator* iter;
DBKey key;
DBData *data;
char partials[MAX_SKILLID_PARTIAL_RESULTS][MAX_SKILLID_PARTIAL_RESULTS_LEN];
-
- nullpo_retr(-1, sd);
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1163)); // Please enter a skill name to look up (usage: @skillid <skill name>).
return false;
@@ -5360,15 +5206,15 @@ ACMD(skillid) {
skillen = strlen(message);
- iter = db_iterator(skilldb_name2id);
+ iter = db_iterator(skill->name2id_db);
for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) {
idx = skill->get_index(DB->data2i(data));
- if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill_db[idx].desc, message, skillen) == 0) {
- sprintf(atcmd_output, msg_txt(1164), DB->data2i(data), skill_db[idx].desc, key.str); // skill %d: %s (%s)
+ if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill->db[idx].desc, message, skillen) == 0) {
+ sprintf(atcmd_output, msg_txt(1164), DB->data2i(data), skill->db[idx].desc, key.str); // skill %d: %s (%s)
clif->message(fd, atcmd_output);
- } else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill_db[idx].desc,message) ) ) {
- snprintf(partials[found++], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_txt(1164), DB->data2i(data), skill_db[idx].desc, key.str);
+ } else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill->db[idx].desc,message) ) ) {
+ snprintf(partials[found++], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_txt(1164), DB->data2i(data), skill->db[idx].desc, key.str);
}
}
@@ -5390,29 +5236,28 @@ ACMD(skillid) {
* @useskill by [MouseJstr]
* A way of using skills without having to find them in the skills menu
*------------------------------------------*/
-ACMD(useskill)
-{
+ACMD(useskill) {
struct map_session_data *pl_sd = NULL;
struct block_list *bl;
uint16 skill_id;
uint16 skill_lv;
char target[100];
- nullpo_retr(-1, sd);
if(!message || !*message || sscanf(message, "%hu %hu %23[^\n]", &skill_id, &skill_lv, target) != 3) {
clif->message(fd, msg_txt(1165)); // Usage: @useskill <skill ID> <skill level> <target>
return false;
}
- if(!strcmp(target,"self")) pl_sd = sd; //quick keyword
- else if ( (pl_sd = iMap->nick2sd(target)) == NULL ){
+ if(!strcmp(target,"self"))
+ pl_sd = sd; //quick keyword
+ else if ( (pl_sd = map->nick2sd(target)) == NULL ) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
- if ( pc->get_group_level(sd) < pc->get_group_level(pl_sd) )
+ if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) )
{
- clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
+ clif->message(fd, msg_txt(81)); // Your GM level don't authorized you to do this action on this player.
return false;
}
@@ -5422,11 +5267,13 @@ ACMD(useskill)
else
bl = &sd->bl;
+ pc->delinvincibletimer(sd);
+
if (skill->get_inf(skill_id)&INF_GROUND_SKILL)
- unit_skilluse_pos(bl, pl_sd->bl.x, pl_sd->bl.y, skill_id, skill_lv);
+ unit->skilluse_pos(bl, pl_sd->bl.x, pl_sd->bl.y, skill_id, skill_lv);
else
- unit_skilluse_id(bl, pl_sd->bl.id, skill_id, skill_lv);
-
+ unit->skilluse_id(bl, pl_sd->bl.id, skill_id, skill_lv);
+
return true;
}
@@ -5435,22 +5282,19 @@ ACMD(useskill)
* Debug command to locate new skill IDs. It sends the
* three possible skill-effect packets to the area.
*------------------------------------------*/
-ACMD(displayskill)
-{
- struct status_data * status;
- unsigned int tick;
+ACMD(displayskill) {
+ struct status_data *st;
+ int64 tick;
uint16 skill_id;
uint16 skill_lv = 1;
- nullpo_retr(-1, sd);
- if (!message || !*message || sscanf(message, "%hu %hu", &skill_id, &skill_lv) < 1)
- {
+ if (!message || !*message || sscanf(message, "%hu %hu", &skill_id, &skill_lv) < 1) {
clif->message(fd, msg_txt(1166)); // Usage: @displayskill <skill ID> {<skill level>}
return false;
}
- status = status_get_status_data(&sd->bl);
- tick = iTimer->gettick();
- clif->skill_damage(&sd->bl,&sd->bl, tick, status->amotion, status->dmotion, 1, 1, skill_id, skill_lv, 5);
+ st = status->get_status_data(&sd->bl);
+ tick = timer->gettick();
+ clif->skill_damage(&sd->bl,&sd->bl, tick, st->amotion, st->dmotion, 1, 1, skill_id, skill_lv, 5);
clif->skill_nodamage(&sd->bl, &sd->bl, skill_id, skill_lv, 1);
clif->skill_poseffect(&sd->bl, skill_id, skill_lv, sd->bl.x, sd->bl.y, tick);
return true;
@@ -5460,22 +5304,19 @@ ACMD(displayskill)
* @skilltree by [MouseJstr]
* prints the skill tree for a player required to get to a skill
*------------------------------------------*/
-ACMD(skilltree)
-{
+ACMD(skilltree) {
struct map_session_data *pl_sd = NULL;
uint16 skill_id;
int meets, j, c=0;
char target[NAME_LENGTH];
struct skill_tree_entry *ent;
- nullpo_retr(-1, sd);
if(!message || !*message || sscanf(message, "%hu %23[^\r\n]", &skill_id, target) != 2) {
clif->message(fd, msg_txt(1167)); // Usage: @skilltree <skill ID> <target>
return false;
}
- if ( (pl_sd = iMap->nick2sd(target)) == NULL )
- {
+ if ( (pl_sd = map->nick2sd(target)) == NULL ) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
@@ -5486,21 +5327,21 @@ ACMD(skilltree)
sprintf(atcmd_output, msg_txt(1168), pc->job_name(c), pc->checkskill(pl_sd, NV_BASIC)); // Player is using %s skill tree (%d basic points).
clif->message(fd, atcmd_output);
- ARR_FIND( 0, MAX_SKILL_TREE, j, skill_tree[c][j].id == 0 || skill_tree[c][j].id == skill_id );
- if( j == MAX_SKILL_TREE || skill_tree[c][j].id == 0 )
+ ARR_FIND( 0, MAX_SKILL_TREE, j, pc->skill_tree[c][j].id == 0 || pc->skill_tree[c][j].id == skill_id );
+ if( j == MAX_SKILL_TREE || pc->skill_tree[c][j].id == 0 )
{
clif->message(fd, msg_txt(1169)); // The player cannot use that skill.
- return true;
+ return false;
}
- ent = &skill_tree[c][j];
+ ent = &pc->skill_tree[c][j];
meets = 1;
for(j=0;j<MAX_PC_SKILL_REQUIRE;j++)
{
if( ent->need[j].id && pc->checkskill(sd,ent->need[j].id) < ent->need[j].lv)
{
- sprintf(atcmd_output, msg_txt(1170), ent->need[j].lv, skill_db[ent->need[j].id].desc); // Player requires level %d of skill %s.
+ sprintf(atcmd_output, msg_txt(1170), ent->need[j].lv, skill->db[ent->need[j].id].desc); // Player requires level %d of skill %s.
clif->message(fd, atcmd_output);
meets = 0;
}
@@ -5513,8 +5354,7 @@ ACMD(skilltree)
}
// Hand a ring with partners name on it to this char
-void getring (struct map_session_data* sd)
-{
+void getring(struct map_session_data* sd) {
int flag, item_id;
struct item item_tmp;
item_id = (sd->status.sex) ? WEDDING_RING_M : WEDDING_RING_F;
@@ -5528,7 +5368,7 @@ void getring (struct map_session_data* sd)
if((flag = pc->additem(sd,&item_tmp,1,LOG_TYPE_COMMAND))) {
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
@@ -5536,19 +5376,16 @@ void getring (struct map_session_data* sd)
* @marry by [MouseJstr], fixed by Lupus
* Marry two players
*------------------------------------------*/
-ACMD(marry)
-{
+ACMD(marry) {
struct map_session_data *pl_sd = NULL;
char player_name[NAME_LENGTH] = "";
-
- nullpo_retr(-1, sd);
-
+
if (!message || !*message || sscanf(message, "%23s", player_name) != 1) {
clif->message(fd, msg_txt(1172)); // Usage: @marry <char name>
return false;
}
- if ((pl_sd = iMap->nick2sd(player_name)) == NULL) {
+ if ((pl_sd = map->nick2sd(player_name)) == NULL) {
clif->message(fd, msg_txt(3));
return false;
}
@@ -5571,8 +5408,6 @@ ACMD(marry)
*------------------------------------------*/
ACMD(divorce)
{
- nullpo_retr(-1, sd);
-
if (pc->divorce(sd) != 0) {
sprintf(atcmd_output, msg_txt(1175), sd->status.name); // '%s' is not married.
clif->message(fd, atcmd_output);
@@ -5615,10 +5450,9 @@ ACMD(changelook)
* Turns on/off Autotrade for a specific player
*------------------------------------------*/
ACMD(autotrade) {
- nullpo_retr(-1, sd);
- if( map[sd->bl.m].flag.autotrade != battle_config.autotrade_mapflag ) {
- clif->message(fd, msg_txt(1179)); // Autotrade is not allowed on this map.
+ if( map->list[sd->bl.m].flag.autotrade != battle_config.autotrade_mapflag ) {
+ clif->message(fd, msg_txt(1179)); // Autotrade is not allowed in this map.
return false;
}
@@ -5628,40 +5462,52 @@ ACMD(autotrade) {
}
if( !sd->state.vending && !sd->state.buyingstore ) { //check if player is vending or buying
- clif->message(fd, msg_txt(549)); // "You should have a shop open to use @autotrade."
+ clif->message(fd, msg_txt(549)); // "You should have a shop open in order to use @autotrade."
return false;
}
sd->state.autotrade = 1;
if( battle_config.at_timeout ) {
int timeout = atoi(message);
- status_change_start(&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0);
+ status->change_start(NULL,&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0);
}
+
+ /* currently standalone is not supporting buyingstores, so we rely on the previous method */
+ if( sd->state.buyingstore ) {
+ clif->authfail_fd(fd, 15);
+ return true;
+ }
+
clif->chsys_quit(sd);
clif->authfail_fd(sd->fd, 15);
+
+#ifdef AUTOTRADE_PERSISTENCY
+ pc->autotrade_prepare(sd);
+
+ return false;/* we fail to not cause it to proceed on is_atcommand */
+#else
return true;
+#endif
}
/*==========================================
* @changegm by durf (changed by Lupus)
* Changes Master of your Guild to a specified guild member
*------------------------------------------*/
-ACMD(changegm)
-{
+ACMD(changegm) {
struct guild *g;
struct map_session_data *pl_sd;
- nullpo_retr(-1, sd);
if (sd->status.guild_id == 0 || (g = sd->guild) == NULL || strcmp(g->master,sd->status.name)) {
clif->message(fd, msg_txt(1181)); // You need to be a Guild Master to use this command.
return false;
}
- if( map[sd->bl.m].flag.guildlock || map[sd->bl.m].flag.gvg_castle ) {
- clif->message(fd, msg_txt(1182)); // You cannot change guild leaders on this map.
+ if( map->list[sd->bl.m].flag.guildlock || map->list[sd->bl.m].flag.gvg_castle ) {
+ clif->message(fd, msg_txt(1182)); // You cannot change guild leaders in this map.
return false;
}
@@ -5670,7 +5516,7 @@ ACMD(changegm)
return false;
}
- if((pl_sd=iMap->nick2sd((char *) message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) {
+ if((pl_sd=map->nick2sd((char *) message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) {
clif->message(fd, msg_txt(1184)); // Target character must be online and be a guild member.
return false;
}
@@ -5683,17 +5529,14 @@ ACMD(changegm)
* @changeleader by Skotlex
* Changes the leader of a party.
*------------------------------------------*/
-ACMD(changeleader)
-{
- nullpo_retr(-1, sd);
+ACMD(changeleader) {
- if( !message[0] )
- {
+ if( !message[0] ) {
clif->message(fd, msg_txt(1185)); // Usage: @changeleader <party_member_name>
return false;
}
- if (party->changeleader(sd, iMap->nick2sd((char *) message)))
+ if (party->changeleader(sd, map->nick2sd((char *) message)))
return true;
return false;
}
@@ -5707,7 +5550,6 @@ ACMD(partyoption)
struct party_data *p;
int mi, option;
char w1[16], w2[16];
- nullpo_retr(-1, sd);
if (sd->status.party_id == 0 || (p = party->search(sd->status.party_id)) == NULL)
{
@@ -5749,7 +5591,7 @@ ACMD(partyoption)
ACMD(autoloot)
{
int rate;
- nullpo_retr(-1, sd);
+
// autoloot command without value
if(!message || !*message)
{
@@ -5795,16 +5637,16 @@ ACMD(autolootitem)
}
else if (!strcmp(message,"reset"))
action = 4;
- }
-
- if (action < 3) // add or remove
- {
- if ((item_data = itemdb_exists(atoi(message))) == NULL)
- item_data = itemdb_searchname(message);
- if (!item_data) {
- // No items founds in the DB with Id or Name
- clif->message(fd, msg_txt(1189)); // Item not found.
- return false;
+
+ if (action < 3) // add or remove
+ {
+ if ((item_data = itemdb->exists(atoi(message))) == NULL)
+ item_data = itemdb->search_name(message);
+ if (!item_data) {
+ // No items founds in the DB with Id or Name
+ clif->message(fd, msg_txt(1189)); // Item not found.
+ return false;
+ }
}
}
@@ -5853,7 +5695,7 @@ ACMD(autolootitem)
{
if (sd->state.autolootid[i] == 0)
continue;
- if (!(item_data = itemdb_exists(sd->state.autolootid[i]))) {
+ if (!(item_data = itemdb->exists(sd->state.autolootid[i]))) {
ShowDebug("Non-existant item %d on autolootitem list (account_id: %d, char_id: %d)", sd->state.autolootid[i], sd->status.account_id, sd->status.char_id);
continue;
}
@@ -5870,39 +5712,115 @@ ACMD(autolootitem)
}
return true;
}
-/**
- * No longer available, keeping here just in case it's back someday. [Ind]
- **/
+
/*==========================================
- * It is made to rain.
+ * @autoloottype
+ * Credits:
+ * chriser,Aleos
*------------------------------------------*/
-//ACMD(rain)
-//{
-// nullpo_retr(-1, sd);
-// if (map[sd->bl.m].flag.rain) {
-// map[sd->bl.m].flag.rain=0;
-// clif->weather(sd->bl.m);
-// clif->message(fd, msg_txt(1201)); // The rain has stopped.
-// } else {
-// map[sd->bl.m].flag.rain=1;
-// clif->weather(sd->bl.m);
-// clif->message(fd, msg_txt(1202)); // It has started to rain.
-// }
-// return true;
-//}
+ACMD(autoloottype) {
+ int i;
+ uint8 action = 3; // 1=add, 2=remove, 3=help+list (default), 4=reset
+ enum item_types type = -1;
+ int ITEM_NONE = 0;
+
+ if (message && *message) {
+ if (message[0] == '+') {
+ message++;
+ action = 1;
+ } else if (message[0] == '-') {
+ message++;
+ action = 2;
+ } else if (strcmp(message,"reset") == 0) {
+ action = 4;
+ }
+
+ if (action < 3) {
+ // add or remove
+ if (strncmp(message, "healing", 3) == 0)
+ type = IT_HEALING;
+ else if (strncmp(message, "usable", 3) == 0)
+ type = IT_USABLE;
+ else if (strncmp(message, "etc", 3) == 0)
+ type = IT_ETC;
+ else if (strncmp(message, "weapon", 3) == 0)
+ type = IT_WEAPON;
+ else if (strncmp(message, "armor", 3) == 0)
+ type = IT_ARMOR;
+ else if (strncmp(message, "card", 3) == 0)
+ type = IT_CARD;
+ else if (strncmp(message, "petegg", 4) == 0)
+ type = IT_PETEGG;
+ else if (strncmp(message, "petarmor", 4) == 0)
+ type = IT_PETARMOR;
+ else if (strncmp(message, "ammo", 3) == 0)
+ type = IT_AMMO;
+ else {
+ clif->message(fd, msg_txt(1491)); // Item type not found.
+ return false;
+ }
+ }
+ }
+
+ switch (action) {
+ case 1:
+ if (sd->state.autoloottype&(1<<type)) {
+ clif->message(fd, msg_txt(1490)); // You're already autolooting this item type.
+ return false;
+ }
+ sd->state.autoloottype |= (1<<type); // Stores the type
+ sprintf(atcmd_output, msg_txt(1492), itemdb->typename(type)); // Autolooting item type: '%s'
+ clif->message(fd, atcmd_output);
+ break;
+ case 2:
+ if (!(sd->state.autoloottype&(1<<type))) {
+ clif->message(fd, msg_txt(1493)); // You're currently not autolooting this item type.
+ return false;
+ }
+ sd->state.autoloottype &= ~(1<<type);
+ sprintf(atcmd_output, msg_txt(1494), itemdb->typename(type)); // Removed item type: '%s' from your autoloottype list.
+ clif->message(fd, atcmd_output);
+ break;
+ case 3:
+ clif->message(fd, msg_txt(38)); // Invalid location number, or name.
+
+ {
+ // attempt to find the text help string
+ const char *text = atcommand_help_string(info);
+ if (text) clif->messageln(fd, text); // send the text to the client
+ }
+
+ if (sd->state.autoloottype == ITEM_NONE) {
+ clif->message(fd, msg_txt(1495)); // Your autoloottype list is empty.
+ } else {
+ clif->message(fd, msg_txt(1496)); // Item types on your autoloottype list:
+ for(i=0; i < IT_MAX; i++) {
+ if (sd->state.autoloottype&(1<<i)) {
+ sprintf(atcmd_output, " '%s'", itemdb->typename(i));
+ clif->message(fd, atcmd_output);
+ }
+ }
+ }
+ break;
+ case 4:
+ sd->state.autoloottype = ITEM_NONE;
+ clif->message(fd, msg_txt(1497)); // Your autoloottype list has been reset.
+ break;
+ }
+ return true;
+}
/*==========================================
* It is made to snow.
*------------------------------------------*/
-ACMD(snow)
-{
- nullpo_retr(-1, sd);
- if (map[sd->bl.m].flag.snow) {
- map[sd->bl.m].flag.snow=0;
+ACMD(snow) {
+
+ if (map->list[sd->bl.m].flag.snow) {
+ map->list[sd->bl.m].flag.snow=0;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1203)); // Snow has stopped falling.
} else {
- map[sd->bl.m].flag.snow=1;
+ map->list[sd->bl.m].flag.snow=1;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1204)); // It has started to snow.
}
@@ -5913,15 +5831,14 @@ ACMD(snow)
/*==========================================
* Cherry tree snowstorm is made to fall. (Sakura)
*------------------------------------------*/
-ACMD(sakura)
-{
- nullpo_retr(-1, sd);
- if (map[sd->bl.m].flag.sakura) {
- map[sd->bl.m].flag.sakura=0;
+ACMD(sakura) {
+
+ if (map->list[sd->bl.m].flag.sakura) {
+ map->list[sd->bl.m].flag.sakura=0;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1205)); // Cherry tree leaves no longer fall.
} else {
- map[sd->bl.m].flag.sakura=1;
+ map->list[sd->bl.m].flag.sakura=1;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1206)); // Cherry tree leaves have begun to fall.
}
@@ -5931,15 +5848,14 @@ ACMD(sakura)
/*==========================================
* Clouds appear.
*------------------------------------------*/
-ACMD(clouds)
-{
- nullpo_retr(-1, sd);
- if (map[sd->bl.m].flag.clouds) {
- map[sd->bl.m].flag.clouds=0;
+ACMD(clouds) {
+
+ if (map->list[sd->bl.m].flag.clouds) {
+ map->list[sd->bl.m].flag.clouds=0;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1207)); // The clouds has disappear.
} else {
- map[sd->bl.m].flag.clouds=1;
+ map->list[sd->bl.m].flag.clouds=1;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1208)); // Clouds appear.
}
@@ -5950,15 +5866,14 @@ ACMD(clouds)
/*==========================================
* Different type of clouds using effect 516
*------------------------------------------*/
-ACMD(clouds2)
-{
- nullpo_retr(-1, sd);
- if (map[sd->bl.m].flag.clouds2) {
- map[sd->bl.m].flag.clouds2=0;
+ACMD(clouds2) {
+
+ if (map->list[sd->bl.m].flag.clouds2) {
+ map->list[sd->bl.m].flag.clouds2=0;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1209)); // The alternative clouds disappear.
} else {
- map[sd->bl.m].flag.clouds2=1;
+ map->list[sd->bl.m].flag.clouds2=1;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1210)); // Alternative clouds appear.
}
@@ -5969,15 +5884,14 @@ ACMD(clouds2)
/*==========================================
* Fog hangs over.
*------------------------------------------*/
-ACMD(fog)
-{
- nullpo_retr(-1, sd);
- if (map[sd->bl.m].flag.fog) {
- map[sd->bl.m].flag.fog=0;
+ACMD(fog) {
+
+ if (map->list[sd->bl.m].flag.fog) {
+ map->list[sd->bl.m].flag.fog=0;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1211)); // The fog has gone.
} else {
- map[sd->bl.m].flag.fog=1;
+ map->list[sd->bl.m].flag.fog=1;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1212)); // Fog hangs over.
}
@@ -5987,15 +5901,14 @@ ACMD(fog)
/*==========================================
* Fallen leaves fall.
*------------------------------------------*/
-ACMD(leaves)
-{
- nullpo_retr(-1, sd);
- if (map[sd->bl.m].flag.leaves) {
- map[sd->bl.m].flag.leaves=0;
+ACMD(leaves) {
+
+ if (map->list[sd->bl.m].flag.leaves) {
+ map->list[sd->bl.m].flag.leaves=0;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1213)); // Leaves no longer fall.
} else {
- map[sd->bl.m].flag.leaves=1;
+ map->list[sd->bl.m].flag.leaves=1;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1214)); // Fallen leaves fall.
}
@@ -6006,15 +5919,14 @@ ACMD(leaves)
/*==========================================
* Fireworks appear.
*------------------------------------------*/
-ACMD(fireworks)
-{
- nullpo_retr(-1, sd);
- if (map[sd->bl.m].flag.fireworks) {
- map[sd->bl.m].flag.fireworks=0;
+ACMD(fireworks) {
+
+ if (map->list[sd->bl.m].flag.fireworks) {
+ map->list[sd->bl.m].flag.fireworks=0;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1215)); // Fireworks have ended.
} else {
- map[sd->bl.m].flag.fireworks=1;
+ map->list[sd->bl.m].flag.fireworks=1;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1216)); // Fireworks have launched.
}
@@ -6025,22 +5937,17 @@ ACMD(fireworks)
/*==========================================
* Clearing Weather Effects by Dexity
*------------------------------------------*/
-ACMD(clearweather)
-{
- nullpo_retr(-1, sd);
- /**
- * No longer available, keeping here just in case it's back someday. [Ind]
- **/
- //map[sd->bl.m].flag.rain=0;
- map[sd->bl.m].flag.snow=0;
- map[sd->bl.m].flag.sakura=0;
- map[sd->bl.m].flag.clouds=0;
- map[sd->bl.m].flag.clouds2=0;
- map[sd->bl.m].flag.fog=0;
- map[sd->bl.m].flag.fireworks=0;
- map[sd->bl.m].flag.leaves=0;
+ACMD(clearweather) {
+
+ map->list[sd->bl.m].flag.snow=0;
+ map->list[sd->bl.m].flag.sakura=0;
+ map->list[sd->bl.m].flag.clouds=0;
+ map->list[sd->bl.m].flag.clouds2=0;
+ map->list[sd->bl.m].flag.fog=0;
+ map->list[sd->bl.m].flag.fireworks=0;
+ map->list[sd->bl.m].flag.leaves=0;
clif->weather(sd->bl.m);
- clif->message(fd, msg_txt(291));
+ clif->message(fd, msg_txt(291)); // "Weather effects will disappear after teleporting or refreshing."
return true;
}
@@ -6076,23 +5983,21 @@ ACMD(mobsearch)
int mob_id;
int number = 0;
struct s_mapiterator* it;
-
- nullpo_retr(-1, sd);
-
+
if (!message || !*message || sscanf(message, "%99[^\n]", mob_name) < 1) {
clif->message(fd, msg_txt(1218)); // Please enter a monster name (usage: @mobsearch <monster name>).
return false;
}
if ((mob_id = atoi(mob_name)) == 0)
- mob_id = mobdb_searchname(mob_name);
- if(mob_id > 0 && mobdb_checkid(mob_id) == 0){
+ mob_id = mob->db_searchname(mob_name);
+ if(mob_id > 0 && mob->db_checkid(mob_id) == 0){
snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1219),mob_name); // Invalid mob ID %s!
clif->message(fd, atcmd_output);
return false;
}
- if(mob_id == atoi(mob_name) && mob_db(mob_id)->jname)
- strcpy(mob_name,mob_db(mob_id)->jname); // --ja--
+ if(mob_id == atoi(mob_name) && mob->db(mob_id)->jname)
+ strcpy(mob_name,mob->db(mob_id)->jname); // --ja--
// strcpy(mob_name,mob_db(mob_id)->name); // --en--
snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1220), mob_name, mapindex_id2name(sd->mapindex)); // Mob Search... %s %s
@@ -6126,33 +6031,28 @@ ACMD(mobsearch)
* @cleanmap - cleans items on the ground
* @cleanarea - cleans items on the ground within an specified area
*------------------------------------------*/
-static int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap)
-{
+int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap) {
nullpo_ret(bl);
- iMap->clearflooritem(bl);
+ map->clearflooritem(bl);
return 0;
}
-ACMD(cleanmap)
-{
- iMap->foreachinmap(atcommand_cleanfloor_sub, sd->bl.m, BL_ITEM);
+ACMD(cleanmap) {
+ map->foreachinmap(atcommand->cleanfloor_sub, sd->bl.m, BL_ITEM);
clif->message(fd, msg_txt(1221)); // All dropped items have been cleaned up.
return true;
}
-ACMD(cleanarea)
-{
+ACMD(cleanarea) {
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
if (!message || !*message || sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) < 1) {
- iMap->foreachinarea(atcommand_cleanfloor_sub, sd->bl.m, sd->bl.x - (AREA_SIZE * 2), sd->bl.y - (AREA_SIZE * 2), sd->bl.x + (AREA_SIZE * 2), sd->bl.y + (AREA_SIZE * 2), BL_ITEM);
- }
- else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 1) {
- iMap->foreachinarea(atcommand_cleanfloor_sub, sd->bl.m, sd->bl.x - x0, sd->bl.y - x0, sd->bl.x + x0, sd->bl.y + x0, BL_ITEM);
- }
- else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 4) {
- iMap->foreachinarea(atcommand_cleanfloor_sub, sd->bl.m, x0, y0, x1, y1, BL_ITEM);
+ map->foreachinrange(atcommand->cleanfloor_sub, &sd->bl, AREA_SIZE * 2, BL_ITEM);
+ } else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 1) {
+ map->foreachinrange(atcommand->cleanfloor_sub, &sd->bl, x0, BL_ITEM);
+ } else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 4) {
+ map->foreachinarea(atcommand->cleanfloor_sub, sd->bl.m, x0, y0, x1, y1, BL_ITEM);
}
clif->message(fd, msg_txt(1221)); // All dropped items have been cleaned up.
@@ -6167,11 +6067,11 @@ ACMD(npctalk)
{
char name[NAME_LENGTH],mes[100],temp[100];
struct npc_data *nd;
- bool ifcolor=(*(command + 8) != 'c' && *(command + 8) != 'C')?0:1;
- unsigned long color=0;
+ bool ifcolor=(*(info->command + 7) != 'c' && *(info->command + 7) != 'C')?0:1;
+ unsigned int color = 0;
if (sd->sc.count && //no "chatting" while muted.
- (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || sd->sc.data[SC__BLOODYLUST] ||
+ (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
@@ -6182,13 +6082,13 @@ ACMD(npctalk)
}
}
else {
- if (!message || !*message || sscanf(message, "%lx %23[^,], %99[^\n]", &color, name, mes) < 3) {
+ if (!message || !*message || sscanf(message, "%u %23[^,], %99[^\n]", &color, name, mes) < 3) {
clif->message(fd, msg_txt(1223)); // Please enter the correct parameters (usage: @npctalkc <color> <npc name>, <message>).
return false;
}
}
- if (!(nd = npc_name2id(name))) {
+ if (!(nd = npc->name2id(name))) {
clif->message(fd, msg_txt(111)); // This NPC doesn't exist
return false;
}
@@ -6206,13 +6106,11 @@ ACMD(pettalk)
{
char mes[100],temp[100];
struct pet_data *pd;
-
- nullpo_retr(-1, sd);
-
+
if ( battle_config.min_chat_delay ) {
- if( DIFF_TICK(sd->cantalk_tick, iTimer->gettick()) > 0 )
+ if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 )
return true;
- sd->cantalk_tick = iTimer->gettick() + battle_config.min_chat_delay;
+ sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
if(!sd->status.pet_id || !(pd=sd->pd))
@@ -6222,7 +6120,7 @@ ACMD(pettalk)
}
if (sd->sc.count && //no "chatting" while muted.
- (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || sd->sc.data[SC__BLOODYLUST] ||
+ (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
@@ -6333,9 +6231,7 @@ ACMD(summon)
int mob_id = 0;
int duration = 0;
struct mob_data *md;
- unsigned int tick=iTimer->gettick();
-
- nullpo_retr(-1, sd);
+ int64 tick=timer->gettick();
if (!message || !*message || sscanf(message, "%23s %d", name, &duration) < 1)
{
@@ -6349,24 +6245,24 @@ ACMD(summon)
duration =60;
if ((mob_id = atoi(name)) == 0)
- mob_id = mobdb_searchname(name);
- if(mob_id == 0 || mobdb_checkid(mob_id) == 0)
+ mob_id = mob->db_searchname(name);
+ if(mob_id == 0 || mob->db_checkid(mob_id) == 0)
{
clif->message(fd, msg_txt(40)); // Invalid monster ID or name.
return false;
}
- md = mob_once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, "--ja--", mob_id, "", SZ_SMALL, AI_NONE);
+ md = mob->once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, "--ja--", mob_id, "", SZ_MEDIUM, AI_NONE);
if(!md)
return false;
md->master_id=sd->bl.id;
md->special_state.ai=1;
- md->deletetimer=iTimer->add_timer(tick+(duration*60000),mob_timer_delete,md->bl.id,0);
+ md->deletetimer=timer->add(tick+(duration*60000),mob->timer_delete,md->bl.id,0);
clif->specialeffect(&md->bl,344,AREA);
- mob_spawn(md);
- sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000);
+ mob->spawn(md);
+ sc_start4(NULL,&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000);
clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,md->bl.x,md->bl.y,tick);
clif->message(fd, msg_txt(39)); // All monster summoned!
@@ -6381,20 +6277,17 @@ ACMD(summon)
ACMD(adjgroup)
{
int new_group = 0;
- nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d", &new_group) != 1) {
clif->message(fd, msg_txt(1226)); // Usage: @adjgroup <group_id>
return false;
}
- if (!pc_group_exists(new_group)) {
+ if (pc->set_group(sd, new_group) != 0) {
clif->message(fd, msg_txt(1227)); // Specified group does not exist.
return false;
}
-
- sd->group_id = new_group;
- pc_group_pc_load(sd);/* update cache */
+
clif->message(fd, msg_txt(1228)); // Group changed successfully.
clif->message(sd->fd, msg_txt(1229)); // Your group has changed.
return true;
@@ -6404,18 +6297,15 @@ ACMD(adjgroup)
* @trade by [MouseJstr]
* Open a trade window with a remote player
*------------------------------------------*/
-ACMD(trade)
-{
+ACMD(trade) {
struct map_session_data *pl_sd = NULL;
- nullpo_retr(-1, sd);
if (!message || !*message) {
clif->message(fd, msg_txt(1230)); // Please enter a player name (usage: @trade <char name>).
return false;
}
- if ( (pl_sd = iMap->nick2sd((char *)message)) == NULL )
- {
+ if ( (pl_sd = map->nick2sd((char *)message)) == NULL ) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
@@ -6431,7 +6321,6 @@ ACMD(trade)
ACMD(setbattleflag)
{
char flag[128], value[128];
- nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%127s %127s", flag, value) != 2) {
clif->message(fd, msg_txt(1231)); // Usage: @setbattleflag <flag> <value>
@@ -6451,17 +6340,15 @@ ACMD(setbattleflag)
/*==========================================
* @unmute [Valaris]
*------------------------------------------*/
-ACMD(unmute)
-{
+ACMD(unmute) {
struct map_session_data *pl_sd = NULL;
- nullpo_retr(-1, sd);
if (!message || !*message) {
clif->message(fd, msg_txt(1234)); // Please enter a player name (usage: @unmute <char name>).
return false;
}
- if ( (pl_sd = iMap->nick2sd((char *)message)) == NULL )
+ if ( (pl_sd = map->nick2sd((char *)message)) == NULL )
{
clif->message(fd, msg_txt(3)); // Character not found.
return false;
@@ -6486,9 +6373,8 @@ ACMD(uptime)
{
unsigned long seconds = 0, day = 24*60*60, hour = 60*60,
minute = 60, days = 0, hours = 0, minutes = 0;
- nullpo_retr(-1, sd);
- seconds = iTimer->get_uptime();
+ seconds = timer->get_uptime();
days = seconds/day;
seconds -= (seconds/day>0)?(seconds/day)*day:0;
hours = seconds/hour;
@@ -6509,38 +6395,35 @@ ACMD(uptime)
ACMD(changesex)
{
int i;
- nullpo_retr(-1, sd);
+
pc->resetskill(sd,4);
- // to avoid any problem with equipment and invalid sex, equipment is unequiped.
+ // to avoid any problem with equipment and invalid sex, equipment is unequipped.
for( i=0; i<EQI_MAX; i++ )
if( sd->equip_index[i] >= 0 ) pc->unequipitem(sd, sd->equip_index[i], 3);
- chrif_changesex(sd);
+ chrif->changesex(sd);
return true;
}
/*================================================
* @mute - Mutes a player for a set amount of time
*------------------------------------------------*/
-ACMD(mute)
-{
+ACMD(mute) {
struct map_session_data *pl_sd = NULL;
int manner;
- nullpo_retr(-1, sd);
if (!message || !*message || sscanf(message, "%d %23[^\n]", &manner, atcmd_player_name) < 1) {
clif->message(fd, msg_txt(1237)); // Usage: @mute <time> <char name>
return false;
}
- if ( (pl_sd = iMap->nick2sd(atcmd_player_name)) == NULL )
- {
+ if ( (pl_sd = map->nick2sd(atcmd_player_name)) == NULL ) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
- if ( pc->get_group_level(sd) < pc->get_group_level(pl_sd) )
+ if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) )
{
- clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
+ clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
return false;
}
@@ -6549,7 +6432,7 @@ ACMD(mute)
if( pl_sd->status.manner < manner ) {
pl_sd->status.manner -= manner;
- sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0);
+ sc_start(NULL,&pl_sd->bl,SC_NOCHAT,100,0,0);
} else {
pl_sd->status.manner = 0;
status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER);
@@ -6565,7 +6448,6 @@ ACMD(mute)
*------------------------------------------*/
ACMD(refresh)
{
- nullpo_retr(-1, sd);
clif->refresh(sd);
return true;
}
@@ -6574,7 +6456,6 @@ ACMD(refreshall)
{
struct map_session_data* iter_sd;
struct s_mapiterator* iter;
- nullpo_retr(-1, sd);
iter = mapit_getallusers();
for (iter_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); iter_sd = (TBL_PC*)mapit->next(iter))
@@ -6590,9 +6471,7 @@ ACMD(refreshall)
ACMD(identify)
{
int i,num;
-
- nullpo_retr(-1, sd);
-
+
for(i=num=0;i<MAX_INVENTORY;i++){
if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify!=1){
num++;
@@ -6608,7 +6487,7 @@ ACMD(identify)
ACMD(misceffect) {
int effect = 0;
- nullpo_retr(-1, sd);
+
if (!message || !*message)
return false;
if (sscanf(message, "%d", &effect) < 1)
@@ -6623,7 +6502,6 @@ ACMD(misceffect) {
*------------------------------------------*/
ACMD(mail)
{
- nullpo_ret(sd);
mail->openmail(sd);
return true;
}
@@ -6639,7 +6517,7 @@ ACMD(mobinfo)
unsigned char melement[10][8] = {"Neutral", "Water", "Earth", "Fire", "Wind", "Poison", "Holy", "Dark", "Ghost", "Undead"};
char atcmd_output2[CHAT_SIZE_MAX];
struct item_data *item_data;
- struct mob_db *mob, *mob_array[MAX_SEARCH];
+ struct mob_db *monster, *mob_array[MAX_SEARCH];
int count;
int i, j, k;
@@ -6652,12 +6530,11 @@ ACMD(mobinfo)
}
// If monster identifier/name argument is a name
- if ((i = mobdb_checkid(atoi(message))))
- {
- mob_array[0] = mob_db(i);
+ if ((i = mob->db_checkid(atoi(message)))) {
+ mob_array[0] = mob->db(i);
count = 1;
} else
- count = mobdb_searchname_array(mob_array, MAX_SEARCH, message);
+ count = mob->db_searchname_array(mob_array, MAX_SEARCH, message, 0);
if (!count) {
clif->message(fd, msg_txt(40)); // Invalid monster ID or name.
@@ -6669,66 +6546,97 @@ ACMD(mobinfo)
clif->message(fd, atcmd_output);
count = MAX_SEARCH;
}
+
for (k = 0; k < count; k++) {
- mob = mob_array[k];
+ unsigned int job_exp, base_exp;
+
+ monster = mob_array[k];
+
+ job_exp = monster->job_exp;
+ base_exp = monster->base_exp;
+
+#ifdef RENEWAL_EXP
+ if( battle_config.atcommand_mobinfo_type ) {
+ base_exp = base_exp * pc->level_penalty_mod(monster->lv - sd->status.base_level, monster->status.race, monster->status.mode, 1) / 100;
+ job_exp = job_exp * pc->level_penalty_mod(monster->lv - sd->status.base_level, monster->status.race, monster->status.mode, 1) / 100;
+ }
+#endif
// stats
- if (mob->mexp)
- sprintf(atcmd_output, msg_txt(1240), mob->name, mob->jname, mob->sprite, mob->vd.class_); // MVP Monster: '%s'/'%s'/'%s' (%d)
+ if (monster->mexp)
+ sprintf(atcmd_output, msg_txt(1240), monster->name, monster->jname, monster->sprite, monster->vd.class_); // MVP Monster: '%s'/'%s'/'%s' (%d)
else
- sprintf(atcmd_output, msg_txt(1241), mob->name, mob->jname, mob->sprite, mob->vd.class_); // Monster: '%s'/'%s'/'%s' (%d)
+ sprintf(atcmd_output, msg_txt(1241), monster->name, monster->jname, monster->sprite, monster->vd.class_); // Monster: '%s'/'%s'/'%s' (%d)
clif->message(fd, atcmd_output);
- sprintf(atcmd_output, msg_txt(1242), mob->lv, mob->status.max_hp, mob->base_exp, mob->job_exp,MOB_HIT(mob), MOB_FLEE(mob)); // Lv:%d HP:%d Base EXP:%u Job EXP:%u HIT:%d FLEE:%d
+
+ sprintf(atcmd_output, msg_txt(1242), monster->lv, monster->status.max_hp, base_exp, job_exp, MOB_HIT(monster), MOB_FLEE(monster)); // Lv:%d HP:%d Base EXP:%u Job EXP:%u HIT:%d FLEE:%d
clif->message(fd, atcmd_output);
+
sprintf(atcmd_output, msg_txt(1243), // DEF:%d MDEF:%d STR:%d AGI:%d VIT:%d INT:%d DEX:%d LUK:%d
- mob->status.def, mob->status.mdef,mob->status.str, mob->status.agi,
- mob->status.vit, mob->status.int_, mob->status.dex, mob->status.luk);
+ monster->status.def, monster->status.mdef, monster->status.str, monster->status.agi,
+ monster->status.vit, monster->status.int_, monster->status.dex, monster->status.luk);
clif->message(fd, atcmd_output);
sprintf(atcmd_output, msg_txt(1244), // ATK:%d~%d Range:%d~%d~%d Size:%s Race: %s Element: %s (Lv:%d)
- mob->status.rhw.atk, mob->status.rhw.atk2, mob->status.rhw.range,
- mob->range2 , mob->range3, msize[mob->status.size],
- mrace[mob->status.race], melement[mob->status.def_ele], mob->status.ele_lv);
+ monster->status.rhw.atk, monster->status.rhw.atk2, monster->status.rhw.range,
+ monster->range2 , monster->range3, msize[monster->status.size],
+ mrace[monster->status.race], melement[monster->status.def_ele], monster->status.ele_lv);
clif->message(fd, atcmd_output);
+
// drops
clif->message(fd, msg_txt(1245)); // Drops:
strcpy(atcmd_output, " ");
j = 0;
for (i = 0; i < MAX_MOB_DROP; i++) {
int droprate;
- if (mob->dropitem[i].nameid <= 0 || mob->dropitem[i].p < 1 || (item_data = itemdb_exists(mob->dropitem[i].nameid)) == NULL)
+
+ if (monster->dropitem[i].nameid <= 0 || monster->dropitem[i].p < 1 || (item_data = itemdb->exists(monster->dropitem[i].nameid)) == NULL)
continue;
- droprate = mob->dropitem[i].p;
+
+ droprate = monster->dropitem[i].p;
+
+#ifdef RENEWAL_DROP
+ if( battle_config.atcommand_mobinfo_type ) {
+ droprate = droprate * pc->level_penalty_mod(monster->lv - sd->status.base_level, monster->status.race, monster->status.mode, 2) / 100;
+
+ if (droprate <= 0 && !battle_config.drop_rate0item)
+ droprate = 1;
+ }
+#endif
if (item_data->slot)
sprintf(atcmd_output2, " - %s[%d] %02.02f%%", item_data->jname, item_data->slot, (float)droprate / 100);
else
sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, (float)droprate / 100);
+
strcat(atcmd_output, atcmd_output2);
+
if (++j % 3 == 0) {
clif->message(fd, atcmd_output);
strcpy(atcmd_output, " ");
}
}
+
if (j == 0)
clif->message(fd, msg_txt(1246)); // This monster has no drops.
else if (j % 3 != 0)
clif->message(fd, atcmd_output);
// mvp
- if (mob->mexp) {
- sprintf(atcmd_output, msg_txt(1247), mob->mexp); // MVP Bonus EXP:%u
+ if (monster->mexp) {
+ sprintf(atcmd_output, msg_txt(1247), monster->mexp); // MVP Bonus EXP:%u
clif->message(fd, atcmd_output);
+
strcpy(atcmd_output, msg_txt(1248)); // MVP Items:
j = 0;
for (i = 0; i < MAX_MVP_DROP; i++) {
- if (mob->mvpitem[i].nameid <= 0 || (item_data = itemdb_exists(mob->mvpitem[i].nameid)) == NULL)
+ if (monster->mvpitem[i].nameid <= 0 || (item_data = itemdb->exists(monster->mvpitem[i].nameid)) == NULL)
continue;
- if (mob->mvpitem[i].p > 0) {
+ if (monster->mvpitem[i].p > 0) {
j++;
- if (j == 1)
- sprintf(atcmd_output2, " %s %02.02f%%", item_data->jname, (float)mob->mvpitem[i].p / 100);
+ if(item_data->slot)
+ sprintf(atcmd_output2, " %s%s[%d] %02.02f%%",j != 1 ? "- " : "", item_data->jname, item_data->slot, (float)monster->mvpitem[i].p / 100);
else
- sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, (float)mob->mvpitem[i].p / 100);
+ sprintf(atcmd_output2, " %s%s %02.02f%%",j != 1 ? "- " : "", item_data->jname, (float)monster->mvpitem[i].p / 100);
strcat(atcmd_output, atcmd_output2);
}
}
@@ -6751,27 +6659,34 @@ ACMD(showmobs)
int mob_id;
int number = 0;
struct s_mapiterator* it;
-
- nullpo_retr(-1, sd);
-
- if(sscanf(message, "%99[^\n]", mob_name) < 0)
+
+ if( sscanf(message, "%99[^\n]", mob_name) < 0 ) {
+ clif->message(fd, msg_txt(546)); // Please enter a mob name/id (usage: @showmobs <mob name/id>)
return false;
-
- if((mob_id = atoi(mob_name)) == 0)
- mob_id = mobdb_searchname(mob_name);
- if(mob_id > 0 && mobdb_checkid(mob_id) == 0){
+ }
+
+ if( (mob_id = atoi(mob_name)) == 0 )
+ mob_id = mob->db_searchname(mob_name);
+
+ if( mob_id == 0 ) {
+ snprintf(atcmd_output, sizeof atcmd_output, msg_txt(547), mob_name); // Invalid mob name %s!
+ clif->message(fd, atcmd_output);
+ return false;
+ }
+
+ if(mob_id > 0 && mob->db_checkid(mob_id) == 0){
snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1250),mob_name); // Invalid mob id %s!
clif->message(fd, atcmd_output);
- return true;
+ return false;
}
- if(mob_db(mob_id)->status.mode&MD_BOSS && !pc_has_permission(sd, PC_PERM_SHOW_BOSS)){ // If player group does not have access to boss mobs.
+ if(mob->db(mob_id)->status.mode&MD_BOSS && !pc_has_permission(sd, PC_PERM_SHOW_BOSS)){ // If player group does not have access to boss mobs.
clif->message(fd, msg_txt(1251)); // Can't show boss mobs!
- return true;
+ return false;
}
- if(mob_id == atoi(mob_name) && mob_db(mob_id)->jname)
- strcpy(mob_name,mob_db(mob_id)->jname); // --ja--
+ if(mob_id == atoi(mob_name) && mob->db(mob_id)->jname)
+ strcpy(mob_name,mob->db(mob_id)->jname); // --ja--
//strcpy(mob_name,mob_db(mob_id)->name); // --en--
snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1252), // Mob Search... %s %s
@@ -6805,33 +6720,55 @@ ACMD(showmobs)
/*==========================================
* homunculus level up [orn]
*------------------------------------------*/
-ACMD(homlevel)
-{
+ACMD(homlevel) {
TBL_HOM * hd;
int level = 0;
+ enum homun_type htype;
- nullpo_retr(-1, sd);
-
- if ( !message || !*message || ( level = atoi(message) ) < 1 ) {
+ if( !message || !*message || ( level = atoi(message) ) < 1 ) {
clif->message(fd, msg_txt(1253)); // Please enter a level adjustment (usage: @homlevel <number of levels>).
return false;
}
- if ( !homun_alive(sd->hd) ) {
+ if( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
}
hd = sd->hd;
+
+ if( (htype = homun->class2type(hd->homunculus.class_)) == HT_INVALID ) {
+ ShowError("atcommand_homlevel: invalid homun class %d (player %s)\n", hd->homunculus.class_,sd->status.name);
+ return false;
+ }
+
+ switch( htype ) {
+ case HT_REG:
+ case HT_EVO:
+ if( hd->homunculus.level >= battle_config.hom_max_level ) {
+ snprintf(atcmd_output, sizeof(atcmd_output), msg_txt(1478), hd->homunculus.level); // Homun reached its maximum level of '%d'
+ clif->message(fd, atcmd_output);
+ return true;
+ }
+ break;
+ case HT_S:
+ if( hd->homunculus.level >= battle_config.hom_S_max_level ) {
+ snprintf(atcmd_output, sizeof(atcmd_output), msg_txt(1478), hd->homunculus.level); // Homun reached its maximum level of '%d'
+ clif->message(fd, atcmd_output);
+ return true;
+ }
+ break;
+ default:
+ ShowError("atcommand_homlevel: unknown htype '%d'\n",htype);
+ return false;
+ }
- if ( battle_config.hom_max_level == hd->homunculus.level ) // Already reach maximum level
- return true;
-
- do{
+
+ do {
hd->homunculus.exp += hd->exp_next;
} while( hd->homunculus.level < level && homun->levelup(hd) );
- status_calc_homunculus(hd,0);
+ status_calc_homunculus(hd,SCO_NONE);
status_percent_heal(&hd->bl, 100, 100);
clif->specialeffect(&hd->bl,568,AREA);
return true;
@@ -6842,8 +6779,6 @@ ACMD(homlevel)
*------------------------------------------*/
ACMD(homevolution)
{
- nullpo_retr(-1, sd);
-
if ( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
@@ -6860,14 +6795,13 @@ ACMD(homevolution)
ACMD(hommutate) {
int homun_id;
enum homun_type m_class, m_id;
- nullpo_retr(-1, sd);
- if (!homun_alive(sd->hd)) {
+ if( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
}
- if (!message || !*message) {
+ if( !message || !*message ) {
homun_id = 6048 + (rnd() % 4);
} else {
homun_id = atoi(message);
@@ -6876,7 +6810,7 @@ ACMD(hommutate) {
m_class = homun->class2type(sd->hd->homunculus.class_);
m_id = homun->class2type(homun_id);
- if (m_class != -1 && m_id != -1 && m_class == HT_EVO && m_id == HT_S && sd->hd->homunculus.level >= 99) {
+ if( m_class != HT_INVALID && m_id != HT_INVALID && m_class == HT_EVO && m_id == HT_S && sd->hd->homunculus.level >= 99 ) {
homun->mutate(sd->hd, homun_id);
} else {
clif->emotion(&sd->hd->bl, E_SWT);
@@ -6889,7 +6823,6 @@ ACMD(hommutate) {
*------------------------------------------*/
ACMD(makehomun) {
int homunid;
- nullpo_retr(-1, sd);
if (!message || !*message) {
clif->message(fd, msg_txt(1256)); // Please enter a homunculus ID (usage: @makehomun <homunculus id>).
@@ -6898,8 +6831,13 @@ ACMD(makehomun) {
homunid = atoi(message);
- if( homunid == -1 && sd->status.hom_id && !homun_alive(sd->hd) ) {
- homun->call(sd);
+ if( homunid == -1 && sd->status.hom_id && !(sd->hd && homun_alive(sd->hd)) ) {
+ if( !sd->hd )
+ homun->call(sd);
+ else if( sd->hd->homunculus.vaporize )
+ homun->ressurect(sd, 100, sd->bl.x, sd->bl.y);
+ else
+ homun->call(sd);
return true;
}
@@ -6924,9 +6862,7 @@ ACMD(makehomun) {
ACMD(homfriendly)
{
int friendly = 0;
-
- nullpo_retr(-1, sd);
-
+
if ( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
@@ -6951,9 +6887,7 @@ ACMD(homfriendly)
ACMD(homhungry)
{
int hungry = 0;
-
- nullpo_retr(-1, sd);
-
+
if ( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
@@ -6978,17 +6912,15 @@ ACMD(homhungry)
ACMD(homtalk)
{
char mes[100],temp[100];
-
- nullpo_retr(-1, sd);
-
+
if ( battle_config.min_chat_delay ) {
- if( DIFF_TICK(sd->cantalk_tick, iTimer->gettick()) > 0 )
+ if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 )
return true;
- sd->cantalk_tick = iTimer->gettick() + battle_config.min_chat_delay;
+ sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
if (sd->sc.count && //no "chatting" while muted.
- (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || sd->sc.data[SC__BLOODYLUST] ||
+ (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
@@ -7011,11 +6943,9 @@ ACMD(homtalk)
/*==========================================
* Show homunculus stats
*------------------------------------------*/
-ACMD(hominfo)
-{
+ACMD(hominfo) {
struct homun_data *hd;
- struct status_data *status;
- nullpo_retr(-1, sd);
+ struct status_data *st;
if ( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
@@ -7023,15 +6953,15 @@ ACMD(hominfo)
}
hd = sd->hd;
- status = status_get_status_data(&hd->bl);
+ st = status->get_status_data(&hd->bl);
clif->message(fd, msg_txt(1261)); // Homunculus stats:
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1262), // HP: %d/%d - SP: %d/%d
- status->hp, status->max_hp, status->sp, status->max_sp);
+ st->hp, st->max_hp, st->sp, st->max_sp);
clif->message(fd, atcmd_output);
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1263), // ATK: %d - MATK: %d~%d
- status->rhw.atk2 +status->batk, status->matk_min, status->matk_max);
+ st->rhw.atk2 +st->batk, st->matk_min, st->matk_max);
clif->message(fd, atcmd_output);
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1264), // Hungry: %d - Intimacy: %u
@@ -7040,8 +6970,8 @@ ACMD(hominfo)
snprintf(atcmd_output, sizeof(atcmd_output) ,
msg_txt(1265), // Stats: Str %d / Agi %d / Vit %d / Int %d / Dex %d / Luk %d
- status->str, status->agi, status->vit,
- status->int_, status->dex, status->luk);
+ st->str, st->agi, st->vit,
+ st->int_, st->dex, st->luk);
clif->message(fd, atcmd_output);
return true;
@@ -7053,9 +6983,7 @@ ACMD(homstats)
struct s_homunculus_db *db;
struct s_homunculus *hom;
int lv, min, max, evo;
-
- nullpo_retr(-1, sd);
-
+
if ( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
@@ -7117,7 +7045,6 @@ ACMD(homstats)
}
ACMD(homshuffle) {
- nullpo_retr(-1, sd);
if(!sd->hd)
return false; // nothing to do
@@ -7143,8 +7070,8 @@ ACMD(iteminfo)
clif->message(fd, msg_txt(1276)); // Please enter an item name/ID (usage: @ii/@iteminfo <item name/ID>).
return false;
}
- if ((item_array[0] = itemdb_exists(atoi(message))) == NULL)
- count = itemdb_searchname_array(item_array, MAX_SEARCH, message);
+ if ((item_array[0] = itemdb->exists(atoi(message))) == NULL)
+ count = itemdb->search_name_array(item_array, MAX_SEARCH, message, 0);
if (!count) {
clif->message(fd, msg_txt(19)); // Invalid item ID or name.
@@ -7160,7 +7087,7 @@ ACMD(iteminfo)
item_data = item_array[i];
sprintf(atcmd_output, msg_txt(1277), // Item: '%s'/'%s'[%d] (%d) Type: %s | Extra Effect: %s
item_data->name,item_data->jname,item_data->slot,item_data->nameid,
- itemdb_typename(item_data->type),
+ itemdb->typename(item_data->type),
(item_data->script==NULL)? msg_txt(1278) : msg_txt(1279) // None / With script
);
clif->message(fd, atcmd_output);
@@ -7170,10 +7097,12 @@ ACMD(iteminfo)
if (item_data->maxchance == -1)
strcpy(atcmd_output, msg_txt(1281)); // - Available in the shops only.
- else if (!battle_config.atcommand_mobinfo_type && item_data->maxchance)
- sprintf(atcmd_output, msg_txt(1282), (float)item_data->maxchance / 100 ); // - Maximal monsters drop chance: %02.02f%%
- else
- strcpy(atcmd_output, msg_txt(1283)); // - Monsters don't drop this item.
+ else if ( !battle_config.atcommand_mobinfo_type ) {
+ if( item_data->maxchance )
+ sprintf(atcmd_output, msg_txt(1282), (float)item_data->maxchance / 100 ); // - Maximal monsters drop chance: %02.02f%%
+ else
+ strcpy(atcmd_output, msg_txt(1283)); // - Monsters don't drop this item.
+ }
clif->message(fd, atcmd_output);
}
@@ -7192,8 +7121,8 @@ ACMD(whodrops)
clif->message(fd, msg_txt(1284)); // Please enter item name/ID (usage: @whodrops <item name/ID>).
return false;
}
- if ((item_array[0] = itemdb_exists(atoi(message))) == NULL)
- count = itemdb_searchname_array(item_array, MAX_SEARCH, message);
+ if ((item_array[0] = itemdb->exists(atoi(message))) == NULL)
+ count = itemdb->search_name_array(item_array, MAX_SEARCH, message, 0);
if (!count) {
clif->message(fd, msg_txt(19)); // Invalid item ID or name.
@@ -7219,7 +7148,7 @@ ACMD(whodrops)
for (j=0; j < MAX_SEARCH && item_data->mob[j].chance > 0; j++)
{
- sprintf(atcmd_output, "- %s (%02.02f%%)", mob_db(item_data->mob[j].id)->jname, item_data->mob[j].chance/100.);
+ sprintf(atcmd_output, "- %s (%02.02f%%)", mob->db(item_data->mob[j].id)->jname, item_data->mob[j].chance/100.);
clif->message(fd, atcmd_output);
}
}
@@ -7229,7 +7158,7 @@ ACMD(whodrops)
ACMD(whereis)
{
- struct mob_db *mob, *mob_array[MAX_SEARCH];
+ struct mob_db *monster, *mob_array[MAX_SEARCH];
int count;
int i, j, k;
@@ -7239,12 +7168,12 @@ ACMD(whereis)
}
// If monster identifier/name argument is a name
- if ((i = mobdb_checkid(atoi(message))))
+ if ((i = mob->db_checkid(atoi(message))))
{
- mob_array[0] = mob_db(i);
+ mob_array[0] = mob->db(i);
count = 1;
} else
- count = mobdb_searchname_array(mob_array, MAX_SEARCH, message);
+ count = mob->db_searchname_array(mob_array, MAX_SEARCH, message, 0);
if (!count) {
clif->message(fd, msg_txt(40)); // Invalid monster ID or name.
@@ -7257,15 +7186,14 @@ ACMD(whereis)
count = MAX_SEARCH;
}
for (k = 0; k < count; k++) {
- mob = mob_array[k];
- snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1289), mob->jname); // %s spawns in:
+ monster = mob_array[k];
+ snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1289), monster->jname); // %s spawns in:
clif->message(fd, atcmd_output);
- for (i = 0; i < ARRAYLENGTH(mob->spawn) && mob->spawn[i].qty; i++)
- {
- j = iMap->mapindex2mapid(mob->spawn[i].mapindex);
+ for (i = 0; i < ARRAYLENGTH(monster->spawn) && monster->spawn[i].qty; i++) {
+ j = map->mapindex2mapid(monster->spawn[i].mapindex);
if (j < 0) continue;
- snprintf(atcmd_output, sizeof atcmd_output, "%s (%d)", map[j].name, mob->spawn[i].qty);
+ snprintf(atcmd_output, sizeof atcmd_output, "%s (%d)", map->list[j].name, monster->spawn[i].qty);
clif->message(fd, atcmd_output);
}
if (i == 0)
@@ -7276,26 +7204,19 @@ ACMD(whereis)
}
ACMD(version) {
- const char *git = get_git_hash();
- const char *svn = get_svn_revision();
-
- if ( git[0] != HERC_UNKNOWN_VER ) {
- sprintf(atcmd_output,msg_txt(1295),git); // Git Hash '%s'
- clif->message(fd,atcmd_output);
- } else if ( svn[0] != HERC_UNKNOWN_VER ) {
- sprintf(atcmd_output,msg_txt(1436),git); // SVN r%s
- clif->message(fd,atcmd_output);
- } else
- clif->message(fd,msg_txt(1296)); // Cannot determine version
-
+ sprintf(atcmd_output, msg_txt(1296), sysinfo->is64bit() ? 64 : 32, sysinfo->platform()); // Hercules %d-bit for %s
+ clif->message(fd, atcmd_output);
+ sprintf(atcmd_output, msg_txt(1295), sysinfo->vcstype(), sysinfo->vcsrevision_src(), sysinfo->vcsrevision_scripts()); // %s revision '%s' (src) / '%s' (scripts)
+ clif->message(fd, atcmd_output);
+
return true;
}
/*==========================================
* @mutearea by MouseJstr
*------------------------------------------*/
-static int atcommand_mutearea_sub(struct block_list *bl,va_list ap)
-{
+int atcommand_mutearea_sub(struct block_list *bl,va_list ap)
+{ // As it is being used [ACMD(mutearea)] there's no need to be a bool, but if there's need to reuse it, it's better to be this way
int time, id;
struct map_session_data *pl_sd = (struct map_session_data *)bl;
@@ -7305,20 +7226,18 @@ static int atcommand_mutearea_sub(struct block_list *bl,va_list ap)
id = va_arg(ap, int);
time = va_arg(ap, int);
- if (id != bl->id && !pc->get_group_level(pl_sd)) {
+ if (id != bl->id && !pc_get_group_level(pl_sd)) {
pl_sd->status.manner -= time;
if (pl_sd->status.manner < 0)
- sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0);
+ sc_start(NULL,&pl_sd->bl,SC_NOCHAT,100,0,0);
else
status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER);
}
- return 0;
+ return 1;
}
-ACMD(mutearea)
-{
+ACMD(mutearea) {
int time;
- nullpo_ret(sd);
if (!message || !*message) {
clif->message(fd, msg_txt(1297)); // Please enter a time in minutes (usage: @mutearea/@stfu <time in minutes>).
@@ -7327,9 +7246,9 @@ ACMD(mutearea)
time = atoi(message);
- iMap->foreachinarea(atcommand_mutearea_sub,sd->bl.m,
- sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE,
- sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd->bl.id, time);
+ map->foreachinarea(atcommand->mutearea_sub,sd->bl.m,
+ sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE,
+ sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd->bl.id, time);
return true;
}
@@ -7339,7 +7258,6 @@ ACMD(rates)
{
char buf[CHAT_SIZE_MAX];
- nullpo_ret(sd);
memset(buf, '\0', sizeof(buf));
snprintf(buf, CHAT_SIZE_MAX, msg_txt(1298), // Experience rates: Base %.2fx / Job %.2fx
@@ -7365,13 +7283,12 @@ ACMD(rates)
ACMD(me)
{
char tempmes[CHAT_SIZE_MAX];
- nullpo_retr(-1, sd);
memset(tempmes, '\0', sizeof(tempmes));
memset(atcmd_output, '\0', sizeof(atcmd_output));
if (sd->sc.count && //no "chatting" while muted.
- (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || sd->sc.data[SC__BLOODYLUST] ||
+ (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
@@ -7394,17 +7311,16 @@ ACMD(me)
ACMD(size)
{
int size = 0;
- nullpo_retr(-1, sd);
- size = cap_value(atoi(message),SZ_SMALL,SZ_BIG);
+ size = cap_value(atoi(message),SZ_MEDIUM,SZ_BIG);
if(sd->state.size) {
- sd->state.size = SZ_SMALL;
+ sd->state.size = SZ_MEDIUM;
pc->setpos(sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_TELEPORT);
}
sd->state.size = size;
- if( size == SZ_MEDIUM )
+ if( size == SZ_SMALL )
clif->specialeffect(&sd->bl,420,AREA);
else if( size == SZ_BIG )
clif->specialeffect(&sd->bl,422,AREA);
@@ -7426,12 +7342,12 @@ ACMD(sizeall)
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) {
if( pl_sd->state.size != size ) {
if( pl_sd->state.size ) {
- pl_sd->state.size = SZ_SMALL;
+ pl_sd->state.size = SZ_MEDIUM;
pc->setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT);
}
pl_sd->state.size = size;
- if( size == SZ_MEDIUM )
+ if( size == SZ_SMALL )
clif->specialeffect(&pl_sd->bl,420,AREA);
else if( size == SZ_BIG )
clif->specialeffect(&pl_sd->bl,422,AREA);
@@ -7449,7 +7365,6 @@ ACMD(sizeguild)
char guild_name[NAME_LENGTH];
struct map_session_data *pl_sd;
struct guild *g;
- nullpo_retr(-1, sd);
memset(guild_name, '\0', sizeof(guild_name));
@@ -7463,17 +7378,17 @@ ACMD(sizeguild)
return false;
}
- size = cap_value(size,SZ_SMALL,SZ_BIG);
+ size = cap_value(size,SZ_MEDIUM,SZ_BIG);
for( i = 0; i < g->max_member; i++ ) {
if( (pl_sd = g->member[i].sd) && pl_sd->state.size != size ) {
if( pl_sd->state.size ) {
- pl_sd->state.size = SZ_SMALL;
+ pl_sd->state.size = SZ_MEDIUM;
pc->setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT);
}
pl_sd->state.size = size;
- if( size == SZ_MEDIUM )
+ if( size == SZ_SMALL )
clif->specialeffect(&pl_sd->bl,420,AREA);
else if( size == SZ_BIG )
clif->specialeffect(&pl_sd->bl,422,AREA);
@@ -7488,9 +7403,7 @@ ACMD(sizeguild)
* @monsterignore
* => Makes monsters ignore you. [Valaris]
*------------------------------------------*/
-ACMD(monsterignore)
-{
- nullpo_retr(-1, sd);
+ACMD(monsterignore) {
if (!sd->state.monster_ignore) {
sd->state.monster_ignore = 1;
@@ -7506,9 +7419,7 @@ ACMD(monsterignore)
* @fakename
* => Gives your character a fake name. [Valaris]
*------------------------------------------*/
-ACMD(fakename)
-{
- nullpo_retr(-1, sd);
+ACMD(fakename){
if( !message || !*message )
{
@@ -7516,6 +7427,8 @@ ACMD(fakename)
{
sd->fakename[0] = '\0';
clif->charnameack(0, &sd->bl);
+ if( sd->disguise )
+ clif->charnameack(sd->fd, &sd->bl);
clif->message(sd->fd, msg_txt(1307)); // Returned to real name.
return true;
}
@@ -7532,6 +7445,8 @@ ACMD(fakename)
safestrncpy(sd->fakename, message, sizeof(sd->fakename));
clif->charnameack(0, &sd->bl);
+ if( sd->disguise ) // Another packet should be sent so the client updates the name for sd
+ clif->charnameack(sd->fd, &sd->bl);
clif->message(sd->fd, msg_txt(1310)); // Fake name enabled.
return true;
@@ -7541,70 +7456,74 @@ ACMD(fakename)
* Ragnarok Resources
*------------------------------------------*/
ACMD(mapflag) {
-#define checkflag( cmd ) if ( map[ sd->bl.m ].flag.cmd ) clif->message(sd->fd,#cmd)
-#define setflag( cmd ) \
-if ( strcmp( flag_name , #cmd ) == 0 ){\
-map[ sd->bl.m ].flag.cmd = flag;\
-sprintf(atcmd_output,"[ @mapflag ] %s flag has been set to %s value = %hd",#cmd,flag?"On":"Off",flag);\
-clif->message(sd->fd,atcmd_output);\
-return true;\
-}
+#define CHECKFLAG( cmd ) do { if ( map->list[ sd->bl.m ].flag.cmd ) clif->message(sd->fd,#cmd); } while(0)
+#define SETFLAG( cmd ) do { \
+ if ( strcmp( flag_name , #cmd ) == 0 ) { \
+ map->list[ sd->bl.m ].flag.cmd = flag; \
+ sprintf(atcmd_output,"[ @mapflag ] %s flag has been set to %s value = %hd",#cmd,flag?"On":"Off",flag); \
+ clif->message(sd->fd,atcmd_output); \
+ return true; \
+ } \
+} while(0)
+
char flag_name[100];
short flag=0,i;
- nullpo_retr(-1, sd);
+
memset(flag_name, '\0', sizeof(flag_name));
if (!message || !*message || (sscanf(message, "%99s %hd", flag_name, &flag) < 1)) {
clif->message(sd->fd,msg_txt(1311)); // Enabled Mapflags in this map:
clif->message(sd->fd,"----------------------------------");
- checkflag(autotrade); checkflag(allowks); checkflag(nomemo); checkflag(noteleport);
- checkflag(noreturn); checkflag(monster_noteleport); checkflag(nosave); checkflag(nobranch);
- checkflag(noexppenalty); checkflag(pvp); checkflag(pvp_noparty); checkflag(pvp_noguild);
- checkflag(pvp_nightmaredrop); checkflag(pvp_nocalcrank); checkflag(gvg_castle); checkflag(gvg);
- checkflag(gvg_dungeon); checkflag(gvg_noparty); checkflag(battleground);checkflag(nozenypenalty);
- checkflag(notrade); checkflag(noskill); checkflag(nowarp); checkflag(nowarpto);
- checkflag(noicewall); checkflag(snow); checkflag(clouds); checkflag(clouds2);
- checkflag(fog); checkflag(fireworks); checkflag(sakura); checkflag(leaves);
- checkflag(nobaseexp);
- checkflag(nojobexp); checkflag(nomobloot); checkflag(nomvploot); checkflag(nightenabled);
- checkflag(nodrop); checkflag(novending); checkflag(loadevent);
- checkflag(nochat); checkflag(partylock); checkflag(guildlock); checkflag(src4instance);
+ CHECKFLAG(autotrade); CHECKFLAG(allowks); CHECKFLAG(nomemo); CHECKFLAG(noteleport);
+ CHECKFLAG(noreturn); CHECKFLAG(monster_noteleport); CHECKFLAG(nosave); CHECKFLAG(nobranch);
+ CHECKFLAG(noexppenalty); CHECKFLAG(pvp); CHECKFLAG(pvp_noparty); CHECKFLAG(pvp_noguild);
+ CHECKFLAG(pvp_nightmaredrop); CHECKFLAG(pvp_nocalcrank); CHECKFLAG(gvg_castle); CHECKFLAG(gvg);
+ CHECKFLAG(gvg_dungeon); CHECKFLAG(gvg_noparty); CHECKFLAG(battleground); CHECKFLAG(nozenypenalty);
+ CHECKFLAG(notrade); CHECKFLAG(noskill); CHECKFLAG(nowarp); CHECKFLAG(nowarpto);
+ CHECKFLAG(noicewall); CHECKFLAG(snow); CHECKFLAG(clouds); CHECKFLAG(clouds2);
+ CHECKFLAG(fog); CHECKFLAG(fireworks); CHECKFLAG(sakura); CHECKFLAG(leaves);
+ CHECKFLAG(nobaseexp);
+ CHECKFLAG(nojobexp); CHECKFLAG(nomobloot); CHECKFLAG(nomvploot); CHECKFLAG(nightenabled);
+ CHECKFLAG(nodrop); CHECKFLAG(novending); CHECKFLAG(loadevent);
+ CHECKFLAG(nochat); CHECKFLAG(partylock); CHECKFLAG(guildlock); CHECKFLAG(src4instance);
+ CHECKFLAG(notomb); CHECKFLAG(nocashshop);
clif->message(sd->fd," ");
clif->message(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On)
clif->message(sd->fd,msg_txt(1313)); // Type "@mapflag available" to list the available mapflags.
- return 1;
+ return true;
}
- for (i = 0; flag_name[i]; i++) flag_name[i] = (char)tolower(flag_name[i]); //lowercase
+ for (i = 0; flag_name[i]; i++) flag_name[i] = TOLOWER(flag_name[i]); //lowercase
if ( strcmp( flag_name , "gvg" ) == 0 ) {
- if( flag && !map[sd->bl.m].flag.gvg )
- iMap->zone_change2(sd->bl.m,strdb_get(zone_db, MAP_ZONE_GVG_NAME));
- else if ( !flag && map[sd->bl.m].flag.gvg )
- iMap->zone_change2(sd->bl.m,map[sd->bl.m].prev_zone);
+ if( flag && !map->list[sd->bl.m].flag.gvg )
+ map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_GVG_NAME));
+ else if ( !flag && map->list[sd->bl.m].flag.gvg )
+ map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
} else if ( strcmp( flag_name , "pvp" ) == 0 ) {
- if( flag && !map[sd->bl.m].flag.pvp )
- iMap->zone_change2(sd->bl.m,strdb_get(zone_db, MAP_ZONE_PVP_NAME));
- else if ( !flag && map[sd->bl.m].flag.pvp )
- iMap->zone_change2(sd->bl.m,map[sd->bl.m].prev_zone);
+ if( flag && !map->list[sd->bl.m].flag.pvp )
+ map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_PVP_NAME));
+ else if ( !flag && map->list[sd->bl.m].flag.pvp )
+ map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
} else if ( strcmp( flag_name , "battleground" ) == 0 ) {
- if( flag && !map[sd->bl.m].flag.battleground )
- iMap->zone_change2(sd->bl.m,strdb_get(zone_db, MAP_ZONE_BG_NAME));
- else if ( !flag && map[sd->bl.m].flag.battleground )
- iMap->zone_change2(sd->bl.m,map[sd->bl.m].prev_zone);
- }
-
- setflag(autotrade); setflag(allowks); setflag(nomemo); setflag(noteleport);
- setflag(noreturn); setflag(monster_noteleport);setflag(nosave); setflag(nobranch);
- setflag(noexppenalty); setflag(pvp); setflag(pvp_noparty); setflag(pvp_noguild);
- setflag(pvp_nightmaredrop); setflag(pvp_nocalcrank); setflag(gvg_castle); setflag(gvg);
- setflag(gvg_dungeon); setflag(gvg_noparty); setflag(battleground); setflag(nozenypenalty);
- setflag(notrade); setflag(noskill); setflag(nowarp); setflag(nowarpto);
- setflag(noicewall); setflag(snow); setflag(clouds); setflag(clouds2);
- setflag(fog); setflag(fireworks); setflag(sakura); setflag(leaves);
- setflag(nobaseexp);
- setflag(nojobexp); setflag(nomobloot); setflag(nomvploot); setflag(nightenabled);
- setflag(nodrop); setflag(novending); setflag(loadevent);
- setflag(nochat); setflag(partylock); setflag(guildlock); setflag(src4instance);
+ if( flag && !map->list[sd->bl.m].flag.battleground )
+ map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_BG_NAME));
+ else if ( !flag && map->list[sd->bl.m].flag.battleground )
+ map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
+ }
+
+ SETFLAG(autotrade); SETFLAG(allowks); SETFLAG(nomemo); SETFLAG(noteleport);
+ SETFLAG(noreturn); SETFLAG(monster_noteleport); SETFLAG(nosave); SETFLAG(nobranch);
+ SETFLAG(noexppenalty); SETFLAG(pvp); SETFLAG(pvp_noparty); SETFLAG(pvp_noguild);
+ SETFLAG(pvp_nightmaredrop); SETFLAG(pvp_nocalcrank); SETFLAG(gvg_castle); SETFLAG(gvg);
+ SETFLAG(gvg_dungeon); SETFLAG(gvg_noparty); SETFLAG(battleground); SETFLAG(nozenypenalty);
+ SETFLAG(notrade); SETFLAG(noskill); SETFLAG(nowarp); SETFLAG(nowarpto);
+ SETFLAG(noicewall); SETFLAG(snow); SETFLAG(clouds); SETFLAG(clouds2);
+ SETFLAG(fog); SETFLAG(fireworks); SETFLAG(sakura); SETFLAG(leaves);
+ SETFLAG(nobaseexp);
+ SETFLAG(nojobexp); SETFLAG(nomobloot); SETFLAG(nomvploot); SETFLAG(nightenabled);
+ SETFLAG(nodrop); SETFLAG(novending); SETFLAG(loadevent);
+ SETFLAG(nochat); SETFLAG(partylock); SETFLAG(guildlock); SETFLAG(src4instance);
+ SETFLAG(notomb); SETFLAG(nocashshop);
clif->message(sd->fd,msg_txt(1314)); // Invalid flag name or flag.
clif->message(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On)
@@ -7616,10 +7535,10 @@ return true;\
clif->message(sd->fd,"nozenypenalty, notrade, noskill, nowarp, nowarpto, noicewall, snow, clouds, clouds2,");
clif->message(sd->fd,"fog, fireworks, sakura, leaves, nobaseexp, nojobexp, nomobloot,");
clif->message(sd->fd,"nomvploot, nightenabled, nodrop, novending, loadevent, nochat, partylock,");
- clif->message(sd->fd,"guildlock, src4instance");
+ clif->message(sd->fd,"guildlock, src4instance, notomb, nocashshop");
-#undef checkflag
-#undef setflag
+#undef CHECKFLAG
+#undef SETFLAG
return true;
}
@@ -7675,157 +7594,154 @@ ACMD(showdelay)
* @reject - reject invitation
* @leave - leave duel
*------------------------------------------*/
-ACMD(invite)
-{
+ACMD(invite) {
unsigned int did = sd->duel_group;
- struct map_session_data *target_sd = iMap->nick2sd((char *)message);
+ struct map_session_data *target_sd = map->nick2sd((char *)message);
- if(did == 0) {
+ if(did == 0)
+ {
// "Duel: @invite without @duel."
clif->message(fd, msg_txt(350));
- return true;
+ return false;
}
- if(duel_list[did].max_players_limit > 0 &&
- duel_list[did].members_count >= duel_list[did].max_players_limit) {
+ if(duel->list[did].max_players_limit > 0 &&
+ duel->list[did].members_count >= duel->list[did].max_players_limit) {
// "Duel: Limit of players is reached."
clif->message(fd, msg_txt(351));
- return true;
+ return false;
}
if(target_sd == NULL) {
// "Duel: Player not found."
clif->message(fd, msg_txt(352));
- return true;
+ return false;
}
if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) {
// "Duel: Player already in duel."
clif->message(fd, msg_txt(353));
- return true;
+ return false;
}
if(battle_config.duel_only_on_same_map && target_sd->bl.m != sd->bl.m)
{
+ // "Duel: You can't invite %s because he/she isn't in the same map."
sprintf(atcmd_output, msg_txt(364), message);
clif->message(fd, atcmd_output);
- return true;
+ return false;
}
- duel_invite(did, sd, target_sd);
+ duel->invite(did, sd, target_sd);
// "Duel: Invitation has been sent."
clif->message(fd, msg_txt(354));
return true;
}
-ACMD(duel)
-{
+ACMD(duel) {
unsigned int maxpl = 0;
if(sd->duel_group > 0) {
- duel_showinfo(sd->duel_group, sd);
+ duel->showinfo(sd->duel_group, sd);
return true;
}
if(sd->duel_invite > 0) {
// "Duel: @duel without @reject."
clif->message(fd, msg_txt(355));
- return true;
+ return false;
}
- if(!duel_checktime(sd)) {
+ if(!duel->checktime(sd)) {
char output[CHAT_SIZE_MAX];
// "Duel: You can take part in duel only one time per %d minutes."
sprintf(output, msg_txt(356), battle_config.duel_time_interval);
clif->message(fd, output);
- return true;
+ return false;
}
if( message[0] ) {
if(sscanf(message, "%d", &maxpl) >= 1) {
if(maxpl < 2 || maxpl > 65535) {
clif->message(fd, msg_txt(357)); // "Duel: Invalid value."
- return true;
+ return false;
}
- duel_create(sd, maxpl);
+ duel->create(sd, maxpl);
} else {
struct map_session_data *target_sd;
- target_sd = iMap->nick2sd((char *)message);
+ target_sd = map->nick2sd((char *)message);
if(target_sd != NULL) {
unsigned int newduel;
- if((newduel = duel_create(sd, 2)) != -1) {
+ if((newduel = duel->create(sd, 2)) != -1) {
if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) {
clif->message(fd, msg_txt(353)); // "Duel: Player already in duel."
- return true;
+ return false;
}
- duel_invite(newduel, sd, target_sd);
+ duel->invite(newduel, sd, target_sd);
clif->message(fd, msg_txt(354)); // "Duel: Invitation has been sent."
}
} else {
// "Duel: Player not found."
clif->message(fd, msg_txt(352));
- return true;
+ return false;
}
}
} else
- duel_create(sd, 0);
+ duel->create(sd, 0);
return true;
}
-ACMD(leave)
-{
+ACMD(leave) {
if(sd->duel_group <= 0) {
// "Duel: @leave without @duel."
clif->message(fd, msg_txt(358));
- return true;
+ return false;
}
- duel_leave(sd->duel_group, sd);
+ duel->leave(sd->duel_group, sd);
clif->message(fd, msg_txt(359)); // "Duel: You left the duel."
return true;
}
-ACMD(accept)
-{
- if(!duel_checktime(sd)) {
+ACMD(accept) {
+ if(!duel->checktime(sd)) {
char output[CHAT_SIZE_MAX];
// "Duel: You can take part in duel only one time per %d minutes."
sprintf(output, msg_txt(356), battle_config.duel_time_interval);
clif->message(fd, output);
- return true;
+ return false;
}
if(sd->duel_invite <= 0) {
- // "Duel: @accept without invititation."
+ // "Duel: @accept without invitation."
clif->message(fd, msg_txt(360));
- return true;
+ return false;
}
- if( duel_list[sd->duel_invite].max_players_limit > 0 && duel_list[sd->duel_invite].members_count >= duel_list[sd->duel_invite].max_players_limit )
- {
+ if( duel->list[sd->duel_invite].max_players_limit > 0
+ && duel->list[sd->duel_invite].members_count >= duel->list[sd->duel_invite].max_players_limit ) {
// "Duel: Limit of players is reached."
clif->message(fd, msg_txt(351));
- return true;
+ return false;
}
- duel_accept(sd->duel_invite, sd);
+ duel->accept(sd->duel_invite, sd);
// "Duel: Invitation has been accepted."
clif->message(fd, msg_txt(361));
return true;
}
-ACMD(reject)
-{
+ACMD(reject) {
if(sd->duel_invite <= 0) {
- // "Duel: @reject without invititation."
+ // "Duel: @reject without invitation."
clif->message(fd, msg_txt(362));
- return true;
+ return false;
}
- duel_reject(sd->duel_invite, sd);
+ duel->reject(sd->duel_invite, sd);
// "Duel: Invitation has been rejected."
clif->message(fd, msg_txt(363));
return true;
@@ -7839,43 +7755,45 @@ ACMD(cash)
char output[128];
int value;
int ret=0;
- nullpo_retr(-1, sd);
if( !message || !*message || (value = atoi(message)) == 0 ) {
clif->message(fd, msg_txt(1322)); // Please enter an amount.
return false;
}
- if( !strcmpi(command+1,"cash") )
- {
+ if( !strcmpi(info->command,"cash") ) {
if( value > 0 ) {
if( (ret=pc->getcash(sd, value, 0)) >= 0){
- sprintf(output, msg_txt(505), ret, sd->cashPoints);
- clif->disp_onlyself(sd, output, strlen(output));
- }
- else clif->message(fd, msg_txt(149)); // Unable to decrease the number/value.
+ // If this option is set, the message is already sent by pc function
+ if( !battle_config.cashshop_show_points ){
+ sprintf(output, msg_txt(505), ret, sd->cashPoints);
+ clif_disp_onlyself(sd, output, strlen(output));
+ }
+ } else
+ clif->message(fd, msg_txt(149)); // Unable to decrease the number/value.
} else {
if( (ret=pc->paycash(sd, -value, 0)) >= 0){
sprintf(output, msg_txt(410), ret, sd->cashPoints);
- clif->disp_onlyself(sd, output, strlen(output));
- }
- else clif->message(fd, msg_txt(41)); // Unable to decrease the number/value.
+ clif_disp_onlyself(sd, output, strlen(output));
+ } else
+ clif->message(fd, msg_txt(41)); // Unable to decrease the number/value.
}
- }
- else
- { // @points
+ } else { // @points
if( value > 0 ) {
- if( (ret=pc->getcash(sd, 0, value)) >= 0){
- sprintf(output, msg_txt(506), ret, sd->kafraPoints);
- clif->disp_onlyself(sd, output, strlen(output));
- }
- else clif->message(fd, msg_txt(149)); // Unable to decrease the number/value.
+ if( (ret=pc->getcash(sd, 0, value)) >= 0) {
+ // If this option is set, the message is already sent by pc function
+ if( !battle_config.cashshop_show_points ){
+ sprintf(output, msg_txt(506), ret, sd->kafraPoints);
+ clif_disp_onlyself(sd, output, strlen(output));
+ }
+ } else
+ clif->message(fd, msg_txt(149)); // Unable to decrease the number/value.
} else {
if( (ret=pc->paycash(sd, -value, -value)) >= 0){
sprintf(output, msg_txt(411), ret, sd->kafraPoints);
- clif->disp_onlyself(sd, output, strlen(output));
- }
- else clif->message(fd, msg_txt(41)); // Unable to decrease the number/value.
+ clif_disp_onlyself(sd, output, strlen(output));
+ } else
+ clif->message(fd, msg_txt(41)); // Unable to decrease the number/value.
}
}
@@ -7883,58 +7801,58 @@ ACMD(cash)
}
// @clone/@slaveclone/@evilclone <playername> [Valaris]
-ACMD(clone)
-{
+ACMD(clone) {
int x=0,y=0,flag=0,master=0,i=0;
struct map_session_data *pl_sd=NULL;
if (!message || !*message) {
clif->message(sd->fd,msg_txt(1323)); // You must enter a player name or ID.
- return true;
+ return false;
}
- if((pl_sd=iMap->nick2sd((char *)message)) == NULL && (pl_sd=iMap->charid2sd(atoi(message))) == NULL) {
+ if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_txt(3)); // Character not found.
- return true;
+ return false;
}
- if(pc->get_group_level(pl_sd) > pc->get_group_level(sd)) {
+ if(pc_get_group_level(pl_sd) > pc_get_group_level(sd)) {
clif->message(fd, msg_txt(126)); // Cannot clone a player of higher GM level than yourself.
- return true;
+ return false;
}
- if (strcmpi(command+1, "clone") == 0)
+ if (strcmpi(info->command, "clone") == 0)
flag = 1;
- else if (strcmpi(command+1, "slaveclone") == 0) {
+ else if (strcmpi(info->command, "slaveclone") == 0) {
flag = 2;
if(pc_isdead(sd)){
+ //"Unable to spawn slave clone."
clif->message(fd, msg_txt(129+flag*2));
- return true;
+ return false;
}
master = sd->bl.id;
if (battle_config.atc_slave_clone_limit
- && mob_countslave(&sd->bl) >= battle_config.atc_slave_clone_limit) {
+ && mob->countslave(&sd->bl) >= battle_config.atc_slave_clone_limit) {
clif->message(fd, msg_txt(127)); // You've reached your slave clones limit.
- return true;
+ return false;
}
}
do {
x = sd->bl.x + (rnd() % 10 - 5);
y = sd->bl.y + (rnd() % 10 - 5);
- } while (iMap->getcell(sd->bl.m,x,y,CELL_CHKNOPASS) && i++ < 10);
+ } while (map->getcell(sd->bl.m,x,y,CELL_CHKNOPASS) && i++ < 10);
if (i >= 10) {
x = sd->bl.x;
y = sd->bl.y;
}
- if((x = mob_clone_spawn(pl_sd, sd->bl.m, x, y, "", master, 0, flag?1:0, 0)) > 0) {
+ if((x = mob->clone_spawn(pl_sd, sd->bl.m, x, y, "", master, 0, flag?1:0, 0)) > 0) {
clif->message(fd, msg_txt(128+flag*2)); // Evil Clone spawned. Clone spawned. Slave clone spawned.
return true;
}
clif->message(fd, msg_txt(129+flag*2)); // Unable to spawn evil clone. Unable to spawn clone. Unable to spawn slave clone.
- return true;
+ return false;
}
/*=====================================
@@ -7966,8 +7884,8 @@ ACMD(request)
}
sprintf(atcmd_output, msg_txt(278), message); // (@request): %s
- intif_wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output);
- clif->disp_onlyself(sd, atcmd_output, strlen(atcmd_output));
+ intif->wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output);
+ clif_disp_onlyself(sd, atcmd_output, strlen(atcmd_output));
clif->message(sd->fd,msg_txt(279)); // @request sent.
return true;
}
@@ -7986,9 +7904,12 @@ ACMD(feelreset)
/*==========================================
* AUCTION SYSTEM
*------------------------------------------*/
-ACMD(auction)
-{
- nullpo_ret(sd);
+ACMD(auction) {
+
+ if( !battle_config.feature_auction ) {
+ clif->colormes(sd->fd,COLOR_RED,msg_txt(1484));
+ return false;
+ }
clif->auction_openwindow(sd);
@@ -8000,8 +7921,6 @@ ACMD(auction)
*------------------------------------------*/
ACMD(ksprotection)
{
- nullpo_retr(-1,sd);
-
if( sd->state.noks ) {
sd->state.noks = 0;
clif->message(fd, msg_txt(1325)); // [ K.S Protection Inactive ]
@@ -8031,23 +7950,19 @@ ACMD(ksprotection)
/*==========================================
* Map Kill Steal Protection Setting
*------------------------------------------*/
-ACMD(allowks)
-{
- nullpo_retr(-1,sd);
+ACMD(allowks) {
- if( map[sd->bl.m].flag.allowks ) {
- map[sd->bl.m].flag.allowks = 0;
+ if( map->list[sd->bl.m].flag.allowks ) {
+ map->list[sd->bl.m].flag.allowks = 0;
clif->message(fd, msg_txt(1330)); // [ Map K.S Protection Active ]
} else {
- map[sd->bl.m].flag.allowks = 1;
+ map->list[sd->bl.m].flag.allowks = 1;
clif->message(fd, msg_txt(1331)); // [ Map K.S Protection Inactive ]
}
return true;
}
-ACMD(resetstat)
-{
- nullpo_retr(-1, sd);
+ACMD(resetstat) {
pc->resetstate(sd);
sprintf(atcmd_output, msg_txt(207), sd->status.name);
@@ -8055,9 +7970,7 @@ ACMD(resetstat)
return true;
}
-ACMD(resetskill)
-{
- nullpo_retr(-1,sd);
+ACMD(resetskill) {
pc->resetskill(sd,1);
sprintf(atcmd_output, msg_txt(206), sd->status.name);
@@ -8077,31 +7990,21 @@ ACMD(itemlist)
const struct item* items;
int size;
StringBuf buf;
-
- nullpo_retr(-1, sd);
-
- if( strcmp(command+1, "storagelist") == 0 )
- {
+
+ if( strcmpi(info->command, "storagelist") == 0 ) {
location = "storage";
items = sd->status.storage.items;
size = MAX_STORAGE;
- }
- else
- if( strcmp(command+1, "cartlist") == 0 )
- {
- location = "cart";
- items = sd->status.cart;
- size = MAX_CART;
- }
- else
- if( strcmp(command+1, "itemlist") == 0 )
- {
- location = "inventory";
- items = sd->status.inventory;
- size = MAX_INVENTORY;
- }
- else
- return 1;
+ } else if( strcmpi(info->command, "cartlist") == 0 ) {
+ location = "cart";
+ items = sd->status.cart;
+ size = MAX_CART;
+ } else if( strcmpi(info->command, "itemlist") == 0 ) {
+ location = "inventory";
+ items = sd->status.inventory;
+ size = MAX_INVENTORY;
+ } else
+ return false;
StrBuf->Init(&buf);
@@ -8112,7 +8015,7 @@ ACMD(itemlist)
const struct item* it = &items[i];
struct item_data* itd;
- if( it->nameid == 0 || (itd = itemdb_exists(it->nameid)) == NULL )
+ if( it->nameid == 0 || (itd = itemdb->exists(it->nameid)) == NULL )
continue;
counter += it->amount;
@@ -8130,8 +8033,7 @@ ACMD(itemlist)
else
StrBuf->Printf(&buf, "%d %s (%s, id: %d)", it->amount, itd->jname, itd->name, it->nameid);
- if( it->equip )
- {
+ if( it->equip ) {
char equipstr[CHAT_SIZE_MAX];
strcpy(equipstr, msg_txt(1333)); // | equipped:
if( it->equip & EQP_GARMENT )
@@ -8170,52 +8072,46 @@ ACMD(itemlist)
clif->message(fd, StrBuf->Value(&buf));
StrBuf->Clear(&buf);
- if( it->card[0] == CARD0_PET )
- {// pet egg
+ if( it->card[0] == CARD0_PET ) {
+ // pet egg
if (it->card[3])
StrBuf->Printf(&buf, msg_txt(1348), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, named)
else
StrBuf->Printf(&buf, msg_txt(1349), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, unnamed)
- }
- else
- if(it->card[0] == CARD0_FORGE)
- {// forged item
- StrBuf->Printf(&buf, msg_txt(1350), (unsigned int)MakeDWord(it->card[2], it->card[3]), it->card[1]>>8, it->card[1]&0x0f); // -> (crafted item, creator id: %u, star crumbs %d, element %d)
+ } else if(it->card[0] == CARD0_FORGE) {
+ // forged item
+ StrBuf->Printf(&buf, msg_txt(1350), (unsigned int)MakeDWord(it->card[2], it->card[3]), it->card[1]>>8, it->card[1]&0x0f); // -> (crafted item, creator id: %u, star crumbs %d, element %d)
+ } else if(it->card[0] == CARD0_CREATE) {
+ // created item
+ StrBuf->Printf(&buf, msg_txt(1351), (unsigned int)MakeDWord(it->card[2], it->card[3])); // -> (produced item, creator id: %u)
+ } else {
+ // normal item
+ int counter2 = 0;
+
+ for( j = 0; j < itd->slot; ++j ) {
+ struct item_data* card;
+
+ if( it->card[j] == 0 || (card = itemdb->exists(it->card[j])) == NULL )
+ continue;
+
+ counter2++;
+
+ if( counter2 == 1 )
+ StrBuf->AppendStr(&buf, msg_txt(1352)); // -> (card(s):
+
+ if( counter2 != 1 )
+ StrBuf->AppendStr(&buf, ", ");
+
+ StrBuf->Printf(&buf, "#%d %s (id: %d)", counter2, card->jname, card->nameid);
}
- else
- if(it->card[0] == CARD0_CREATE)
- {// created item
- StrBuf->Printf(&buf, msg_txt(1351), (unsigned int)MakeDWord(it->card[2], it->card[3])); // -> (produced item, creator id: %u)
- }
- else
- {// normal item
- int counter2 = 0;
-
- for( j = 0; j < itd->slot; ++j )
- {
- struct item_data* card;
-
- if( it->card[j] == 0 || (card = itemdb_exists(it->card[j])) == NULL )
- continue;
-
- counter2++;
-
- if( counter2 == 1 )
- StrBuf->AppendStr(&buf, msg_txt(1352)); // -> (card(s):
-
- if( counter2 != 1 )
- StrBuf->AppendStr(&buf, ", ");
-
- StrBuf->Printf(&buf, "#%d %s (id: %d)", counter2, card->jname, card->nameid);
- }
-
- if( counter2 > 0 )
- StrBuf->AppendStr(&buf, ")");
- }
+
+ if( counter2 > 0 )
+ StrBuf->AppendStr(&buf, ")");
+ }
if( StrBuf->Length(&buf) > 0 )
clif->message(fd, StrBuf->Value(&buf));
-
+
StrBuf->Clear(&buf);
}
@@ -8294,21 +8190,18 @@ ACMD(stats)
return true;
}
-ACMD(delitem)
-{
+ACMD(delitem) {
char item_name[100];
int nameid, amount = 0, total, idx;
struct item_data* id;
-
- nullpo_retr(-1, sd);
-
+
if( !message || !*message || ( sscanf(message, "\"%99[^\"]\" %d", item_name, &amount) < 2 && sscanf(message, "%99s %d", item_name, &amount) < 2 ) || amount < 1 )
{
clif->message(fd, msg_txt(1355)); // Please enter an item name/ID, a quantity, and a player name (usage: #delitem <player> <item_name_or_ID> <quantity>).
return false;
}
- if( ( id = itemdb_searchname(item_name) ) != NULL || ( id = itemdb_exists(atoi(item_name)) ) != NULL )
+ if( ( id = itemdb->search_name(item_name) ) != NULL || ( id = itemdb->exists(atoi(item_name)) ) != NULL )
{
nameid = id->nameid;
}
@@ -8321,13 +8214,12 @@ ACMD(delitem)
total = amount;
// delete items
- while( amount && ( idx = pc->search_inventory(sd, nameid) ) != -1 )
- {
+ while (amount && (idx = pc->search_inventory(sd, nameid)) != INDEX_NOT_FOUND) {
int delamount = ( amount < sd->status.inventory[idx].amount ) ? amount : sd->status.inventory[idx].amount;
if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET )
{// delete pet
- intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2]));
+ intif->delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2]));
}
pc->delitem(sd, idx, delamount, 0, 0, LOG_TYPE_COMMAND);
@@ -8360,17 +8252,15 @@ ACMD(delitem)
/*==========================================
* Custom Fonts
*------------------------------------------*/
-ACMD(font)
-{
+ACMD(font) {
int font_id;
- nullpo_retr(-1,sd);
font_id = atoi(message);
if( font_id == 0 )
{
- if( sd->user_font )
+ if( sd->status.font )
{
- sd->user_font = 0;
+ sd->status.font = 0;
clif->message(fd, msg_txt(1356)); // Returning to normal font.
clif->font(sd);
}
@@ -8382,9 +8272,9 @@ ACMD(font)
}
else if( font_id < 0 || font_id > 9 )
clif->message(fd, msg_txt(1359)); // Invalid font. Use a value from 0 to 9.
- else if( font_id != sd->user_font )
+ else if( font_id != sd->status.font )
{
- sd->user_font = font_id;
+ sd->status.font = font_id;
clif->font(sd);
clif->message(fd, msg_txt(1360)); // Font changed.
}
@@ -8397,7 +8287,7 @@ ACMD(font)
/*==========================================
* type: 1 = commands (@), 2 = charcommands (#)
*------------------------------------------*/
-static void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommandType type)
+void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommandType type)
{
char line_buff[CHATBOX_SIZE];
char* cur = line_buff;
@@ -8408,18 +8298,18 @@ static void atcommand_commands_sub(struct map_session_data* sd, const int fd, At
memset(line_buff,' ',CHATBOX_SIZE);
line_buff[CHATBOX_SIZE-1] = 0;
- clif->message(fd, msg_txt(273)); // "Commands available:"
+ clif->message(fd, msg_txt(273)); // "Available commands:"
for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) {
- unsigned int slen = 0;
+ size_t slen;
switch( type ) {
case COMMAND_CHARCOMMAND:
- if( cmd->char_groups[sd->group_pos] == 0 )
+ if( cmd->char_groups[pcg->get_idx(sd->group)] == 0 )
continue;
break;
case COMMAND_ATCOMMAND:
- if( cmd->at_groups[sd->group_pos] == 0 )
+ if( cmd->at_groups[pcg->get_idx(sd->group)] == 0 )
continue;
break;
default:
@@ -8457,7 +8347,7 @@ static void atcommand_commands_sub(struct map_session_data* sd, const int fd, At
*------------------------------------------*/
ACMD(commands)
{
- atcommand_commands_sub(sd, fd, COMMAND_ATCOMMAND);
+ atcommand->commands_sub(sd, fd, COMMAND_ATCOMMAND);
return true;
}
@@ -8466,16 +8356,21 @@ ACMD(commands)
*------------------------------------------*/
ACMD(charcommands)
{
- atcommand_commands_sub(sd, fd, COMMAND_CHARCOMMAND);
+ atcommand->commands_sub(sd, fd, COMMAND_CHARCOMMAND);
return true;
}
/* for new mounts */
ACMD(mount2) {
+ if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) ) {
+ clif->message(fd, msg_txt(1476)); // You are already mounting something else
+ return false;
+ }
+
clif->message(sd->fd,msg_txt(1362)); // NOTICE: If you crash with mount your LUA is outdated.
if( !(sd->sc.data[SC_ALL_RIDING]) ) {
clif->message(sd->fd,msg_txt(1363)); // You have mounted.
- sc_start(&sd->bl,SC_ALL_RIDING,100,0,-1);
+ sc_start(NULL,&sd->bl,SC_ALL_RIDING,100,0,-1);
} else {
clif->message(sd->fd,msg_txt(1364)); // You have released your mount.
status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER);
@@ -8495,7 +8390,7 @@ ACMD(accinfo) {
//remove const type
safestrncpy(query, message, NAME_LENGTH);
- intif_request_accinfo( sd->fd, sd->bl.id, pc->get_group_level(sd), query );
+ intif->request_accinfo( sd->fd, sd->bl.id, pc_get_group_level(sd), query );
return true;
}
@@ -8504,8 +8399,9 @@ ACMD(accinfo) {
ACMD(set) {
char reg[32], val[128];
struct script_data* data;
- int toset = 0, len;
+ int toset = 0;
bool is_str = false;
+ size_t len;
if( !message || !*message || (toset = sscanf(message, "%31s %128[^\n]s", reg, val)) < 1 ) {
clif->message(fd, msg_txt(1367)); // Usage: @set <variable name> <value>
@@ -8535,9 +8431,9 @@ ACMD(set) {
if( toset >= 2 ) {/* we only set the var if there is an val, otherwise we only output the value */
if( is_str )
- set_var(sd, reg, (void*) val);
+ script->set_var(sd, reg, (void*) val);
else
- set_var(sd, reg, (void*)__64BPTRSIZE((atoi(val))));
+ script->set_var(sd, reg, (void*)h64BPTRSIZE((atoi(val))));
}
@@ -8548,19 +8444,19 @@ ACMD(set) {
switch( reg[0] ) {
case '@':
- data->u.str = pc->readregstr(sd, add_str(reg));
+ data->u.str = pc->readregstr(sd, script->add_str(reg));
break;
case '$':
- data->u.str = mapreg_readregstr(add_str(reg));
+ data->u.str = mapreg->readregstr(script->add_str(reg));
break;
case '#':
if( reg[1] == '#' )
- data->u.str = pc_readaccountreg2str(sd, reg);// global
+ data->u.str = pc_readaccountreg2str(sd, script->add_str(reg));// global
else
- data->u.str = pc_readaccountregstr(sd, reg);// local
+ data->u.str = pc_readaccountregstr(sd, script->add_str(reg));// local
break;
default:
- data->u.str = pc_readglobalreg_str(sd, reg);
+ data->u.str = pc_readglobalreg_str(sd, script->add_str(reg));
break;
}
@@ -8577,19 +8473,19 @@ ACMD(set) {
data->type = C_INT;
switch( reg[0] ) {
case '@':
- data->u.num = pc->readreg(sd, add_str(reg));
+ data->u.num = pc->readreg(sd, script->add_str(reg));
break;
case '$':
- data->u.num = mapreg_readreg(add_str(reg));
+ data->u.num = mapreg->readreg(script->add_str(reg));
break;
case '#':
if( reg[1] == '#' )
- data->u.num = pc_readaccountreg2(sd, reg);// global
+ data->u.num = pc_readaccountreg2(sd, script->add_str(reg));// global
else
- data->u.num = pc_readaccountreg(sd, reg);// local
+ data->u.num = pc_readaccountreg(sd, script->add_str(reg));// local
break;
default:
- data->u.num = pc_readglobalreg(sd, reg);
+ data->u.num = pc_readglobalreg(sd, script->add_str(reg));
break;
}
@@ -8618,13 +8514,13 @@ ACMD(set) {
return true;
}
ACMD(reloadquestdb) {
- do_reload_quest();
+ quest->reload();
clif->message(fd, msg_txt(1377)); // Quest database has been reloaded.
return true;
}
ACMD(addperm) {
- int perm_size = ARRAYLENGTH(pc_g_permission_name);
- bool add = (strcmpi(command+1, "addperm") == 0) ? true : false;
+ int perm_size = pcg->permission_count;
+ bool add = (strcmpi(info->command, "addperm") == 0) ? true : false;
int i;
if( !message || !*message ) {
@@ -8632,37 +8528,37 @@ ACMD(addperm) {
clif->message(fd, atcmd_output);
clif->message(fd, msg_txt(1379)); // -- Permission List
for( i = 0; i < perm_size; i++ ) {
- sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name);
+ sprintf(atcmd_output,"- %s",pcg->permissions[i].name);
clif->message(fd, atcmd_output);
}
return false;
}
- ARR_FIND(0, perm_size, i, strcmpi(pc_g_permission_name[i].name, message) == 0);
+ ARR_FIND(0, perm_size, i, strcmpi(pcg->permissions[i].name, message) == 0);
if( i == perm_size ) {
sprintf(atcmd_output,msg_txt(1380),message); // '%s' is not a known permission.
clif->message(fd, atcmd_output);
clif->message(fd, msg_txt(1379)); // -- Permission List
for( i = 0; i < perm_size; i++ ) {
- sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name);
+ sprintf(atcmd_output,"- %s",pcg->permissions[i].name);
clif->message(fd, atcmd_output);
}
return false;
}
- if( add && (sd->permissions&pc_g_permission_name[i].permission) ) {
- sprintf(atcmd_output, msg_txt(1381),sd->status.name,pc_g_permission_name[i].name); // User '%s' already possesses the '%s' permission.
+ if( add && (sd->extra_temp_permissions&pcg->permissions[i].permission) ) {
+ sprintf(atcmd_output, msg_txt(1381),sd->status.name,pcg->permissions[i].name); // User '%s' already possesses the '%s' permission.
clif->message(fd, atcmd_output);
return false;
- } else if ( !add && !(sd->permissions&pc_g_permission_name[i].permission) ) {
- sprintf(atcmd_output, msg_txt(1382),sd->status.name,pc_g_permission_name[i].name); // User '%s' doesn't possess the '%s' permission.
+ } else if ( !add && !(sd->extra_temp_permissions&pcg->permissions[i].permission) ) {
+ sprintf(atcmd_output, msg_txt(1382),sd->status.name,pcg->permissions[i].name); // User '%s' doesn't possess the '%s' permission.
clif->message(fd, atcmd_output);
sprintf(atcmd_output,msg_txt(1383),sd->status.name); // -- User '%s' Permissions
clif->message(fd, atcmd_output);
for( i = 0; i < perm_size; i++ ) {
- if( sd->permissions&pc_g_permission_name[i].permission ) {
- sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name);
+ if( sd->extra_temp_permissions&pcg->permissions[i].permission ) {
+ sprintf(atcmd_output,"- %s",pcg->permissions[i].name);
clif->message(fd, atcmd_output);
}
}
@@ -8671,9 +8567,9 @@ ACMD(addperm) {
}
if( add )
- sd->permissions |= pc_g_permission_name[i].permission;
+ sd->extra_temp_permissions |= pcg->permissions[i].permission;
else
- sd->permissions &=~ pc_g_permission_name[i].permission;
+ sd->extra_temp_permissions &=~ pcg->permissions[i].permission;
sprintf(atcmd_output, msg_txt(1384),sd->status.name); // User '%s' permissions updated successfully. The changes are temporary.
@@ -8688,7 +8584,7 @@ ACMD(unloadnpcfile) {
return false;
}
- if( npc_unloadfile(message) )
+ if( npc->unloadfile(message) )
clif->message(fd, msg_txt(1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed.
else {
clif->message(fd, msg_txt(1387)); // File not found.
@@ -8697,10 +8593,11 @@ ACMD(unloadnpcfile) {
return true;
}
ACMD(cart) {
-#define MC_CART_MDFY(x,idx) \
-sd->status.skill[idx].id = x?MC_PUSHCART:0; \
-sd->status.skill[idx].lv = x?1:0; \
-sd->status.skill[idx].flag = x?1:0;
+#define MC_CART_MDFY(x,idx) do { \
+ sd->status.skill[idx].id = (x)?MC_PUSHCART:0; \
+ sd->status.skill[idx].lv = (x)?1:0; \
+ sd->status.skill[idx].flag = (x)?1:0; \
+} while(0)
int val = atoi(message);
bool need_skill = pc->checkskill(sd, MC_PUSHCART) ? false : true;
@@ -8739,32 +8636,40 @@ sd->status.skill[idx].flag = x?1:0;
}
/* [Ind/Hercules] */
ACMD(join) {
- struct hChSysCh *channel;
+ struct hChSysCh *channel = NULL;
char name[HCHSYS_NAME_LENGTH], pass[HCHSYS_NAME_LENGTH];
- if( !message || !*message || sscanf(message, "%s %s", name, pass) < 1 ) {
+ if (!message || !*message || sscanf(message, "%19s %19s", name, pass) < 1) {
sprintf(atcmd_output, msg_txt(1399),command); // Unknown Channel (usage: %s <#channel_name>)
clif->message(fd, atcmd_output);
return false;
}
if( hChSys.local && strcmpi(name + 1, hChSys.local_name) == 0 ) {
- if( !map[sd->bl.m].channel ) {
+ if( !map->list[sd->bl.m].channel ) {
clif->chsys_mjoin(sd);
- return true;
+ if( map->list[sd->bl.m].channel ) /* join might have refused, map has chatting capabilities disabled */
+ return true;
} else
- channel = map[sd->bl.m].channel;
+ channel = map->list[sd->bl.m].channel;
} else if( hChSys.ally && sd->status.guild_id && strcmpi(name + 1, hChSys.ally_name) == 0 ) {
struct guild *g = sd->guild;
if( !g ) return false;/* unlikely, but we wont let it crash anyway. */
- channel = (struct hChSysCh *)g->channel;
+ channel = g->channel;
} else if( !( channel = strdb_get(clif->channel_db, name + 1) ) ) {
sprintf(atcmd_output, msg_txt(1400),name,command); // Unknown Channel '%s' (usage: %s <#channel_name>)
clif->message(fd, atcmd_output);
return false;
}
+ if( !channel ) {
+ sprintf(atcmd_output, msg_txt(1400),name,command); // Unknown Channel '%s' (usage: %s <#channel_name>)
+ clif->message(fd, atcmd_output);
+ return false;
+ }
+
+
if( idb_exists(channel->users, sd->status.char_id) ) {
- sprintf(atcmd_output, msg_txt(1475),name); // You're already in the '%s' channel
+ sprintf(atcmd_output, msg_txt(1436),name); // You're already in the '%s' channel
clif->message(fd, atcmd_output);
return false;
}
@@ -8793,8 +8698,8 @@ ACMD(join) {
int i;
for (i = 0; i < MAX_GUILDALLIANCE; i++) {
if( g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id) ) ) {
- if( !(((struct hChSysCh*)sg->channel)->banned && idb_exists(((struct hChSysCh*)sg->channel)->banned, sd->status.account_id))) {
- clif->chsys_join((struct hChSysCh *)sg->channel,sd);
+ if( !(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id))) {
+ clif->chsys_join(sg->channel,sd);
}
}
}
@@ -8857,28 +8762,29 @@ static inline void atcmd_channel_help(int fd, const char *command, bool can_crea
/* [Ind/Hercules] */
ACMD(channel) {
struct hChSysCh *channel;
- char key[HCHSYS_NAME_LENGTH], sub1[HCHSYS_NAME_LENGTH], sub2[HCHSYS_NAME_LENGTH], sub3[HCHSYS_NAME_LENGTH];
+ char subcmd[HCHSYS_NAME_LENGTH], sub1[HCHSYS_NAME_LENGTH], sub2[HCHSYS_NAME_LENGTH], sub3[HCHSYS_NAME_LENGTH];
unsigned char k = 0;
sub1[0] = sub2[0] = sub3[0] = '\0';
- if( !message || !*message || sscanf(message, "%s %s %s %s", key, sub1, sub2, sub3) < 1 ) {
+ if (!message || !*message || sscanf(message, "%19s %19s %19s %19s", subcmd, sub1, sub2, sub3) < 1) {
atcmd_channel_help(fd,command,( hChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ));
return true;
}
- if( strcmpi(key,"create") == 0 && ( hChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) ) {
- if( sub1[0] != '#' ) {
+ if (strcmpi(subcmd,"create") == 0 && (hChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))) {
+ // sub1 = channel name; sub2 = password; sub3 = unused
+ if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
- } else if ( strlen(sub1) < 3 || strlen(sub1) > HCHSYS_NAME_LENGTH ) {
+ } else if (strlen(sub1) < 3 || strlen(sub1) > HCHSYS_NAME_LENGTH) {
sprintf(atcmd_output, msg_txt(1406), HCHSYS_NAME_LENGTH);// Channel length must be between 3 and %d
clif->message(fd, atcmd_output);
return false;
- } else if ( sub3[0] != '\0' ) {
+ } else if (sub3[0] != '\0') {
clif->message(fd, msg_txt(1408)); // Channel password may not contain spaces
return false;
}
- if( strcmpi(sub1 + 1,hChSys.local_name) == 0 || strcmpi(sub1 + 1,hChSys.ally_name) == 0 || strdb_exists(clif->channel_db, sub1 + 1) ) {
+ if (strcmpi(sub1 + 1,hChSys.local_name) == 0 || strcmpi(sub1 + 1,hChSys.ally_name) == 0 || strdb_exists(clif->channel_db, sub1 + 1)) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
@@ -8897,11 +8803,11 @@ ACMD(channel) {
}
clif->chsys_join(channel,sd);
-
- } else if ( strcmpi(key,"list") == 0 ) {
- if( sub1[0] != '\0' && strcmpi(sub1,"colors") == 0 ) {
+ } else if (strcmpi(subcmd,"list") == 0) {
+ // sub1 = list type; sub2 = unused; sub3 = unused
+ if (sub1[0] != '\0' && strcmpi(sub1,"colors") == 0) {
char mout[40];
- for( k = 0; k < hChSys.colors_count; k++ ) {
+ for (k = 0; k < hChSys.colors_count; k++) {
unsigned short msg_len = 1;
msg_len += sprintf(mout, "[ %s list colors ] : %s",command,hChSys.colors_name[k]);
@@ -8917,48 +8823,48 @@ ACMD(channel) {
DBIterator *iter = db_iterator(clif->channel_db);
bool show_all = pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ? true : false;
clif->message(fd, msg_txt(1410)); // -- Public Channels
- if( hChSys.local ) {
- sprintf(atcmd_output, msg_txt(1409), hChSys.local_name, map[sd->bl.m].channel ? db_size(map[sd->bl.m].channel->users) : 0);// - #%s ( %d users )
+ if (hChSys.local) {
+ sprintf(atcmd_output, msg_txt(1409), hChSys.local_name, map->list[sd->bl.m].channel ? db_size(map->list[sd->bl.m].channel->users) : 0);// - #%s ( %d users )
clif->message(fd, atcmd_output);
}
- if( hChSys.ally && sd->status.guild_id ) {
+ if (hChSys.ally && sd->status.guild_id) {
struct guild *g = sd->guild;
if( !g ) { dbi_destroy(iter); return false; }
- sprintf(atcmd_output, msg_txt(1409), hChSys.ally_name, db_size(((struct hChSysCh *)g->channel)->users));// - #%s ( %d users )
+ sprintf(atcmd_output, msg_txt(1409), hChSys.ally_name, db_size(g->channel->users));// - #%s ( %d users )
clif->message(fd, atcmd_output);
}
- for(channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter)) {
- if( show_all || channel->type == hChSys_PUBLIC || channel->type == hChSys_IRC ) {
+ for (channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter)) {
+ if (show_all || channel->type == hChSys_PUBLIC || channel->type == hChSys_IRC) {
sprintf(atcmd_output, msg_txt(1409), channel->name, db_size(channel->users));// - #%s ( %d users )
clif->message(fd, atcmd_output);
}
}
dbi_destroy(iter);
}
- } else if ( strcmpi(key,"setcolor") == 0 ) {
-
- if( sub1[0] != '#' ) {
+ } else if (strcmpi(subcmd,"setcolor") == 0) {
+ // sub1 = channel name; sub2 = color; sub3 = unused
+ if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) {
+ if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) {
+ if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
- for( k = 0; k < hChSys.colors_count; k++ ) {
- if( strcmpi(sub2,hChSys.colors_name[k]) == 0 )
+ for (k = 0; k < hChSys.colors_count; k++) {
+ if (strcmpi(sub2, hChSys.colors_name[k]) == 0)
break;
}
- if( k == hChSys.colors_count ) {
+ if (k == hChSys.colors_count) {
sprintf(atcmd_output, msg_txt(1411), sub2);// Unknown color '%s'
clif->message(fd, atcmd_output);
return false;
@@ -8966,104 +8872,113 @@ ACMD(channel) {
channel->color = k;
sprintf(atcmd_output, msg_txt(1413),sub1,hChSys.colors_name[k]);// '%s' channel color updated to '%s'
clif->message(fd, atcmd_output);
- } else if ( strcmpi(key,"leave") == 0 ) {
-
- if( sub1[0] != '#' ) {
+ } else if (strcmpi(subcmd,"leave") == 0) {
+ // sub1 = channel name; sub2 = unused; sub3 = unused
+ if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- for(k = 0; k < sd->channel_count; k++) {
- if( strcmpi(sub1+1,sd->channels[k]->name) == 0 )
+ for (k = 0; k < sd->channel_count; k++) {
+ if (strcmpi(sub1+1,sd->channels[k]->name) == 0)
break;
}
- if( k == sd->channel_count ) {
+ if (k == sd->channel_count) {
sprintf(atcmd_output, msg_txt(1425),sub1);// You're not part of the '%s' channel
clif->message(fd, atcmd_output);
return false;
}
- if( sd->channels[k]->type == hChSys_ALLY ) {
+ if (sd->channels[k]->type == hChSys_ALLY) {
do {
- for(k = 0; k < sd->channel_count; k++) {
- if( sd->channels[k]->type == hChSys_ALLY ) {
+ for (k = 0; k < sd->channel_count; k++) {
+ if (sd->channels[k]->type == hChSys_ALLY) {
clif->chsys_left(sd->channels[k],sd);
break;
}
}
- } while( k != sd->channel_count );
- } else
+ } while (k != sd->channel_count);
+ } else {
clif->chsys_left(sd->channels[k],sd);
+ }
sprintf(atcmd_output, msg_txt(1426),sub1); // You've left the '%s' channel
clif->message(fd, atcmd_output);
- } else if ( strcmpi(key,"bindto") == 0 ) {
-
- if( sub1[0] != '#' ) {
+ } else if (strcmpi(subcmd,"bindto") == 0) {
+ // sub1 = channel name; sub2 = unused; sub3 = unused
+ if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- for(k = 0; k < sd->channel_count; k++) {
- if( strcmpi(sub1+1,sd->channels[k]->name) == 0 )
+ for (k = 0; k < sd->channel_count; k++) {
+ if (strcmpi(sub1+1,sd->channels[k]->name) == 0)
break;
}
- if( k == sd->channel_count ) {
+ if (k == sd->channel_count) {
sprintf(atcmd_output, msg_txt(1425),sub1);// You're not part of the '%s' channel
clif->message(fd, atcmd_output);
return false;
}
sd->gcbind = sd->channels[k];
- sprintf(atcmd_output, msg_txt(1431),sub1); // Your global chat is now binded to the '%s' channel
+ sprintf(atcmd_output, msg_txt(1431),sub1); // Your global chat is now bound to the '%s' channel
clif->message(fd, atcmd_output);
- } else if ( strcmpi(key,"unbind") == 0 ) {
-
- if( sd->gcbind == NULL ) {
- clif->message(fd, msg_txt(1432));// Your global chat is not binded to any channel
+ } else if (strcmpi(subcmd,"unbind") == 0) {
+ // sub1 = unused; sub2 = unused; sub3 = unused
+ if (sd->gcbind == NULL) {
+ clif->message(fd, msg_txt(1432));// Your global chat is not bound to any channel
return false;
}
- sprintf(atcmd_output, msg_txt(1433),sd->gcbind->name); // Your global chat is now unbinded from the '#%s' channel
+ sprintf(atcmd_output, msg_txt(1433),sd->gcbind->name); // Your global chat is no longer bound to the '#%s' channel
clif->message(fd, atcmd_output);
sd->gcbind = NULL;
- } else if ( strcmpi(key,"ban") == 0 ) {
+ } else if (strcmpi(subcmd,"ban") == 0) {
+ // sub1 = channel name; sub2 = unused; sub3 = unused
struct map_session_data *pl_sd = NULL;
struct hChSysBanEntry *entry = NULL;
+ char sub4[NAME_LENGTH]; ///< player name
- if( sub1[0] != '#' ) {
+ if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) {
+ if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) {
+ if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
- if( sub2[0] == '\0' || ( pl_sd = iMap->nick2sd(sub2) ) == NULL ) {
- sprintf(atcmd_output, msg_txt(1434), sub2);// Player '%s' was not found
+ if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) {
+ sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found
clif->message(fd, atcmd_output);
return false;
}
+
+ if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4)) == NULL) {
+ sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found
+ clif->message(fd, atcmd_output);
+ return false;
+ }
- if( pc_has_permission(pl_sd, PC_PERM_HCHSYS_ADMIN) ) {
+ if (pc_has_permission(pl_sd, PC_PERM_HCHSYS_ADMIN)) {
clif->message(fd, msg_txt(1464)); // Ban failed, not possible to ban this user.
return false;
}
- if( channel->banned && idb_exists(channel->banned,pl_sd->status.account_id) ) {
+ if (channel->banned && idb_exists(channel->banned,pl_sd->status.account_id)) {
sprintf(atcmd_output, msg_txt(1465), pl_sd->status.name);// Player '%s' is already banned from this channel
clif->message(fd, atcmd_output);
return false;
}
- if( !channel->banned )
+ if (!channel->banned)
channel->banned = idb_alloc(DB_OPT_BASE|DB_OPT_ALLOW_NULL_DATA|DB_OPT_RELEASE_DATA);
CREATE(entry, struct hChSysBanEntry, 1);
@@ -9076,39 +8991,47 @@ ACMD(channel) {
sprintf(atcmd_output, msg_txt(1437),pl_sd->status.name,sub1); // Player '%s' has now been banned from '%s' channel
clif->message(fd, atcmd_output);
- } else if ( strcmpi(key,"unban") == 0 ) {
+ } else if (strcmpi(subcmd,"unban") == 0) {
+ // sub1 = channel name; sub2 = unused; sub3 = unused
struct map_session_data *pl_sd = NULL;
+ char sub4[NAME_LENGTH]; ///< player name
- if( sub1[0] != '#' ) {
+ if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) {
+ if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) {
+ if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
- if( !channel->banned ) {
+ if (!channel->banned) {
sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players
clif->message(fd, atcmd_output);
return false;
}
- if( sub2[0] == '\0' || ( pl_sd = iMap->nick2sd(sub2) ) == NULL ) {
- sprintf(atcmd_output, msg_txt(1434), sub2);// Player '%s' was not found
+ if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) {
+ sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found
+ clif->message(fd, atcmd_output);
+ return false;
+ }
+
+ if (sub4[0] == '\0' || (pl_sd = map->nick2sd(sub4)) == NULL) {
+ sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found
clif->message(fd, atcmd_output);
return false;
}
- if( !idb_exists(channel->banned,pl_sd->status.account_id) ) {
+ if (!idb_exists(channel->banned,pl_sd->status.account_id)) {
sprintf(atcmd_output, msg_txt(1440), pl_sd->status.name);// Player '%s' is not banned from this channel
clif->message(fd, atcmd_output);
return false;
@@ -9116,32 +9039,33 @@ ACMD(channel) {
idb_remove(channel->banned, pl_sd->status.account_id);
- if( !db_size(channel->banned) ) {
+ if (!db_size(channel->banned)) {
db_destroy(channel->banned);
channel->banned = NULL;
}
sprintf(atcmd_output, msg_txt(1441),pl_sd->status.name,sub1); // Player '%s' has now been unbanned from the '%s' channel
clif->message(fd, atcmd_output);
- } else if ( strcmpi(key,"unbanall") == 0 ) {
- if( sub1[0] != '#' ) {
+ } else if (strcmpi(subcmd,"unbanall") == 0) {
+ // sub1 = channel name; sub2 = unused; sub3 = unused
+ if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) {
+ if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) {
+ if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
- if( !channel->banned ) {
+ if (!channel->banned) {
sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players
clif->message(fd, atcmd_output);
return false;
@@ -9152,29 +9076,30 @@ ACMD(channel) {
sprintf(atcmd_output, msg_txt(1442),sub1); // Removed all bans from '%s' channel
clif->message(fd, atcmd_output);
- } else if ( strcmpi(key,"banlist") == 0 ) {
+ } else if (strcmpi(subcmd,"banlist") == 0) {
+ // sub1 = channel name; sub2 = unused; sub3 = unused
DBIterator *iter = NULL;
DBKey key;
DBData *data;
bool isA = pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)?true:false;
- if( sub1[0] != '#' ) {
+ if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) {
+ if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if( channel->owner != sd->status.char_id && !isA ) {
+ if (channel->owner != sd->status.char_id && !isA) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
- if( !channel->banned ) {
+ if (!channel->banned) {
sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players
clif->message(fd, atcmd_output);
return false;
@@ -9184,10 +9109,10 @@ ACMD(channel) {
iter = db_iterator(channel->banned);
- for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) {
+ for (data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key)) {
struct hChSysBanEntry * entry = DB->data2ptr(data);
- if( !isA )
+ if (!isA)
sprintf(atcmd_output, msg_txt(1444), entry->name);// - %s %s
else
sprintf(atcmd_output, msg_txt(1445), entry->name, key.i);// - %s (%d)
@@ -9197,57 +9122,58 @@ ACMD(channel) {
dbi_destroy(iter);
- } else if ( strcmpi(key,"setopt") == 0 ) {
+ } else if (strcmpi(subcmd,"setopt") == 0) {
+ // sub1 = channel name; sub2 = option name; sub3 = value
const char* opt_str[3] = {
"None",
"JoinAnnounce",
"MessageDelay",
};
- if( sub1[0] != '#' ) {
+ if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
- if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) {
+ if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
- if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) {
+ if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
- if( sub2[0] == '\0' ) {
+ if (sub2[0] == '\0') {
clif->message(fd, msg_txt(1446));// You need to input a option
return false;
}
- for( k = 1; k < 3; k++ ) {
- if( strcmpi(sub2,opt_str[k]) == 0 )
+ for (k = 1; k < 3; k++) {
+ if (strcmpi(sub2,opt_str[k]) == 0)
break;
}
- if( k == 3 ) {
+ if (k == 3) {
sprintf(atcmd_output, msg_txt(1447), sub2);// '%s' is not a known channel option
clif->message(fd, atcmd_output);
clif->message(fd, msg_txt(1448)); // -- Available options
- for( k = 1; k < 3; k++ ) {
+ for (k = 1; k < 3; k++) {
sprintf(atcmd_output, msg_txt(1444), opt_str[k]);// - '%s'
clif->message(fd, atcmd_output);
}
return false;
}
- if( sub3[0] == '\0' ) {
- if ( k == hChSys_OPT_MSG_DELAY ) {
+ if (sub3[0] == '\0') {
+ if (k == hChSys_OPT_MSG_DELAY) {
sprintf(atcmd_output, msg_txt(1466), opt_str[k]);// For '%s' you need the amount of seconds (from 0 to 10)
clif->message(fd, atcmd_output);
return false;
- } else if( channel->opt & k ) {
+ } else if (channel->opt & k) {
sprintf(atcmd_output, msg_txt(1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel setopt %s 0'
clif->message(fd, atcmd_output);
return false;
@@ -9259,13 +9185,13 @@ ACMD(channel) {
}
} else {
int v = atoi(sub3);
- if( k == hChSys_OPT_MSG_DELAY ) {
- if( v < 0 || v > 10 ) {
+ if (k == hChSys_OPT_MSG_DELAY) {
+ if (v < 0 || v > 10) {
sprintf(atcmd_output, msg_txt(1451), v, opt_str[k]);// value '%d' for option '%s' is out of range (limit is 0-10)
clif->message(fd, atcmd_output);
return false;
}
- if( v == 0 ) {
+ if (v == 0) {
channel->opt &=~ k;
channel->msg_delay = 0;
sprintf(atcmd_output, msg_txt(1453), opt_str[k],channel->name,v);// option '%s' is now disabled for channel '%s'
@@ -9279,8 +9205,8 @@ ACMD(channel) {
return true;
}
} else {
- if( v ) {
- if( channel->opt & k ) {
+ if (v) {
+ if (channel->opt & k) {
sprintf(atcmd_output, msg_txt(1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel opt %s 0'
clif->message(fd, atcmd_output);
return false;
@@ -9290,7 +9216,7 @@ ACMD(channel) {
clif->message(fd, atcmd_output);
}
} else {
- if( !(channel->opt & k) ) {
+ if (!(channel->opt & k)) {
sprintf(atcmd_output, msg_txt(1454), opt_str[k],channel->name); // option '%s' is not enabled on channel '%s'
clif->message(fd, atcmd_output);
return false;
@@ -9304,7 +9230,6 @@ ACMD(channel) {
}
}
-
} else {
atcmd_channel_help(fd,command,( hChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ));
}
@@ -9376,17 +9301,28 @@ ACMD(searchstore){
return true;
}
ACMD(costume){
- const char* names[4] = {
+ const char* names[] = {
"Wedding",
"Xmas",
"Summer",
"Hanbok",
+#if PACKETVER >= 20131218
+ "Oktoberfest",
+#endif
};
- const int name2id[4] = { SC_WEDDING, SC_XMAS, SC_SUMMER, SC_HANBOK };
- unsigned short k = 0;
+ const int name2id[] = {
+ SC_WEDDING,
+ SC_XMAS,
+ SC_SUMMER,
+ SC_HANBOK,
+#if PACKETVER >= 20131218
+ SC_OKTOBERFEST,
+#endif
+ };
+ unsigned short k = 0, len = ARRAYLENGTH(names);
if( !message || !*message ) {
- for( k = 0; k < 4; k++ ) {
+ for( k = 0; k < len; k++ ) {
if( sd->sc.data[name2id[k]] ) {
sprintf(atcmd_output,msg_txt(1473),names[k]);//Costume '%s' removed.
clif->message(sd->fd,atcmd_output);
@@ -9396,14 +9332,14 @@ ACMD(costume){
}
clif->message(sd->fd,msg_txt(1472));
- for( k = 0; k < 4; k++ ) {
+ for( k = 0; k < len; k++ ) {
sprintf(atcmd_output,msg_txt(1471),names[k]);//-- %s
clif->message(sd->fd,atcmd_output);
}
return false;
}
- for( k = 0; k < 4; k++ ) {
+ for( k = 0; k < len; k++ ) {
if( sd->sc.data[name2id[k]] ) {
sprintf(atcmd_output,msg_txt(1470),names[k]);// You're already with a '%s' costume, type '@costume' to remove it.
clif->message(sd->fd,atcmd_output);
@@ -9411,20 +9347,33 @@ ACMD(costume){
}
}
- for( k = 0; k < 4; k++ ) {
+ for( k = 0; k < len; k++ ) {
if( strcmpi(message,names[k]) == 0 )
break;
}
- if( k == 4 ) {
+ if( k == len ) {
sprintf(atcmd_output,msg_txt(1469),message);// '%s' is not a known costume
clif->message(sd->fd,atcmd_output);
return false;
}
- sc_start(&sd->bl, name2id[k], 100, 0, -1);
+ sc_start(NULL,&sd->bl, name2id[k], 100, 0, -1);
return true;
}
+/* for debugging purposes (so users can easily provide us with debug info) */
+/* should be trashed as soon as its no longer necessary */
+ACMD(skdebug) {
+ sprintf(atcmd_output,"second: %d; third: %d",sd->sktree.second,sd->sktree.third);
+ clif->message(fd,atcmd_output);
+ sprintf(atcmd_output,"pc_calc_skilltree_normalize_job: %d",pc->calc_skilltree_normalize_job(sd));
+ clif->message(fd,atcmd_output);
+ sprintf(atcmd_output,"change_lv_2nd/3rd: %d/%d",sd->change_level_2nd,sd->change_level_3rd);
+ clif->message(fd,atcmd_output);
+ sprintf(atcmd_output,"pc_calc_skillpoint:%d",pc->calc_skillpoint(sd));
+ clif->message(fd,atcmd_output);
+ return true;
+}
/**
* Fills the reference of available commands in atcommand DBMap
**/
@@ -9463,6 +9412,8 @@ void atcommand_basecommands(void) {
ACMD_DEF(heal),
ACMD_DEF(item),
ACMD_DEF(item2),
+ ACMD_DEF2("itembound", item),
+ ACMD_DEF2("itembound2", item2),
ACMD_DEF(itemreset),
ACMD_DEF(clearstorage),
ACMD_DEF(cleargstorage),
@@ -9539,7 +9490,9 @@ void atcommand_basecommands(void) {
ACMD_DEF2("allstats", stat_all),
ACMD_DEF2("block", char_block),
ACMD_DEF2("ban", char_ban),
+ ACMD_DEF2("charban", char_ban),/* char-specific ban time */
ACMD_DEF2("unblock", char_unblock),
+ ACMD_DEF2("charunban", char_unban),/* char-specific ban time */
ACMD_DEF2("unban", char_unban),
ACMD_DEF2("mount", mount_peco),
ACMD_DEF(guildspy),
@@ -9610,6 +9563,7 @@ void atcommand_basecommands(void) {
ACMD_DEF(changelook),
ACMD_DEF(autoloot),
ACMD_DEF2("alootid", autolootitem),
+ ACMD_DEF(autoloottype),
ACMD_DEF(mobinfo),
ACMD_DEF(exp),
ACMD_DEF(version),
@@ -9688,24 +9642,43 @@ void atcommand_basecommands(void) {
ACMD_DEF(fontcolor),
ACMD_DEF(searchstore),
ACMD_DEF(costume),
+ ACMD_DEF(skdebug),
};
- AtCommandInfo* cmd;
int i;
for( i = 0; i < ARRAYLENGTH(atcommand_base); i++ ) {
- if(atcommand->exists(atcommand_base[i].command)) { // Should not happen if atcommand_base[] array is OK
+ if(!atcommand->add(atcommand_base[i].command,atcommand_base[i].func,false)) { // Should not happen if atcommand_base[] array is OK
ShowDebug("atcommand_basecommands: duplicate ACMD_DEF for '%s'.\n", atcommand_base[i].command);
continue;
}
- CREATE(cmd, AtCommandInfo, 1);
- safestrncpy(cmd->command, atcommand_base[i].command, sizeof(cmd->command));
- cmd->func = atcommand_base[i].func;
- cmd->help = NULL;/* start as null dear */
- cmd->log = true;
- strdb_put(atcommand->db, cmd->command, cmd);
}
+
+ /* @commands from plugins */
+ HPM_map_atcommands();
+
return;
}
+#undef ACMD_DEF
+#undef ACMD_DEF2
+
+bool atcommand_add(char *name,AtCommandFunc func, bool replace) {
+ AtCommandInfo* cmd;
+
+ if( (cmd = atcommand->exists(name)) ) { //caller will handle/display on false
+ if( !replace )
+ return false;
+ } else {
+ CREATE(cmd, AtCommandInfo, 1);
+ strdb_put(atcommand->db, name, cmd);
+ }
+
+ safestrncpy(cmd->command, name, sizeof(cmd->command));
+ cmd->func = func;
+ cmd->help = NULL;
+ cmd->log = true;
+
+ return true;
+}
/*==========================================
* Command lookup functions
@@ -9714,15 +9687,14 @@ AtCommandInfo* atcommand_exists(const char* name) {
return strdb_get(atcommand->db, name);
}
-static AtCommandInfo* get_atcommandinfo_byname(const char *name) {
+AtCommandInfo* get_atcommandinfo_byname(const char *name) {
AtCommandInfo *cmd;
if ((cmd = strdb_get(atcommand->db, name)))
return cmd;
return NULL;
}
-static const char* atcommand_checkalias(const char *aliasname)
-{
+const char* atcommand_checkalias(const char *aliasname) {
AliasInfo *alias_info = NULL;
if ((alias_info = (AliasInfo*)strdb_get(atcommand->alias_db, aliasname)) != NULL)
return alias_info->command->command;
@@ -9730,7 +9702,7 @@ static const char* atcommand_checkalias(const char *aliasname)
}
/// AtCommand suggestion
-static void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool is_atcmd_cmd) {
+void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool is_atcmd_cmd) {
DBIterator* atcommand_iter;
DBIterator* alias_iter;
AtCommandInfo* command_info = NULL;
@@ -9801,9 +9773,14 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n
dbi_destroy(alias_iter);
}
-/// Executes an at-command.
-bool is_atcommand(const int fd, struct map_session_data* sd, const char* message, int type)
-{
+/**
+ * Executes an at-command
+ * @param fd fd associated to the invoking character
+ * @param sd sd associated to the invoking character
+ * @param message atcommand arguments
+ * @param player_invoked true if the command was invoked by a player, false if invoked by the server (bypassing any restrictions)
+ */
+bool atcommand_exec(const int fd, struct map_session_data *sd, const char *message, bool player_invoked) {
char charname[NAME_LENGTH], params[100];
char charname2[NAME_LENGTH], params2[100];
char command[100];
@@ -9833,11 +9810,9 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
if ( *message != atcommand->at_symbol && *message != atcommand->char_symbol )
return false;
- // type value 0 = server invoked: bypass restrictions
- // 1 = player invoked
- if ( type == 1) {
+ if (player_invoked) {
//Commands are disabled on maps flagged as 'nocommand'
- if ( map[sd->bl.m].nocommand && pc->get_group_level(sd) < map[sd->bl.m].nocommand ) {
+ if ( map->list[sd->bl.m].nocommand && pc_get_group_level(sd) < map->list[sd->bl.m].nocommand ) {
clif->message(fd, msg_txt(143));
return false;
}
@@ -9872,10 +9847,10 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
break;
}
- if( !pc->get_group_level(sd) ) {
+ if( !pc_get_group_level(sd) ) {
if( x >= 1 || y >= 1 ) { /* we have command */
- info = get_atcommandinfo_byname(atcommand_checkalias(command + 1));
- if( !info || info->char_groups[sd->group_pos] == 0 ) /* if we can't use or doesn't exist: don't even display the command failed message */
+ info = atcommand->get_info_byname(atcommand->check_alias(command + 1));
+ if( !info || info->char_groups[pcg->get_idx(sd->group)] == 0 ) /* if we can't use or doesn't exist: don't even display the command failed message */
return false;
} else
return false;/* display as normal message */
@@ -9886,13 +9861,16 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
return true;
} while(0);
}
- else if (*message == atcommand->at_symbol) {
+ else /*if (*message == atcommand->at_symbol)*/ {
//atcmd_msg is constructed above differently for charcommands
//it's copied from message if not a charcommand so it can
//pass through the rest of the code compatible with both symbols
sprintf(atcmd_msg, "%s", message);
}
+ if( battle_config.idletime_criteria & BCIDLE_ATCOMMAND )
+ sd->idletime = sockt->last_tick;
+
//Clearing these to be used once more.
memset(command, '\0', sizeof(command));
memset(params, '\0', sizeof(params));
@@ -9902,23 +9880,28 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
params[0] = '\0';
// @commands (script based)
- if(type == 1 && atcommand->binding_count > 0) {
+ if(player_invoked && atcommand->binding_count > 0) {
struct atcmd_binding_data * binding;
// Get atcommand binding
binding = atcommand->get_bind_byname(command);
// Check if the binding isn't NULL and there is a NPC event, level of usage met, et cetera
- if( binding != NULL && binding->npc_event[0] &&
- ((*atcmd_msg == atcommand->at_symbol && pc->get_group_level(sd) >= binding->group_lv) ||
- (*atcmd_msg == atcommand->char_symbol && pc->get_group_level(sd) >= binding->group_lv_char)))
- {
+ if( binding != NULL
+ && binding->npc_event[0]
+ && (
+ (*atcmd_msg == atcommand->at_symbol && pc_get_group_level(sd) >= binding->group_lv)
+ || (*atcmd_msg == atcommand->char_symbol && pc_get_group_level(sd) >= binding->group_lv_char)
+ )
+ ) {
// Check if self or character invoking; if self == character invoked, then self invoke.
bool invokeFlag = ((*atcmd_msg == atcommand->at_symbol) ? 1 : 0);
// Check if the command initiated is a character command
- if (*message == atcommand->char_symbol &&
- (ssd = iMap->nick2sd(charname)) == NULL && (ssd = iMap->nick2sd(charname2)) == NULL ) {
+ if (*message == atcommand->char_symbol
+ && (ssd = map->nick2sd(charname)) == NULL
+ && (ssd = map->nick2sd(charname2)) == NULL
+ ) {
sprintf(output, msg_txt(1389), command); // %s failed. Player not found.
clif->message(fd, output);
return true;
@@ -9927,37 +9910,36 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
if( binding->log ) /* log only if this command should be logged [Ind/Hercules] */
logs->atcommand(sd, atcmd_msg);
- npc_do_atcmd_event((invokeFlag ? sd : ssd), command, params, binding->npc_event);
+ npc->do_atcmd_event((invokeFlag ? sd : ssd), command, params, binding->npc_event);
return true;
}
}
//Grab the command information and check for the proper GM level required to use it or if the command exists
- info = get_atcommandinfo_byname(atcommand_checkalias(command + 1));
+ info = atcommand->get_info_byname(atcommand->check_alias(command + 1));
if (info == NULL) {
- if( pc->get_group_level(sd) ) { // TODO: remove or replace with proper permission
+ if( pc_get_group_level(sd) ) { // TODO: remove or replace with proper permission
sprintf(output, msg_txt(153), command); // "%s is Unknown Command."
clif->message(fd, output);
- atcommand_get_suggestions(sd, command + 1, *message == atcommand->at_symbol);
+ atcommand->get_suggestions(sd, command + 1, *message == atcommand->at_symbol);
return true;
} else
return false;
}
- // type == 1 : player invoked
- if (type == 1) {
+ if (player_invoked) {
int i;
- if ((*command == atcommand->at_symbol && info->at_groups[sd->group_pos] == 0) ||
- (*command == atcommand->char_symbol && info->char_groups[sd->group_pos] == 0) ) {
+ if ((*command == atcommand->at_symbol && info->at_groups[pcg->get_idx(sd->group)] == 0) ||
+ (*command == atcommand->char_symbol && info->char_groups[pcg->get_idx(sd->group)] == 0) ) {
return false;
}
if( pc_isdead(sd) && pc_has_permission(sd,PC_PERM_DISABLE_CMD_DEAD) ) {
clif->message(fd, msg_txt(1393)); // You can't use commands while dead
return true;
}
- for(i = 0; i < map[sd->bl.m].zone->disabled_commands_count; i++) {
- if( info->func == map[sd->bl.m].zone->disabled_commands[i]->cmd ) {
- if( sd->group_level < map[sd->bl.m].zone->disabled_commands[i]->group_lv ) {
+ for(i = 0; i < map->list[sd->bl.m].zone->disabled_commands_count; i++) {
+ if( info->func == map->list[sd->bl.m].zone->disabled_commands[i]->cmd ) {
+ if( pc_get_group_level(sd) < map->list[sd->bl.m].zone->disabled_commands[i]->group_lv ) {
clif->colormes(sd->fd,COLOR_RED,"This command is disabled in this area");
return true;
} else
@@ -9967,8 +9949,10 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
}
// Check if target is valid only if confirmed that player can use command.
- if (*message == atcommand->char_symbol &&
- (ssd = iMap->nick2sd(charname)) == NULL && (ssd = iMap->nick2sd(charname2)) == NULL ) {
+ if (*message == atcommand->char_symbol
+ && (ssd = map->nick2sd(charname)) == NULL
+ && (ssd = map->nick2sd(charname2)) == NULL
+ ) {
sprintf(output, msg_txt(1389), command); // %s failed. Player not found.
clif->message(fd, output);
return true;
@@ -9976,6 +9960,11 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
//Attempt to use the command
if ( (info->func(fd, (*atcmd_msg == atcommand->at_symbol) ? sd : ssd, command, params,info) != true) ) {
+#ifdef AUTOTRADE_PERSISTENCY
+ // Autotrade was successful if standalone is set
+ if( ((*atcmd_msg == atcommand->at_symbol) ? sd->state.standalone : ssd->state.standalone) )
+ return true;
+#endif
sprintf(output,msg_txt(154), command); // %s failed.
clif->message(fd, output);
return true;
@@ -9990,17 +9979,17 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
/*==========================================
*
*------------------------------------------*/
-static void atcommand_config_read(const char* config_filename) {
+void atcommand_config_read(const char* config_filename) {
config_t atcommand_config;
config_setting_t *aliases = NULL, *help = NULL, *nolog = NULL;
const char *symbol = NULL;
int num_aliases = 0;
- if (conf_read_file(&atcommand_config, config_filename))
+ if (libconfig->read_file(&atcommand_config, config_filename))
return;
// Command symbols
- if (config_lookup_string(&atcommand_config, "atcommand_symbol", &symbol)) {
+ if (libconfig->lookup_string(&atcommand_config, "atcommand_symbol", &symbol)) {
if (ISPRINT(*symbol) && // no control characters
*symbol != '/' && // symbol of client commands
*symbol != '%' && // symbol of party chat
@@ -10009,7 +9998,7 @@ static void atcommand_config_read(const char* config_filename) {
atcommand->at_symbol = *symbol;
}
- if (config_lookup_string(&atcommand_config, "charcommand_symbol", &symbol)) {
+ if (libconfig->lookup_string(&atcommand_config, "charcommand_symbol", &symbol)) {
if (ISPRINT(*symbol) && // no control characters
*symbol != '/' && // symbol of client commands
*symbol != '%' && // symbol of party chat
@@ -10019,10 +10008,10 @@ static void atcommand_config_read(const char* config_filename) {
}
// Command aliases
- aliases = config_lookup(&atcommand_config, "aliases");
+ aliases = libconfig->lookup(&atcommand_config, "aliases");
if (aliases != NULL) {
int i = 0;
- int count = config_setting_length(aliases);
+ int count = libconfig->setting_length(aliases);
for (i = 0; i < count; ++i) {
config_setting_t *command;
@@ -10030,7 +10019,7 @@ static void atcommand_config_read(const char* config_filename) {
int j = 0, alias_count = 0;
AtCommandInfo *commandinfo = NULL;
- command = config_setting_get_elem(aliases, i);
+ command = libconfig->setting_get_elem(aliases, i);
if (config_setting_type(command) != CONFIG_TYPE_ARRAY)
continue;
commandname = config_setting_name(command);
@@ -10038,9 +10027,9 @@ static void atcommand_config_read(const char* config_filename) {
ShowConfigWarning(command, "atcommand_config_read: can not set alias for non-existent command %s", commandname);
continue;
}
- alias_count = config_setting_length(command);
+ alias_count = libconfig->setting_length(command);
for (j = 0; j < alias_count; ++j) {
- const char *alias = config_setting_get_string_elem(command, j);
+ const char *alias = libconfig->setting_get_string_elem(command, j);
if (alias != NULL) {
AliasInfo *alias_info;
if (strdb_exists(atcommand->alias_db, alias)) {
@@ -10057,17 +10046,17 @@ static void atcommand_config_read(const char* config_filename) {
}
}
- nolog = config_lookup(&atcommand_config, "nolog");
+ nolog = libconfig->lookup(&atcommand_config, "nolog");
if (nolog != NULL) {
int i = 0;
- int count = config_setting_length(nolog);
+ int count = libconfig->setting_length(nolog);
for (i = 0; i < count; ++i) {
config_setting_t *command;
const char *commandname = NULL;
AtCommandInfo *commandinfo = NULL;
- command = config_setting_get_elem(nolog, i);
+ command = libconfig->setting_get_elem(nolog, i);
commandname = config_setting_name(command);
if ( !( commandinfo = atcommand_exists(commandname) ) ) {
ShowConfigWarning(command, "atcommand_config_read: can not disable logging for non-existent command %s", commandname);
@@ -10075,13 +10064,13 @@ static void atcommand_config_read(const char* config_filename) {
}
commandinfo->log = false;
}
- }
+ }
// Commands help
// We only check if all commands exist
- help = config_lookup(&atcommand_config, "help");
+ help = libconfig->lookup(&atcommand_config, "help");
if (help != NULL) {
- int count = config_setting_length(help);
+ int count = libconfig->setting_length(help);
int i;
for (i = 0; i < count; ++i) {
@@ -10089,14 +10078,14 @@ static void atcommand_config_read(const char* config_filename) {
const char *commandname;
AtCommandInfo *commandinfo = NULL;
- command = config_setting_get_elem(help, i);
+ command = libconfig->setting_get_elem(help, i);
commandname = config_setting_name(command);
if ( !( commandinfo = atcommand_exists(commandname) ) )
ShowConfigWarning(command, "atcommand_config_read: command %s does not exist", commandname);
else {
if( commandinfo->help == NULL ) {
- const char *str = config_setting_get_string(command);
- int len = strlen(str);
+ const char *str = libconfig->setting_get_string(command);
+ size_t len = strlen(str);
commandinfo->help = aMalloc( len * sizeof(char) );
safestrncpy(commandinfo->help, str, len);
}
@@ -10106,129 +10095,166 @@ static void atcommand_config_read(const char* config_filename) {
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' command aliases in '"CL_WHITE"%s"CL_RESET"'.\n", num_aliases, config_filename);
- config_destroy(&atcommand_config);
+ libconfig->destroy(&atcommand_config);
return;
}
-void atcommand_db_load_groups(void) {
+
+/**
+ * In group configuration file, setting for each command is either
+ * <commandname> : <bool> (only atcommand), or
+ * <commandname> : [ <bool>, <bool> ] ([ atcommand, charcommand ])
+ * Maps AtCommandType enums to indexes of <commandname> value array,
+ * COMMAND_ATCOMMAND (1) being index 0, COMMAND_CHARCOMMAND (2) being index 1.
+ * @private
+ */
+static inline int AtCommandType2idx(AtCommandType type) { return (type-1); }
+
+/**
+ * Loads permissions for groups to use commands.
+ *
+ */
+void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **commands_, size_t sz)
+{
DBIterator *iter = db_iterator(atcommand->db);
- AtCommandInfo* cmd;
- int i;
+ AtCommandInfo *atcmd;
- for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) {
- cmd->at_groups = aMalloc( pc_group_max * sizeof(char) );
- cmd->char_groups = aMalloc( pc_group_max * sizeof(char) );
- for(i = 0; i < pc_group_max; i++) {
- int idx = pc_group_id2idx(atcommand->group_ids[i]);
- if( pc_group_can_use_command(atcommand->group_ids[i], cmd->command, COMMAND_ATCOMMAND ) )
- cmd->at_groups[idx] = 1;
- else
- cmd->at_groups[idx] = 0;
- if( pc_group_can_use_command(atcommand->group_ids[i], cmd->command, COMMAND_CHARCOMMAND ) )
- cmd->char_groups[idx] = 1;
- else
- cmd->char_groups[idx] = 0;
+ for (atcmd = dbi_first(iter); dbi_exists(iter); atcmd = dbi_next(iter)) {
+ int i;
+ CREATE(atcmd->at_groups, char, sz);
+ CREATE(atcmd->char_groups, char, sz);
+ for (i = 0; i < sz; i++) {
+ GroupSettings *group = groups[i];
+ config_setting_t *commands = commands_[i];
+ int result = 0;
+ int idx = -1;
+
+ if (group == NULL) {
+ ShowError("atcommand_db_load_groups: group is NULL\n");
+ continue;
+ }
+
+ idx = pcg->get_idx(group);
+ if (idx < 0 || idx >= sz) {
+ ShowError("atcommand_db_load_groups: index (%d) out of bounds [0,%"PRIuS"]\n", idx, sz - 1);
+ continue;
+ }
+
+ if (pcg->has_permission(group, PC_PERM_USE_ALL_COMMANDS)) {
+ atcmd->at_groups[idx] = atcmd->char_groups[idx] = 1;
+ continue;
+ }
+
+ if (commands != NULL) {
+ config_setting_t *cmd = NULL;
+
+ // <commandname> : <bool> (only atcommand)
+ if (config_setting_lookup_bool(commands, atcmd->command, &result) && result) {
+ atcmd->at_groups[idx] = 1;
+ }
+ else
+ // <commandname> : [ <bool>, <bool> ] ([ atcommand, charcommand ])
+ if ((cmd = config_setting_get_member(commands, atcmd->command)) != NULL &&
+ config_setting_is_aggregate(cmd) &&
+ config_setting_length(cmd) == 2
+ ) {
+ if (config_setting_get_bool_elem(cmd, AtCommandType2idx(COMMAND_ATCOMMAND))) {
+ atcmd->at_groups[idx] = 1;
+ }
+ if (config_setting_get_bool_elem(cmd, AtCommandType2idx(COMMAND_CHARCOMMAND))) {
+ atcmd->char_groups[idx] = 1;
+ }
+ }
+ }
}
}
-
dbi_destroy(iter);
-
return;
}
+
bool atcommand_can_use(struct map_session_data *sd, const char *command) {
- AtCommandInfo *info = get_atcommandinfo_byname(atcommand_checkalias(command + 1));
+ AtCommandInfo *info = atcommand->get_info_byname(atcommand->check_alias(command + 1));
if (info == NULL)
return false;
- if ((*command == atcommand->at_symbol && info->at_groups[sd->group_pos] != 0) ||
- (*command == atcommand->char_symbol && info->char_groups[sd->group_pos] != 0) ) {
+ if ((*command == atcommand->at_symbol && info->at_groups[pcg->get_idx(sd->group)] != 0) ||
+ (*command == atcommand->char_symbol && info->char_groups[pcg->get_idx(sd->group)] != 0) ) {
return true;
}
return false;
}
bool atcommand_can_use2(struct map_session_data *sd, const char *command, AtCommandType type) {
- AtCommandInfo *info = get_atcommandinfo_byname(atcommand_checkalias(command));
+ AtCommandInfo *info = atcommand->get_info_byname(atcommand->check_alias(command));
if (info == NULL)
return false;
- if ((type == COMMAND_ATCOMMAND && info->at_groups[sd->group_pos] != 0) ||
- (type == COMMAND_CHARCOMMAND && info->char_groups[sd->group_pos] != 0) ) {
+ if ((type == COMMAND_ATCOMMAND && info->at_groups[pcg->get_idx(sd->group)] != 0) ||
+ (type == COMMAND_CHARCOMMAND && info->char_groups[pcg->get_idx(sd->group)] != 0) ) {
return true;
}
return false;
}
bool atcommand_hp_add(char *name, AtCommandFunc func) {
- AtCommandInfo* cmd;
-
+ /* if commands are added after group permissions are thrown in, they end up with no permissions */
+ /* so we restrict commands to be linked in during boot */
if( runflag == MAPSERVER_ST_RUNNING ) {
ShowDebug("atcommand_hp_add: Commands can't be added after server is ready, skipping '%s'...\n",name);
return false;
}
- if( !atcommand->db )
- atcommand->db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH);
-
- if( atcommand->exists(name) ) {
- ShowDebug("atcommand_hp_add: duplicate command '%s', skipping...\n", name);
- return false;
- }
-
- CREATE(cmd, AtCommandInfo, 1);
-
- safestrncpy(cmd->command, name, sizeof(cmd->command));
- cmd->func = func;
- cmd->help = NULL;/* start as null dear */
- cmd->log = true;
-
- strdb_put(atcommand->db, cmd->command, cmd);
- return true;
+ return HPM_map_add_atcommand(name,func);
}
-void atcommand_db_clear(void) {
- if (atcommand->db != NULL) {
- DBIterator *iter = db_iterator(atcommand->db);
- AtCommandInfo* cmd;
-
- for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) {
- aFree(cmd->at_groups);
- aFree(cmd->char_groups);
- if( cmd->help != NULL )
- aFree(cmd->help);
- }
- dbi_destroy(iter);
+/**
+ * @see DBApply
+ */
+int atcommand_db_clear_sub(DBKey key, DBData *data, va_list args) {
+ AtCommandInfo *cmd = DB->data2ptr(data);
+ aFree(cmd->at_groups);
+ aFree(cmd->char_groups);
+ if (cmd->help != NULL)
+ aFree(cmd->help);
+ return 0;
+}
- db_destroy(atcommand->db);
+void atcommand_db_clear(void) {
+ if( atcommand->db != NULL ) {
+ atcommand->db->destroy(atcommand->db, atcommand->cmd_db_clear_sub);
atcommand->db = NULL;
}
- if (atcommand->alias_db != NULL)
+ if( atcommand->alias_db != NULL ) {
db_destroy(atcommand->alias_db);
+ atcommand->alias_db = NULL;
+ }
}
void atcommand_doload(void) {
if( runflag >= MAPSERVER_ST_RUNNING )
- atcommand_db_clear();
- if( !atcommand->db )
+ atcommand->cmd_db_clear();
+ if( atcommand->db == NULL )
atcommand->db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH);
- atcommand->alias_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH);
- atcommand_basecommands(); //fills initial atcommand_db with known commands
- atcommand_config_read(iMap->ATCOMMAND_CONF_FILENAME);
+ if( atcommand->alias_db == NULL )
+ atcommand->alias_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH);
+ atcommand->base_commands(); //fills initial atcommand_db with known commands
+ atcommand->config_read(map->ATCOMMAND_CONF_FILENAME);
}
-void do_init_atcommand(void) {
+void do_init_atcommand(bool minimal) {
+ if (minimal)
+ return;
+
atcommand->at_symbol = '@';
atcommand->char_symbol = '#';
atcommand->binding_count = 0;
- atcommand_doload();
+ atcommand->doload();
}
void do_final_atcommand(void) {
- atcommand_db_clear();
- if( atcommand->group_ids )
- aFree(atcommand->group_ids);
+ atcommand->cmd_db_clear();
}
void atcommand_defaults(void) {
@@ -10237,16 +10263,37 @@ void atcommand_defaults(void) {
atcommand->db = NULL;
atcommand->alias_db = NULL;
+ memset(atcommand->msg_table, 0, sizeof(atcommand->msg_table));
+
atcommand->init = do_init_atcommand;
atcommand->final = do_final_atcommand;
- atcommand->parse = is_atcommand;
+ atcommand->exec = atcommand_exec;
+ atcommand->create = atcommand_hp_add;
atcommand->can_use = atcommand_can_use;
atcommand->can_use2 = atcommand_can_use2;
- atcommand->create = atcommand_hp_add;
atcommand->load_groups = atcommand_db_load_groups;
atcommand->exists = atcommand_exists;
atcommand->msg_read = msg_config_read;
atcommand->final_msg = do_final_msg;
atcommand->get_bind_byname = get_atcommandbind_byname;
+ atcommand->get_info_byname = get_atcommandinfo_byname;
+ atcommand->check_alias = atcommand_checkalias;
+ atcommand->get_suggestions = atcommand_get_suggestions;
+ atcommand->config_read = atcommand_config_read;
+ atcommand->stopattack = atcommand_stopattack;
+ atcommand->pvpoff_sub = atcommand_pvpoff_sub;
+ atcommand->pvpon_sub = atcommand_pvpon_sub;
+ atcommand->atkillmonster_sub = atkillmonster_sub;
+ atcommand->raise_sub = atcommand_raise_sub;
+ atcommand->get_jail_time = get_jail_time;
+ atcommand->cleanfloor_sub = atcommand_cleanfloor_sub;
+ atcommand->mutearea_sub = atcommand_mutearea_sub;
+ atcommand->commands_sub = atcommand_commands_sub;
+ atcommand->cmd_db_clear = atcommand_db_clear;
+ atcommand->cmd_db_clear_sub = atcommand_db_clear_sub;
+ atcommand->doload = atcommand_doload;
+ atcommand->base_commands = atcommand_basecommands;
+ atcommand->add = atcommand_add;
+ atcommand->msg = atcommand_msg;
}
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index f09b1f2b8..356487bd1 100644
--- a/src/map/atcommand.h
+++ b/src/map/atcommand.h
@@ -2,9 +2,11 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _ATCOMMAND_H_
-#define _ATCOMMAND_H_
+#ifndef MAP_ATCOMMAND_H
+#define MAP_ATCOMMAND_H
+#include "pc_groups.h"
+#include "../common/conf.h"
#include "../common/db.h"
/**
@@ -12,13 +14,14 @@
**/
struct map_session_data;
struct AtCommandInfo;
+struct block_list;
/**
* Defines
**/
#define ATCOMMAND_LENGTH 50
#define MAX_MSG 1500
-
+#define msg_txt(idx) atcommand->msg(idx)
/**
* Enumerations
**/
@@ -68,32 +71,54 @@ struct atcommand_interface {
/* atcommand binding */
struct atcmd_binding_data** binding;
int binding_count;
- unsigned int *group_ids;
/* other vars */
DBMap* db; //name -> AtCommandInfo
DBMap* alias_db; //alias -> AtCommandInfo
/* */
- void (*init) (void);
+ char* msg_table[MAX_MSG]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
+ /* */
+ void (*init) (bool minimal);
void (*final) (void);
/* */
- bool (*parse) (const int fd, struct map_session_data* sd, const char* message, int type);
+ bool (*exec) (const int fd, struct map_session_data *sd, const char *message, bool player_invoked);
bool (*create) (char *name, AtCommandFunc func);
bool (*can_use) (struct map_session_data *sd, const char *command);
bool (*can_use2) (struct map_session_data *sd, const char *command, AtCommandType type);
- void (*load_groups) (void);
+ void (*load_groups) (GroupSettings **groups, config_setting_t **commands_, size_t sz);
AtCommandInfo* (*exists) (const char* name);
- int (*msg_read) (const char* cfgName);
+ bool (*msg_read) (const char *cfg_name, bool allow_override);
void (*final_msg) (void);
/* atcommand binding */
struct atcmd_binding_data* (*get_bind_byname) (const char* name);
-} atcommand_s;
+ /* */
+ AtCommandInfo* (*get_info_byname) (const char *name); // @help
+ const char* (*check_alias) (const char *aliasname); // @help
+ void (*get_suggestions) (struct map_session_data* sd, const char *name, bool is_atcmd_cmd); // @help
+ void (*config_read) (const char* config_filename);
+ /* command-specific subs */
+ int (*stopattack) (struct block_list *bl,va_list ap);
+ int (*pvpoff_sub) (struct block_list *bl,va_list ap);
+ int (*pvpon_sub) (struct block_list *bl,va_list ap);
+ int (*atkillmonster_sub) (struct block_list *bl, va_list ap);
+ void (*raise_sub) (struct map_session_data* sd);
+ void (*get_jail_time) (int jailtime, int* year, int* month, int* day, int* hour, int* minute);
+ int (*cleanfloor_sub) (struct block_list *bl, va_list ap);
+ int (*mutearea_sub) (struct block_list *bl,va_list ap);
+ /* */
+ void (*commands_sub) (struct map_session_data* sd, const int fd, AtCommandType type);
+ void (*cmd_db_clear) (void);
+ int (*cmd_db_clear_sub) (DBKey key, DBData *data, va_list args);
+ void (*doload) (void);
+ void (*base_commands) (void);
+ bool (*add) (char *name, AtCommandFunc func, bool replace);
+ const char* (*msg) (int msg_number);
+};
struct atcommand_interface *atcommand;
-const char* msg_txt(int msg_number);
void atcommand_defaults(void);
+
/* stay here */
#define ACMD(x) static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info)
-#define ACMD_A(x) atcommand_ ## x
-#endif /* _ATCOMMAND_H_ */
+#endif /* MAP_ATCOMMAND_H */
diff --git a/src/map/battle.c b/src/map/battle.c
index 731c6f618..fc159c921 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -2,44 +2,47 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/malloc.h"
-#include "../common/showmsg.h"
-#include "../common/ers.h"
-#include "../common/random.h"
-#include "../common/socket.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
+#define HERCULES_CORE
-#include "map.h"
-#include "path.h"
-#include "pc.h"
-#include "status.h"
-#include "skill.h"
-#include "homunculus.h"
-#include "mercenary.h"
-#include "elemental.h"
-#include "mob.h"
-#include "itemdb.h"
-#include "clif.h"
-#include "pet.h"
-#include "guild.h"
-#include "party.h"
+#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, HMAP_ZONE_DAMAGE_CAP_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, RE_LVL_DMOD(), RE_LVL_MDMOD(), RE_LVL_TMDMOD(), RE_SKILL_REDUCTION(), SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, STATS_OPT_OUT
#include "battle.h"
-#include "battleground.h"
-#include "chrif.h"
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
-int attr_fix_table[4][ELE_MAX][ELE_MAX];
+#include "battleground.h"
+#include "chrif.h"
+#include "clif.h"
+#include "elemental.h"
+#include "guild.h"
+#include "homunculus.h"
+#include "itemdb.h"
+#include "map.h"
+#include "mercenary.h"
+#include "mob.h"
+#include "party.h"
+#include "path.h"
+#include "pc.h"
+#include "pet.h"
+#include "skill.h"
+#include "status.h"
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/sysinfo.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
struct Battle_Config battle_config;
-static struct eri *delay_damage_ers; //For battle delay damage structures.
+struct battle_interface battle_s;
int battle_getcurrentskill(struct block_list *bl) { //Returns the current/last skill in use by this bl.
struct unit_data *ud;
@@ -49,13 +52,13 @@ int battle_getcurrentskill(struct block_list *bl) { //Returns the current/last s
return su->group?su->group->skill_id:0;
}
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
return ud?ud->skill_id:0;
}
/*==========================================
- * Get random targetting enemy
+ * Get random targeting enemy
*------------------------------------------*/
int battle_gettargeted_sub(struct block_list *bl, va_list ap) {
struct block_list **bl_list;
@@ -73,7 +76,7 @@ int battle_gettargeted_sub(struct block_list *bl, va_list ap) {
if (*c >= 24)
return 0;
- if ( !(ud = unit_bl2ud(bl)) )
+ if ( !(ud = unit->bl2ud(bl)) )
return 0;
if (ud->target == target_id || ud->skilltarget == target_id) {
@@ -90,7 +93,7 @@ struct block_list* battle_gettargeted(struct block_list *target) {
nullpo_retr(NULL, target);
memset(bl_list, 0, sizeof(bl_list));
- iMap->foreachinrange(battle->get_targeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id);
+ map->foreachinrange(battle->get_targeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id);
if ( c == 0 )
return NULL;
if( c > 24 )
@@ -99,7 +102,7 @@ struct block_list* battle_gettargeted(struct block_list *target) {
}
-//Returns the id of the current targetted character of the passed bl. [Skotlex]
+//Returns the id of the current targeted character of the passed bl. [Skotlex]
int battle_gettarget(struct block_list* bl) {
switch (bl->type) {
@@ -129,7 +132,7 @@ int battle_getenemy_sub(struct block_list *bl, va_list ap) {
if (*c >= 24)
return 0;
- if (status_isdead(bl))
+ if (status->isdead(bl))
return 0;
if (battle->check_target(target, bl, BCT_ENEMY) > 0) {
@@ -146,7 +149,7 @@ struct block_list* battle_getenemy(struct block_list *target, int type, int rang
int c = 0;
memset(bl_list, 0, sizeof(bl_list));
- iMap->foreachinrange(battle->get_enemy_sub, target, range, type, bl_list, &c, target);
+ map->foreachinrange(battle->get_enemy_sub, target, range, type, bl_list, &c, target);
if ( c == 0 )
return NULL;
@@ -171,7 +174,7 @@ int battle_getenemyarea_sub(struct block_list *bl, va_list ap) {
if( *c >= 23 )
return 0;
- if( status_isdead(bl) )
+ if( status->isdead(bl) )
return 0;
if( battle->check_target(src, bl, BCT_ENEMY) > 0 ) {// Is Enemy!...
@@ -188,7 +191,7 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int
int c = 0;
memset(bl_list, 0, sizeof(bl_list));
- iMap->foreachinarea(battle->get_enemy_area_sub, src->m, x - range, y - range, x + range, y + range, type, bl_list, &c, src, ignore_id);
+ map->foreachinarea(battle->get_enemy_area_sub, src->m, x - range, y - range, x + range, y + range, type, bl_list, &c, src, ignore_id);
if( c == 0 )
return NULL;
@@ -198,81 +201,76 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int
return bl_list[rnd()%c];
}
-// Dammage delayed info
-struct delay_damage {
- int src_id;
- int target_id;
- int damage;
- int delay;
- unsigned short distance;
- uint16 skill_lv;
- uint16 skill_id;
- enum damage_lv dmg_lv;
- unsigned short attack_type;
- bool additional_effects;
-};
-
-int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) {
+int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
struct delay_damage *dat = (struct delay_damage *)data;
if ( dat ) {
- struct block_list* src;
- struct block_list* target = iMap->id2bl(dat->target_id);
+ struct block_list* src = NULL;
+ struct block_list* target = map->id2bl(dat->target_id);
- if( !target || status_isdead(target) ) {/* nothing we can do */
- ers_free(delay_damage_ers, dat);
+ if( !target || status->isdead(target) ) {/* nothing we can do */
+ if( dat->src_type == BL_PC && ( src = map->id2bl(dat->src_id) ) && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) {
+ ((TBL_PC*)src)->state.hold_recalc = 0;
+ status_calc_pc(((TBL_PC*)src),SCO_FORCE);
+ }
+ ers_free(battle->delay_damage_ers, dat);
return 0;
}
- src = iMap->id2bl(dat->src_id);
-
- if( src && target->m == src->m &&
- (target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == INVALID_TIMER) &&
- check_distance_bl(src, target, dat->distance) ) //Check to see if you haven't teleported. [Skotlex]
- {
- iMap->freeblock_lock();
+ src = map->id2bl(dat->src_id);
+
+ //Check to see if you haven't teleported. [Skotlex]
+ if( src && target->m == src->m
+ && (target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == INVALID_TIMER)
+ && check_distance_bl(src, target, dat->distance)
+ ) {
+ map->freeblock_lock();
status_fix_damage(src, target, dat->damage, dat->delay);
- if( dat->attack_type && !status_isdead(target) && dat->additional_effects )
+ if( dat->attack_type && !status->isdead(target) && dat->additional_effects )
skill->additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,dat->dmg_lv,tick);
if( dat->dmg_lv > ATK_BLOCK && dat->attack_type )
skill->counter_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
} else if( !src && dat->skill_id == CR_REFLECTSHIELD ) {
/**
* it was monster reflected damage, and the monster died, we pass the damage to the character as expected
**/
- iMap->freeblock_lock();
+ map->freeblock_lock();
status_fix_damage(target, target, dat->damage, dat->delay);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
+ }
+
+ if( src && src->type == BL_PC && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) {
+ ((TBL_PC*)src)->state.hold_recalc = 0;
+ status_calc_pc(((TBL_PC*)src),SCO_FORCE);
}
}
- ers_free(delay_damage_ers, dat);
+ ers_free(battle->delay_damage_ers, dat);
return 0;
}
-int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects)
-{
+int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) {
struct delay_damage *dat;
struct status_change *sc;
nullpo_ret(src);
nullpo_ret(target);
- sc = status_get_sc(target);
+ sc = status->get_sc(target);
if( sc && sc->data[SC_DEVOTION] && damage > 0 && skill_id != PA_PRESSURE && skill_id != CR_REFLECTSHIELD )
damage = 0;
if ( !battle_config.delay_battle_damage || amotion <= 1 ) {
- iMap->freeblock_lock();
- status_fix_damage(src, target, damage, ddelay); // We have to seperate here between reflect damage and others [icescope]
- if( attack_type && !status_isdead(target) && additional_effects )
- skill->additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, iTimer->gettick());
+ map->freeblock_lock();
+ status_fix_damage(src, target, damage, ddelay); // We have to separate here between reflect damage and others [icescope]
+ if( attack_type && !status->isdead(target) && additional_effects )
+ skill->additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, timer->gettick());
if( dmg_lv > ATK_BLOCK && attack_type )
- skill->counter_additional_effect(src, target, skill_id, skill_lv, attack_type, iTimer->gettick());
- iMap->freeblock_unlock();
+ skill->counter_additional_effect(src, target, skill_id, skill_lv, attack_type, timer->gettick());
+ map->freeblock_unlock();
return 0;
}
- dat = ers_alloc(delay_damage_ers, struct delay_damage);
+ dat = ers_alloc(battle->delay_damage_ers, struct delay_damage);
dat->src_id = src->id;
dat->target_id = target->id;
dat->skill_id = skill_id;
@@ -283,10 +281,15 @@ int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src,
dat->delay = ddelay;
dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported.
dat->additional_effects = additional_effects;
+ dat->src_type = src->type;
if (src->type != BL_PC && amotion > 1000)
amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex]
- iTimer->add_timer(tick+amotion, battle->delay_damage_sub, 0, (intptr_t)dat);
+ if( src->type == BL_PC ) {
+ ((TBL_PC*)src)->delayed_damage++;
+ }
+
+ timer->add(tick+amotion, battle->delay_damage_sub, 0, (intptr_t)dat);
return 0;
}
@@ -299,7 +302,7 @@ int battle_attr_ratio(int atk_elem,int def_type, int def_lv)
if (def_type < 0 || def_type > ELE_MAX || def_lv < 1 || def_lv > 4)
return 100;
- return attr_fix_table[def_lv-1][atk_elem][def_type];
+ return battle->attr_fix_table[def_lv-1][atk_elem][def_type];
}
/*==========================================
@@ -307,13 +310,13 @@ int battle_attr_ratio(int atk_elem,int def_type, int def_lv)
* Added passing of the chars so that the status changes can affect it. [Skotlex]
* Note: Passing src/target == NULL is perfectly valid, it skips SC_ checks.
*------------------------------------------*/
-int battle_attr_fix(struct block_list *src, struct block_list *target, int damage,int atk_elem,int def_type, int def_lv)
+int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 damage,int atk_elem,int def_type, int def_lv)
{
struct status_change *sc=NULL, *tsc=NULL;
int ratio;
- if (src) sc = status_get_sc(src);
- if (target) tsc = status_get_sc(target);
+ if (src) sc = status->get_sc(src);
+ if (target) tsc = status->get_sc(target);
if (atk_elem < 0 || atk_elem >= ELE_MAX)
atk_elem = rnd()%ELE_MAX;
@@ -324,70 +327,74 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
return damage;
}
- ratio = attr_fix_table[def_lv-1][atk_elem][def_type];
+ ratio = battle->attr_fix_table[def_lv-1][atk_elem][def_type];
if (sc && sc->count) {
if(sc->data[SC_VOLCANO] && atk_elem == ELE_FIRE)
- ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1];
+ ratio += skill->enchant_eff[sc->data[SC_VOLCANO]->val1-1];
if(sc->data[SC_VIOLENTGALE] && atk_elem == ELE_WIND)
- ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1];
+ ratio += skill->enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1];
if(sc->data[SC_DELUGE] && atk_elem == ELE_WATER)
- ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1];
+ ratio += skill->enchant_eff[sc->data[SC_DELUGE]->val1-1];
+ if(sc->data[SC_FIRE_CLOAK_OPTION] && atk_elem == ELE_FIRE)
+ damage += damage * sc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100;
}
if( target && target->type == BL_SKILL ) {
if( atk_elem == ELE_FIRE && battle->get_current_skill(target) == GN_WALLOFTHORN ) {
struct skill_unit *su = (struct skill_unit*)target;
struct skill_unit_group *sg;
- struct block_list *src;
+ struct block_list *sgsrc;
- if( !su || !su->alive || (sg = su->group) == NULL || !sg || sg->val3 == -1 ||
- (src = iMap->id2bl(sg->src_id)) == NULL || status_isdead(src) )
+ if( !su || !su->alive
+ || (sg = su->group) == NULL || sg->val3 == -1
+ || (sgsrc = map->id2bl(sg->src_id)) == NULL || status->isdead(sgsrc)
+ )
return 0;
if( sg->unit_id != UNT_FIREWALL ) {
int x,y;
x = sg->val3 >> 16;
y = sg->val3 & 0xffff;
- skill->unitsetting(src,su->group->skill_id,su->group->skill_lv,x,y,1);
+ skill->unitsetting(sgsrc,su->group->skill_id,su->group->skill_lv,x,y,1);
sg->val3 = -1;
- sg->limit = DIFF_TICK(iTimer->gettick(),sg->tick)+300;
+ sg->limit = DIFF_TICK32(timer->gettick(),sg->tick)+300;
}
}
}
- if( tsc && tsc->count ) { //since an atk can only have one type let's optimise this a bit
+ if( tsc && tsc->count ) { //since an atk can only have one type let's optimize this a bit
switch(atk_elem){
- case ELE_FIRE:
- if( tsc->data[SC_SPIDERWEB]) {
- tsc->data[SC_SPIDERWEB]->val1 = 0; // free to move now
- if( tsc->data[SC_SPIDERWEB]->val2-- > 0 )
- damage <<= 1; // double damage
- if( tsc->data[SC_SPIDERWEB]->val2 == 0 )
- status_change_end(target, SC_SPIDERWEB, INVALID_TIMER);
- }
- if( tsc->data[SC_THORNS_TRAP])
- status_change_end(target, SC_THORNS_TRAP, INVALID_TIMER);
- if( tsc->data[SC_FIRE_CLOAK_OPTION])
- damage -= damage * tsc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100;
- if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB)
- status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER);
- if( tsc->data[SC_EARTH_INSIGNIA]) damage += damage/2;
- if( tsc->data[SC_VOLCANIC_ASH]) damage += damage/2; //150%
- break;
- case ELE_HOLY:
- if( tsc->data[SC_ORATIO]) ratio += tsc->data[SC_ORATIO]->val1 * 2;
- break;
- case ELE_POISON:
- if( tsc->data[SC_VENOMIMPRESS]) ratio += tsc->data[SC_VENOMIMPRESS]->val2;
- break;
- case ELE_WIND:
- if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB) damage += damage/2;
- if( tsc->data[SC_WATER_INSIGNIA]) damage += damage/2;
- break;
- case ELE_WATER:
- if( tsc->data[SC_FIRE_INSIGNIA]) damage += damage/2;
- break;
- case ELE_EARTH:
- if( tsc->data[SC_WIND_INSIGNIA]) damage += damage/2;
- break;
+ case ELE_FIRE:
+ if( tsc->data[SC_SPIDERWEB]) {
+ tsc->data[SC_SPIDERWEB]->val1 = 0; // free to move now
+ if( tsc->data[SC_SPIDERWEB]->val2-- > 0 )
+ damage <<= 1; // double damage
+ if( tsc->data[SC_SPIDERWEB]->val2 == 0 )
+ status_change_end(target, SC_SPIDERWEB, INVALID_TIMER);
+ }
+ if( tsc->data[SC_THORNS_TRAP])
+ status_change_end(target, SC_THORNS_TRAP, INVALID_TIMER);
+ if( tsc->data[SC_COLD] && target->type != BL_MOB)
+ status_change_end(target, SC_COLD, INVALID_TIMER);
+ if( tsc->data[SC_EARTH_INSIGNIA]) damage += damage/2;
+ if( tsc->data[SC_FIRE_CLOAK_OPTION])
+ damage -= damage * tsc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100;
+ if( tsc->data[SC_VOLCANIC_ASH]) damage += damage/2; //150%
+ break;
+ case ELE_HOLY:
+ if( tsc->data[SC_ORATIO]) ratio += tsc->data[SC_ORATIO]->val1 * 2;
+ break;
+ case ELE_POISON:
+ if( tsc->data[SC_VENOMIMPRESS] && atk_elem == ELE_POISON ) ratio += tsc->data[SC_VENOMIMPRESS]->val2;
+ break;
+ case ELE_WIND:
+ if( tsc->data[SC_COLD] && target->type != BL_MOB) damage += damage/2;
+ if( tsc->data[SC_WATER_INSIGNIA]) damage += damage/2;
+ break;
+ case ELE_WATER:
+ if( tsc->data[SC_FIRE_INSIGNIA]) damage += damage/2;
+ break;
+ case ELE_EARTH:
+ if( tsc->data[SC_WIND_INSIGNIA]) damage += damage/2;
+ break;
}
} //end tsc check
if( src && src->type == BL_PC ){
@@ -408,77 +415,78 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
if( t < 5 && atk_elem == t )
damage -= damage * ( tsd->charm[t] * 3 ) / 100;// -3% custom value
}
- return damage*ratio/100;
+ if( ratio < 100 )
+ return damage - (damage * (100 - ratio) / 100);
+ else
+ return damage + (damage * (ratio - 100) / 100);
}
+int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2){ // [malufett]
#ifdef RENEWAL
-int battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2){ // [malufett]
- int damage, eatk = 0;
+ int64 damage, eatk = 0;
struct status_change *sc;
struct map_session_data *sd;
if( !src || !bl )
return 0;
- sc = status_get_sc(src);
+ sc = status->get_sc(src);
sd = BL_CAST(BL_PC, src);
- damage = status_get_weapon_atk(src, watk, flag);
+ damage = status->get_weapon_atk(src, watk, flag);
if( sd ){
if( type == EQI_HAND_R )
damage = battle->calc_sizefix(sd, damage, EQI_HAND_R, size, flag&8);
else
damage = battle->calc_sizefix(sd, damage, EQI_HAND_L, size, flag&8);
-
- if( sd->bonus.eatk > 0 )
- eatk = sd->bonus.eatk;
+
if( flag&2 && sd->bonus.arrow_atk )
- eatk += sd->bonus.arrow_atk;
+ damage += sd->bonus.arrow_atk;
+
+ if( sd->battle_status.equip_atk != 0 )
+ eatk = sd->base_status.equip_atk;
}
-
+
if( sc && sc->count ){
if( sc->data[SC_ZENKAI] && watk->ele == sc->data[SC_ZENKAI]->val2 )
eatk += 200;
- #ifdef RENEWAL_EDP
- if( sc->data[SC_EDP] && skill_id != AS_GRIMTOOTH && skill_id != AS_VENOMKNIFE ){
- eatk = eatk * sc->data[SC_EDP]->val3 / 100; // 400%
- damage = damage * sc->data[SC_EDP]->val4 / 100; // 500%
- damage--; // temporary until we find the correct formula [malufett]
+ #ifdef RENEWAL_EDP
+ if( sc->data[SC_EDP] && skill_id != AS_GRIMTOOTH && skill_id != AS_VENOMKNIFE && skill_id != ASC_BREAKER ){
+ eatk = eatk * (sc->data[SC_EDP]->val4 / 100 - 1);
+ damage = damage * (sc->data[SC_EDP]->val4 / 100);
}
#endif
}
- /* [malufett]
- some unknown factors that needs to be discovered. PS: it's something related with ranged attacks
- if( eatk ){
- eatk += unknown value;
- eatk = eatk * (unknown value) / 100;
+ if( skill_id != ASC_METEORASSAULT ){
+ if( sc && sc->data[SC_SUB_WEAPONPROPERTY] ) // Temporary. [malufett]
+ damage += damage * sc->data[SC_SUB_WEAPONPROPERTY]->val2 / 100;
}
- */
- if( sc && sc->data[SC_WATK_ELEMENT] )
- damage = damage + eatk;
- else
- damage = battle->calc_elefix(src, bl, skill_id, skill_lv, damage + eatk, nk, n_ele, s_ele, s_ele_, false, flag);
-
+ // Temporary. [malufett]
+ damage = battle->calc_elefix(src, bl, skill_id, skill_lv, damage + eatk, nk, n_ele, s_ele, s_ele_, type == EQI_HAND_L, flag);
+
/**
- * In RE Shield Bommerang takes weapon element only for damage calculation,
+ * In RE Shield Boomerang takes weapon element only for damage calculation,
* - resist calculation is always against neutral
**/
if ( skill_id == CR_SHIELDBOOMERANG )
s_ele = s_ele_ = ELE_NEUTRAL;
- if( type == EQI_HAND_R )
- damage = battle->calc_cardfix(BF_WEAPON, src, bl, nk, s_ele, s_ele_, damage, 2, flag2);
- else
- damage = battle->calc_cardfix(BF_WEAPON, src, bl, nk, s_ele, s_ele_, damage, 3, flag2);
+ // attacker side
+ damage = battle->calc_cardfix(BF_WEAPON, src, bl, nk, s_ele, s_ele_, damage, 2|(type == EQI_HAND_L), flag2);
+ // target side
+ damage = battle->calc_cardfix(BF_WEAPON, src, bl, nk, s_ele, s_ele_, damage, 0, flag2);
+
return damage;
-}
+#else
+ return 0;
#endif
+}
/*==========================================
* Calculates the standard damage of a normal attack assuming it hits,
- * it calculates nothing extra fancy, is needed for magnum break's WATK_ELEMENT bonus. [Skotlex]
+ * it calculates nothing extra fancy, is needed for magnum breaks WATK_ELEMENT bonus. [Skotlex]
*------------------------------------------
* Pass damage2 as NULL to not calc it.
* Flag values:
@@ -488,34 +496,29 @@ int battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, uin
* &8: Skip target size adjustment (Extremity Fist?)
*&16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX)
*/
-
-#ifdef RENEWAL
-int battle_calc_base_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2)
-{
- int damage, batk;
- struct status_change *sc = status_get_sc(src);
- struct status_data *status = status_get_status_data(src);
+/* 'battle_calc_base_damage' is used on renewal, 'battle_calc_base_damage2' otherwise. */
+int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2) {
+ int64 damage, batk;
+ struct status_data *st = status->get_status_data(src);
- if( sc && sc->data[SC_TK_SEVENWIND] && !sc->data[SC_WATK_ELEMENT] )
- batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->batk, nk, n_ele, s_ele, s_ele_, false, flag);
- else
- batk = status->batk;
+ batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, status->get_sc(src), st->batk, false), nk, n_ele, ELE_NEUTRAL, ELE_NEUTRAL, false, flag);
if( type == EQI_HAND_L )
- damage = batk + 3 * battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &status->lhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2) / 4;
+ damage = batk + 3 * battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->lhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2) / 4;
else
- damage = (batk << 1) + battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &status->rhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2);
-#else
-static int battle_calc_base_damage(struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag)
-{
+ damage = (batk << 1) + battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->rhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2);
+
+ return damage;
+}
+int64 battle_calc_base_damage2(struct status_data *st, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag) {
unsigned int atkmin=0, atkmax=0;
short type = 0;
- int damage = 0;
+ int64 damage = 0;
if (!sd) { //Mobs/Pets
if(flag&4) {
- atkmin = status->matk_min;
- atkmax = status->matk_max;
+ atkmin = st->matk_min;
+ atkmax = st->matk_max;
} else {
atkmin = wa->atk;
atkmax = wa->atk2;
@@ -524,10 +527,10 @@ static int battle_calc_base_damage(struct status_data *status, struct weapon_atk
atkmin = atkmax;
} else { //PCs
atkmax = wa->atk;
- type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R;
+ type = (wa == &st->lhw)?EQI_HAND_L:EQI_HAND_R;
if (!(flag&1) || (flag&2)) { //Normal attacks
- atkmin = status->dex;
+ atkmin = st->dex;
if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]])
atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->wlv*20)/100;
@@ -564,11 +567,11 @@ static int battle_calc_base_damage(struct status_data *status, struct weapon_atk
//Finally, add baseatk
if(flag&4)
- damage += status->matk_min;
+ damage += st->matk_min;
else
- damage += status->batk;
+ damage += st->batk;
- //rodatazone says that Overrefine bonuses are part of baseatk
+ //rodatazone says that Overrefined bonuses are part of baseatk
//Here we also apply the weapon_atk_rate bonus so it is correctly applied on left/right hands.
if(sd) {
if (type == EQI_HAND_L) {
@@ -583,11 +586,10 @@ static int battle_calc_base_damage(struct status_data *status, struct weapon_atk
damage += damage * sd->weapon_atk_rate[sd->weapontype1] / 100;
}
}
-#endif
return damage;
}
-int battle_calc_sizefix(struct map_session_data *sd, int damage, int type, int size, bool ignore){
+int64 battle_calc_sizefix(struct map_session_data *sd, int64 damage, int type, int size, bool ignore){
//SizeFix only for players
if (!(sd->special_state.no_sizefix || (ignore)))
damage = damage * ( type == EQI_HAND_L ? sd->left_weapon.atkmods[size] : sd->right_weapon.atkmods[size] ) / 100;
@@ -597,32 +599,31 @@ int battle_calc_sizefix(struct map_session_data *sd, int damage, int type, int s
/*==========================================
* Passive skill damages increases
*------------------------------------------*/
-int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type)
-{
- int damage,skill;
- struct status_data *status = status_get_status_data(target);
- int weapon;
+int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,int64 dmg,int type) {
+ int64 damage;
+ struct status_data *st = status->get_status_data(target);
+ int weapon, skill_lv;
damage = dmg;
nullpo_ret(sd);
- if((skill = pc->checkskill(sd,AL_DEMONBANE)) > 0 &&
- target->type == BL_MOB && //This bonus doesnt work against players.
- (battle->check_undead(status->race,status->def_ele) || status->race==RC_DEMON) )
- damage += (int)(skill*(3+sd->status.base_level/20.0));
- //damage += (skill * 3);
- if( (skill = pc->checkskill(sd, RA_RANGERMAIN)) > 0 && (status->race == RC_BRUTE || status->race == RC_PLANT || status->race == RC_FISH) )
- damage += (skill * 5);
- if( (skill = pc->checkskill(sd,NC_RESEARCHFE)) > 0 && (status->def_ele == ELE_FIRE || status->def_ele == ELE_EARTH) )
- damage += (skill * 10);
+ if((skill_lv = pc->checkskill(sd,AL_DEMONBANE)) > 0 &&
+ target->type == BL_MOB && //This bonus doesn't work against players.
+ (battle->check_undead(st->race,st->def_ele) || st->race==RC_DEMON) )
+ damage += (int)(skill_lv*(3+sd->status.base_level/20.0));
+ //damage += (skill_lv * 3);
+ if( (skill_lv = pc->checkskill(sd, RA_RANGERMAIN)) > 0 && (st->race == RC_BRUTE || st->race == RC_PLANT || st->race == RC_FISH) )
+ damage += (skill_lv * 5);
+ if( (skill_lv = pc->checkskill(sd,NC_RESEARCHFE)) > 0 && (st->def_ele == ELE_FIRE || st->def_ele == ELE_EARTH) )
+ damage += (skill_lv * 10);
if( pc_ismadogear(sd) )
- damage += 20 + 20 * pc->checkskill(sd, NC_MADOLICENCE);
+ damage += 15 * pc->checkskill(sd, NC_MADOLICENCE);
#ifdef RENEWAL
- if( (skill = pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0 )
- damage += (skill * 2);
+ if( (skill_lv = pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0 )
+ damage += (skill_lv * 2);
#endif
- if((skill = pc->checkskill(sd,HT_BEASTBANE)) > 0 && (status->race==RC_BRUTE || status->race==RC_INSECT) ) {
- damage += (skill * 4);
+ if((skill_lv = pc->checkskill(sd,HT_BEASTBANE)) > 0 && (st->race==RC_BRUTE || st->race==RC_INSECT) ) {
+ damage += (skill_lv * 4);
if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_HUNTER)
damage += sd->status.str;
}
@@ -631,76 +632,74 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int
weapon = sd->weapontype1;
else
weapon = sd->weapontype2;
- switch(weapon)
- {
+ switch(weapon) {
case W_1HSWORD:
#ifdef RENEWAL
- if((skill = pc->checkskill(sd,AM_AXEMASTERY)) > 0)
- damage += (skill * 3);
+ if((skill_lv = pc->checkskill(sd,AM_AXEMASTERY)) > 0)
+ damage += (skill_lv * 3);
#endif
case W_DAGGER:
- if((skill = pc->checkskill(sd,SM_SWORD)) > 0)
- damage += (skill * 4);
- if((skill = pc->checkskill(sd,GN_TRAINING_SWORD)) > 0)
- damage += skill * 10;
+ if((skill_lv = pc->checkskill(sd,SM_SWORD)) > 0)
+ damage += (skill_lv * 4);
+ if((skill_lv = pc->checkskill(sd,GN_TRAINING_SWORD)) > 0)
+ damage += skill_lv * 10;
break;
case W_2HSWORD:
#ifdef RENEWAL
- if((skill = pc->checkskill(sd,AM_AXEMASTERY)) > 0)
- damage += (skill * 3);
+ if((skill_lv = pc->checkskill(sd,AM_AXEMASTERY)) > 0)
+ damage += (skill_lv * 3);
#endif
- if((skill = pc->checkskill(sd,SM_TWOHAND)) > 0)
- damage += (skill * 4);
+ if((skill_lv = pc->checkskill(sd,SM_TWOHAND)) > 0)
+ damage += (skill_lv * 4);
break;
case W_1HSPEAR:
case W_2HSPEAR:
- if((skill = pc->checkskill(sd,KN_SPEARMASTERY)) > 0) {
-
- if(!pc_isriding(sd))
- damage += (skill * 4);
- else if(pc_isridingdragon(sd))
- damage += (skill * 10);
+ if((skill_lv = pc->checkskill(sd,KN_SPEARMASTERY)) > 0) {
+ if(pc_isridingdragon(sd))
+ damage += (skill_lv * 10);
+ else if(pc_isriding(sd))
+ damage += (skill_lv * 5);
else
- damage += (skill * 5);
+ damage += (skill_lv * 4);
}
break;
case W_1HAXE:
case W_2HAXE:
- if((skill = pc->checkskill(sd,AM_AXEMASTERY)) > 0)
- damage += (skill * 3);
- if((skill = pc->checkskill(sd,NC_TRAININGAXE)) > 0)
- damage += (skill * 5);
+ if((skill_lv = pc->checkskill(sd,AM_AXEMASTERY)) > 0)
+ damage += (skill_lv * 3);
+ if((skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0)
+ damage += (skill_lv * 5);
break;
case W_MACE:
case W_2HMACE:
- if((skill = pc->checkskill(sd,PR_MACEMASTERY)) > 0)
- damage += (skill * 3);
- if((skill = pc->checkskill(sd,NC_TRAININGAXE)) > 0)
- damage += (skill * 5);
+ if((skill_lv = pc->checkskill(sd,PR_MACEMASTERY)) > 0)
+ damage += (skill_lv * 3);
+ if((skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0)
+ damage += (skill_lv * 5);
break;
case W_FIST:
- if((skill = pc->checkskill(sd,TK_RUN)) > 0)
- damage += (skill * 10);
- // No break, fallthrough to Knuckles
+ if((skill_lv = pc->checkskill(sd,TK_RUN)) > 0)
+ damage += (skill_lv * 10);
+ // No break, fall through to Knuckles
case W_KNUCKLE:
- if((skill = pc->checkskill(sd,MO_IRONHAND)) > 0)
- damage += (skill * 3);
+ if((skill_lv = pc->checkskill(sd,MO_IRONHAND)) > 0)
+ damage += (skill_lv * 3);
break;
case W_MUSICAL:
- if((skill = pc->checkskill(sd,BA_MUSICALLESSON)) > 0)
- damage += (skill * 3);
+ if((skill_lv = pc->checkskill(sd,BA_MUSICALLESSON)) > 0)
+ damage += (skill_lv * 3);
break;
case W_WHIP:
- if((skill = pc->checkskill(sd,DC_DANCINGLESSON)) > 0)
- damage += (skill * 3);
+ if((skill_lv = pc->checkskill(sd,DC_DANCINGLESSON)) > 0)
+ damage += (skill_lv * 3);
break;
case W_BOOK:
- if((skill = pc->checkskill(sd,SA_ADVANCEDBOOK)) > 0)
- damage += (skill * 3);
+ if((skill_lv = pc->checkskill(sd,SA_ADVANCEDBOOK)) > 0)
+ damage += (skill_lv * 3);
break;
case W_KATAR:
- if((skill = pc->checkskill(sd,AS_KATAR)) > 0)
- damage += (skill * 3);
+ if((skill_lv = pc->checkskill(sd,AS_KATAR)) > 0)
+ damage += (skill_lv * 3);
break;
}
@@ -710,19 +709,23 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int
/*==========================================
* Calculates ATK masteries.
*------------------------------------------*/
-int battle_calc_masteryfix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int div, bool left, bool weapon){
- int skill, i;
- struct map_session_data *sd;
+int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int div, bool left, bool weapon) {
+ int skill2_lv, i;
struct status_change *sc;
+ struct map_session_data *sd;
+ struct status_data *tstatus;
nullpo_ret(src);
nullpo_ret(target);
-
+
+ sc = status->get_sc(src);
sd = BL_CAST(BL_PC, src);
- sc = status_get_sc(src);
+ tstatus = status->get_status_data(target);
if ( !sd )
return damage;
+
+ damage = battle->add_mastery(sd, target, damage, left);
switch( skill_id ){ // specific skill masteries
case MO_INVESTIGATE:
@@ -732,119 +735,164 @@ int battle_calc_masteryfix(struct block_list *src, struct block_list *target, ui
case CR_ACIDDEMONSTRATION:
return damage;
case NJ_SYURIKEN:
- if( (skill = pc->checkskill(sd,NJ_TOBIDOUGU)) > 0 && weapon )
- damage += 3 * skill;
- break;
+ if( (skill2_lv = pc->checkskill(sd,NJ_TOBIDOUGU)) > 0
+#ifndef RENEWAL
+ && weapon
+#endif
+ )
+ damage += 3 * skill2_lv;
+ break;
+#ifndef RENEWAL
case NJ_KUNAI:
if( weapon )
damage += 60;
break;
- case RA_WUGDASH:
+#endif
+ case RA_WUGDASH://(Caster Current Weight x 10 / 8)
+ if( sd->weight )
+ damage += sd->weight / 8 ;
case RA_WUGSTRIKE:
- case RA_WUGBITE:
+ case RA_WUGBITE:
damage += 30*pc->checkskill(sd, RA_TOOTHOFWUG);
break;
- }
-
- if ( sc && sc->data[SC_MIRACLE] ) i = 2; //Star anger
- else
- ARR_FIND(0, MAX_PC_FEELHATE, i, status_get_class(target) == sd->hate_mob[i]);
- if ( i < MAX_PC_FEELHATE && (skill=pc->checkskill(sd,sg_info[i].anger_id)) && weapon ){
- int ratio = sd->status.base_level + status_get_dex(src) + status_get_luk(src);
- if ( i == 2 ) ratio += status_get_str(src); //Star Anger
- if (skill < 4 )
- ratio /= (12 - 3 * skill);
- damage += damage * ratio / 100;
+ case HT_FREEZINGTRAP:
+ damage += 40 * pc->checkskill(sd, RA_RESEARCHTRAP);
+ break;
}
- if( sc ){
+ if( sc ){ // sc considered as masteries
if(sc->data[SC_GN_CARTBOOST])
damage += 10 * sc->data[SC_GN_CARTBOOST]->val1;
if(sc->data[SC_CAMOUFLAGE])
damage += 30 * ( 10 - sc->data[SC_CAMOUFLAGE]->val4 );
+#ifdef RENEWAL
+ if(sc->data[SC_NIBELUNGEN] && weapon)
+ damage += sc->data[SC_NIBELUNGEN]->val2;
+ if(sc->data[SC_IMPOSITIO])
+ damage += sc->data[SC_IMPOSITIO]->val2;
+ if(sc->data[SC_DRUMBATTLE]){
+ if(tstatus->size == SZ_MEDIUM)
+ damage += sc->data[SC_DRUMBATTLE]->val2;
+ else if(tstatus->size == SZ_SMALL)
+ damage += 10 * sc->data[SC_DRUMBATTLE]->val1;
+ //else no bonus for large target
+ }
+ if(sc->data[SC_GS_MADNESSCANCEL])
+ damage += 100;
+ if(sc->data[SC_GS_GATLINGFEVER]){
+ if(tstatus->size == SZ_MEDIUM)
+ damage += 10 * sc->data[SC_GS_GATLINGFEVER]->val1;
+ else if(tstatus->size == SZ_SMALL)
+ damage += -5 * sc->data[SC_GS_GATLINGFEVER]->val1;
+ else
+ damage += sc->data[SC_GS_GATLINGFEVER]->val1;
+ }
+ //if(sc->data[SC_SPECIALZONE])
+ // damage += sc->data[SC_SPECIALZONE]->val2 >> 4;
+#endif
}
// general skill masteries
#ifdef RENEWAL
+ if( div < 0 ) // div fix
+ div = 1;
if( skill_id == MO_FINGEROFFENSIVE )//The finger offensive spheres on moment of attack do count. [Skotlex]
damage += div * sd->spiritball_old * 3;
else
damage += div * sd->spiritball * 3;
if( skill_id != CR_SHIELDBOOMERANG ) // Only Shield boomerang doesn't takes the Star Crumbs bonus.
damage += div * (left ? sd->left_weapon.star : sd->right_weapon.star);
+ if( skill_id != MC_CARTREVOLUTION && (skill2_lv=pc->checkskill(sd,BS_HILTBINDING)) > 0 )
+ damage += 4;
+
+ if(sd->status.party_id && (skill2_lv=pc->checkskill(sd,TK_POWER)) > 0) {
+ if( (i = party->foreachsamemap(party->sub_count, sd, 0)) > 1 )
+ damage += 2 * skill2_lv * i * (damage /*+ unknown value*/) / 100 /*+ unknown value*/;
+ }
#else
if( skill_id != ASC_BREAKER && weapon ) // Adv Katar Mastery is does not applies to ASC_BREAKER, but other masteries DO apply >_>
- if( sd->status.weapon == W_KATAR && (skill=pc->checkskill(sd,ASC_KATAR)) > 0 )
- damage += damage * (10 + 2 * skill) / 100;
+ if( sd->status.weapon == W_KATAR && (skill2_lv=pc->checkskill(sd,ASC_KATAR)) > 0 )
+ damage += damage * (10 + 2 * skill2_lv) / 100;
#endif
+ // percentage factor masteries
+ if ( sc && sc->data[SC_MIRACLE] )
+ i = 2; //Star anger
+ else
+ ARR_FIND(0, MAX_PC_FEELHATE, i, status->get_class(target) == sd->hate_mob[i]);
+ if ( i < MAX_PC_FEELHATE && (skill2_lv=pc->checkskill(sd,pc->sg_info[i].anger_id)) && weapon ) {
+ int ratio = sd->status.base_level + status_get_dex(src) + status_get_luk(src);
+ if ( i == 2 ) ratio += status_get_str(src); //Star Anger
+ if (skill2_lv < 4 )
+ ratio /= (12 - 3 * skill2_lv);
+ damage += damage * ratio / 100;
+ }
- damage = battle->add_mastery(sd, target, damage, left);
-
- if((skill = pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
- (status_get_status_data(target)->race == RC_DEMON || status_get_status_data(target)->def_ele == ELE_DARK) )
- damage += damage * skill / 100;
+ if( sd->status.class_ == JOB_ARCH_BISHOP_T || sd->status.class_ == JOB_ARCH_BISHOP ){
+ if((skill2_lv = pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
+ (tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) )
+ damage += damage * skill2_lv / 100;
+ }
return damage;
}
/*==========================================
* Elemental attribute fix.
*------------------------------------------*/
-int battle_calc_elefix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag){
- struct status_data *sstatus, *tstatus;
- struct status_change *sc;
-
+int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag){
+ struct status_data *tstatus;
+
nullpo_ret(src);
nullpo_ret(target);
- sstatus = status_get_status_data(src);
- tstatus = status_get_status_data(target);
- sc = status_get_sc(src);
-
- if( (nk&NK_NO_ELEFIX) && n_ele )
+ tstatus = status->get_status_data(target);
+
+ if( (nk&NK_NO_ELEFIX) || n_ele )
return damage;
- if( damage > 0 )
- {
+ if( damage > 0 ) {
if( left )
damage = battle->attr_fix(src, target, damage, s_ele_, tstatus->def_ele, tstatus->ele_lv);
else{
damage=battle->attr_fix(src, target, damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
if( skill_id == MC_CARTREVOLUTION ) //Cart Revolution applies the element fix once more with neutral element
damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
+ if( skill_id == NC_ARMSCANNON )
+ damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
+ if( skill_id == GN_CARTCANNON )
+ damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
if( skill_id == GS_GROUNDDRIFT ) //Additional 50*lv Neutral damage.
- damage += battle_attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
+ damage += battle->attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
}
}
- if( sc && sc->data[SC_WATK_ELEMENT] )
- { // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex]
- damage =
-#ifndef RENEWAL
- battle->calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, ((TBL_PC*)src), (flag?2:0))
-#else
- battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (flag?2:0)|(sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), 0)
-#endif
- * sc->data[SC_WATK_ELEMENT]->val2 / 100;
-
- damage += battle->attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv);
- if( left ){
- damage =
+
#ifndef RENEWAL
- battle->calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, ((TBL_PC*)src), (flag?2:0))
-#else
- battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_L, (flag?2:0)|(sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), 0)
-#endif
- * sc->data[SC_WATK_ELEMENT]->val2 / 100;
- damage += battle->attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv);
+ {
+ struct status_data *sstatus;
+ struct status_change *sc;
+
+ sstatus = status->get_status_data(src);
+ sc = status->get_sc(src);
+
+ if( sc && sc->data[SC_SUB_WEAPONPROPERTY] ) { // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex]
+ int64 temp = battle->calc_base_damage2(sstatus, &sstatus->rhw, sc, tstatus->size, BL_CAST(BL_PC, src), (flag?2:0)) * sc->data[SC_SUB_WEAPONPROPERTY]->val2 / 100;
+ damage += battle->attr_fix(src, target, temp, sc->data[SC_SUB_WEAPONPROPERTY]->val1, tstatus->def_ele, tstatus->ele_lv);
+ if( left ) {
+ temp = battle->calc_base_damage2(sstatus, &sstatus->lhw, sc, tstatus->size, BL_CAST(BL_PC, src), (flag?2:0)) * sc->data[SC_SUB_WEAPONPROPERTY]->val2 / 100;
+ damage += battle->attr_fix(src, target, temp, sc->data[SC_SUB_WEAPONPROPERTY]->val1, tstatus->def_ele, tstatus->ele_lv);
}
+ }
}
-
+#endif
return damage;
}
/*==========================================
* Calculates card bonuses damage adjustments.
+ * cflag(cardfix flag):
+ * &1 - calc for left hand.
+ * &2 - atker side cardfix(BF_WEAPON) otherwise target side(BF_WEAPON).
*------------------------------------------*/
-int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int damage, int left, int flag){
+int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int cflag, int wflag){
struct map_session_data *sd, *tsd;
short cardfix = 1000, t_class, s_class, s_race2, t_race2;
struct status_data *sstatus, *tstatus;
@@ -858,24 +906,24 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, target);
- t_class = status_get_class(target);
- s_class = status_get_class(src);
- sstatus = status_get_status_data(src);
- tstatus = status_get_status_data(target);
- s_race2 = status_get_race2(src);
-
+ t_class = status->get_class(target);
+ s_class = status->get_class(src);
+ sstatus = status->get_status_data(src);
+ tstatus = status->get_status_data(target);
+ s_race2 = status->get_race2(src);
+
switch(attack_type){
case BF_MAGIC:
if ( sd && !(nk&NK_NO_CARDFIX_ATK) ) {
- cardfix=cardfix*(100+sd->magic_addrace[tstatus->race])/100;
+ cardfix = cardfix * (100 + sd->magic_addrace[tstatus->race]) / 100;
if (!(nk&NK_NO_ELEFIX))
- cardfix=cardfix*(100+sd->magic_addele[tstatus->def_ele])/100;
- cardfix=cardfix*(100+sd->magic_addsize[tstatus->size])/100;
- cardfix=cardfix*(100+sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
- cardfix=cardfix*(100+sd->magic_atk_ele[s_ele])/100;
- for(i=0; i< ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate;i++) {
+ cardfix = cardfix*(100+sd->magic_addele[tstatus->def_ele]) / 100;
+ cardfix = cardfix * (100 + sd->magic_addsize[tstatus->size]) / 100;
+ cardfix = cardfix * (100 + sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100;
+ cardfix = cardfix * (100 + sd->magic_atk_ele[s_ele])/100;
+ for(i=0; i< ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate; i++) {
if(sd->add_mdmg[i].class_ == t_class) {
- cardfix=cardfix*(100+sd->add_mdmg[i].rate)/100;
+ cardfix = cardfix * (100 + sd->add_mdmg[i].rate) / 100;
break;
}
}
@@ -891,225 +939,217 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
{
if(tsd->subele2[i].ele != s_ele) continue;
- if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK &&
- tsd->subele2[i].flag&flag&BF_RANGEMASK &&
- tsd->subele2[i].flag&flag&BF_SKILLMASK))
+ if(!(tsd->subele2[i].flag&wflag&BF_WEAPONMASK &&
+ tsd->subele2[i].flag&wflag&BF_RANGEMASK &&
+ tsd->subele2[i].flag&wflag&BF_SKILLMASK))
continue;
ele_fix += tsd->subele2[i].rate;
}
- cardfix=cardfix*(100-ele_fix)/100;
+ cardfix = cardfix * (100 - ele_fix) / 100;
}
- cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
- cardfix=cardfix*(100-tsd->subrace2[s_race2])/100;
- cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
- cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
+ cardfix = cardfix * (100 - tsd->subsize[sstatus->size]) / 100;
+ cardfix = cardfix * (100 - tsd->subrace2[s_race2]) / 100;
+ cardfix = cardfix * (100 - tsd->subrace[sstatus->race]) / 100;
+ cardfix = cardfix * (100 - tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100;
if( sstatus->race != RC_DEMIHUMAN )
- cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100;
+ cardfix = cardfix * (100-tsd->subrace[RC_NONDEMIHUMAN]) / 100;
for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) {
if(tsd->add_mdef[i].class_ == s_class) {
- cardfix=cardfix*(100-tsd->add_mdef[i].rate)/100;
+ cardfix = cardfix * (100-tsd->add_mdef[i].rate) / 100;
break;
}
}
+#ifndef RENEWAL
//It was discovered that ranged defense also counts vs magic! [Skotlex]
- if ( flag&BF_SHORT )
+ if ( wflag&BF_SHORT )
cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100;
else
cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100;
+#endif
cardfix = cardfix * ( 100 - tsd->bonus.magic_def_rate ) / 100;
if( tsd->sc.data[SC_PROTECT_MDEF] )
cardfix = cardfix * ( 100 - tsd->sc.data[SC_PROTECT_MDEF]->val1 ) / 100;
- if (cardfix != 1000)
+ if( cardfix != 1000 )
damage = damage * cardfix / 1000;
}
break;
case BF_WEAPON:
- t_race2 = status_get_race2(target);
- if( sd && !(nk&NK_NO_CARDFIX_ATK) && (left&2) )
- {
- short cardfix_ = 1000;
- if(sd->state.arrow_atk)
- {
- cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->arrow_addrace[tstatus->race])/100;
- if (!(nk&NK_NO_ELEFIX))
- {
- int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele];
- for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) {
- if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue;
- if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK &&
- sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK &&
- sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK))
- continue;
- ele_fix += sd->right_weapon.addele2[i].rate;
- }
- cardfix=cardfix*(100+ele_fix)/100;
- }
- cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100;
- cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100;
- cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
- if( tstatus->race != RC_DEMIHUMAN )
- cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN])/100;
- }
- else
- { // Melee attack
- if( !battle_config.left_cardfix_to_right )
- {
- cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100;
- if (!(nk&NK_NO_ELEFIX)) {
- int ele_fix = sd->right_weapon.addele[tstatus->def_ele];
- for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) {
+ t_race2 = status->get_race2(target);
+ if( cflag&2 ){
+ if( sd && !(nk&NK_NO_CARDFIX_ATK) ){
+ short cardfix_ = 1000;
+ if( sd->state.arrow_atk ){
+ cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->arrow_addrace[tstatus->race]) / 100;
+ if( !(nk&NK_NO_ELEFIX) ){
+ int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele];
+ for(i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++){
if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue;
- if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK &&
- sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK &&
- sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK))
+ if(!(sd->right_weapon.addele2[i].flag&wflag&BF_WEAPONMASK &&
+ sd->right_weapon.addele2[i].flag&wflag&BF_RANGEMASK &&
+ sd->right_weapon.addele2[i].flag&wflag&BF_SKILLMASK))
continue;
ele_fix += sd->right_weapon.addele2[i].rate;
}
- cardfix=cardfix*(100+ele_fix)/100;
+ cardfix = cardfix * (100 + ele_fix) / 100;
}
- cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100;
- cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100;
- cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
+ cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size]) / 100;
+ cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2]) / 100;
+ cardfix = cardfix * (100 + sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS] + sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100;
if( tstatus->race != RC_DEMIHUMAN )
- cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN])/100;
-
- if( left&1 )
- {
- cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100;
- if (!(nk&NK_NO_ELEFIX)) {
- int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele];
- for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) {
- if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue;
- if(!(sd->left_weapon.addele2[i].flag&flag&BF_WEAPONMASK &&
- sd->left_weapon.addele2[i].flag&flag&BF_RANGEMASK &&
- sd->left_weapon.addele2[i].flag&flag&BF_SKILLMASK))
+ cardfix = cardfix * (100 + sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN]) / 100;
+ }else{ // Melee attack
+ if( !battle_config.left_cardfix_to_right ){
+ cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100;
+ if( !(nk&NK_NO_ELEFIX) ){
+ int ele_fix = sd->right_weapon.addele[tstatus->def_ele];
+ for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) {
+ if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue;
+ if(!(sd->right_weapon.addele2[i].flag&wflag&BF_WEAPONMASK &&
+ sd->right_weapon.addele2[i].flag&wflag&BF_RANGEMASK &&
+ sd->right_weapon.addele2[i].flag&wflag&BF_SKILLMASK))
continue;
- ele_fix_lh += sd->left_weapon.addele2[i].rate;
+ ele_fix += sd->right_weapon.addele2[i].rate;
+ }
+ cardfix = cardfix * (100+ele_fix) / 100;
+ }
+ cardfix = cardfix * (100+sd->right_weapon.addsize[tstatus->size]) / 100;
+ cardfix = cardfix * (100+sd->right_weapon.addrace2[t_race2]) / 100;
+ cardfix = cardfix * (100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100;
+ if( tstatus->race != RC_DEMIHUMAN )
+ cardfix = cardfix * (100 + sd->right_weapon.addrace[RC_NONDEMIHUMAN]) / 100;
+
+ if( cflag&1 ){
+ cardfix_ = cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100;
+ if (!(nk&NK_NO_ELEFIX)){
+ int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele];
+ for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) {
+ if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue;
+ if(!(sd->left_weapon.addele2[i].flag&wflag&BF_WEAPONMASK &&
+ sd->left_weapon.addele2[i].flag&wflag&BF_RANGEMASK &&
+ sd->left_weapon.addele2[i].flag&wflag&BF_SKILLMASK))
+ continue;
+ ele_fix_lh += sd->left_weapon.addele2[i].rate;
+ }
+ cardfix = cardfix * (100+ele_fix_lh) / 100;
}
- cardfix=cardfix*(100+ele_fix_lh)/100;
+ cardfix_ = cardfix_ * (100+sd->left_weapon.addsize[tstatus->size]) / 100;
+ cardfix_ = cardfix_ * (100+sd->left_weapon.addrace2[t_race2]) / 100;
+ cardfix_ = cardfix_ * (100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100;
+ if( tstatus->race != RC_DEMIHUMAN )
+ cardfix_ = cardfix_*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100;
+ }
+ }else{
+ int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele];
+ for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++){
+ if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue;
+ if(!(sd->right_weapon.addele2[i].flag&wflag&BF_WEAPONMASK &&
+ sd->right_weapon.addele2[i].flag&wflag&BF_RANGEMASK &&
+ sd->right_weapon.addele2[i].flag&wflag&BF_SKILLMASK))
+ continue;
+ ele_fix += sd->right_weapon.addele2[i].rate;
+ }
+ for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++){
+ if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue;
+ if(!(sd->left_weapon.addele2[i].flag&wflag&BF_WEAPONMASK &&
+ sd->left_weapon.addele2[i].flag&wflag&BF_RANGEMASK &&
+ sd->left_weapon.addele2[i].flag&wflag&BF_SKILLMASK))
+ continue;
+ ele_fix += sd->left_weapon.addele2[i].rate;
}
- cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100;
- cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100;
- cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
+
+ cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->left_weapon.addrace[tstatus->race]) / 100;
+ cardfix = cardfix * (100 + ele_fix) / 100;
+ cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size] + sd->left_weapon.addsize[tstatus->size])/100;
+ cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2] + sd->left_weapon.addrace2[t_race2])/100;
+ cardfix = cardfix * (100 + sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS] + sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100;
if( tstatus->race != RC_DEMIHUMAN )
- cardfix_=cardfix_*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100;
+ cardfix = cardfix * (100+sd->right_weapon.addrace[RC_NONDEMIHUMAN] + sd->left_weapon.addrace[RC_NONDEMIHUMAN]) / 100;
}
}
- else
- {
- int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele];
- for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) {
- if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue;
- if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK &&
- sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK &&
- sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK))
- continue;
- ele_fix += sd->right_weapon.addele2[i].rate;
- }
- for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) {
- if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue;
- if(!(sd->left_weapon.addele2[i].flag&flag&BF_WEAPONMASK &&
- sd->left_weapon.addele2[i].flag&flag&BF_RANGEMASK &&
- sd->left_weapon.addele2[i].flag&flag&BF_SKILLMASK))
- continue;
- ele_fix += sd->left_weapon.addele2[i].rate;
+
+ for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ ){
+ if( sd->right_weapon.add_dmg[i].class_ == t_class ){
+ cardfix = cardfix * (100 + sd->right_weapon.add_dmg[i].rate) / 100;
+ break;
}
+ }
- cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100;
- cardfix=cardfix*(100+ele_fix)/100;
- cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100;
- cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100;
- cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
- if( tstatus->race != RC_DEMIHUMAN )
- cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100;
+ if( cflag&1 ){
+ for( i = 0; i < ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate; i++ ){
+ if( sd->left_weapon.add_dmg[i].class_ == t_class ){
+ cardfix_ = cardfix_ * (100 + sd->left_weapon.add_dmg[i].rate) / 100;
+ break;
+ }
+ }
}
+#ifndef RENEWAL
+ if( wflag&BF_LONG )
+ cardfix = cardfix * (100 + sd->bonus.long_attack_atk_rate) / 100;
+#endif
+ if( (cflag&1) && cardfix_ != 1000 )
+ damage = damage * cardfix_ / 1000;
+ else if( cardfix != 1000 )
+ damage = damage * cardfix / 1000;
}
- for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ )
- {
- if( sd->right_weapon.add_dmg[i].class_ == t_class )
- {
- cardfix=cardfix*(100+sd->right_weapon.add_dmg[i].rate)/100;
- break;
+ }else{
+ // Target side
+ if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){
+ if( !(nk&NK_NO_ELEFIX) ){
+ int ele_fix = tsd->subele[s_ele];
+ for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
+ {
+ if(tsd->subele2[i].ele != s_ele) continue;
+ if(!(tsd->subele2[i].flag&wflag&BF_WEAPONMASK &&
+ tsd->subele2[i].flag&wflag&BF_RANGEMASK &&
+ tsd->subele2[i].flag&wflag&BF_SKILLMASK))
+ continue;
+ ele_fix += tsd->subele2[i].rate;
+ }
+ cardfix = cardfix * (100-ele_fix) / 100;
+ if( cflag&1 && s_ele_ != s_ele ){
+ int ele_fix_lh = tsd->subele[s_ele_];
+ for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++){
+ if(tsd->subele2[i].ele != s_ele_) continue;
+ if(!(tsd->subele2[i].flag&wflag&BF_WEAPONMASK &&
+ tsd->subele2[i].flag&wflag&BF_RANGEMASK &&
+ tsd->subele2[i].flag&wflag&BF_SKILLMASK))
+ continue;
+ ele_fix_lh += tsd->subele2[i].rate;
+ }
+ cardfix = cardfix * (100 - ele_fix_lh) / 100;
+ }
}
- }
-
- if( left&1 )
- {
- for( i = 0; i < ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate; i++ )
- {
- if( sd->left_weapon.add_dmg[i].class_ == t_class )
+ cardfix = cardfix * (100-tsd->subsize[sstatus->size]) / 100;
+ cardfix = cardfix * (100-tsd->subrace2[s_race2]) / 100;
+ cardfix = cardfix * (100-tsd->subrace[sstatus->race]) / 100;
+ cardfix = cardfix * (100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100;
+ if( sstatus->race != RC_DEMIHUMAN )
+ cardfix = cardfix * (100-tsd->subrace[RC_NONDEMIHUMAN]) / 100;
+
+ for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ ){
+ if( tsd->add_def[i].class_ == s_class )
{
- cardfix_=cardfix_*(100+sd->left_weapon.add_dmg[i].rate)/100;
+ cardfix = cardfix * (100 - tsd->add_def[i].rate) / 100;
break;
}
}
- }
- if( flag&BF_LONG )
- cardfix = cardfix * ( 100 + sd->bonus.long_attack_atk_rate ) / 100;
- if( (left&1) && cardfix_ != 1000 )
- damage = damage * cardfix_ / 1000;
- else if( cardfix != 1000 )
- damage = damage * cardfix / 1000;
+ if( wflag&BF_SHORT )
+ cardfix = cardfix * (100 - tsd->bonus.near_attack_def_rate) / 100;
+ else // BF_LONG (there's no other choice)
+ cardfix = cardfix * (100 - tsd->bonus.long_attack_def_rate) / 100;
- }else if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){
- if( !(nk&NK_NO_ELEFIX) )
- {
- int ele_fix = tsd->subele[s_ele];
- for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
- {
- if(tsd->subele2[i].ele != s_ele) continue;
- if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK &&
- tsd->subele2[i].flag&flag&BF_RANGEMASK &&
- tsd->subele2[i].flag&flag&BF_SKILLMASK))
- continue;
- ele_fix += tsd->subele2[i].rate;
- }
- cardfix=cardfix*(100-ele_fix)/100;
- if( left&1 && s_ele_ != s_ele )
- {
- int ele_fix_lh = tsd->subele[s_ele_];
- for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
- {
- if(tsd->subele2[i].ele != s_ele_) continue;
- if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK &&
- tsd->subele2[i].flag&flag&BF_RANGEMASK &&
- tsd->subele2[i].flag&flag&BF_SKILLMASK))
- continue;
- ele_fix_lh += tsd->subele2[i].rate;
- }
- cardfix=cardfix*(100-ele_fix_lh)/100;
- }
- }
- cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
- cardfix=cardfix*(100-tsd->subrace2[s_race2])/100;
- cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
- cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
- if( sstatus->race != RC_DEMIHUMAN )
- cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100;
+ if( tsd->sc.data[SC_PROTECT_DEF] )
+ cardfix = cardfix * (100 - tsd->sc.data[SC_PROTECT_DEF]->val1) / 100;
- for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ ) {
- if( tsd->add_def[i].class_ == s_class ) {
- cardfix=cardfix*(100-tsd->add_def[i].rate)/100;
- break;
+ if( cardfix != 1000 )
+ damage = damage * cardfix / 1000;
}
}
-
- if( flag&BF_SHORT )
- cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100;
- else // BF_LONG (there's no other choice)
- cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100;
-
- if( tsd->sc.data[SC_PROTECT_DEF] )
- cardfix = cardfix * ( 100 - tsd->sc.data[SC_PROTECT_DEF]->val1 ) / 100;
-
- if( cardfix != 1000 )
- damage = damage * cardfix / 1000;
- }
break;
case BF_MISC:
if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){
@@ -1120,25 +1160,25 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
{
if(tsd->subele2[i].ele != s_ele) continue;
- if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK &&
- tsd->subele2[i].flag&flag&BF_RANGEMASK &&
- tsd->subele2[i].flag&flag&BF_SKILLMASK))
+ if(!(tsd->subele2[i].flag&wflag&BF_WEAPONMASK &&
+ tsd->subele2[i].flag&wflag&BF_RANGEMASK &&
+ tsd->subele2[i].flag&wflag&BF_SKILLMASK))
continue;
ele_fix += tsd->subele2[i].rate;
}
- cardfix=cardfix*(100-ele_fix)/100;
+ cardfix = cardfix * (100 - ele_fix) / 100;
}
- cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
- cardfix=cardfix*(100-tsd->subrace2[s_race2])/100;
- cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
- cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
+ cardfix = cardfix*(100-tsd->subsize[sstatus->size]) / 100;
+ cardfix = cardfix*(100-tsd->subrace2[s_race2]) / 100;
+ cardfix = cardfix*(100-tsd->subrace[sstatus->race]) / 100;
+ cardfix = cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100;
if( sstatus->race != RC_DEMIHUMAN )
- cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100;
+ cardfix = cardfix * (100 - tsd->subrace[RC_NONDEMIHUMAN]) / 100;
cardfix = cardfix * ( 100 - tsd->bonus.misc_def_rate ) / 100;
- if( flag&BF_SHORT )
+ if( wflag&BF_SHORT )
cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100;
- else // BF_LONG (there's no other choice)
+ else // BF_LONG (there's no other choice)
cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100;
if (cardfix != 1000)
@@ -1157,7 +1197,7 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
* &2 - pdef(Pierce defense)
* &4 - tdef(Total defense reduction)
*------------------------------------------*/
-int battle_calc_defense(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int flag, int pdef){
+int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int flag, int pdef){
struct status_data *sstatus, *tstatus;
struct map_session_data *sd, *tsd;
struct status_change *sc, *tsc;
@@ -1171,10 +1211,10 @@ int battle_calc_defense(int attack_type, struct block_list *src, struct block_li
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, target);
- sstatus = status_get_status_data(src);
- tstatus = status_get_status_data(target);
- sc = status_get_sc(src);
- tsc = status_get_sc(target);
+ sstatus = status->get_status_data(src);
+ tstatus = status->get_status_data(target);
+ sc = status->get_sc(src);
+ tsc = status->get_sc(target);
switch(attack_type){
case BF_WEAPON:
@@ -1183,14 +1223,14 @@ int battle_calc_defense(int attack_type, struct block_list *src, struct block_li
* def1 = equip def
* def2 = status def
**/
- defType def1 = status_get_def(target); //Don't use tstatus->def1 due to skill timer reductions.
+ defType def1 = status->get_def(target); //Don't use tstatus->def1 due to skill timer reductions.
short def2 = tstatus->def2, vit_def;
-#ifdef RENEWAL
- def1 = status_calc_def2(target, tsc, def1, false); // equip def(RE)
- def2 = status_calc_def(target, tsc, def2, false); // status def(RE)
+#ifdef RENEWAL
+ def1 = status->calc_def2(target, tsc, def1, false); // equip def(RE)
+ def2 = status->calc_def(target, tsc, def2, false); // status def(RE)
#else
- def1 = status_calc_def(target, tsc, def1, false); // equip def(RE)
- def2 = status_calc_def2(target, tsc, def2, false); // status def(RE)
+ def1 = status->calc_def(target, tsc, def1, false); // equip def(RE)
+ def2 = status->calc_def2(target, tsc, def2, false); // status def(RE)
#endif
if( sd ){
@@ -1211,7 +1251,7 @@ int battle_calc_defense(int attack_type, struct block_list *src, struct block_li
if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) {
unsigned char target_count; //256 max targets should be a sane max
- target_count = unit_counttargeted(target);
+ target_count = unit->counttargeted(target);
if(target_count >= battle_config.vit_penalty_count) {
if(battle_config.vit_penalty_type == 1) {
if( !tsc || !tsc->data[SC_STEELBODY] )
@@ -1236,9 +1276,9 @@ int battle_calc_defense(int attack_type, struct block_list *src, struct block_li
#else
vit_def = def2;
#endif
- if((battle->check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesnt work vs players
+ if((battle->check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesn't work vs players
src->type == BL_MOB && (i=pc->checkskill(tsd,AL_DP)) > 0)
- vit_def += i*(int)(3 +(tsd->status.base_level+1)*0.04); // submitted by orn
+ vit_def += i*(int)(3 +(tsd->status.base_level+1)*0.04); // [orn]
if( src->type == BL_MOB && (i=pc->checkskill(tsd,RA_RANGERMAIN))>0 &&
(sstatus->race == RC_BRUTE || sstatus->race == RC_FISH || sstatus->race == RC_PLANT) )
vit_def += i*5;
@@ -1260,12 +1300,12 @@ int battle_calc_defense(int attack_type, struct block_list *src, struct block_li
#ifdef RENEWAL
/**
* RE DEF Reduction
- * Damage = Attack * (4000+eDEF)/(4000+eDEF*10) - sDEF
- * Pierce defence gains 1 atk per def/2
+ * Pierce defense gains 1 atk per def/2
**/
- if( def1 == -400 ) /* being hit by a gazillion units, you hit the jackpot and got -400 which creates a division by 0 and subsequently crashes */
- def1 = -399;
+ if( def1 < -399 ) // it stops at -399
+ def1 = 399; // in aegis it set to 1 but in our case it may lead to exploitation so limit it to 399
+ //return 1;
if( flag&2 )
damage += def1 >> 1;
@@ -1274,7 +1314,7 @@ int battle_calc_defense(int attack_type, struct block_list *src, struct block_li
if( flag&4 )
damage -= (def1 + vit_def);
else
- damage = damage * (4000+def1) / (4000+10*def1) - vit_def;
+ damage = (int)((100.0f - def1 / (def1 + 400.0f) * 90.0f) / 100.0f * damage - vit_def);
}
#else
@@ -1296,11 +1336,11 @@ int battle_calc_defense(int attack_type, struct block_list *src, struct block_li
defType mdef = tstatus->mdef;
short mdef2= tstatus->mdef2;
#ifdef RENEWAL
- mdef2 = status_calc_mdef(target, tsc, mdef2, false); // status mdef(RE)
- mdef = status_calc_mdef2(target, tsc, mdef, false); // equip mde(RE)
+ mdef2 = status->calc_mdef(target, tsc, mdef2, false); // status mdef(RE)
+ mdef = status->calc_mdef2(target, tsc, mdef, false); // equip mde(RE)
#else
- mdef2 = status_calc_mdef2(target, tsc, mdef2, false); // status mdef(RE)
- mdef = status_calc_mdef(target, tsc, mdef, false); // equip mde(RE)
+ mdef2 = status->calc_mdef2(target, tsc, mdef2, false); // status mdef(RE)
+ mdef = status->calc_mdef(target, tsc, mdef, false); // equip mde(RE)
#endif
if( flag&1 )
mdef = 0;
@@ -1318,9 +1358,12 @@ int battle_calc_defense(int attack_type, struct block_list *src, struct block_li
#ifdef RENEWAL
/**
* RE MDEF Reduction
- * Damage = Magic Attack * (1000+eMDEF)/(1000+eMDEF) - sMDEF
**/
- damage = damage * (1000 + mdef) / (1000 + mdef * 10) - mdef2;
+ if( mdef < -99 ) // it stops at -99
+ mdef = 99; // in aegis it set to 1 but in our case it may lead to exploitation so limit it to 99
+ //return 1;
+
+ damage = (int)((100.0f - mdef / (mdef + 100.0f) * 90.0f) / 100.0f * damage - mdef2);
#else
if(battle_config.magic_defense_type)
damage = damage - mdef*battle_config.magic_defense_type - mdef2;
@@ -1333,23 +1376,37 @@ int battle_calc_defense(int attack_type, struct block_list *src, struct block_li
return damage;
}
+// Minstrel/Wanderer number check for chorus skills.
+int battle_calc_chorusbonus(struct map_session_data *sd) {
+ int members = 0;
+
+ if (!sd || !sd->status.party_id)
+ return 0;
+
+ members = party->foreachsamemap(party->sub_count_chorus, sd, 0);
+
+ if (members < 3)
+ return 0; // Bonus remains 0 unless 3 or more Minstrel's/Wanderer's are in the party.
+ if (members > 7)
+ return 5; // Maximum effect possible from 7 or more Minstrel's/Wanderer's
+ return members - 2; // Effect bonus from additional Minstrel's/Wanderer's if not above the max possible
+}
+
int battle_calc_skillratio(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int skillratio, int flag){
- int i, addedratio;
+ int i;
struct status_change *sc, *tsc;
struct map_session_data *sd, *tsd;
- struct status_data *status, *tstatus;
+ struct status_data *st, *tst;
nullpo_ret(src);
nullpo_ret(target);
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, target);
- sc = status_get_sc(src);
- tsc = status_get_sc(target);
- status = status_get_status_data(src);
- tstatus = status_get_status_data(target);
-
- addedratio = skillratio - 100;
+ sc = status->get_sc(src);
+ tsc = status->get_sc(target);
+ st = status->get_status_data(src);
+ tst = status->get_status_data(target);
switch(attack_type){
case BF_MAGIC:
@@ -1365,7 +1422,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
#endif
break;
case MG_SOULSTRIKE:
- if (battle->check_undead(tstatus->race,tstatus->def_ele))
+ if (battle->check_undead(tst->race,tst->def_ele))
skillratio += 5*skill_lv;
break;
case MG_FIREWALL:
@@ -1412,13 +1469,13 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 10 * skill_lv - 30;
break;
case SL_STIN:
- skillratio += (tstatus->size!=SZ_SMALL?-99:10*skill_lv); //target size must be small (0) for full damage.
+ skillratio += (tst->size!=SZ_SMALL?-99:10*skill_lv); //target size must be small (0) for full damage.
break;
case SL_STUN:
- skillratio += (tstatus->size!=SZ_BIG?5*skill_lv:-99); //Full damage is dealt on small/medium targets
+ skillratio += (tst->size!=SZ_BIG?5*skill_lv:-99); //Full damage is dealt on small/medium targets
break;
case SL_SMA:
- skillratio += -60 + status_get_lv(src); //Base damage is 40% + lv%
+ skillratio += -60 + status->get_lv(src); //Base damage is 40% + lv%
break;
case NJ_KOUENKA:
skillratio -= 10;
@@ -1471,25 +1528,24 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
* Arch Bishop
**/
case AB_JUDEX:
- skillratio += 180 + 20 * skill_lv;
- if (skill_lv > 4) skillratio += 20;
+ skillratio = 300 + 20 * skill_lv;
RE_LVL_DMOD(100);
break;
case AB_ADORAMUS:
- skillratio += 400 + 100 * skill_lv;
+ skillratio = 500 + 100 * skill_lv;
RE_LVL_DMOD(100);
break;
case AB_DUPLELIGHT_MAGIC:
- skillratio += 100 + 20 * skill_lv;
+ skillratio = 200 + 20 * skill_lv;
break;
/**
* Warlock
**/
- case WL_SOULEXPANSION: // MATK [{( Skill Level + 4 ) x 100 ) + ( Caster?s INT )} x ( Caster?s Base Level / 100 )] %
- skillratio += 300 + 100 * skill_lv + status_get_int(src);
+ case WL_SOULEXPANSION: // MATK [{( Skill Level + 4 ) x 100 ) + ( Caster's INT )} x ( Caster's Base Level / 100 )] %
+ skillratio = 100 * (skill_lv + 4) + st->int_;
RE_LVL_DMOD(100);
break;
- case WL_FROSTMISTY: // MATK [{( Skill Level x 100 ) + 200 } x ( Caster痴 Base Level / 100 )] %
+ case WL_FROSTMISTY: // MATK [{( Skill Level x 100 ) + 200 } x ( Caster's Base Level / 100 )] %
skillratio += 100 + 100 * skill_lv;
RE_LVL_DMOD(100);
break;
@@ -1532,14 +1588,14 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
if( sd && sd->status.party_id ){
struct map_session_data* psd;
- int static p_sd[5] = {0, 0, 0, 0, 0}, c; // just limit it to 5
+ int p_sd[5] = {0, 0, 0, 0, 0}, c; // just limit it to 5
c = 0;
memset (p_sd, 0, sizeof(p_sd));
- party_foreachsamemap(skill->check_condition_char_sub, sd, 3, &sd->bl, &c, &p_sd, skill_id);
- c = ( c > 1 ? rand()%c : 0 );
+ party->foreachsamemap(skill->check_condition_char_sub, sd, 3, &sd->bl, &c, &p_sd, skill_id);
+ c = ( c > 1 ? rnd()%c : 0 );
- if( (psd = iMap->id2sd(p_sd[c])) && pc->checkskill(psd,WL_COMET) > 0 ){
+ if( (psd = map->id2sd(p_sd[c])) && pc->checkskill(psd,WL_COMET) > 0 ){
skillratio = skill_lv * 400; //MATK [{( Skill Level x 400 ) x ( Caster's Base Level / 120 )} + 2500 ] %
RE_LVL_DMOD(120);
skillratio += 2500;
@@ -1554,7 +1610,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 100 * flag;
break;
case WL_EARTHSTRAIN:
- skillratio += 1900 + 100 * skill_lv;
+ skillratio = 2000 + 100 * skill_lv;
RE_LVL_DMOD(100);
break;
case WL_TETRAVORTEX_FIRE:
@@ -1567,107 +1623,91 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
case WL_SUMMON_ATK_WATER:
case WL_SUMMON_ATK_WIND:
case WL_SUMMON_ATK_GROUND:
- skillratio = skill_lv * (status_get_lv(src) + ( sd ? sd->status.job_level : 50 ));// This is close to official, but lacking a little info to finalize. [Rytech]
+ skillratio = (1 + skill_lv) / 2 * (status->get_lv(src) + (sd ? sd->status.job_level : 50));
RE_LVL_DMOD(100);
break;
case LG_RAYOFGENESIS:
{
- int16 lv = skill_lv;
+ uint16 lv = skill_lv;
int bandingBonus = 0;
if( sc && sc->data[SC_BANDING] )
bandingBonus = 200 * (sd ? skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),0) : 1);
skillratio = ((300 * skill_lv) + bandingBonus) * (sd ? sd->status.job_level : 1) / 25;
}
- break;
- case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield MDEF x 100) + (Casters INT x 2)] %
- if( sd ) {
- skillratio = status_get_lv(src) * 4 + sd->bonus.shieldmdef * 100 + status_get_int(src) * 2;
- } else
- skillratio += 1900; //2000%
break;
- case WM_METALICSOUND:
- skillratio += 120 * skill_lv + 60 * ( sd? pc->checkskill(sd, WM_LESSON) : 10 ) - 100;
+ case LG_SHIELDSPELL:
+ if ( sd && skill_lv == 2 ) // [(Casters Base Level x 4) + (Shield MDEF x 100) + (Casters INT x 2)] %
+ skillratio = 4 * status->get_lv(src) + 100 * sd->bonus.shieldmdef + 2 * st->int_;
+ else
+ skillratio = 0;
break;
- /*case WM_SEVERE_RAINSTORM:
- skillratio += 50 * skill_lv;
+ case WM_METALICSOUND:
+ skillratio = 120 * skill_lv + 60 * ( sd? pc->checkskill(sd, WM_LESSON) : 10 );
+ RE_LVL_DMOD(100);
break;
-
- WM_SEVERE_RAINSTORM just set a unit place,
- refer to WM_SEVERE_RAINSTORM_MELEE to set the formula.
- */
case WM_REVERBERATION_MAGIC:
- // MATK [{(Skill Level x 100) + 100} x Casters Base Level / 100] %
- skillratio += 100 * (sd ? pc->checkskill(sd, WM_REVERBERATION) : 1);
+ skillratio = 100 * skill_lv + 100;
RE_LVL_DMOD(100);
break;
case SO_FIREWALK:
- skillratio = 300;
+ skillratio = 60 * skill_lv;
RE_LVL_DMOD(100);
if( sc && sc->data[SC_HEATER_OPTION] )
- skillratio += sc->data[SC_HEATER_OPTION]->val3;
+ skillratio += sc->data[SC_HEATER_OPTION]->val3 / 2;
break;
case SO_ELECTRICWALK:
- skillratio = 300;
+ skillratio = 60 * skill_lv;
RE_LVL_DMOD(100);
if( sc && sc->data[SC_BLAST_OPTION] )
- skillratio += sd ? sd->status.job_level / 2 : 0;
+ skillratio += sc->data[SC_BLAST_OPTION]->val2 / 2;
break;
case SO_EARTHGRAVE:
- skillratio = ( 200 * ( sd ? pc->checkskill(sd, SA_SEISMICWEAPON) : 10 ) + status_get_int(src) * skill_lv );
+ skillratio = st->int_ * skill_lv + 200 * (sd ? pc->checkskill(sd,SA_SEISMICWEAPON) : 1);
RE_LVL_DMOD(100);
if( sc && sc->data[SC_CURSED_SOIL_OPTION] )
- skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2;
+ skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3 * 5;
break;
case SO_DIAMONDDUST:
- skillratio = ( 200 * ( sd ? pc->checkskill(sd, SA_FROSTWEAPON) : 10 ) + status_get_int(src) * skill_lv );
- RE_LVL_DMOD(100);
+ skillratio = (st->int_ * skill_lv + 200 * (sd ? pc->checkskill(sd, SA_FROSTWEAPON) : 1)) * status->get_lv(src) / 100;
if( sc && sc->data[SC_COOLER_OPTION] )
- skillratio += sc->data[SC_COOLER_OPTION]->val3;
+ skillratio += sc->data[SC_COOLER_OPTION]->val3 * 5;
break;
case SO_POISON_BUSTER:
- skillratio += 1100 + 300 * skill_lv;
+ skillratio += 900 + 300 * skill_lv;
+ RE_LVL_DMOD(100);
if( sc && sc->data[SC_CURSED_SOIL_OPTION] )
- skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2;
+ skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3 * 5;
break;
case SO_PSYCHIC_WAVE:
- skillratio += -100 + skill_lv * 70 + (status_get_int(src) * 3);
+ skillratio = 70 * skill_lv + 3 * st->int_;
RE_LVL_DMOD(100);
- if( sc ){
- if( sc->data[SC_HEATER_OPTION] )
- skillratio += sc->data[SC_HEATER_OPTION]->val3;
- else if(sc->data[SC_COOLER_OPTION] )
- skillratio += sc->data[SC_COOLER_OPTION]->val3;
- else if(sc->data[SC_BLAST_OPTION] )
- skillratio += sc->data[SC_BLAST_OPTION]->val2;
- else if(sc->data[SC_CURSED_SOIL_OPTION] )
- skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3;
- }
+ if( sc && ( sc->data[SC_HEATER_OPTION] || sc->data[SC_COOLER_OPTION]
+ || sc->data[SC_BLAST_OPTION] || sc->data[SC_CURSED_SOIL_OPTION] ) )
+ skillratio += skillratio * 20 / 100;
break;
- case SO_VARETYR_SPEAR: //MATK [{( Endow Tornado skill level x 50 ) + ( Caster INT x Varetyr Spear Skill level )} x Caster Base Level / 100 ] %
+ case SO_VARETYR_SPEAR:
skillratio = status_get_int(src) * skill_lv + ( sd ? pc->checkskill(sd, SA_LIGHTNINGLOADER) * 50 : 0 );
RE_LVL_DMOD(100);
if( sc && sc->data[SC_BLAST_OPTION] )
- skillratio += sd ? sd->status.job_level * 5 : 0;
+ skillratio += sc->data[SC_BLAST_OPTION]->val2 * 5;
break;
case SO_CLOUD_KILL:
- skillratio += -100 + skill_lv * 40;
+ skillratio = 40 * skill_lv;
RE_LVL_DMOD(100);
if( sc && sc->data[SC_CURSED_SOIL_OPTION] )
- skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2;
- break;
- case GN_DEMONIC_FIRE:
- if( skill_lv > 20)
- { // Fire expansion Lv.2
- skillratio += 110 + 20 * (skill_lv - 20) + status_get_int(src) * 3; // Need official INT bonus. [LimitLine]
- }
- else if( skill_lv > 10 )
- { // Fire expansion Lv.1
- skillratio += 110 + 20 * (skill_lv - 10) / 2;
+ skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3;
+ break;
+ case GN_DEMONIC_FIRE: {
+ int fire_expansion_lv = skill_lv / 100;
+ skill_lv = skill_lv % 100;
+ skillratio = 110 + 20 * skill_lv;
+ if ( fire_expansion_lv == 1 )
+ skillratio += status_get_int(src) + (sd?sd->status.job_level:50);
+ else if ( fire_expansion_lv == 2 )
+ skillratio += status_get_int(src) * 10;
}
- else
- skillratio += 110 + 20 * skill_lv;
break;
- // Magical Elemental Spirits Attack Skills
+ // Magical Elemental Spirits Attack Skills
case EL_FIRE_MANTLE:
case EL_WATER_SCREW:
skillratio += 900;
@@ -1686,9 +1726,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 1100;
break;
case MH_ERASER_CUTTER:
- if(skill_lv%2) skillratio += 400; //600:800:1000
- else skillratio += 700; //1000:1200
- skillratio += 100 * skill_lv;
+ skillratio += 400 + 100 * skill_lv + (skill_lv%2 > 0 ? 0 : 300);
break;
case MH_XENO_SLASHER:
if(skill_lv%2) skillratio += 350 + 50 * skill_lv; //500:600:700
@@ -1788,7 +1826,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 30 * skill_lv;
break;
case AS_SONICBLOW:
- skillratio += -50 + 5 * skill_lv;
+ skillratio += 300 + 40 * skill_lv;
break;
case TF_SPRINKLESAND:
skillratio += 30;
@@ -1866,7 +1904,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
#ifndef RENEWAL
case MO_EXTREMITYFIST:
{ //Overflow check. [Skotlex]
- unsigned int ratio = skillratio + 100*(8 + status->sp/10);
+ unsigned int ratio = skillratio + 100*(8 + st->sp/10);
//You'd need something like 6K SP to reach this max, so should be fine for most purposes.
if (ratio > 60000) ratio = 60000; //We leave some room here in case skillratio gets further increased.
skillratio = (unsigned short)ratio;
@@ -1922,8 +1960,12 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
#ifndef RENEWAL
case ASC_BREAKER:
skillratio += 100*skill_lv-100;
- break;
+ #else
+ case LK_SPIRALPIERCE:
+ case ML_SPIRALPIERCE:
+ skillratio += 50 * skill_lv;
#endif
+ break;
case PA_SACRIFICE:
skillratio += 10 * skill_lv - 10;
break;
@@ -1954,10 +1996,9 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
case TK_JUMPKICK:
skillratio += -70 + 10*skill_lv;
if (sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == skill_id)
- skillratio += 10 * status_get_lv(src) / 3; //Tumble bonus
- if (flag)
- {
- skillratio += 10 * status_get_lv(src) / 3; //Running bonus (TODO: What is the real bonus?)
+ skillratio += 10 * status->get_lv(src) / 3; //Tumble bonus
+ if (flag) {
+ skillratio += 10 * status->get_lv(src) / 3; //Running bonus (TODO: What is the real bonus?)
if( sc && sc->data[SC_STRUP] ) // Spurt bonus
skillratio *= 2;
}
@@ -1966,16 +2007,21 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 50 * skill_lv;
break;
case GS_BULLSEYE:
- //Only works well against brute/demihumans non bosses.
- if((tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN)
- && !(tstatus->mode&MD_BOSS))
+ //Only works well against brute/demi-humans non bosses.
+ if((tst->race == RC_BRUTE || tst->race == RC_DEMIHUMAN)
+ && !(tst->mode&MD_BOSS))
skillratio += 400;
break;
case GS_TRACKING:
skillratio += 100 * (skill_lv+1);
break;
case GS_PIERCINGSHOT:
- skillratio += 20 * skill_lv;
+#ifdef RENEWAL
+ if( sd && sd->weapontype1 == W_RIFLE )
+ skillratio += 50 + 30 * skill_lv;
+ else
+#endif
+ skillratio += 20 * skill_lv;
break;
case GS_RAPIDSHOWER:
skillratio += 10 * skill_lv;
@@ -2008,6 +2054,11 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
case NJ_KIRIKAGE:
skillratio += 100 * (skill_lv-1);
break;
+#ifdef RENEWAL
+ case NJ_KUNAI:
+ skillratio += 50 + 150 * skill_lv;
+ break;
+#endif
case KN_CHARGEATK:
{
int k = (flag-1)/3; //+100% every 3 cells of distance
@@ -2031,8 +2082,8 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += ((skill_lv-1)%5+1) * 100;
break;
case RK_SONICWAVE:
- skillratio += -100 + 100 * (skill_lv + 5);
- skillratio = skillratio * (100 + (status_get_lv(src)-100) / 2) / 100;
+ skillratio = (skill_lv + 5) * 100;
+ skillratio = skillratio * (100 + (status->get_lv(src)-100) / 2) / 100;
break;
case RK_HUNDREDSPEAR:
skillratio += 500 + (80 * skill_lv);
@@ -2041,43 +2092,34 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
if( index >= 0 && sd->inventory_data[index]
&& sd->inventory_data[index]->type == IT_WEAPON )
skillratio += (10000 - min(10000, sd->inventory_data[index]->weight)) / 10;
- skillratio = skillratio * (100 + (status_get_lv(src)-100) / 2) / 100 + 50 * pc->checkskill(sd,LK_SPIRALPIERCE);
+ skillratio = skillratio * (100 + (status->get_lv(src)-100) / 2) / 100 + 50 * pc->checkskill(sd,LK_SPIRALPIERCE);
}
break;
case RK_WINDCUTTER:
- skillratio += -100 + 50 * (skill_lv + 2);
+ skillratio = (skill_lv + 2) * 50;
RE_LVL_DMOD(100);
break;
case RK_IGNITIONBREAK:
- i = distance_bl(src,target);
- if( i < 2 )
- skillratio += 300 * skill_lv;
- else if( i < 4 )
- skillratio += 250 * skill_lv;
- else
- skillratio += 200 * skill_lv;
- skillratio = (skillratio - 100) * (100 + (status_get_lv(src)-100)) / 100;
- if( status->rhw.ele == ELE_FIRE )
- skillratio += 100 * skill_lv;
- break;
- case RK_CRUSHSTRIKE:
- if( sd )
- {//ATK [{Weapon Level * (Weapon Upgrade Level + 6) * 100} + (Weapon ATK) + (Weapon Weight)]%
- short index = sd->equip_index[EQI_HAND_R];
- if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
- skillratio += -100 + sd->inventory_data[index]->weight/10 + status->rhw.atk +
- 100 * sd->inventory_data[index]->wlv * (sd->status.inventory[index].refine + 6);
- }
+ i = distance_bl(src,target);
+ if( i < 2 )
+ skillratio = 300 * skill_lv;
+ else if( i < 4 )
+ skillratio = 250 * skill_lv;
+ else
+ skillratio = 200 * skill_lv;
+ skillratio = skillratio * status->get_lv(src) / 100;
+ if( st->rhw.ele == ELE_FIRE )
+ skillratio += 100 * skill_lv;
break;
case RK_STORMBLAST:
- skillratio += -100 + 100 * (sd ? pc->checkskill(sd,RK_RUNEMASTERY) : 1) + 100 * (status_get_int(src) / 4);
+ skillratio = ((sd ? pc->checkskill(sd,RK_RUNEMASTERY) : 1) + status_get_int(src) / 8) * 100;
break;
case RK_PHANTOMTHRUST:
- skillratio += -100 + 50 * skill_lv + 10 * ( sd ? pc->checkskill(sd,KN_SPEARMASTERY) : 10);
+ skillratio = 50 * skill_lv + 10 * (sd ? pc->checkskill(sd,KN_SPEARMASTERY) : 10);
RE_LVL_DMOD(150);
break;
/**
- * GC Guilotine Cross
+ * GC Guillotine Cross
**/
case GC_CROSSIMPACT:
skillratio += 900 + 100 * skill_lv;
@@ -2090,10 +2132,9 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
//ATK [{(Skill Level x 100) + 300} x Caster's Base Level / 120]% + ATK [(AGI x 2) + (Caster's Job Level x 4)]%
skillratio += 200 + (100 * skill_lv);
RE_LVL_DMOD(120);
- skillratio += status_get_agi(src) * 2 + (sd?sd->status.job_level:0) * 4;
break;
case GC_ROLLINGCUTTER:
- skillratio += -50 + 50 * skill_lv;
+ skillratio = 50 + 50 * skill_lv;
RE_LVL_DMOD(100);
break;
case GC_CROSSRIPPERSLASHER:
@@ -2126,127 +2167,142 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 100 + 100 * skill_lv;
break;
case RA_WUGDASH:// ATK 300%
- skillratio += 200;
+ skillratio = 300;
+ if( sc && sc->data[SC_DANCE_WITH_WUG] )
+ skillratio += 10 * sc->data[SC_DANCE_WITH_WUG]->val1 * (2 + battle->calc_chorusbonus(sd));
break;
case RA_WUGSTRIKE:
- skillratio += -100 + 200 * skill_lv;
+ skillratio = 200 * skill_lv;
+ if( sc && sc->data[SC_DANCE_WITH_WUG] )
+ skillratio += 10 * sc->data[SC_DANCE_WITH_WUG]->val1 * (2 + battle->calc_chorusbonus(sd));
break;
case RA_WUGBITE:
skillratio += 300 + 200 * skill_lv;
if ( skill_lv == 5 ) skillratio += 100;
break;
case RA_SENSITIVEKEEN:
- skillratio += 50 * skill_lv;
+ skillratio = 150 * skill_lv;
break;
/**
* Mechanic
**/
case NC_BOOSTKNUCKLE:
- skillratio += 100 + 100 * skill_lv + status_get_dex(src);
- RE_LVL_DMOD(100);
+ skillratio = skill_lv * 100 + 200 + st->dex;
+ RE_LVL_DMOD(120);
break;
case NC_PILEBUNKER:
- skillratio += 200 + 100 * skill_lv + status_get_str(src);
+ skillratio = skill_lv*100 + 300 + status_get_str(src);
RE_LVL_DMOD(100);
break;
case NC_VULCANARM:
- skillratio += -100 + 70 * skill_lv + status_get_dex(src);
+ skillratio = 70 * skill_lv + status_get_dex(src);
RE_LVL_DMOD(100);
break;
case NC_FLAMELAUNCHER:
case NC_COLDSLOWER:
- skillratio += 200 + 300 * skill_lv;
+ skillratio += 200 + 100 * skill_lv + status_get_str(src);
RE_LVL_DMOD(100);
break;
case NC_ARMSCANNON:
- switch( tstatus->size ) {
- case SZ_SMALL: skillratio += 100 + 500 * skill_lv; break;// Small
- case SZ_MEDIUM: skillratio += 100 + 400 * skill_lv; break;// Medium
- case SZ_BIG: skillratio += 100 + 300 * skill_lv; break;// Large
+ switch( tst->size ) {
+ case SZ_MEDIUM: skillratio = 300 + 350 * skill_lv; break; // Medium
+ case SZ_SMALL: skillratio = 300 + 400 * skill_lv; break; // Small
+ case SZ_BIG: skillratio = 300 + 300 * skill_lv; break; // Large
}
- RE_LVL_DMOD(100);
- //NOTE: Their's some other factors that affects damage, but not sure how exactly. Will recheck one day. [Rytech]
+ RE_LVL_DMOD(120);
break;
case NC_AXEBOOMERANG:
- skillratio += 60 + 40 * skill_lv;
+ skillratio = 250 + 50 * skill_lv;
if( sd ) {
short index = sd->equip_index[EQI_HAND_R];
if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
- skillratio += sd->inventory_data[index]->weight / 10;// Weight is divided by 10 since 10 weight in coding make 1 whole actural weight. [Rytech]
+ skillratio += sd->inventory_data[index]->weight / 10;
}
RE_LVL_DMOD(100);
break;
case NC_POWERSWING:
- skillratio += 80 + 20 * skill_lv + status_get_str(src) + status_get_dex(src);
- RE_LVL_DMOD(100);
+ skillratio = 300 + 100*skill_lv + ( status_get_str(src)+status_get_dex(src) ) * status->get_lv(src) / 100;
break;
case NC_AXETORNADO:
- skillratio += 100 + 100 * skill_lv + status_get_vit(src);
+ skillratio = 200 + 100 * skill_lv + st->vit;
RE_LVL_DMOD(100);
+ if( st->rhw.ele == ELE_WIND )
+ skillratio = skillratio * 125 / 100;
+ if ( distance_bl(src, target) > 2 ) // Will deal 75% damage outside of 5x5 area.
+ skillratio = skillratio * 75 / 100;
break;
case SC_FATALMENACE:
- skillratio += 100 * skill_lv;
+ skillratio = 100 * (skill_lv+1) * status->get_lv(src) / 100;
break;
case SC_TRIANGLESHOT:
- skillratio += 270 + 30 * skill_lv;
+ skillratio = ( 300 + (skill_lv-1) * status_get_agi(src)/2 ) * status->get_lv(src) / 120;
break;
case SC_FEINTBOMB:
- skillratio += 100 + 100 * skill_lv;
+ skillratio = (skill_lv+1) * (st->dex/2) * (sd?sd->status.job_level:50)/10 * status->get_lv(src) / 120;
break;
- case LG_CANNONSPEAR:// Stimated formula. Still need confirm it.
- skillratio += -100 + (50 + status_get_str(src)) * skill_lv;
+ case LG_CANNONSPEAR:
+ skillratio = (50 + st->str) * skill_lv;
RE_LVL_DMOD(100);
break;
case LG_BANISHINGPOINT:
- skillratio += -100 + ((50 * skill_lv) + (30 * ((sd)?pc->checkskill(sd,SM_BASH):1)));
+ skillratio = 50 * skill_lv + 30 * (sd ? pc->checkskill(sd,SM_BASH) : 10);
RE_LVL_DMOD(100);
break;
case LG_SHIELDPRESS:
- skillratio += 60 + 43 * skill_lv;
+ skillratio = 150 * skill_lv + st->str;
+ if( sd ) {
+ short index = sd->equip_index[EQI_HAND_L];
+ if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
+ skillratio += sd->inventory_data[index]->weight / 10;
+ }
RE_LVL_DMOD(100);
break;
case LG_PINPOINTATTACK:
- skillratio += -100 + ((100 * skill_lv) + (10 * status_get_agi(src)) );
- RE_LVL_DMOD(100);
+ skillratio = 100 * skill_lv + 5 * st->agi;
+ RE_LVL_DMOD(120);
break;
case LG_RAGEBURST:
- if( sd && sd->spiritball_old )
- skillratio += -100 + (sd->spiritball_old * 200);
- else
- skillratio += -100 + 15 * 200;
+ if( sc ){
+ skillratio += -100 + (status_get_max_hp(src) - status_get_hp(src)) / 100 + sc->fv_counter * 200;
+ clif->millenniumshield(src, (sc->fv_counter = 0));
+ }
RE_LVL_DMOD(100);
break;
- case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield DEF x 10) + (Casters VIT x 2)] %
- if( sd ) {
+ case LG_SHIELDSPELL:
+ if ( sd && skill_lv == 1 ) {
struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]];
- skillratio += -100 + status_get_lv(src) * 4 + status_get_vit(src) * 2;
if( shield_data )
- skillratio += shield_data->def * 10;
- } else
- skillratio += 2400; //2500%
+ skillratio = 4 * status->get_lv(src) + 10 * shield_data->def + 2 * st->vit;
+ }
+ else
+ skillratio = 0; // Prevents ATK damage from being done on LV 2 usage since LV 2 us MATK. [Rytech]
break;
case LG_MOONSLASHER:
- skillratio += -100 + (120 * skill_lv + ((sd) ? pc->checkskill(sd,LG_OVERBRAND) : 5) * 80);
+ skillratio = 120 * skill_lv + 80 * (sd ? pc->checkskill(sd,LG_OVERBRAND) : 5);
RE_LVL_DMOD(100);
break;
case LG_OVERBRAND:
- skillratio += -100 + 400 * skill_lv + (pc->checkskill(sd,CR_SPEARQUICKEN) * 30);
- RE_LVL_DMOD(100);
+ skillratio += -100 + 50 * (((sd) ? pc->checkskill(sd,CR_SPEARQUICKEN) : 1) + 8 * skill_lv);
+ RE_LVL_DMOD(150);
break;
case LG_OVERBRAND_BRANDISH:
- skillratio += -100 + 300 * skill_lv + (2 * (status_get_str(src) + status_get_dex(src)) / 3);
- RE_LVL_DMOD(100);
+ skillratio += -100 + 300 * skill_lv + status_get_str(src) + status_get_dex(src);
+ RE_LVL_DMOD(150);
break;
case LG_OVERBRAND_PLUSATK:
- skillratio += -100 + 150 * skill_lv;
+ skillratio += -100 + 100 * skill_lv;
RE_LVL_DMOD(100);
break;
case LG_RAYOFGENESIS:
- skillratio += 200 + 300 * skill_lv;
+ skillratio = 300 + 300 * skill_lv;
RE_LVL_DMOD(100);
break;
case LG_EARTHDRIVE:
- skillratio = (skillratio + 100) * skill_lv;
+ if( sd ) {
+ short index = sd->equip_index[EQI_HAND_L];
+ if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
+ skillratio = (1 + skill_lv) * sd->inventory_data[index]->weight / 10;
+ }
RE_LVL_DMOD(100);
break;
case LG_HESPERUSLIT:
@@ -2284,7 +2340,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
int hp = status_get_max_hp(src) * (10 + 2 * skill_lv) / 100,
sp = status_get_max_sp(src) * (6 + skill_lv) / 100;
if( sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE ) // ATK [((Caster consumed HP + SP) / 2) x Caster Base Level / 100] %
- skillratio += -100 + hp+sp / 2;
+ skillratio += -100 + (hp+sp) / 2;
else
skillratio += -100 + (hp+sp) / 4;
RE_LVL_DMOD(100);
@@ -2292,15 +2348,17 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
case SR_RAMPAGEBLASTER:
skillratio += 20 * skill_lv * (sd?sd->spiritball_old:5) - 100;
- if( sc && sc->data[SC_EXPLOSIONSPIRITS] ){
+ if( sc && sc->data[SC_EXPLOSIONSPIRITS] ) {
skillratio += sc->data[SC_EXPLOSIONSPIRITS]->val1 * 20;
RE_LVL_DMOD(120);
- }else
+ } else {
RE_LVL_DMOD(150);
+ }
break;
case SR_KNUCKLEARROW:
- if( flag&4 ){ // ATK [(Skill Level x 150) + (1000 x Target current weight / Maximum weight) + (Target Base Level x 5) x (Caster Base Level / 150)] %
- skillratio += -100 + 150 * skill_lv + status_get_lv(target) * 5 * (status_get_lv(src) / 100) ;
+ if ( flag&4 || map->list[src->m].flag.gvg_castle || tst->mode&MD_BOSS ) {
+ // ATK [(Skill Level x 150) + (1000 x Target current weight / Maximum weight) + (Target Base Level x 5) x (Caster Base Level / 150)] %
+ skillratio = 150 * skill_lv + status->get_lv(target) * 5 * (status->get_lv(src) / 100) ;
if( tsd && tsd->weight )
skillratio += 100 * (tsd->weight / tsd->max_weight);
}else // ATK [(Skill Level x 100 + 500) x Caster Base Level / 100] %
@@ -2308,7 +2366,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(100);
break;
case SR_WINDMILL: // ATK [(Caster Base Level + Caster DEX) x Caster Base Level / 100] %
- skillratio += -100 + status_get_lv(src) + status_get_dex(src);
+ skillratio = status->get_lv(src) + status_get_dex(src);
RE_LVL_DMOD(100);
break;
case SR_GATEOFHELL:
@@ -2328,74 +2386,77 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(150);
break;
case SR_RIDEINLIGHTNING: // ATK [{(Skill Level x 200) + Additional Damage} x Caster Base Level / 100] %
- if( (status->rhw.ele) == ELE_WIND || (status->lhw.ele) == ELE_WIND )
+ if( (st->rhw.ele) == ELE_WIND || (st->lhw.ele) == ELE_WIND )
skillratio += skill_lv * 50;
skillratio += -100 + 200 * skill_lv;
RE_LVL_DMOD(100);
break;
case WM_REVERBERATION_MELEE:
- // ATK [{(Skill Level x 100) + 300} x Caster Base Level / 100]
- skillratio += 200 + 100 * pc->checkskill(sd, WM_REVERBERATION);
+ skillratio += 200 + 100 * skill_lv;
RE_LVL_DMOD(100);
break;
case WM_SEVERE_RAINSTORM_MELEE:
- //ATK [{(Caster DEX + AGI) x (Skill Level / 5)} x Caster Base Level / 100] %
- skillratio += -100 + (status_get_dex(src) + status_get_agi(src)) * (skill_lv * 2);
+ skillratio = (st->agi + st->dex) * skill_lv / 5;
RE_LVL_DMOD(100);
- skillratio /= 10;
break;
case WM_GREAT_ECHO:
- skillratio += 800 + 100 * skill_lv;
- if( sd ) { // Still need official value [pakpil]
- short lv = (short)skill_lv;
- skillratio += 100 * skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),0);
- }
- break;
- case WM_SOUND_OF_DESTRUCTION:
- skillratio += 400;
+ {
+ int chorusbonus = battle->calc_chorusbonus(sd);
+ skillratio += 300 + 200 * skill_lv;
+ //Chorus bonus don't count the first 2 Minstrel's/Wanderer's and only increases when their's 3 or more. [Rytech]
+ if (chorusbonus >= 1 && chorusbonus <= 5)
+ skillratio += 100<<(chorusbonus-1); // 1->100; 2->200; 3->400; 4->800; 5->1600
+ RE_LVL_DMOD(100);
+ }
break;
case GN_CART_TORNADO:
- // ATK [( Skill Level x 50 ) + ( Cart Weight / ( 150 - Caster Base STR ))] + ( Cart Remodeling Skill Level x 50 )] %
- skillratio += -100 + 50 * skill_lv;
- if( sd && sd->cart_weight)
- skillratio += sd->cart_weight/10 / max(150-status_get_str(src),1) + pc->checkskill(sd, GN_REMODELING_CART) * 50;
+ {
+ int strbonus = st->str; // FIXME Supposed to take only base STR, but current code wont allow that. So well just take STR for now. [Rytech]
+ if ( strbonus > 130 ) // Max base stat limit on official is 130. So well allow no higher then 125 STR here. This limit prevents
+ strbonus = 130; // the division from going any lower then 30 so the server wont divide by 0 if someone has 150 STR.
+ skillratio = 50 * skill_lv + (sd ? sd->cart_weight : battle_config.max_cart_weight) / 10 / (150 - strbonus) + 50 * (sd ? pc->checkskill(sd, GN_REMODELING_CART) : 5);
+ }
break;
case GN_CARTCANNON:
- // ATK [{( Cart Remodeling Skill Level x 50 ) x ( INT / 40 )} + ( Cart Cannon Skill Level x 60 )] %
- skillratio += -100 + 60 * skill_lv;
- if( sd ) skillratio += pc->checkskill(sd, GN_REMODELING_CART) * 50 * (status_get_int(src) / 40);
+ skillratio = 50 * (sd ? pc->checkskill(sd, GN_REMODELING_CART) : 5) * (st->int_ / 40) + 60 * skill_lv;
break;
case GN_SPORE_EXPLOSION:
- skillratio += 200 + 100 * skill_lv;
- break;
+ skillratio = 100 * skill_lv + (200 + st->int_) * status->get_lv(src) / 100;
case GN_CRAZYWEED_ATK:
skillratio += 400 + 100 * skill_lv;
break;
case GN_SLINGITEM_RANGEMELEEATK:
if( sd ) {
switch( sd->itemid ) {
- case 13260: // Apple Bomob
- case 13261: // Coconut Bomb
- case 13262: // Melon Bomb
- case 13263: // Pinapple Bomb
- skillratio += 400; // Unconfirded
+ case ITEMID_APPLE_BOMB:
+ skillratio = st->str + st->dex + 300;
+ break;
+ case ITEMID_MELON_BOMB:
+ skillratio = st->str + st->dex + 500;
+ break;
+ case ITEMID_COCONUT_BOMB:
+ case ITEMID_PINEAPPLE_BOMB:
+ case ITEMID_BANANA_BOMB:
+ skillratio = st->str + st->dex + 800;
+ break;
+ case ITEMID_BLACK_LUMP:
+ skillratio = (st->str + st->agi + st->dex) / 3; // Black Lump
+ break;
+ case ITEMID_BLACK_HARD_LUMP:
+ skillratio = (st->str + st->agi + st->dex) / 2; // Hard Black Lump
break;
- case 13264: // Banana Bomb 2000%
- skillratio += 1900;
+ case ITEMID_VERY_HARD_LUMP:
+ skillratio = st->str + st->agi + st->dex; // Extremely Hard Black Lump
break;
- case 13265: skillratio -= 75; break; // Black Lump 25%
- case 13266: skillratio -= 25; break; // Hard Black Lump 75%
- case 13267: skillratio += 100; break; // Extremely Hard Black Lump 200%
}
- } else
- skillratio += 300; // Bombs
+ }
break;
case SO_VARETYR_SPEAR://ATK [{( Striking Level x 50 ) + ( Varetyr Spear Skill Level x 50 )} x Caster Base Level / 100 ] %
skillratio += -100 + 50 * skill_lv + ( sd ? pc->checkskill(sd, SO_STRIKING) * 50 : 0 );
if( sc && sc->data[SC_BLAST_OPTION] )
- skillratio += sd ? sd->status.job_level * 5 : 0;
+ skillratio += (sd ? sd->status.job_level * 5 : 0);
break;
- // Physical Elemantal Spirits Attack Skills
+ // Physical Elemental Spirits Attack Skills
case EL_CIRCLE_OF_FIRE:
case EL_FIRE_BOMB_ATK:
case EL_STONE_RAIN:
@@ -2427,7 +2488,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += -100 + 150 * skill_lv;
RE_LVL_DMOD(120);
if( tsc && tsc->data[SC_KO_JYUMONJIKIRI] )
- skillratio += status_get_lv(src) * skill_lv;
+ skillratio += status->get_lv(src) * skill_lv;
case KO_HUUMARANKA:
skillratio += -100 + 150 * skill_lv + status_get_agi(src) + status_get_dex(src) + 100 * (sd ? pc->checkskill(sd, NJ_HUUMA) : 0);
break;
@@ -2454,13 +2515,43 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += -100 + 100 * skill_lv;
break;
}
- if( sc && sc->data[SC_EDP] ){
- skillratio -= addedratio;
- if( skill_id == AS_SONICBLOW ||
- skill_id == GC_COUNTERSLASH ||
- skill_id == GC_CROSSIMPACT )
- skillratio >>= 1;
- skillratio += addedratio;
+ //Skill damage modifiers that stack linearly
+ if(sc && skill_id != PA_SACRIFICE){
+#ifdef RENEWAL_EDP
+ if( sc->data[SC_EDP] ){
+ if( skill_id == AS_SONICBLOW ||
+ skill_id == GC_COUNTERSLASH ||
+ skill_id == GC_CROSSIMPACT )
+ skillratio >>= 1;
+ }
+#endif
+ if(sc->data[SC_OVERTHRUST])
+ skillratio += sc->data[SC_OVERTHRUST]->val3;
+ if(sc->data[SC_OVERTHRUSTMAX])
+ skillratio += sc->data[SC_OVERTHRUSTMAX]->val2;
+ if(sc->data[SC_BERSERK])
+#ifndef RENEWAL
+ skillratio += 100;
+#else
+ skillratio += 200;
+ if( sc->data[SC_TRUESIGHT] )
+ skillratio += 2*sc->data[SC_TRUESIGHT]->val1;
+ if( sc->data[SC_LKCONCENTRATION] )
+ skillratio += sc->data[SC_LKCONCENTRATION]->val2;
+ if( sd && sd->status.weapon == W_KATAR && (i=pc->checkskill(sd,ASC_KATAR)) > 0 )
+ skillratio += skillratio * (10 + 2 * i) / 100;
+#endif
+ if( (!skill_id || skill_id == KN_AUTOCOUNTER) && sc->data[SC_CRUSHSTRIKE] ){
+ if( sd )
+ {//ATK [{Weapon Level * (Weapon Upgrade Level + 6) * 100} + (Weapon ATK) + (Weapon Weight)]%
+ short index = sd->equip_index[EQI_HAND_R];
+ if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
+ skillratio += -100 + sd->inventory_data[index]->weight/10 + st->rhw.atk +
+ 100 * sd->inventory_data[index]->wlv * (sd->status.inventory[index].refine + 6);
+ }
+ status_change_end(src, SC_CRUSHSTRIKE, INVALID_TIMER);
+ skill->break_equip(src,EQP_WEAPON,2000,BCT_SELF); // 20% chance to destroy the weapon.
+ }
}
}
if( skillratio < 1 )
@@ -2468,14 +2559,13 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
return skillratio;
}
/*==========================================
- * Check dammage trough status.
- * ATK may be MISS, BLOCKED FAIL, reduc, increase, end status...
+ * Check damage trough status.
+ * ATK may be MISS, BLOCKED FAIL, reduce, increase, end status...
* After this we apply bg/gvg reduction
*------------------------------------------*/
-int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int damage,uint16 skill_id,uint16 skill_lv)
-{
+int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int64 damage,uint16 skill_id,uint16 skill_lv) {
struct map_session_data *sd = NULL;
- struct status_change *sc;
+ struct status_change *sc, *tsc;
struct status_change_entry *sce;
int div_ = d->div_, flag = d->flag;
@@ -2483,9 +2573,8 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
if( !damage )
return 0;
- if( battle_config.ksprotection && mob_ksprotected(src, bl) )
+ if( battle_config.ksprotection && mob->ksprotected(src, bl) )
return 0;
-
if (bl->type == BL_PC) {
sd=(struct map_session_data *)bl;
//Special no damage states
@@ -2501,7 +2590,8 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
if(!damage) return 0;
}
- sc = status_get_sc(bl);
+ sc = status->get_sc(bl);
+ tsc = status->get_sc(src);
if( sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
return 1;
@@ -2522,7 +2612,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
skill_id == MG_SOULSTRIKE ||
skill_id == WL_SOULEXPANSION ||
(skill_id && skill->get_ele(skill_id, skill_lv) == ELE_GHOST) ||
- (!skill_id && (status_get_status_data(src))->rhw.ele == ELE_GHOST)
+ (!skill_id && (status->get_status_data(src))->rhw.ele == ELE_GHOST)
){
if( skill_id == WL_SOULEXPANSION )
damage <<= 1; // If used against a player in White Imprison, the skill deals double damage.
@@ -2533,8 +2623,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
}
}
- if(sc->data[SC_ZEPHYR] &&
- flag&(BF_LONG|BF_SHORT)){
+ if( sc->data[SC_ZEPHYR] && ((flag&BF_LONG) || rand()%100 < 10) ) {
d->dmg_lv = ATK_BLOCK;
return 0;
}
@@ -2542,30 +2631,38 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT )
{
struct skill_unit_group* group = skill->id2group(sc->data[SC_SAFETYWALL]->val3);
- uint16 skill_id = sc->data[SC_SAFETYWALL]->val2;
+ uint16 src_skill_id = sc->data[SC_SAFETYWALL]->val2;
if (group) {
- if(skill_id == MH_STEINWAND){
- if (--group->val2<=0)
- skill->del_unitgroup(group,ALC_MARK);
- d->dmg_lv = ATK_BLOCK;
- return 0;
+ d->dmg_lv = ATK_BLOCK;
+ if(src_skill_id == MH_STEINWAND){
+ if (--group->val2<=0)
+ skill->del_unitgroup(group,ALC_MARK);
+ if( (group->val3 - damage) > 0 )
+ group->val3 -= (int)cap_value(damage, INT_MIN, INT_MAX);
+ else
+ skill->del_unitgroup(group,ALC_MARK);
+ return 0;
+ }
+ if( skill_id == SO_ELEMENTAL_SHIELD ) {
+ if ( ( group->val2 - damage) > 0 ) {
+ group->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX);
+ } else
+ skill->del_unitgroup(group,ALC_MARK);
+ return 0;
}
/**
* in RE, SW possesses a lifetime equal to 3 times the caster's health
**/
#ifdef RENEWAL
- d->dmg_lv = ATK_BLOCK;
if ( ( group->val2 - damage) > 0 ) {
- group->val2 -= damage;
+ group->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX);
} else
skill->del_unitgroup(group,ALC_MARK);
- return 0;
#else
if (--group->val2<=0)
skill->del_unitgroup(group,ALC_MARK);
- d->dmg_lv = ATK_BLOCK;
- return 0;
#endif
+ return 0;
}
status_change_end(bl, SC_SAFETYWALL, INVALID_TIMER);
}
@@ -2574,11 +2671,26 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
d->dmg_lv = ATK_BLOCK;
return 0;
}
+ if( sc->data[SC_NEUTRALBARRIER] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG && skill_id != CR_ACIDDEMONSTRATION ) {
+ d->dmg_lv = ATK_BLOCK;
+ return 0;
+ }
+ if( sc->data[SC__MAELSTROM] && (flag&BF_MAGIC) && skill_id && (skill->get_inf(skill_id)&INF_GROUND_SKILL) ) {
+ // {(Maelstrom Skill LevelxAbsorbed Skill Level)+(Caster's Job/5)}/2
+ int sp = (sc->data[SC__MAELSTROM]->val1 * skill_lv + sd->status.job_level / 5) / 2;
+ status->heal(bl, 0, sp, 3);
+ d->dmg_lv = ATK_BLOCK;
+ return 0;
+ }
if( sc->data[SC_WEAPONBLOCKING] && flag&(BF_SHORT|BF_WEAPON) && rnd()%100 < sc->data[SC_WEAPONBLOCKING]->val2 )
{
clif->skill_nodamage(bl,src,GC_WEAPONBLOCKING,1,1);
d->dmg_lv = ATK_BLOCK;
- sc_start2(bl,SC_COMBOATTACK,100,GC_WEAPONBLOCKING,src->id,2000);
+ sc_start2(src,bl,SC_COMBOATTACK,100,GC_WEAPONBLOCKING,src->id,2000);
+ return 0;
+ }
+ if( sc->data[SC_HOVERING] && skill_id && (skill->get_inf(skill_id)&INF_GROUND_SKILL || skill_id == SR_WINDMILL) ) {
+ d->dmg_lv = ATK_BLOCK;
return 0;
}
if( (sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2 )
@@ -2592,23 +2704,23 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
delay = 200;
else
delay = 100;
- unit_set_walkdelay(bl, iTimer->gettick(), delay, 1);
+ unit->set_walkdelay(bl, timer->gettick(), delay, 1);
if(sc->data[SC_CR_SHRINK] && rnd()%100<5*sce->val1)
skill->blown(bl,src,skill->get_blewcount(CR_SHRINK,1),-1,0);
+ d->dmg_lv = ATK_MISS;
return 0;
}
if( (sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0 ) {
clif->skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1);
- sce->val3 -= damage; // absorb damage
+ sce->val3 -= (int)cap_value(damage,INT_MIN,INT_MAX); // absorb damage
d->dmg_lv = ATK_BLOCK;
- sc_start(bl,SC_STUN,15,0,skill->get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stuned when one shield is broken.
+ sc_start(src,bl,SC_STUN,15,0,skill->get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stunned when one shield is broken.
if( sce->val3 <= 0 ) { // Shield Down
sce->val2--;
if( sce->val2 > 0 ) {
- if( sd )
- clif->millenniumshield(sd,sce->val2);
+ clif->millenniumshield(bl,sce->val2);
sce->val3 = 1000; // Next Shield
} else
status_change_end(bl,SC_MILLENNIUMSHIELD,INVALID_TIMER); // All shields down
@@ -2629,21 +2741,16 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
if (sd && pc_issit(sd)) pc->setstand(sd); //Stand it to dodge.
clif->skill_nodamage(bl,bl,TK_DODGE,1,1);
if (!sc->data[SC_COMBOATTACK])
- sc_start4(bl, SC_COMBOATTACK, 100, TK_JUMPKICK, src->id, 1, 0, 2000);
+ sc_start4(src, bl, SC_COMBOATTACK, 100, TK_JUMPKICK, src->id, 1, 0, 2000);
return 0;
}
- if(sc->data[SC_HERMODE] && flag&BF_MAGIC)
+ if((sc->data[SC_HERMODE] || sc->data[SC_HOVERING]) && flag&BF_MAGIC)
return 0;
if(sc->data[SC_NJ_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG)
return 0;
- if( sc->data[SC_NEUTRALBARRIER] && (flag&(BF_MAGIC|BF_LONG)) == (BF_MAGIC|BF_LONG) ) {
- d->dmg_lv = ATK_MISS;
- return 0;
- }
-
if((sce=sc->data[SC_KAUPE]) && rnd()%100 < sce->val2)
{ //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries.
clif->specialeffect(bl, 462, AREA);
@@ -2662,9 +2769,9 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
if (((sce=sc->data[SC_NJ_UTSUSEMI]) || sc->data[SC_NJ_BUNSINJYUTSU])
&& flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK)) {
- skill->additional_effect (src, bl, skill_id, skill_lv, flag, ATK_BLOCK, iTimer->gettick() );
- if( !status_isdead(src) )
- skill->counter_additional_effect( src, bl, skill_id, skill_lv, flag, iTimer->gettick() );
+ skill->additional_effect (src, bl, skill_id, skill_lv, flag, ATK_BLOCK, timer->gettick() );
+ if( !status->isdead(src) )
+ skill->counter_additional_effect( src, bl, skill_id, skill_lv, flag, timer->gettick() );
if (sce) {
clif->specialeffect(bl, 462, AREA);
skill->blown(src,bl,sce->val3,-1,0);
@@ -2703,7 +2810,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
damage += damage / 2; // 1.5 times more damage while in Deep Sleep.
status_change_end(bl,SC_DEEP_SLEEP,INVALID_TIMER);
}
- if( tsd && sd && sc->data[SC_CRYSTALIZE] && flag&BF_WEAPON ){
+ if( tsd && sd && sc->data[SC_COLD] && flag&BF_WEAPON ){
switch(tsd->status.weapon){
case W_MACE:
case W_2HMACE:
@@ -2744,32 +2851,37 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
#endif
if(sc->data[SC_DEFENDER] &&
- (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
+ ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON) || skill_id == CR_ACIDDEMONSTRATION))
damage = damage * ( 100 - sc->data[SC_DEFENDER]->val2 ) / 100;
if(sc->data[SC_GS_ADJUSTMENT] &&
(flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
damage -= damage * 20 / 100;
- if(sc->data[SC_FOGWALL] && skill_id != RK_DRAGONBREATH && skill_id != RK_DRAGONBREATH_WATER) {
- if(flag&BF_SKILL) //25% reduction
- damage -= damage * 25 / 100;
+ if(sc->data[SC_FOGWALL]) {
+ if(flag&BF_SKILL) { //25% reduction
+ if ( !(skill->get_inf(skill_id)&INF_GROUND_SKILL) && !(skill->get_nk(skill_id)&NK_SPLASH) )
+ damage -= 25*damage/100;
+ }
else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
damage >>= 2; //75% reduction
}
+ if ( sc->data[SC_WATER_BARRIER] )
+ damage = damage * ( 100 - 20 ) / 100;
+
// Compressed code, fixed by map.h [Epoque]
if (src->type == BL_MOB) {
int i;
if (sc->data[SC_MANU_DEF])
- for (i=0;ARRAYLENGTH(mob_manuk)>i;i++)
- if (mob_manuk[i]==((TBL_MOB*)src)->class_) {
+ for (i=0;ARRAYLENGTH(mob->manuk)>i;i++)
+ if (mob->manuk[i]==((TBL_MOB*)src)->class_) {
damage -= damage * sc->data[SC_MANU_DEF]->val1 / 100;
break;
}
if (sc->data[SC_SPL_DEF])
- for (i=0;ARRAYLENGTH(mob_splendide)>i;i++)
- if (mob_splendide[i]==((TBL_MOB*)src)->class_) {
+ for (i=0;ARRAYLENGTH(mob->splendide)>i;i++)
+ if (mob->splendide[i]==((TBL_MOB*)src)->class_) {
damage -= damage * sc->data[SC_SPL_DEF]->val1 / 100;
break;
}
@@ -2779,17 +2891,19 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
sce->val3&flag && sce->val4&flag)
damage -= damage * sc->data[SC_ARMOR]->val2 / 100;
+ if( sc->data[SC_ENERGYCOAT] && (skill_id == GN_HELLS_PLANT_ATK ||
#ifdef RENEWAL
- if(sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON || flag&BF_MAGIC) && skill_id != WS_CARTTERMINATION)
+ ((flag&BF_WEAPON || flag&BF_MAGIC) && skill_id != WS_CARTTERMINATION)
#else
- if(sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON && skill_id != WS_CARTTERMINATION))
+ (flag&BF_WEAPON && skill_id != WS_CARTTERMINATION)
#endif
+ ) )
{
- struct status_data *status = status_get_status_data(bl);
- int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval
+ struct status_data *sstatus = status->get_status_data(bl);
+ int per = 100*sstatus->sp / sstatus->max_sp -1; //100% should be counted as the 80~99% interval
per /=20; //Uses 20% SP intervals.
//SP Cost: 1% + 0.5% per every 20% SP
- if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000))
+ if (!status->charge(bl, 0, (10+5*per)*sstatus->max_sp/1000))
status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER);
//Reduction: 6% + 6% every 20%
damage -= damage * (6 * (1+per)) / 100;
@@ -2801,11 +2915,14 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
damage -= damage * sc->data[SC_PAIN_KILLER]->val3 / 100;
}
if((sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2) ){
- skill->castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,iTimer->gettick(),0);
+ skill->castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,timer->gettick(),0);
}
+ if( sc->data[SC_DARKCROW] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT )
+ damage += damage * sc->data[SC_DARKCROW]->val2 / 100;
+
if( (sce = sc->data[SC_STONEHARDSKIN]) && flag&(BF_SHORT|BF_WEAPON) && damage > 0 ) {
- sce->val2 -= damage;
+ sce->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX);
if( src->type == BL_PC ) {
TBL_PC *ssd = BL_CAST(BL_PC, src);
if (ssd && ssd->status.weapon != W_BOW)
@@ -2814,7 +2931,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF);
// 30% chance to reduce monster's ATK by 25% for 10 seconds.
if( src->type == BL_MOB )
- sc_start(src, SC_NOEQUIPWEAPON, 30, 0, skill->get_time2(RK_STONEHARDSKIN, sce->val1));
+ sc_start(bl,src, SC_NOEQUIPWEAPON, 30, 0, skill->get_time2(RK_STONEHARDSKIN, sce->val1));
if( sce->val2 <= 0 )
status_change_end(bl, SC_STONEHARDSKIN, INVALID_TIMER);
}
@@ -2838,12 +2955,12 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
//Finally Kyrie because it may, or not, reduce damage to 0.
if((sce = sc->data[SC_KYRIE]) && damage > 0){
- sce->val2-=damage;
+ sce->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX);
if(flag&BF_WEAPON || skill_id == TF_THROWSTONE){
if(sce->val2>=0)
damage=0;
else
- damage=-sce->val2;
+ damage=-sce->val2;
}
if((--sce->val3)<=0 || (sce->val2<=0) || skill_id == AL_HOLYLIGHT)
status_change_end(bl, SC_KYRIE, INVALID_TIMER);
@@ -2858,10 +2975,10 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
if( (sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && rnd()%100 < sce->val1 ) {
int dx[8]={0,-1,-1,-1,0,1,1,1};
int dy[8]={1,1,0,-1,-1,-1,0,1};
- uint8 dir = iMap->calc_dir(bl, src->x, src->y);
- if( unit_movepos(bl, src->x-dx[dir], src->y-dy[dir], 1, 1) ) {
+ uint8 dir = map->calc_dir(bl, src->x, src->y);
+ if( unit->movepos(bl, src->x-dx[dir], src->y-dy[dir], 1, 1) ) {
clif->slide(bl,src->x-dx[dir],src->y-dy[dir]);
- unit_setdir(bl, dir);
+ unit->setdir(bl, dir);
}
d->dmg_lv = ATK_DEF;
status_change_end(bl, SC_LIGHTNINGWALK, INVALID_TIMER);
@@ -2872,42 +2989,23 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
//(since battle_drain is strictly for players currently)
if ((sce=sc->data[SC_HAMI_BLOODLUST]) && flag&BF_WEAPON && damage > 0 &&
rnd()%100 < sce->val3)
- status_heal(src, damage*sce->val4/100, 0, 3);
+ status->heal(src, damage*sce->val4/100, 0, 3);
- if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 )
- pc->addspiritball(sd,skill->get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3);
- if (sc->data[SC_STYLE_CHANGE] && rnd()%2) {
- TBL_HOM *hd = BL_CAST(BL_HOM,bl);
- if (hd) homun->addspiritball(hd, 10); //add a sphere
- }
+ if( (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON
+ && rnd()%100 < sce->val2 && sc->fv_counter <= sce->val3 )
+ clif->millenniumshield(bl, sc->fv_counter++);
- if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
- status_change_spread(bl, src); // Deadly infect attacked side
-
- if( sc && sc->data[SC__SHADOWFORM] ) {
- struct block_list *s_bl = iMap->id2bl(sc->data[SC__SHADOWFORM]->val2);
- if( !s_bl || s_bl->m != bl->m ) { // If the shadow form target is not present remove the sc.
- status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
- } else if( status_isdead(s_bl) || !battle->check_target(src,s_bl,BCT_ENEMY)) { // If the shadow form target is dead or not your enemy remove the sc in both.
- status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
- if( s_bl->type == BL_PC )
- ((TBL_PC*)s_bl)->shadowform_id = 0;
- } else {
- if( (--sc->data[SC__SHADOWFORM]->val3) < 0 ) { // If you have exceded max hits supported, remove the sc in both.
- status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
- if( s_bl->type == BL_PC )
- ((TBL_PC*)s_bl)->shadowform_id = 0;
- } else {
- status_damage(bl, s_bl, damage, 0, clif->damage(s_bl, s_bl, iTimer->gettick(), 500, 500, damage, -1, 0, 0), 0);
- return ATK_NONE;
- }
- }
+ if (sc->data[SC_STYLE_CHANGE] && rnd()%2) {
+ TBL_HOM *hd = BL_CAST(BL_HOM,bl);
+ if (hd) homun->addspiritball(hd, 10); //add a sphere
}
+ if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) )
+ status->change_spread(bl, src); // Deadly infect attacked side
}
//SC effects from caster side.
- sc = status_get_sc(src);
+ sc = status->get_sc(src);
if (sc && sc->count) {
if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
@@ -2919,24 +3017,33 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
if ( ((sce=sc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) ||
((sce=sc->data[SC_MANU_MATK]) && (flag&BF_MAGIC))
)
- for (i=0;ARRAYLENGTH(mob_manuk)>i;i++)
- if (((TBL_MOB*)bl)->class_==mob_manuk[i]) {
+ for (i=0;ARRAYLENGTH(mob->manuk)>i;i++)
+ if (((TBL_MOB*)bl)->class_==mob->manuk[i]) {
damage += damage * sce->val1 / 100;
break;
}
if ( ((sce=sc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) ||
((sce=sc->data[SC_SPL_MATK]) && (flag&BF_MAGIC))
)
- for (i=0;ARRAYLENGTH(mob_splendide)>i;i++)
- if (((TBL_MOB*)bl)->class_==mob_splendide[i]) {
+ for (i=0;ARRAYLENGTH(mob->splendide)>i;i++)
+ if (((TBL_MOB*)bl)->class_==mob->splendide[i]) {
damage += damage * sce->val1 / 100;
break;
}
}
- if( sc->data[SC_POISONINGWEAPON] && skill_id != GC_VENOMPRESSURE && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < sc->data[SC_POISONINGWEAPON]->val3 )
- sc_start(bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON, 1));
- if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
- status_change_spread(src, bl);
+ if( tsc->data[SC_POISONINGWEAPON] ) {
+ short rate = 100;
+ struct status_data *tstatus = status->get_status_data(bl);
+ if ( !(flag&BF_SKILL) && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < tsc->data[SC_POISONINGWEAPON]->val3 ) {
+ if ( tsc->data[SC_POISONINGWEAPON]->val1 == 9 ) // Oblivion Curse gives a 2nd success chance after the 1st one passes which is reducible. [Rytech]
+ rate = 100 - tstatus->int_ * 4 / 5;
+ sc_start(src,bl,tsc->data[SC_POISONINGWEAPON]->val2,rate,tsc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000);
+ }
+ }
+ if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) )
+ status->change_spread(src, bl);
+ if (sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0)
+ skill->break_equip(bl,EQP_ARMOR,10000,BCT_ENEMY );
if (sc->data[SC_STYLE_CHANGE] && rnd()%2) {
TBL_HOM *hd = BL_CAST(BL_HOM,bl);
if (hd) homun->addspiritball(hd, 10);
@@ -2945,7 +3052,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
/* no data claims these settings affect anything other than players */
if( damage && sd && bl->type == BL_PC ) {
switch( skill_id ) {
- //case PA_PRESSURE: /* pressure also belongs to this list but it doesn't reach this area -- so dont worry about it */
+ //case PA_PRESSURE: /* pressure also belongs to this list but it doesn't reach this area -- so don't worry about it */
case HW_GRAVITATION:
case NJ_ZENYNAGE:
case KO_MUCHANAGE:
@@ -2953,16 +3060,16 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
default:
if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
if (flag&BF_WEAPON)
- damage = damage * map[bl->m].weapon_damage_rate / 100;
+ damage = damage * map->list[bl->m].weapon_damage_rate / 100;
if (flag&BF_MAGIC)
- damage = damage * map[bl->m].magic_damage_rate / 100;
+ damage = damage * map->list[bl->m].magic_damage_rate / 100;
if (flag&BF_MISC)
- damage = damage * map[bl->m].misc_damage_rate / 100;
+ damage = damage * map->list[bl->m].misc_damage_rate / 100;
} else { //Normal attacks get reductions based on range.
if (flag & BF_SHORT)
- damage = damage * map[bl->m].short_damage_rate / 100;
+ damage = damage * map->list[bl->m].short_damage_rate / 100;
if (flag & BF_LONG)
- damage = damage * map[bl->m].long_damage_rate / 100;
+ damage = damage * map->list[bl->m].long_damage_rate / 100;
}
if(!damage) damage = 1;
break;
@@ -2978,11 +3085,11 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
damage = div_;
}
- if( bl->type == BL_MOB && !status_isdead(bl) && src != bl) {
+ if( bl->type == BL_MOB && !status->isdead(bl) && src != bl) {
if (damage > 0 )
- mobskill_event((TBL_MOB*)bl,src,iTimer->gettick(),flag);
+ mob->skill_event((TBL_MOB*)bl,src,timer->gettick(),flag);
if (skill_id)
- mobskill_event((TBL_MOB*)bl,src,iTimer->gettick(),MSC_SKILLUSED|(skill_id<<16));
+ mob->skill_event((TBL_MOB*)bl,src,timer->gettick(),MSC_SKILLUSED|(skill_id<<16));
}
if( sd ) {
if( pc_ismadogear(sd) && rnd()%100 < 50 ) {
@@ -2991,12 +3098,12 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
struct status_data *sstatus = NULL;
if( src->type == BL_PC && ((TBL_PC*)src)->bonus.arrow_ele )
element = ((TBL_PC*)src)->bonus.arrow_ele;
- else if( (sstatus = status_get_status_data(src)) ) {
+ else if( (sstatus = status->get_status_data(src)) ) {
element = sstatus->rhw.ele;
}
}
else if( element == -2 ) //Use enchantment's element
- element = status_get_attack_sc_element(src,status_get_sc(src));
+ element = status_get_attack_sc_element(src,status->get_sc(src));
else if( element == -3 ) //Use random element
element = rnd()%ELE_MAX;
if( element == ELE_FIRE || element == ELE_WATER )
@@ -3010,7 +3117,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
/*==========================================
* Calculates BG related damage adjustments.
*------------------------------------------*/
-int battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int damage, int div_, uint16 skill_id, uint16 skill_lv, int flag)
+int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag)
{
if( !damage )
return 0;
@@ -3028,10 +3135,9 @@ int battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int dam
/*==========================================
* Calculates GVG related damage adjustments.
*------------------------------------------*/
-int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,uint16 skill_id,uint16 skill_lv,int flag)
-{
+int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64 damage,int div_,uint16 skill_id,uint16 skill_lv,int flag) {
struct mob_data* md = BL_CAST(BL_MOB, bl);
- int class_ = status_get_class(bl);
+ int class_ = status->get_class(bl);
if (!damage) //No reductions to make.
return 0;
@@ -3050,7 +3156,7 @@ int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int dama
}
}
if(src->type != BL_MOB) {
- struct guild *g = src->type == BL_PC ? ((TBL_PC *)src)->guild : guild->search(status_get_guild_id(src));
+ struct guild *g = src->type == BL_PC ? ((TBL_PC *)src)->guild : guild->search(status->get_guild_id(src));
if (class_ == MOBID_EMPERIUM && (!g || guild->checkskill(g,GD_APPROVAL) <= 0 ))
return 0;
@@ -3065,6 +3171,7 @@ int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int dama
case HW_GRAVITATION:
case NJ_ZENYNAGE:
case KO_MUCHANAGE:
+ case NC_SELFDESTRUCTION:
break;
default:
/* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka]
@@ -3081,8 +3188,8 @@ int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int dama
/*==========================================
* HP/SP drain calculation
*------------------------------------------*/
-int battle_calc_drain(int damage, int rate, int per) {
- int diff = 0;
+int battle_calc_drain(int64 damage, int rate, int per) {
+ int64 diff = 0;
if (per && rnd()%1000 < rate) {
diff = (damage * per) / 100;
@@ -3093,7 +3200,7 @@ int battle_calc_drain(int damage, int rate, int per) {
diff = -1;
}
}
- return diff;
+ return (int)cap_value(diff,INT_MIN,INT_MAX);
}
/*==========================================
@@ -3104,7 +3211,7 @@ void battle_consume_ammo(TBL_PC*sd, int skill_id, int lv) {
if (!battle_config.arrow_decrement)
return;
- if (skill) {
+ if (skill_id) {
qty = skill->get_ammo_qty(skill_id, lv);
if (!qty) qty = 1;
}
@@ -3123,19 +3230,26 @@ int battle_range_type(struct block_list *src, struct block_list *target, uint16
return BF_SHORT;
return BF_LONG;
}
+
+ if (skill_id == SR_GATEOFHELL) {
+ if (skill_lv < 5)
+ return BF_SHORT;
+ else
+ return BF_LONG;
+ }
+
//based on used skill's range
if (skill->get_range2(src, skill_id, skill_lv) < 5)
return BF_SHORT;
return BF_LONG;
}
int battle_adjust_skill_damage(int m, unsigned short skill_id) {
-
- if( map[m].skill_count ) {
+ if( map->list[m].skill_count ) {
int i;
- ARR_FIND(0, map[m].skill_count, i, map[m].skills[i]->skill_id == skill_id );
+ ARR_FIND(0, map->list[m].skill_count, i, map->list[m].skills[i]->skill_id == skill_id );
- if( i < map[m].skill_count ) {
- return map[m].skills[i]->modifier;
+ if( i < map->list[m].skill_count ) {
+ return map->list[m].skills[i]->modifier;
}
}
@@ -3146,7 +3260,7 @@ int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) {
int i;
if (!sd->skillblown[0].id)
return 0;
- //Apply the bonus blewcount. [Skotlex]
+ //Apply the bonus blow count. [Skotlex]
for (i = 0; i < ARRAYLENGTH(sd->skillblown) && sd->skillblown[i].id; i++) {
if (sd->skillblown[i].id == skill_id)
return sd->skillblown[i].val;
@@ -3154,7 +3268,7 @@ int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) {
return 0;
}
//For quick div adjustment.
-#define damage_div_fix(dmg, div) { if (div > 1) (dmg)*=div; else if (div < 0) (div)*=-1; }
+#define damage_div_fix(dmg, div) do { if ((div) > 1) (dmg)*=(div); else if ((div) < 0) (div)*=-1; } while(0)
/*==========================================
* battle_calc_magic_attack [DracoRPG]
*------------------------------------------*/
@@ -3164,11 +3278,10 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
unsigned int skillratio = 100; //Skill dmg modifiers.
TBL_PC *sd;
-// TBL_PC *tsd;
- struct status_change *sc, *tsc;
+ struct status_change *sc;
struct Damage ad;
- struct status_data *sstatus = status_get_status_data(src);
- struct status_data *tstatus = status_get_status_data(target);
+ struct status_data *sstatus = status->get_status_data(src);
+ struct status_data *tstatus = status->get_status_data(target);
struct {
unsigned imdef : 1;
unsigned infdef : 1;
@@ -3177,11 +3290,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
memset(&ad,0,sizeof(ad));
memset(&flag,0,sizeof(flag));
- if(src==NULL || target==NULL)
- {
- nullpo_info(NLP_MARK);
- return ad;
- }
+ nullpo_retr(ad, src);
+ nullpo_retr(ad, target);
+
//Initial Values
ad.damage = 1;
ad.div_=skill->get_num(skill_id,skill_lv);
@@ -3194,9 +3305,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
flag.imdef = nk&NK_IGNORE_DEF?1:0;
sd = BL_CAST(BL_PC, src);
-// tsd = BL_CAST(BL_PC, target);
- sc = status_get_sc(src);
- tsc = status_get_sc(target);
+
+ sc = status->get_sc(src);
//Initialize variables that will be used afterwards
s_ele = skill->get_ele(skill_id, skill_lv);
@@ -3208,7 +3318,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
if( i < 5 ) s_ele = i;
}
}else if (s_ele == -2) //Use status element
- s_ele = status_get_attack_sc_element(src,status_get_sc(src));
+ s_ele = status_get_attack_sc_element(src,status->get_sc(src));
else if( s_ele == -3 ) //Use random element
s_ele = rnd()%ELE_MAX;
@@ -3230,11 +3340,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
//Skill Range Criteria
ad.flag |= battle->range_type(src, target, skill_id, skill_lv);
flag.infdef=(tstatus->mode&MD_PLANT?1:0);
- if( target->type == BL_SKILL){
- TBL_SKILL *su = (TBL_SKILL*)target;
- if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
- flag.infdef = 1;
- }
+ if( !flag.infdef && target->type == BL_SKILL && ((TBL_SKILL*)target)->group->unit_id == UNT_REVERBERATION )
+ flag.infdef = 1; // Reverberation takes 1 damage
switch(skill_id) {
case MG_FIREWALL:
@@ -3272,22 +3379,24 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
ad.damage = 0; //reinitialize..
#endif
//MATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc
-#define MATK_RATE( a ) { ad.damage= ad.damage*(a)/100; }
+#define MATK_RATE( a ) ( ad.damage= ad.damage*(a)/100 )
//Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage
-#define MATK_ADDRATE( a ) { ad.damage+= ad.damage*(a)/100; }
+#define MATK_ADDRATE( a ) ( ad.damage+= ad.damage*(a)/100 )
//Adds an absolute value to damage. 100 = +100 damage
-#define MATK_ADD( a ) { ad.damage+= a; }
+#define MATK_ADD( a ) ( ad.damage+= (a) )
switch (skill_id)
{ //Calc base damage according to skill
case AL_HEAL:
case PR_BENEDICTIO:
case PR_SANCTUARY:
+ ad.damage = skill->calc_heal(src, target, skill_id, skill_lv, false);
+ break;
/**
* Arch Bishop
**/
case AB_HIGHNESSHEAL:
- ad.damage = skill->calc_heal(src, target, skill_id, skill_lv, false);
+ ad.damage = skill->calc_heal(src, target, AL_HEAL, 10, false) * ( 17 + 3 * skill_lv ) / 10;
break;
case PR_ASPERSIO:
ad.damage = 40;
@@ -3295,16 +3404,16 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
case ALL_RESURRECTION:
case PR_TURNUNDEAD:
//Undead check is on skill_castend_damageid code.
- i = 20*skill_lv + sstatus->luk + sstatus->int_ + status_get_lv(src)
+ i = 20*skill_lv + sstatus->luk + sstatus->int_ + status->get_lv(src)
+ 200 - 200*tstatus->hp/tstatus->max_hp; // there is no changed in success chance in renewal. [malufett]
if(i > 700) i = 700;
if(rnd()%1000 < i && !(tstatus->mode&MD_BOSS))
ad.damage = tstatus->hp;
else {
#ifdef RENEWAL
- MATK_ADD(status_get_matk(src, 2));
+ MATK_ADD(status->get_matk(src, 2));
#else
- ad.damage = status_get_lv(src) + sstatus->int_ + skill_lv * 10;
+ ad.damage = status->get_lv(src) + sstatus->int_ + skill_lv * 10;
#endif
}
break;
@@ -3316,10 +3425,10 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
**/
case AB_RENOVATIO:
//Damage calculation from iRO wiki. [Jobbie]
- ad.damage = (int)((15 * status_get_lv(src)) + (1.5 * sstatus->int_));
+ ad.damage = status->get_lv(src) * 10 + sstatus->int_;
break;
- default: {
- MATK_ADD( status_get_matk(src, 2) );
+ default: {
+ MATK_ADD( status->get_matk(src, 2) );
if (nk&NK_SPLASHSPLIT) { // Divide MATK in case of multiple targets skill
if(mflag>0)
@@ -3330,44 +3439,44 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
if (sc){
if( sc->data[SC_TELEKINESIS_INTENSE] && s_ele == ELE_GHOST )
- skillratio += sc->data[SC_TELEKINESIS_INTENSE]->val3;
+ ad.damage += sc->data[SC_TELEKINESIS_INTENSE]->val3;
}
switch(skill_id){
case MG_FIREBOLT:
case MG_COLDBOLT:
case MG_LIGHTNINGBOLT:
if ( sc && sc->data[SC_SPELLFIST] && mflag&BF_SHORT ) {
- skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech]
+ skillratio = sc->data[SC_SPELLFIST]->val2 * 50 + sc->data[SC_SPELLFIST]->val4 * 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech]
ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax]
ad.flag = BF_WEAPON|BF_SHORT;
ad.type = 0;
}
- break;
default:
MATK_RATE(battle->calc_skillratio(BF_MAGIC, src, target, skill_id, skill_lv, skillratio, mflag));
}
//Constant/misc additions from skills
if (skill_id == WZ_FIREPILLAR)
MATK_ADD(50);
- if( sd && (i=pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
+ if( sd && ( sd->status.class_ == JOB_ARCH_BISHOP_T || sd->status.class_ == JOB_ARCH_BISHOP ) &&
+ (i=pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
(tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) )
MATK_ADDRATE(i);
}
}
#ifndef HMAP_ZONE_DAMAGE_CAP_TYPE
if( target && skill_id ) {
- for(i = 0; i < map[target->m].zone->capped_skills_count; i++) {
- if( skill_id == map[target->m].zone->capped_skills[i]->nameid && (map[target->m].zone->capped_skills[i]->type & target->type) ) {
- if( target->type == BL_MOB && map[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) {
- if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) )
+ for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) {
+ if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) {
+ if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) {
+ if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map->list[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) )
continue;
- if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) )
+ if( ((TBL_MOB*)target)->special_state.clone && !(map->list[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) )
continue;
}
- if( ad.damage > map[target->m].zone->capped_skills[i]->cap )
- ad.damage = map[target->m].zone->capped_skills[i]->cap;
- if( ad.damage2 > map[target->m].zone->capped_skills[i]->cap )
- ad.damage2 = map[target->m].zone->capped_skills[i]->cap;
+ if( ad.damage > map->list[target->m].zone->capped_skills[i]->cap )
+ ad.damage = map->list[target->m].zone->capped_skills[i]->cap;
+ if( ad.damage2 > map->list[target->m].zone->capped_skills[i]->cap )
+ ad.damage2 = map->list[target->m].zone->capped_skills[i]->cap;
break;
}
}
@@ -3377,11 +3486,36 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag);
#endif
if(sd) {
+ uint16 rskill;/* redirect skill */
//Damage bonuses
if ((i = pc->skillatk_bonus(sd, skill_id)))
ad.damage += ad.damage*i/100;
-
- if( (i = battle->adjust_skill_damage(src->m,skill_id)) )
+ switch(skill_id){
+ case WL_CHAINLIGHTNING_ATK:
+ rskill = WL_CHAINLIGHTNING;
+ break;
+ case AB_DUPLELIGHT_MAGIC:
+ rskill = AB_DUPLELIGHT;
+ break;
+ case WL_TETRAVORTEX_FIRE:
+ case WL_TETRAVORTEX_WATER:
+ case WL_TETRAVORTEX_WIND:
+ case WL_TETRAVORTEX_GROUND:
+ rskill = WL_TETRAVORTEX;
+ break;
+ case WL_SUMMON_ATK_FIRE:
+ case WL_SUMMON_ATK_WIND:
+ case WL_SUMMON_ATK_WATER:
+ case WL_SUMMON_ATK_GROUND:
+ rskill = WL_RELEASE;
+ break;
+ case WM_REVERBERATION_MAGIC:
+ rskill = WM_REVERBERATION;
+ break;
+ default:
+ rskill = skill_id;
+ }
+ if( (i = battle->adjust_skill_damage(src->m,rskill)) )
MATK_RATE(i);
//Ignore Defense?
@@ -3439,7 +3573,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
ad.damage = 0;
}
}
-
#ifndef RENEWAL
ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag);
#endif
@@ -3453,7 +3586,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
ad.damage=battle->calc_damage(src,target,&ad,ad.damage,skill_id,skill_lv);
if( map_flag_gvg2(target->m) )
ad.damage=battle->calc_gvg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag);
- else if( map[target->m].flag.battleground )
+ else if( map->list[target->m].flag.battleground )
ad.damage=battle->calc_bg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag);
switch( skill_id ) { /* post-calc modifiers */
@@ -3467,10 +3600,13 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
}
return ad;
+#undef MATK_RATE
+#undef MATK_ADDRATE
+#undef MATK_ADD
}
/*==========================================
- * Calculate Misc dammage for skill_id
+ * Calculate Misc damage for skill_id
*------------------------------------------*/
struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) {
int temp;
@@ -3479,19 +3615,17 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
struct map_session_data *sd, *tsd;
struct Damage md; //DO NOT CONFUSE with md of mob_data!
- struct status_data *sstatus = status_get_status_data(src);
- struct status_data *tstatus = status_get_status_data(target);
- struct status_change *tsc = status_get_sc(target);
+ struct status_data *sstatus = status->get_status_data(src);
+ struct status_data *tstatus = status->get_status_data(target);
+ struct status_change *tsc = status->get_sc(target);
#ifdef RENEWAL
- struct status_change *sc = status_get_sc(src);
+ struct status_change *sc = status->get_sc(src);
#endif
memset(&md,0,sizeof(md));
- if( src == NULL || target == NULL ){
- nullpo_info(NLP_MARK);
- return md;
- }
+ nullpo_retr(md, src);
+ nullpo_retr(md, target);
//Some initial values
md.amotion=skill->get_inf(skill_id)&INF_GROUND_SKILL?0:sstatus->amotion;
@@ -3527,7 +3661,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
case MA_LANDMINE:
case HT_BLASTMINE:
case HT_CLAYMORETRAP:
- md.damage = skill_lv * sstatus->dex * (3+status_get_lv(src)/100) * (1+sstatus->int_/35);
+ md.damage = skill_lv * sstatus->dex * (3+status->get_lv(src)/100) * (1+sstatus->int_/35);
md.damage += md.damage * (rnd()%20-10) / 100;
md.damage += 40 * (sd?pc->checkskill(sd,RA_RESEARCHTRAP):0);
break;
@@ -3585,12 +3719,12 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
case PA_GOSPEL:
md.damage = 1+rnd()%9999;
break;
- case CR_ACIDDEMONSTRATION:
+ case CR_ACIDDEMONSTRATION:
#ifdef RENEWAL
{// [malufett]
- int matk=0, atk;
- short tdef = status_get_total_def(target);
- short tmdef = status_get_total_mdef(target);
+ int64 matk=0, atk;
+ short tdef = status->get_total_def(target);
+ short tmdef = status->get_total_mdef(target);
int targetVit = min(120, status_get_vit(target));
short totaldef = (tmdef + tdef - ((uint64)(tmdef + tdef) >> 32)) >> 1;
@@ -3602,19 +3736,19 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage = 7 * targetVit * skill_lv * (atk + matk) / 100;
/*
// Pending [malufett]
- if( unknown condition )
- md.damage >>= 1;
if( unknown condition ){
md.damage = 7 * md.damage % 20;
md.damage = 7 * md.damage / 20;
}*/
}else{
- float vitfactor = 0.0f, temp;
+ float vitfactor = 0.0f, ftemp;
if( (vitfactor=(status_get_vit(target)-120.0f)) > 0)
vitfactor = (vitfactor * (matk + atk) / 10) / status_get_vit(target);
- temp = max(0, vitfactor) + (targetVit * (matk + atk)) / 10;
- md.damage = (int)(temp * 70 * skill_lv / 100);
+ ftemp = max(0, vitfactor) + (targetVit * (matk + atk)) / 10;
+ md.damage = (int64)(ftemp * 70 * skill_lv / 100);
+ if (target->type == BL_PC)
+ md.damage >>= 1;
}
md.damage -= totaldef;
}
@@ -3626,7 +3760,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage = 0;
if (tsd) md.damage>>=1;
#endif
- if (md.damage < 0 || md.damage > INT_MAX>>1)
+ // Some monsters have totaldef higher than md.damage in some cases, leading to md.damage < 0
+ if( md.damage < 0 )
+ md.damage = 0;
+ if( md.damage > INT_MAX>>1 )
//Overflow prevention, will anyone whine if I cap it to a few billion?
//Not capped to INT_MAX to give some room for further damage increase.
md.damage = INT_MAX>>1;
@@ -3648,7 +3785,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage=md.damage / 2;
break;
case GS_FLING:
- md.damage = sd?sd->status.job_level:status_get_lv(src);
+ md.damage = sd?sd->status.job_level:status->get_lv(src);
break;
case HVAN_EXPLOSION: //[orn]
md.damage = sstatus->max_hp * (50 + 50 * skill_lv) / 100;
@@ -3660,9 +3797,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
nk|=NK_IGNORE_FLEE|NK_NO_ELEFIX; //These two are not properties of the weapon based part.
#else
int ratio = 300 + 50 * skill_lv;
- int matk = battle->calc_magic_attack(src, target, skill_id, skill_lv, mflag).damage;
- short totaldef = status_get_total_def(target) + status_get_total_mdef(target);
- int atk = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, false, s_ele, ELE_NEUTRAL, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), md.flag);
+ int64 matk = battle->calc_magic_attack(src, target, skill_id, skill_lv, mflag).damage;
+ short totaldef = status->get_total_def(target) + status->get_total_mdef(target);
+ int64 atk = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, false, s_ele, ELE_NEUTRAL, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), md.flag);
if( sc && sc->data[SC_EDP] )
ratio >>= 1;
@@ -3682,7 +3819,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
case RK_DRAGONBREATH_WATER:
md.damage = ((status_get_hp(src) / 50) + (status_get_max_sp(src) / 4)) * skill_lv;
RE_LVL_MDMOD(150);
- if (sd) md.damage = md.damage * (100 + 5 * (pc->checkskill(sd,RK_DRAGONTRAINING) - 1)) / 100;
+ if (sd) md.damage = md.damage * (95 + 5 * pc->checkskill(sd,RK_DRAGONTRAINING)) / 100;
md.flag |= BF_LONG|BF_WEAPON;
break;
/**
@@ -3704,15 +3841,19 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage = md.damage * 200 / (skill_id == RA_CLUSTERBOMB?50:100);
break;
+ case WM_SOUND_OF_DESTRUCTION:
+ md.damage = 1000 * skill_lv + sstatus->int_ * (sd ? pc->checkskill(sd,WM_LESSON) : 10);
+ md.damage += md.damage * 10 * battle->calc_chorusbonus(sd) / 100;
+ break;
/**
* Mechanic
**/
case NC_SELFDESTRUCTION:
{
#ifdef RENEWAL
- short totaldef = status_get_total_def(target);
+ short totaldef = status->get_total_def(target);
#else
- short totaldef = tstatus->def2 + (short)status_get_def(target);
+ short totaldef = tstatus->def2 + (short)status->get_def(target);
#endif
md.damage = ( (sd?pc->checkskill(sd,NC_MAINFRAME):10) + 8 ) * ( skill_lv + 1 ) * ( status_get_sp(src) + sstatus->vit );
RE_LVL_MDMOD(100);
@@ -3726,16 +3867,16 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage = 100 + 200 * skill_lv + sstatus->int_;
break;
case GN_HELLS_PLANT_ATK:
- //[{( Hell Plant Skill Level x Casters Base Level ) x 10 } + {( Casters INT x 7 ) / 2 } x { 18 + ( Casters Job Level / 4 )] x ( 5 / ( 10 - Summon Flora Skill Level ))
- md.damage = ( skill_lv * status_get_lv(src) * 10 ) + ( sstatus->int_ * 7 / 2 ) * ( 18 + (sd?sd->status.job_level:0) / 4 ) * ( 5 / (10 - (sd?pc->checkskill(sd,AM_CANNIBALIZE):0)) );
+ md.damage = skill_lv * status->get_lv(src) * 10 + sstatus->int_ * 7 / 2 * (18 + (sd ? sd->status.job_level : 0) / 4) * (5 / (10 - (sd ? pc->checkskill(sd, AM_CANNIBALIZE) : 0)));
+ md.damage = md.damage*(1000 + tstatus->mdef) / (1000 + tstatus->mdef * 10) - tstatus->mdef2;
break;
case KO_HAPPOKUNAI:
{
struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag);
#ifdef RENEWAL
- short totaldef = status_get_total_def(target);
+ short totaldef = status->get_total_def(target);
#else
- short totaldef = tstatus->def2 + (short)status_get_def(target);
+ short totaldef = tstatus->def2 + (short)status->get_def(target);
#endif
md.damage = 3 * wd.damage * (5 + skill_lv) / 5;
md.damage -= totaldef;
@@ -3768,12 +3909,12 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) {
unsigned char attacker_count; //256 max targets should be a sane max
- attacker_count = unit_counttargeted(target);
+ attacker_count = unit->counttargeted(target);
if(attacker_count >= battle_config.agi_penalty_count)
{
if (battle_config.agi_penalty_type == 1)
flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
- else //asume type 2: absolute reduction
+ else // assume type 2: absolute reduction
flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
if(flee < 1) flee = 1;
}
@@ -3799,28 +3940,36 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
}
#ifndef HMAP_ZONE_DAMAGE_CAP_TYPE
if( target && skill_id ) {
- for(i = 0; i < map[target->m].zone->capped_skills_count; i++) {
- if( skill_id == map[target->m].zone->capped_skills[i]->nameid && (map[target->m].zone->capped_skills[i]->type & target->type) ) {
- if( target->type == BL_MOB && map[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) {
- if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) )
+ for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) {
+ if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) {
+ if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) {
+ if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map->list[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) )
continue;
- if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) )
+ if( ((TBL_MOB*)target)->special_state.clone && !(map->list[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) )
continue;
}
- if( md.damage > map[target->m].zone->capped_skills[i]->cap )
- md.damage = map[target->m].zone->capped_skills[i]->cap;
- if( md.damage2 > map[target->m].zone->capped_skills[i]->cap )
- md.damage2 = map[target->m].zone->capped_skills[i]->cap;
+ if( md.damage > map->list[target->m].zone->capped_skills[i]->cap )
+ md.damage = map->list[target->m].zone->capped_skills[i]->cap;
+ if( md.damage2 > map->list[target->m].zone->capped_skills[i]->cap )
+ md.damage2 = map->list[target->m].zone->capped_skills[i]->cap;
break;
}
}
}
#endif
md.damage = battle->calc_cardfix(BF_MISC, src, target, nk, s_ele, 0, md.damage, 0, md.flag);
-
- if (sd && (i = pc->skillatk_bonus(sd, skill_id)))
- md.damage += md.damage*i/100;
-
+ if(skill_id){
+ uint16 rskill;/* redirect skill id */
+ switch(skill_id){
+ case GN_HELLS_PLANT_ATK:
+ rskill = GN_HELLS_PLANT;
+ break;
+ default:
+ rskill = skill_id;
+ }
+ if (sd && (i = pc->skillatk_bonus(sd, rskill)))
+ md.damage += md.damage*i/100;
+ }
if( (i = battle->adjust_skill_damage(src->m,skill_id)) )
md.damage = md.damage * i / 100;
@@ -3839,10 +3988,6 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
default:
md.damage = 1;
}
- }else if( target->type == BL_SKILL ){
- TBL_SKILL *su = (TBL_SKILL*)target;
- if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
- md.damage = 1;
}
if(!(nk&NK_NO_ELEFIX))
@@ -3851,7 +3996,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage=battle->calc_damage(src,target,&md,md.damage,skill_id,skill_lv);
if( map_flag_gvg2(target->m) )
md.damage=battle->calc_gvg_damage(src,target,md.damage,md.div_,skill_id,skill_lv,md.flag);
- else if( map[target->m].flag.battleground )
+ else if( map->list[target->m].flag.battleground )
md.damage=battle->calc_bg_damage(src,target,md.damage,md.div_,skill_id,skill_lv,md.flag);
switch( skill_id ) {
@@ -3869,7 +4014,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
if( sd ) {
if ( md.damage > sd->status.zeny )
md.damage = sd->status.zeny;
- pc->payzeny(sd, md.damage,LOG_TYPE_STEAL,NULL);
+ pc->payzeny(sd, (int)cap_value(md.damage,INT_MIN,INT_MAX),LOG_TYPE_STEAL,NULL);
}
break;
}
@@ -3884,16 +4029,16 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
{
unsigned int skillratio = 100; //Skill dmg modifiers.
short temp=0;
- short s_ele, s_ele_, t_class;
+ short s_ele, s_ele_;
int i, nk;
bool n_ele = false; // non-elemental
struct map_session_data *sd, *tsd;
struct Damage wd;
- struct status_change *sc = status_get_sc(src);
- struct status_change *tsc = status_get_sc(target);
- struct status_data *sstatus = status_get_status_data(src);
- struct status_data *tstatus = status_get_status_data(target);
+ struct status_change *sc = status->get_sc(src);
+ struct status_change *tsc = status->get_sc(target);
+ struct status_data *sstatus = status->get_status_data(src);
+ struct status_data *tstatus = status->get_status_data(target);
struct {
unsigned hit : 1; //the attack Hit? (not a miss)
unsigned cri : 1; //Critical hit
@@ -3907,18 +4052,16 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
unsigned lh : 1; //Attack considers left hand (wd.damage2)
unsigned weapon : 1; //It's a weapon attack (consider VVS, and all that)
#ifdef RENEWAL
- unsigned tdef : 1; //Total defence reduction
+ unsigned tdef : 1; //Total defense reduction
#endif
} flag;
memset(&wd,0,sizeof(wd));
memset(&flag,0,sizeof(flag));
- if(src==NULL || target==NULL)
- {
- nullpo_info(NLP_MARK);
- return wd;
- }
+ nullpo_retr(wd, src);
+ nullpo_retr(wd, target);
+
//Initial flag
flag.rh=1;
flag.weapon=1;
@@ -3927,11 +4070,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
&& skill_id != HT_FREEZINGTRAP
#endif
?1:0);
- if( target->type == BL_SKILL){
- TBL_SKILL *su = (TBL_SKILL*)target;
- if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) )
- flag.infdef = 1;
- }
+ if( !flag.infdef && target->type == BL_SKILL && ((TBL_SKILL*)target)->group->unit_id == UNT_REVERBERATION )
+ flag.infdef = 1; // Reverberation takes 1 damage
//Initial Values
wd.type=0; //Normal attack
@@ -4050,7 +4190,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
return wd;
}
- t_class = status_get_class(target);
s_ele = s_ele_ = skill->get_ele(skill_id, skill_lv);
if( !skill_id || s_ele == -1 )
{ //Take weapon's element
@@ -4116,7 +4255,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW
&& (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1){
- int chance = rand()%100;
+ int chance = rnd()%100;
wd.type = 0x08;
switch(sc->data[SC_FEARBREEZE]->val1){
case 5:
@@ -4167,13 +4306,17 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
//Therefore, we use the old value 3 on cases when an sd gets attacked by a mob
cri -= tstatus->luk*(!sd&&tsd?3:2);
#else
- cri -= status_get_lv(target) / 15 + 2 * status_get_luk(target);
+ cri -= status->get_lv(target) / 15 + 2 * status_get_luk(target);
#endif
if( tsc && tsc->data[SC_SLEEP] ) {
cri <<= 1;
}
switch (skill_id) {
+ case 0:
+ if(!(sc && sc->data[SC_AUTOCOUNTER]))
+ break;
+ status_change_end(src, SC_AUTOCOUNTER, INVALID_TIMER);
case KN_AUTOCOUNTER:
if(battle_config.auto_counter_type &&
(battle_config.auto_counter_type&src->type))
@@ -4235,7 +4378,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) {
unsigned char attacker_count; //256 max targets should be a sane max
- attacker_count = unit_counttargeted(target);
+ attacker_count = unit->counttargeted(target);
if(attacker_count >= battle_config.agi_penalty_count) {
if (battle_config.agi_penalty_type == 1)
flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
@@ -4300,6 +4443,12 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
case GC_VENOMPRESSURE:
hitrate += 10 + 4 * skill_lv;
break;
+ case SC_FATALMENACE:
+ hitrate -= 35 - 5 * skill_lv;
+ break;
+ case LG_BANISHINGPOINT:
+ hitrate += 3 * skill_lv;
+ break;
}
if( sd ) {
@@ -4317,8 +4466,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if( !sd )
hitrate = cap_value(hitrate, 5, 95);
#endif
- if(rnd()%100 >= hitrate)
+ if(rnd()%100 >= hitrate){
wd.dmg_lv = ATK_FLEE;
+ if (skill_id == SR_GATEOFHELL)
+ flag.hit = 1;/* will hit with the special */
+ }
else
flag.hit = 1;
} //End hit/miss calculation
@@ -4328,51 +4480,67 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
//Assuming that 99% of the cases we will not need to check for the flag.rh... we don't.
//ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc
-#define ATK_RATE( a ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(a)/100; }
-#define ATK_RATE2( a , b ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(b)/100; }
-#define ATK_RATER(a){ wd.damage = wd.damage*(a)/100;}
-#define ATK_RATEL(a){ wd.damage2 = wd.damage2*(a)/100;}
+#define ATK_RATE( a ) do { int64 temp__ = (a); wd.damage= wd.damage*temp__/100 ; if(flag.lh) wd.damage2= wd.damage2*temp__/100; } while(0)
+#define ATK_RATE2( a , b ) do { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(b)/100; } while(0)
+#define ATK_RATER(a) ( wd.damage = wd.damage*(a)/100 )
+#define ATK_RATEL(a) ( wd.damage2 = wd.damage2*(a)/100 )
//Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage
-#define ATK_ADDRATE( a ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(a)/100; }
-#define ATK_ADDRATE2( a , b ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(b)/100; }
+#define ATK_ADDRATE( a ) do { int64 temp__ = (a); wd.damage+= wd.damage*temp__/100; if(flag.lh) wd.damage2+= wd.damage2*temp__/100; } while(0)
+#define ATK_ADDRATE2( a , b ) do { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(b)/100; } while(0)
//Adds an absolute value to damage. 100 = +100 damage
-#define ATK_ADD( a ) { wd.damage+= a; if (flag.lh) wd.damage2+= a; }
-#define ATK_ADD2( a , b ) { wd.damage+= a; if (flag.lh) wd.damage2+= b; }
-
+#define ATK_ADD( a ) do { int64 temp__ = (a); wd.damage += temp__; if (flag.lh) wd.damage2 += temp__; } while(0)
+#define ATK_ADD2( a , b ) do { wd.damage += (a); if (flag.lh) wd.damage2 += (b); } while(0)
+#ifdef RENEWAL
+#define GET_NORMAL_ATTACK( f ) ( wd.damage = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (f), wd.flag) )
+#define GET_NORMAL_ATTACK2( f ) ( wd.damage2 = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_L, (f), wd.flag) )
+#endif
switch (skill_id)
{ //Calc base damage according to skill
case PA_SACRIFICE:
wd.damage = sstatus->max_hp* 9/100;
wd.damage2 = 0;
- break;
-
#ifdef RENEWAL
- case MO_EXTREMITYFIST: // [malufett]
- wd.damage = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|8, wd.flag);
- // first value is still not confirm.
- wd.damage = status_get_sp(src) + 10 * status_get_sp(src) * wd.damage / 100 + 8 * wd.damage;
- flag.tdef = 1;
+ wd.damage = battle->calc_elefix(src, target, skill_id, skill_lv, wd.damage, nk, n_ele, s_ele, s_ele_, false, wd.flag); // temporary [malufett]
+#endif
break;
case NJ_ISSEN: // [malufett]
+#ifndef RENEWAL
+ wd.damage = 40*sstatus->str +skill_lv*(sstatus->hp/10 + 35);
+ wd.damage2 = 0;
+#else
{
- short totaldef = status_get_total_def(target);
+ short totaldef = status->get_total_def(target);
i = 0;
- wd.damage = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), wd.flag);
+ GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) );
if( sc && sc->data[SC_NJ_BUNSINJYUTSU] && (i=sc->data[SC_NJ_BUNSINJYUTSU]->val2) > 0 )
wd.div_ = ~( i++ + 2 ) + 1;
- wd.damage *= sstatus->hp * skill_lv;
- wd.damage = wd.damage / sstatus->max_hp + sstatus->hp + i * (wd.damage / sstatus->max_hp + sstatus->hp) / 5;
+ if( wd.damage ){
+ wd.damage *= sstatus->hp * skill_lv;
+ wd.damage = wd.damage / sstatus->max_hp + sstatus->hp + i * (wd.damage / sstatus->max_hp + sstatus->hp) / 5;
+ }
ATK_ADD(-totaldef);
if( is_boss(target) )
ATK_RATE(50);
- flag.idef = 1;
+ RE_SKILL_REDUCTION();
+ }
+ break;
+ case NJ_SYURIKEN: // [malufett]
+ GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) );
+ wd.damage += battle->calc_masteryfix(src, target, skill_id, skill_lv, 4 * skill_lv + (sd ? sd->bonus.arrow_atk : 0), wd.div_, 0, flag.weapon) - status->get_total_def(target);
+ RE_SKILL_REDUCTION();
+ break;
+ case MO_EXTREMITYFIST: // [malufett]
+ {
+ short totaldef = status->get_total_def(target);
+ GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|8 );
+ if( wd.damage ){
+ wd.damage = (250 + 150 * skill_lv) + (10 * (status_get_sp(src)+1) * wd.damage / 100) + (8 * wd.damage);
+ ATK_ADD(-totaldef);
+ }
+ RE_SKILL_REDUCTION();
}
-#else
-
- wd.damage = 40*sstatus->str +skill_lv*(sstatus->hp/10 + 35);
- wd.damage2 = 0;
#endif
- break;
+ break;
#ifndef RENEWAL
case LK_SPIRALPIERCE:
case ML_SPIRALPIERCE:
@@ -4383,18 +4551,18 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
sd->inventory_data[index] &&
sd->inventory_data[index]->type == IT_WEAPON)
wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight
- } else
- wd.damage = sstatus->rhw.atk2*8/10; //Else use Atk2
-
- ATK_ADDRATE(50*skill_lv); //Skill modifier applies to weight only.
+ ATK_ADDRATE(50*skill_lv); //Skill modifier applies to weight only.
+ } else {
+ wd.damage = battle->calc_base_damage2(sstatus, &sstatus->rhw, sc, tstatus->size, sd, 0); //Monsters have no weight and use ATK instead
+ }
i = sstatus->str/10;
i*=i;
ATK_ADD(i); //Add str bonus.
switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection?
- case SZ_SMALL: //Small: 125%
+ case SZ_MEDIUM: //Medium: 125%
ATK_RATE(125);
break;
- //case SZ_MEDIUM: //Medium: 100%
+ //case SZ_SMALL: //Medium: 100%
case SZ_BIG: //Large: 75%
ATK_RATE(75);
break;
@@ -4403,16 +4571,14 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
#endif
case CR_SHIELDBOOMERANG:
case PA_SHIELDCHAIN:
- case LG_SHIELDPRESS:
- case LG_EARTHDRIVE:
wd.damage = sstatus->batk;
if (sd) {
+ int damagevalue = 0;
short index = sd->equip_index[EQI_HAND_L];
- if (index >= 0 &&
- sd->inventory_data[index] &&
- sd->inventory_data[index]->type == IT_ARMOR)
- ATK_ADD(sd->inventory_data[index]->weight/10);
+ if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
+ damagevalue = sd->inventory_data[index]->weight/10;
+ ATK_ADD(damagevalue);
} else
ATK_ADD(sstatus->rhw.atk2); //Else use Atk2
break;
@@ -4447,16 +4613,16 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
i |= 16; // for ex. shuriken must not be influenced by DEX
}
#ifdef RENEWAL
- wd.damage = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, i, wd.flag);
+ GET_NORMAL_ATTACK( i );
wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon);
if (flag.lh){
- wd.damage2 = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_L, i, wd.flag);
+ GET_NORMAL_ATTACK2( i );
wd.damage2 = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage2, wd.div_, 1, flag.weapon);
}
#else
- wd.damage = battle->calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i);
+ wd.damage = battle->calc_base_damage2(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i);
if (flag.lh)
- wd.damage2 = battle->calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i);
+ wd.damage2 = battle->calc_base_damage2(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i);
#endif
if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets
if(wflag>0)
@@ -4469,133 +4635,171 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if(sd) {
if (sd->bonus.atk_rate)
ATK_ADDRATE(sd->bonus.atk_rate);
-
if(flag.cri && sd->bonus.crit_atk_rate)
ATK_ADDRATE(sd->bonus.crit_atk_rate);
+ if(flag.cri && sc && sc->data[SC_MTF_CRIDAMAGE])
+ ATK_ADDRATE(25);// temporary it should be 'bonus.crit_atk_rate'
+#ifndef RENEWAL
if(sd->status.party_id && (temp=pc->checkskill(sd,TK_POWER)) > 0){
- if( (i = party_foreachsamemap(party->sub_count, sd, 0)) > 1 ) // exclude the player himself [Inkfish]
+ if( (i = party->foreachsamemap(party->sub_count, sd, 0)) > 1 ) // exclude the player himself [Inkfish]
ATK_ADDRATE(2*temp*i);
}
+#endif
}
break;
} //End default case
} //End switch(skill_id)
- //Skill damage modifiers that stack linearly
- if( sd && sd->status.weapon == W_KATAR && (i=pc->checkskill(sd,ASC_KATAR)) > 0 )
- skillratio += skillratio * (13 + 2 * i) / 100;
- if(sc && skill_id != PA_SACRIFICE)
- {
- if(sc->data[SC_OVERTHRUST])
- skillratio += sc->data[SC_OVERTHRUST]->val3;
- if(sc->data[SC_OVERTHRUSTMAX])
- skillratio += sc->data[SC_OVERTHRUSTMAX]->val2;
- if (sc->data[SC_BERSERK] || sc->data[SC_SATURDAY_NIGHT_FEVER] || sc->data[SC__BLOODYLUST])
- skillratio += 100;
-#ifdef RENEWAL
- if( sc->data[SC_TRUESIGHT] )
- skillratio += 2*sc->data[SC_TRUESIGHT]->val1;
- if( sc->data[SC_LKCONCENTRATION] )
- skillratio += sc->data[SC_LKCONCENTRATION]->val2;
-#endif
- if( sc->data[SC_UNLIMIT] && wd.flag&BF_LONG )
- ATK_ADD( 50 * sc->data[SC_UNLIMIT]->val1 );
+ if( sc && skill_id != PA_SACRIFICE && sc->data[SC_UNLIMIT] && (wd.flag&(BF_LONG|BF_MAGIC)) == BF_LONG) {
+ switch(skill_id) {
+ case RA_WUGDASH:
+ case RA_WUGSTRIKE:
+ case RA_WUGBITE:
+ break;
+ default:
+ ATK_ADDRATE( 50 * sc->data[SC_UNLIMIT]->val1 );
+ }
}
- if( tsc && skill_id != PA_SACRIFICE ){
- if( tsc->data[SC_DARKCROW] && wd.flag&BF_SHORT )
- ATK_ADD( 30 * tsc->data[SC_DARKCROW]->val1 );
+
+ if ( sc && !skill_id && sc->data[SC_EXEEDBREAK] ) {
+ ATK_ADDRATE(sc->data[SC_EXEEDBREAK]->val1);
+ status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER);
}
- if( !skill_id )
- {
- ATK_RATE(skillratio);
+
+ #ifdef RENEWAL
+ if( sd && skill_id == NJ_KUNAI ){
+ flag.tdef = 1;
+ ATK_ADD( sd->bonus.arrow_atk );
}
- else
- {
- switch(skill_id){
+ #endif
+ switch(skill_id){
+ case SR_GATEOFHELL:
#ifdef RENEWAL
- case LK_SPIRALPIERCE:
- case ML_SPIRALPIERCE:
- {// Formula: Floor[Floor(Weapon Weight/2)*skill level + ATK ]*(100%+50%*s.lvl) * 5 multi-hits
+ RE_SKILL_REDUCTION();
+ #endif // RENEWAL
+ if (wd.dmg_lv != ATK_FLEE)
+ ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag));
+ else
+ wd.dmg_lv = ATK_DEF;
+ break;
+ #ifdef RENEWAL
+ case NJ_TATAMIGAESHI:
+ ATK_RATE(200);
+ case LK_SPIRALPIERCE:
+ case ML_SPIRALPIERCE: // [malufett]
+ if( skill_id != NJ_TATAMIGAESHI ){
short index = sd?sd->equip_index[EQI_HAND_R]:0;
- int weight = 0;
-
+ GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) );
+ wd.damage = wd.damage * 70 / 100;
+ //n_ele = true; // FIXME: This is has no effect if it's after GET_NORMAL_ATTACK (was this intended, or was it supposed to be put above?)
+
if (sd && index >= 0 &&
sd->inventory_data[index] &&
sd->inventory_data[index]->type == IT_WEAPON)
- weight = sd->inventory_data[index]->weight/20;
- ATK_ADD(weight * skill_lv);
+ ATK_ADD(sd->inventory_data[index]->weight * 7 / 100);
+
+ switch (tstatus->size) {
+ case SZ_MEDIUM: //Medium: 115%
+ ATK_RATE(115);
+ break;
+ case SZ_BIG: //Large: 85%
+ ATK_RATE(85);
+ }
+ wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon);
}
- case NJ_TATAMIGAESHI:
- if( skill_id != LK_SPIRALPIERCE && skill_id != ML_SPIRALPIERCE )
- ATK_RATE(200);
#endif
- default:
- ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag));
- }
+ default:
+ ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag));
+ }
//Constant/misc additions from skills
- switch (skill_id) {
- case MO_EXTREMITYFIST:
- ATK_ADD(250 + 150*skill_lv);
- break;
+ switch (skill_id) {
#ifdef RENEWAL
- case HW_MAGICCRASHER:
- ATK_ADD(battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag).damage / 5);
- break;
+ case HW_MAGICCRASHER:
+ ATK_ADD(battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag).damage / 5);
+ break;
+#else
+ case MO_EXTREMITYFIST:
+ ATK_ADD(250 + 150*skill_lv);
+ break;
#endif
- case TK_DOWNKICK:
- case TK_STORMKICK:
- case TK_TURNKICK:
- case TK_COUNTER:
- case TK_JUMPKICK:
- //TK_RUN kick damage bonus.
- if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST)
- ATK_ADD(10*pc->checkskill(sd, TK_RUN));
- break;
- case GS_MAGICALBULLET:
+ case TK_DOWNKICK:
+ case TK_STORMKICK:
+ case TK_TURNKICK:
+ case TK_COUNTER:
+ case TK_JUMPKICK:
+ //TK_RUN kick damage bonus.
+ if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST)
+ ATK_ADD(10*pc->checkskill(sd, TK_RUN));
+ break;
+ case GS_MAGICALBULLET:
#ifndef RENEWAL
- ATK_ADD( status_get_matk(src, 2) );
+ ATK_ADD( status->get_matk(src, 2) );
#else
- ATK_ADD( battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag).damage );
- flag.tdef = 1;
+ ATK_ADD( battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag).damage );
+ flag.tdef = 1;
#endif
- case NJ_SYURIKEN:
- ATK_ADD(4*skill_lv);
- break;
- case HT_FREEZINGTRAP:
- if(sd)
- ATK_ADD( 40 * pc->checkskill(sd, RA_RESEARCHTRAP) );
- break;
- case RA_WUGDASH ://(Caster Current Weight x 10 / 8)
- if( sd && sd->weight )
- ATK_ADD( sd->weight / 8 );
- break;
- case SR_TIGERCANNON: // (Tiger Cannon skill level x 240) + (Target Base Level x 40)
- ATK_ADD( skill_lv * 240 + status_get_lv(target) * 40 );
- if( sc && sc->data[SC_COMBOATTACK]
- && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE ) // (Tiger Cannon skill level x 500) + (Target Base Level x 40)
- ATK_ADD( skill_lv * 500 + status_get_lv(target) * 40 );
- break;
- case SR_FALLENEMPIRE:// [(Target Size value + Skill Level - 1) x Caster STR] + [(Target current weight x Caster DEX / 120)]
- ATK_ADD( ((tstatus->size+1)*2 + skill_lv - 1) * sstatus->str);
- if( tsd && tsd->weight ){
- ATK_ADD( (tsd->weight/10) * sstatus->dex / 120 );
- }else{
- ATK_ADD( status_get_lv(target) * 50 ); //mobs
- }
- break;
- case KO_SETSUDAN:
- if( tsc && tsc->data[SC_SOULLINK] ){
- ATK_ADDRATE(200*tsc->data[SC_SOULLINK]->val1);
- status_change_end(target,SC_SOULLINK,INVALID_TIMER);
- }
- break;
- case KO_MAKIBISHI:
- wd.damage = 20 * skill_lv;
- break;
- }
+#ifndef RENEWAL
+ case NJ_SYURIKEN:
+ ATK_ADD(4*skill_lv);
+#endif
+ break;
+ case GC_COUNTERSLASH:
+ ATK_ADD( status_get_agi(src) * 2 + (sd?sd->status.job_level:0) * 4 );
+ break;
+ case RA_WUGDASH:
+ if( sc && sc->data[SC_DANCE_WITH_WUG] )
+ ATK_ADD(2 * sc->data[SC_DANCE_WITH_WUG]->val1 * (2 + battle->calc_chorusbonus(sd)));
+ break;
+ case SR_TIGERCANNON:
+ ATK_ADD( skill_lv * 240 + status->get_lv(target) * 40 );
+ if( sc && sc->data[SC_COMBOATTACK]
+ && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE )
+ ATK_ADD( skill_lv * 500 + status->get_lv(target) * 40 );
+ break;
+ case RA_WUGSTRIKE:
+ case RA_WUGBITE:
+ if(sd)
+ ATK_ADD(30*pc->checkskill(sd, RA_TOOTHOFWUG));
+ if( sc && sc->data[SC_DANCE_WITH_WUG] )
+ ATK_ADD(2 * sc->data[SC_DANCE_WITH_WUG]->val1 * (2 + battle->calc_chorusbonus(sd)));
+ break;
+ case LG_SHIELDPRESS:
+ if( sd ) {
+ int damagevalue = 0;
+ short index = sd->equip_index[EQI_HAND_L];
+ if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
+ damagevalue = sstatus->vit * sd->status.inventory[index].refine;
+ ATK_ADD(damagevalue);
+ }
+ break;
+ case SR_GATEOFHELL:
+ ATK_ADD (sstatus->max_hp - status_get_hp(src));
+ if(sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE) {
+ ATK_ADD( (sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status->get_lv(src) );
+ } else {
+ ATK_ADD( (sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status->get_lv(src) );
+ }
+ break;
+ case SR_FALLENEMPIRE:// [(Target Size value + Skill Level - 1) x Caster STR] + [(Target current weight x Caster DEX / 120)]
+ ATK_ADD( ((tstatus->size+1)*2 + skill_lv - 1) * sstatus->str);
+ if( tsd && tsd->weight ){
+ ATK_ADD( (tsd->weight/10) * sstatus->dex / 120 );
+ }else{
+ ATK_ADD( status->get_lv(target) * 50 ); //mobs
+ }
+ break;
+ case KO_SETSUDAN:
+ if( tsc && tsc->data[SC_SOULLINK] ){
+ ATK_ADDRATE(200*tsc->data[SC_SOULLINK]->val1);
+ status_change_end(target,SC_SOULLINK,INVALID_TIMER);
+ }
+ break;
+ case KO_MAKIBISHI:
+ wd.damage = 20 * skill_lv;
+ break;
}
#ifndef RENEWAL
//Div fix.
@@ -4607,24 +4811,20 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if( sc->data[SC_TRUESIGHT] )
ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1);
#endif
- if( sc->data[SC_GLOOMYDAY_SK] &&
- ( skill_id == LK_SPIRALPIERCE || skill_id == KN_BRANDISHSPEAR ||
- skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ||
- skill_id == LG_SHIELDPRESS || skill_id == RK_HUNDREDSPEAR ||
- skill_id == CR_SHIELDCHARGE ) )
- ATK_ADDRATE(sc->data[SC_GLOOMYDAY_SK]->val2);
+
+#ifndef RENEWAL_EDP
if( sc->data[SC_EDP] ){
switch(skill_id){
-#ifndef RENEWAL_EDP
- case AS_SPLASHER: case AS_VENOMKNIFE:
+ case AS_SPLASHER:
case AS_GRIMTOOTH:
- break;
+ case ASC_BREAKER:
+ case AS_VENOMKNIFE:
case ASC_METEORASSAULT: break;
default:
ATK_ADDRATE(sc->data[SC_EDP]->val3);
-#endif
}
}
+#endif
if(sc->data[SC_STYLE_CHANGE]){
TBL_HOM *hd = BL_CAST(BL_HOM,src);
if (hd) ATK_ADD(hd->homunculus.spiritball * 3);
@@ -4645,18 +4845,54 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
sc->data[SC_SOULLINK]->val2 == SL_CRUSADER)
ATK_ADDRATE(100);
break;
- case NC_AXETORNADO:
- if( (sstatus->rhw.ele) == ELE_WIND || (sstatus->lhw.ele) == ELE_WIND )
- ATK_ADDRATE(50);
- break;
+ }
+ if( skill_id ){
+ uint16 rskill;/* redirect skill id */
+ switch(skill_id){
+ case AB_DUPLELIGHT_MELEE:
+ rskill = AB_DUPLELIGHT;
+ break;
+ case LG_OVERBRAND_BRANDISH:
+ case LG_OVERBRAND_PLUSATK:
+ rskill = LG_OVERBRAND;
+ break;
+ case WM_SEVERE_RAINSTORM_MELEE:
+ rskill = WM_SEVERE_RAINSTORM;
+ break;
+ case WM_REVERBERATION_MELEE:
+ rskill = WM_REVERBERATION;
+ break;
+ case GN_CRAZYWEED_ATK:
+ rskill = GN_CRAZYWEED;
+ break;
+ case GN_SLINGITEM_RANGEMELEEATK:
+ rskill = GN_SLINGITEM;
+ break;
+ case RL_R_TRIP_PLUSATK:
+ rskill = RL_R_TRIP;
+ break;
+ case RL_B_FLICKER_ATK:
+ rskill = RL_FLICKER;
+ break;
+ case RL_GLITTERING_GREED_ATK:
+ rskill = RL_GLITTERING_GREED;
+ break;
+ default:
+ rskill = skill_id;
+ }
+ if( (i = battle->adjust_skill_damage(src->m,rskill)) )
+ ATK_RATE(i);
}
- if( (i = battle->adjust_skill_damage(src->m,skill_id)) )
- ATK_RATE(i);
-
if( sd ) {
if (skill_id && (i = pc->skillatk_bonus(sd, skill_id)))
ATK_ADDRATE(i);
+ #ifdef RENEWAL
+ if( wd.flag&BF_LONG )
+ ATK_ADDRATE(sd->bonus.long_attack_atk_rate);
+ if( sc && sc->data[SC_MTF_RANGEATK] )
+ ATK_ADDRATE(25);// temporary it should be 'bonus.long_attack_atk_rate'
+ #endif
if( (i=pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
(tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) )
ATK_ADDRATE(-i);
@@ -4736,6 +4972,19 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
#endif
ATK_ADD(20*lv);
}
+
+ if( !skill_id ) {
+ if( sc->data[SC_ENCHANTBLADE] ) {
+ //[( ( Skill Lv x 20 ) + 100 ) x ( casterBaseLevel / 150 )] + casterInt
+ i = ( sc->data[SC_ENCHANTBLADE]->val1 * 20 + 100 ) * status->get_lv(src) / 150 + status_get_int(src);
+ i = i - status->get_total_mdef(target) + status->get_matk(src, 2);
+ if( i )
+ ATK_ADD(i);
+ }
+ if( sc->data[SC_GIANTGROWTH] && rnd()%100 < 15 )
+ ATK_ADDRATE(200); // Triple Damage
+ }
+
}
#ifndef RENEWAL
//Refine bonus
@@ -4758,10 +5007,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
#ifndef RENEWAL
wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon);
- if( flag.lh)
+ if( flag.lh )
wd.damage2 = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage2, wd.div_, 1, flag.weapon);
#else
- if( flag.cri )
+ if( sd && flag.cri )
ATK_ADDRATE(40);
#endif
} //Here ends flag.hit section, the rest of the function applies to both hitting and missing attacks
@@ -4784,23 +5033,24 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
return wd; //Enough, rest is not needed.
#ifndef HMAP_ZONE_DAMAGE_CAP_TYPE
if( target && skill_id ) {
- for(i = 0; i < map[target->m].zone->capped_skills_count; i++) {
- if( skill_id == map[target->m].zone->capped_skills[i]->nameid && (map[target->m].zone->capped_skills[i]->type & target->type) ) {
- if( target->type == BL_MOB && map[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) {
- if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) )
+ for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) {
+ if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) {
+ if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) {
+ if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map->list[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) )
continue;
- if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) )
+ if( ((TBL_MOB*)target)->special_state.clone && !(map->list[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) )
continue;
}
- if( wd.damage > map[target->m].zone->capped_skills[i]->cap )
- wd.damage = map[target->m].zone->capped_skills[i]->cap;
- if( wd.damage2 > map[target->m].zone->capped_skills[i]->cap )
- wd.damage2 = map[target->m].zone->capped_skills[i]->cap;
+ if( wd.damage > map->list[target->m].zone->capped_skills[i]->cap )
+ wd.damage = map->list[target->m].zone->capped_skills[i]->cap;
+ if( wd.damage2 > map->list[target->m].zone->capped_skills[i]->cap )
+ wd.damage2 = map->list[target->m].zone->capped_skills[i]->cap;
break;
}
}
}
#endif
+
#ifndef RENEWAL
if (sd) {
if (skill_id != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus.
@@ -4811,13 +5061,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
ATK_ADD(wd.div_*sd->spiritball*3);
}
//Card Fix, sd side
+
wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 2, wd.flag);
if( flag.lh )
wd.damage2 = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage2, 3, wd.flag);
-#ifdef RENEWAL
- if( flag.cri )
- ATK_ADDRATE(sd->bonus.crit_atk_rate>=100?sd->bonus.crit_atk_rate-60:40);
-#endif
+
if( skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN )
{ //Refine bonus applies after cards and elements.
short index= sd->equip_index[EQI_HAND_L];
@@ -4827,13 +5075,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
//Card Fix, tsd side
if(tsd){ //if player on player then it was already measured above
- wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 2, wd.flag);
- if( flag.lh )
- wd.damage2 = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage2, 3, wd.flag);
+ wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, (flag.lh?1:0), wd.flag);
}
#endif
if( flag.infdef ) { //Plants receive 1 damage when hit
- short class_ = status_get_class(target);
+ short class_ = status->get_class(target);
if( flag.hit || wd.damage > 0 )
wd.damage = wd.div_; // In some cases, right hand no need to have a weapon to increase damage
if( flag.lh && (flag.hit || wd.damage2 > 0) )
@@ -4884,12 +5130,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
temp = pc->checkskill(sd,TF_DOUBLE);
wd.damage2 = wd.damage * (1 + (temp * 2))/100;
- if(wd.damage && !wd.damage2) wd.damage2 =
+ if(wd.damage && !wd.damage2) {
#ifdef RENEWAL
- 0;
+ wd.damage2 = 0;
#else
- 1;
+ wd.damage2 = 1;
#endif
+ }
flag.lh = 1;
}
}
@@ -4900,6 +5147,19 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if(!flag.lh && wd.damage2)
wd.damage2=0;
+ if( sc && sc->data[SC_GLOOMYDAY] ) {
+ switch( skill_id ) {
+ case KN_BRANDISHSPEAR:
+ case LK_SPIRALPIERCE:
+ case CR_SHIELDCHARGE:
+ case CR_SHIELDBOOMERANG:
+ case PA_SHIELDCHAIN:
+ case RK_HUNDREDSPEAR:
+ case LG_SHIELDPRESS:
+ wd.damage += wd.damage * sc->data[SC_GLOOMYDAY]->val2 / 100;
+ }
+ }
+
if( sc ) {
//SG_FUSION hp penalty [Komurka]
if (sc->data[SC_FUSION]) {
@@ -4912,12 +5172,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
hp = 2*hp/100; //2% hp loss per hit
status_zap(src, hp, 0);
}
- if( !skill_id ) {
- if( sc->data[SC_ENCHANTBLADE] ) { // it also works with bear hands..intended in official
- //[( ( Skill Lv x 20 ) + 100 ) x ( casterBaseLevel / 150 )] + casterInt
- ATK_ADD(( sc->data[SC_ENCHANTBLADE]->val1 * 20 + 100 ) * status_get_lv(src) / 150 + status_get_int(src));
- }
- }
status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);
}
@@ -4928,82 +5182,34 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.damage += md.damage;
break;
}
- case SR_GATEOFHELL:
- ATK_ADD (sstatus->max_hp - status_get_hp(src));
- if(sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE){
- ATK_ADD ( (sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status_get_lv(src) );
- }else{
- ATK_ADD ( (sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status_get_lv(src) );
- }
- break;
}
- if( wd.damage + wd.damage2 )
- { //There is a total damage value
- int damage = wd.damage + wd.damage2, rdamage = 0, rdelay = 0;
-
- if( src != target &&
- (!skill_id || skill_id ||
- ( src->type == BL_SKILL && ( skill_id == SG_SUN_WARM || skill_id == SG_MOON_WARM || skill_id == SG_STAR_WARM ) )) ){
-
- rdamage = battle->calc_return_damage(target, src, &damage, wd.flag, 0, &rdelay);
-
- if( tsc && tsc->count ) {
- if( tsc && tsc->data[SC_DEATHBOUND] ){
- wd.damage = damage;
- wd.damage2 = 0;
- status_change_end(target,SC_DEATHBOUND,INVALID_TIMER);
- }
- }
- if( rdamage > 0 ) {
- if( tsc && tsc->data[SC_LG_REFLECTDAMAGE] ) {
- if( src != target ) {// Don't reflect your own damage (Grand Cross)
- bool change = false;
- if( sd && !sd->state.autocast )
- change = true;
- if( change )
- sd->state.autocast = 1;
- iMap->foreachinshootrange(battle->damage_area,target,skill->get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,iTimer->gettick(),target,wd.amotion,sstatus->dmotion,rdamage,tstatus->race);
- if( change )
- sd->state.autocast = 0;
- }
- } else {
- //Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
- if( tsd && src != target )
- battle->drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src));
- battle->delay_damage(iTimer->gettick(), wd.amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
- skill->additional_effect(target, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,iTimer->gettick());
- }
- }
- }
- if(!wd.damage2)
- {
+ if( wd.damage + wd.damage2 ) { //There is a total damage value
+ int64 damage = wd.damage + wd.damage2;
+
+ if(!wd.damage2) {
wd.damage = battle->calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv);
if( map_flag_gvg2(target->m) )
wd.damage=battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag);
- else if( map[target->m].flag.battleground )
+ else if( map->list[target->m].flag.battleground )
wd.damage=battle->calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag);
- }
- else if(!wd.damage)
- {
+ } else if(!wd.damage) {
wd.damage2 = battle->calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv);
if( map_flag_gvg2(target->m) )
wd.damage2 = battle->calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag);
- else if( map[target->m].flag.battleground )
+ else if( map->list[target->m].flag.battleground )
wd.damage = battle->calc_bg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag);
- }
- else
- {
+ } else {
#ifdef RENEWAL
wd.damage = battle->calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv);
wd.damage2 = battle->calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv);
#else
- int d1 = wd.damage + wd.damage2,d2 = wd.damage2;
+ int64 d1 = wd.damage + wd.damage2,d2 = wd.damage2;
wd.damage = battle->calc_damage(src,target,&wd,d1,skill_id,skill_lv);
#endif
if( map_flag_gvg2(target->m) )
wd.damage = battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag);
- else if( map[target->m].flag.battleground )
+ else if( map->list[target->m].flag.battleground )
wd.damage = battle->calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag);
#ifndef RENEWAL
wd.damage2 = d2*100/d1 * wd.damage/100;
@@ -5011,6 +5217,25 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.damage-=wd.damage2;
#endif
}
+
+ if( src != target ) { // Don't reflect your own damage (Grand Cross)
+
+ if( wd.dmg_lv == ATK_MISS || wd.dmg_lv == ATK_BLOCK ) {
+ int64 prev1 = wd.damage, prev2 = wd.damage2;
+
+ wd.damage = damage;
+ wd.damage2 = 0;
+
+ battle->reflect_damage(target, src, &wd, skill_id);
+
+ wd.damage = prev1;
+ wd.damage2 = prev2;
+
+ } else
+ battle->reflect_damage(target, src, &wd, skill_id);
+
+ }
+
}
//Reject Sword bugreport:4493 by Daegaladh
if(wd.damage && tsc && tsc->data[SC_SWORDREJECT] &&
@@ -5021,8 +5246,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
)) &&
rnd()%100 < tsc->data[SC_SWORDREJECT]->val2
) {
- ATK_RATER(50)
- status_fix_damage(target,src,wd.damage,clif->damage(target,src,iTimer->gettick(),0,0,wd.damage,0,0,0));
+ ATK_RATER(50);
+ status_fix_damage(target,src,wd.damage,clif->damage(target,src,0,0,wd.damage,0,0,0));
clif->skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_SWORDREJECT]->val1,1);
if( --(tsc->data[SC_SWORDREJECT]->val3) <= 0 )
status_change_end(target, SC_SWORDREJECT, INVALID_TIMER);
@@ -5043,6 +5268,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,uint16 skill_id,uint16 skill_lv,int count)
{
struct Damage d;
+ struct map_session_data *sd=BL_CAST(BL_PC,bl);
switch(attack_type) {
case BF_WEAPON: d = battle->calc_weapon_attack(bl,target,skill_id,skill_lv,count); break;
case BF_MAGIC: d = battle->calc_magic_attack(bl,target,skill_id,skill_lv,count); break;
@@ -5056,18 +5282,18 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl
#ifdef HMAP_ZONE_DAMAGE_CAP_TYPE
if( target && skill_id ) {
int i;
- for(i = 0; i < map[target->m].zone->capped_skills_count; i++) {
- if( skill_id == map[target->m].zone->capped_skills[i]->nameid && (map[target->m].zone->capped_skills[i]->type & target->type) ) {
- if( target->type == BL_MOB && map[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) {
- if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) )
+ for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) {
+ if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) {
+ if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) {
+ if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map->list[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) )
continue;
- if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) )
+ if( ((TBL_MOB*)target)->special_state.clone && !(map->list[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) )
continue;
}
- if( d.damage > map[target->m].zone->capped_skills[i]->cap )
- d.damage = map[target->m].zone->capped_skills[i]->cap;
- if( d.damage2 > map[target->m].zone->capped_skills[i]->cap )
- d.damage2 = map[target->m].zone->capped_skills[i]->cap;
+ if( d.damage > map->list[target->m].zone->capped_skills[i]->cap )
+ d.damage = map->list[target->m].zone->capped_skills[i]->cap;
+ if( d.damage2 > map->list[target->m].zone->capped_skills[i]->cap )
+ d.damage2 = map->list[target->m].zone->capped_skills[i]->cap;
break;
}
}
@@ -5081,90 +5307,206 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl
d.dmotion = 0;
} else // Some skills like Weaponry Research will cause damage even if attack is dodged
d.dmg_lv = ATK_DEF;
+
+ if(sd && d.damage+d.damage2>1) {
+ if(sd->bonus.sp_vanish_rate && sd->bonus.sp_vanish_trigger && rnd()%10000<sd->bonus.sp_vanish_rate &&
+ ( (d.flag&sd->bonus.sp_vanish_trigger&BF_WEAPONMASK) || (d.flag&sd->bonus.sp_vanish_trigger&BF_RANGEMASK)
+ || (d.flag&sd->bonus.sp_vanish_trigger&BF_SKILLMASK) ))
+ status_percent_damage(&sd->bl,target,0,-sd->bonus.sp_vanish_per,false);
+ }
return d;
}
-
-//Calculates BF_WEAPON returned damage.
-int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int *dmg, int flag, uint16 skill_id, int *delay){
- int rdamage = 0, damage = *dmg, rdelay = *delay, trdamage = 0;
- struct map_session_data* sd;
- struct status_change* sc;
+//Performs reflect damage (magic (maya) is performed over skill.c).
+void battle_reflect_damage(struct block_list *target, struct block_list *src, struct Damage *wd,uint16 skill_id) {
+ int64 damage = wd->damage + wd->damage2, rdamage = 0, trdamage = 0;
+ struct map_session_data *sd, *tsd;
+ struct status_change *sc;
+ struct status_change *ssc;
+ int64 tick = timer->gettick();
+ int delay = 50, rdelay = 0;
+#ifdef RENEWAL
int max_reflect_damage;
- sd = BL_CAST(BL_PC, bl);
- sc = status_get_sc(bl);
- max_reflect_damage = max(status_get_max_hp(bl), status_get_max_hp(bl) * status_get_lv(bl) / 100);
+ max_reflect_damage = max(status_get_max_hp(target), status_get_max_hp(target) * status->get_lv(target) / 100);
+#endif
-#define NORMALIZE_RDAMAGE(d){ trdamage += rdamage = max(1, min(max_reflect_damage, d)); }
-
- if( sc && sc->data[SC_CRESCENTELBOW] && !is_boss(src) && rnd()%100 < sc->data[SC_CRESCENTELBOW]->val2 ){
- //ATK [{(Target HP / 100) x Skill Level} x Caster Base Level / 125] % + [Received damage x {1 + (Skill Level x 0.2)}]
- int ratio = (status_get_hp(src) / 100) * sc->data[SC_CRESCENTELBOW]->val1 * status_get_lv(bl) / 125;
- if (ratio > 5000) ratio = 5000; // Maximum of 5000% ATK
- rdamage = rdamage * ratio / 100 + (*dmg) * (10 + sc->data[SC_CRESCENTELBOW]->val1 * 20 / 10) / 10;
- skill->blown(bl, src, skill->get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1), unit_getdir(src), 0);
- clif->skill_damage(bl, src, iTimer->gettick(), status_get_amotion(src), 0, rdamage,
- 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does
- clif->damage(src, bl, iTimer->gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, 0, 0);
- status_damage(src, bl, status_damage(bl, src, rdamage, 0, 0, 1)/10, 0, 0, 1);
- status_change_end(bl, SC_CRESCENTELBOW, INVALID_TIMER);
- return 0; // Just put here to minimize redundancy
- }
- if( flag & BF_SHORT) {//Bounces back part of the damage.
- if ( sd && sd->bonus.short_weapon_damage_return ){
- NORMALIZE_RDAMAGE(damage * sd->bonus.short_weapon_damage_return / 100);
- rdelay = clif->damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4, 0);
- }
- if( sc && sc->count ) {
- if( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ){
- NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100);
- rdelay = clif->skill_damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, CR_REFLECTSHIELD, 1, 4);
+ sd = BL_CAST(BL_PC, src);
+
+ tsd = BL_CAST(BL_PC, target);
+ sc = status->get_sc(target);
+
+#ifdef RENEWAL
+#define NORMALIZE_RDAMAGE(d) ( trdamage += rdamage = max(1, min(max_reflect_damage, (d))) )
+#else
+#define NORMALIZE_RDAMAGE(d) ( trdamage += rdamage = max(1, (d)) )
+#endif
+
+ if( sc && !sc->count )
+ sc = NULL;
+
+ if( sc ) {
+ if (wd->flag & BF_SHORT && !(skill->get_inf(skill_id) & (INF_GROUND_SKILL | INF_SELF_SKILL))) {
+ if( sc->data[SC_CRESCENTELBOW] && !is_boss(src) && rnd()%100 < sc->data[SC_CRESCENTELBOW]->val2 ){
+ //ATK [{(Target HP / 100) x Skill Level} x Caster Base Level / 125] % + [Received damage x {1 + (Skill Level x 0.2)}]
+ int ratio = (status_get_hp(src) / 100) * sc->data[SC_CRESCENTELBOW]->val1 * status->get_lv(target) / 125;
+ if (ratio > 5000) ratio = 5000; // Maximum of 5000% ATK
+ rdamage = ratio + (damage)* (10 + sc->data[SC_CRESCENTELBOW]->val1 * 20 / 10) / 10;
+ skill->blown(target, src, skill->get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1), unit->getdir(src), 0);
+ clif->skill_damage(target, src, tick, status_get_amotion(src), 0, rdamage,
+ 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does
+ clif->delay_damage(tick + delay, src, target,status_get_amotion(src)+1000,0, rdamage/10, 1, 0);
+ status->damage(src, target, status->damage(target, src, rdamage, 0, 0, 1)/10, 0, 0, 1);
+ status_change_end(target, SC_CRESCENTELBOW, INVALID_TIMER);
+ /* shouldn't this trigger skill->additional_effect? */
+ return; // Just put here to minimize redundancy
}
- if( sc->data[SC_LG_REFLECTDAMAGE] && rand()%100 < (30 + 10*sc->data[SC_LG_REFLECTDAMAGE]->val1) ) {
- if( skill_id != HT_LANDMINE && skill_id != HT_CLAYMORETRAP
- && skill_id != RA_CLUSTERBOMB && (skill_id <= RA_VERDURETRAP || skill_id > RA_ICEBOUNDTRAP) && skill_id != MA_LANDMINE ){
- NORMALIZE_RDAMAGE((*dmg) * sc->data[SC_LG_REFLECTDAMAGE]->val2 / 100);
- rdelay = clif->damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4, 0);
+ }
+
+ if( wd->flag & BF_SHORT ) {
+ if( !is_boss(src) ) {
+ if( sc->data[SC_DEATHBOUND] && skill_id != WS_CARTTERMINATION ) {
+ uint8 dir = map->calc_dir(target,src->x,src->y),
+ t_dir = unit->getdir(target);
+
+ if( !map->check_dir(dir,t_dir) ) {
+ int64 rd1 = damage * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage.
+
+ trdamage += rdamage = rd1 - (damage = rd1 * 30 / 100); // not normalized as intended.
+ rdelay = clif->skill_damage(src, target, tick, status_get_amotion(src), status_get_dmotion(src), -3000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, 6);
+ skill->blown(target, src, skill->get_blewcount(RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1), unit->getdir(src), 0);
+
+ if( tsd ) /* is this right? rdamage as both left and right? */
+ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
+ battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
+
+ delay += 100;/* gradual increase so the numbers don't clip in the client */
+ }
+ wd->damage = wd->damage + wd->damage2;
+ wd->damage2 = 0;
+ status_change_end(target,SC_DEATHBOUND,INVALID_TIMER);
}
}
- if( sc->data[SC_DEATHBOUND] && skill_id != WS_CARTTERMINATION && !is_boss(src) ) {
- uint8 dir = iMap->calc_dir(bl,src->x,src->y),
- t_dir = unit_getdir(bl);
-
- if( !iMap->check_dir(dir,t_dir) ) {
- int rd1 = damage * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage.
- trdamage += rdamage = rd1 - (*dmg = rd1 * 30 / 100); // not normalized as intended.
- clif->skill_damage(src, bl, iTimer->gettick(), status_get_amotion(src), 0, -3000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, 6);
- skill->blown(bl, src, skill->get_blewcount(RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1), unit_getdir(src), 0);
- if( skill_id )
- status_change_end(bl, SC_DEATHBOUND, INVALID_TIMER);
- rdelay = clif->damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4, 0);
+ }
+
+ if( sc->data[SC_KYOMU] ){
+ // Nullify reflecting ability of the conditions onwards
+ return;
+ }
+
+ }
+
+ if( wd->flag & BF_SHORT ) {
+ if ( tsd && tsd->bonus.short_weapon_damage_return ) {
+ NORMALIZE_RDAMAGE(damage * tsd->bonus.short_weapon_damage_return / 100);
+
+ rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
+
+ /* is this right? rdamage as both left and right? */
+ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
+ battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
+
+ delay += 100;/* gradual increase so the numbers don't clip in the client */
+ }
+
+ if( wd->dmg_lv >= ATK_BLOCK ) {/* yes block still applies, somehow gravity thinks it makes sense. */
+ if( sc ) {
+ if( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ) {
+ NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100);
+
+#ifndef RENEWAL
+ rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
+#else
+ rdelay = clif->skill_damage(src, src, tick, delay, status_get_dmotion(src), rdamage, 1, CR_REFLECTSHIELD, 1, 4);
+#endif
+ /* is this right? rdamage as both left and right? */
+ if( tsd )
+ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
+ battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
+
+ delay += 100;/* gradual increase so the numbers don't clip in the client */
+ }
+ if( sc->data[SC_LG_REFLECTDAMAGE] && rand()%100 < (30 + 10*sc->data[SC_LG_REFLECTDAMAGE]->val1) ) {
+ bool change = false;
+
+ NORMALIZE_RDAMAGE(damage * sc->data[SC_LG_REFLECTDAMAGE]->val2 / 100);
+
+ trdamage -= rdamage;/* wont count towards total */
+
+ if( sd && !sd->state.autocast ) {
+ change = true;
+ sd->state.autocast = 1;
+ }
+
+ map->foreachinshootrange(battle->damage_area,target,skill->get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,delay,wd->dmotion,rdamage,status_get_race(target));
+
+ if( change )
+ sd->state.autocast = 0;
+
+ delay += 150;/* gradual increase so the numbers don't clip in the client */
+
+ if( (--sc->data[SC_LG_REFLECTDAMAGE]->val3) <= 0 )
+ status_change_end(target, SC_LG_REFLECTDAMAGE, INVALID_TIMER);
+ }
+ if( sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 2 ){
+ NORMALIZE_RDAMAGE(damage * sc->data[SC_SHIELDSPELL_DEF]->val2 / 100);
+
+ rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
+
+ /* is this right? rdamage as both left and right? */
+ if( tsd )
+ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
+ battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
+
+ delay += 100;/* gradual increase so the numbers don't clip in the client */
}
}
- if( sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 2 && !is_boss(src) ){
- NORMALIZE_RDAMAGE(damage * sc->data[SC_SHIELDSPELL_DEF]->val2 / 100);
- rdelay = clif->damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4, 0);
+ if( ( ssc = status->get_sc(src) ) ) {
+ if( ssc->data[SC_INSPIRATION] ) {
+ NORMALIZE_RDAMAGE(damage / 100);
+
+ rdelay = clif->delay_damage(tick+delay,target, target, status_get_amotion(target), status_get_dmotion(target), rdamage, 1, 4);
+
+ /* is this right? rdamage as both left and right? */
+ if( sd )
+ battle->drain(sd, target, rdamage, rdamage, status_get_race(target), 0);
+ battle->delay_damage(tick, wd->amotion,src,target,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
+
+ delay += 100;/* gradual increase so the numbers don't clip in the client */
+ }
}
}
- } else {
- if (sd && sd->bonus.long_weapon_damage_return){
- NORMALIZE_RDAMAGE(damage * sd->bonus.long_weapon_damage_return / 100);
- rdelay = clif->damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4, 0);
+ } else {/* long */
+ if ( tsd && tsd->bonus.long_weapon_damage_return ) {
+ NORMALIZE_RDAMAGE(damage * tsd->bonus.long_weapon_damage_return / 100);
+
+ rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
+
+ /* is this right? rdamage as both left and right? */
+ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0);
+ battle->delay_damage(tick, wd->amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
+
+ delay += 100;/* gradual increase so the numbers don't clip in the client */
}
}
-
- if( !(sc && sc->data[SC_DEATHBOUND]) ){
- if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability
- return 0;
+
+#ifdef __clang_analyzer__
+ // Tell Clang's static analyzer that we want to += it even the value is currently unused (it'd be used if we added new checks)
+ (void)delay;
+#endif // __clang_analyzer
+
+ /* something caused reflect */
+ if( trdamage ) {
+ skill->additional_effect(target, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
}
- return max(0, trdamage);
+ return;
+#undef NORMALIZE_RDAMAGE
}
-
-void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage, int race, int boss)
+void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int boss)
{
struct weapon_data *wd;
- int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i, *damage;
+ int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i;
+ int64 *damage;
for (i = 0; i < 4; i++) {
//First two iterations: Right hand
if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; }
@@ -5196,7 +5538,7 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage,
}
}
- if (sd->bonus.sp_vanish_rate && rnd()%1000 < sd->bonus.sp_vanish_rate)
+ if (sd->bonus.sp_vanish_rate && rnd()%1000 < sd->bonus.sp_vanish_rate && !sd->bonus.sp_vanish_trigger)
status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->bonus.sp_vanish_per, false);
if( sd->sp_gain_race_attack[race] )
@@ -5206,20 +5548,20 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage,
if (!thp && !tsp) return;
- status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1);
+ status->heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1);
if (rhp || rsp)
status_zap(tbl, rhp, rsp);
}
// Deals the same damage to targets in area. [pakpil]
-int battle_damage_area( struct block_list *bl, va_list ap) {
- unsigned int tick;
+int battle_damage_area(struct block_list *bl, va_list ap) {
+ int64 tick;
int amotion, dmotion, damage;
struct block_list *src;
nullpo_ret(bl);
- tick=va_arg(ap, unsigned int);
+ tick = va_arg(ap, int64);
src=va_arg(ap,struct block_list *);
amotion=va_arg(ap,int);
dmotion=va_arg(ap,int);
@@ -5227,17 +5569,17 @@ int battle_damage_area( struct block_list *bl, va_list ap) {
if( bl->type == BL_MOB && ((TBL_MOB*)bl)->class_ == MOBID_EMPERIUM )
return 0;
if( bl != src && battle->check_target(src,bl,BCT_ENEMY) > 0 ) {
- iMap->freeblock_lock();
+ map->freeblock_lock();
if( src->type == BL_PC )
battle->drain((TBL_PC*)src, bl, damage, damage, status_get_race(bl), is_boss(bl));
if( amotion )
battle->delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true);
else
status_fix_damage(src,bl,damage,0);
- clif->damage(bl,bl,tick,amotion,dmotion,damage,1,ATK_BLOCK,0);
+ clif->damage(bl,bl,amotion,dmotion,damage,1,ATK_BLOCK,0);
if( !(src && src->type == BL_PC && ((TBL_PC*)src)->state.autocast) )
skill->additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
}
return 0;
@@ -5245,11 +5587,11 @@ int battle_damage_area( struct block_list *bl, va_list ap) {
/*==========================================
* Do a basic physical attack (call trough unit_attack_timer)
*------------------------------------------*/
-enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, unsigned int tick, int flag) {
+enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, int64 tick, int flag) {
struct map_session_data *sd = NULL, *tsd = NULL;
struct status_data *sstatus, *tstatus;
struct status_change *sc, *tsc;
- int damage;
+ int64 damage;
int skillv;
struct Damage wd;
@@ -5262,11 +5604,11 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, target);
- sstatus = status_get_status_data(src);
- tstatus = status_get_status_data(target);
+ sstatus = status->get_status_data(src);
+ tstatus = status->get_status_data(target);
- sc = status_get_sc(src);
- tsc = status_get_sc(target);
+ sc = status->get_sc(src);
+ tsc = status->get_sc(target);
if (sc && !sc->count) //Avoid sc checks when there's none to check for. [Skotlex]
sc = NULL;
@@ -5310,38 +5652,35 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
}
}
}
- if (sc && sc->count) {
- if (sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4 & 2))
- status_change_end(src, SC_CLOAKING, INVALID_TIMER);
- else if (sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4 & 2))
- status_change_end(src, SC_CLOAKINGEXCEED, INVALID_TIMER);
- }
- if( tsc && tsc->data[SC_AUTOCOUNTER] && status_check_skilluse(target, src, KN_AUTOCOUNTER, 1) )
- {
- uint8 dir = iMap->calc_dir(target,src->x,src->y);
- int t_dir = unit_getdir(target);
+ if (sc && sc->count) {
+ if (sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4 & 2))
+ status_change_end(src, SC_CLOAKING, INVALID_TIMER);
+ else if (sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4 & 2))
+ status_change_end(src, SC_CLOAKINGEXCEED, INVALID_TIMER);
+ }
+ if( tsc && tsc->data[SC_AUTOCOUNTER] && status->check_skilluse(target, src, KN_AUTOCOUNTER, 1) ) {
+ uint8 dir = map->calc_dir(target,src->x,src->y);
+ int t_dir = unit->getdir(target);
int dist = distance_bl(src, target);
- if(dist <= 0 || (!iMap->check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1))
- {
+ if(dist <= 0 || (!map->check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) {
uint16 skill_lv = tsc->data[SC_AUTOCOUNTER]->val1;
clif->skillcastcancel(target); //Remove the casting bar. [Skotlex]
- clif->damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
+ clif->damage(src, target, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER);
skill->attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0);
return ATK_BLOCK;
}
}
-
if( tsc && tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src) && (src->type == BL_PC || tsd == NULL || distance_bl(src, target) <= (tsd->status.weapon == W_FIST ? 1 : 2)) )
{
uint16 skill_lv = tsc->data[SC_BLADESTOP_WAIT]->val1;
int duration = skill->get_time2(MO_BLADESTOP,skill_lv);
status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER);
- if(sc_start4(src, SC_BLADESTOP, 100, sd?pc->checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration))
- { //Target locked.
- clif->damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
+ if(sc_start4(target, src, SC_BLADESTOP, 100, sd?pc->checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration)) {
+ //Target locked.
+ clif->damage(src, target, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
clif->bladestop(target, src->id, 1);
- sc_start4(target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration);
+ sc_start4(target, target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration);
return ATK_BLOCK;
}
}
@@ -5369,7 +5708,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
/**
* We need to calculate the DMG before the hp reduction, because it can kill the source.
- * For futher information: bugreport:4950
+ * For further information: bugreport:4950
**/
ret_val = (damage_lv)skill->attack(BF_WEAPON,src,src,target,PA_SACRIFICE,skill_lv,tick,0);
@@ -5395,25 +5734,18 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
skill->get_time(MO_CALLSPIRITS, tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1),
tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1);
}
- if( sc && sc->data[SC_CRUSHSTRIKE] ){
- uint16 skill_lv = sc->data[SC_CRUSHSTRIKE]->val1;
- status_change_end(src, SC_CRUSHSTRIKE, INVALID_TIMER);
- if( skill->attack(BF_WEAPON,src,src,target,RK_CRUSHSTRIKE,skill_lv,tick,0) )
- return ATK_DEF;
- return ATK_MISS;
- }
+
+ if( tsc && tsc->data[SC_MTF_MLEATKED] && rnd()%100 < 20 )
+ clif->skill_nodamage(target, target, SM_ENDURE, 5,
+ sc_start(target,target, SC_ENDURE, 100, 5, skill->get_time(SM_ENDURE, 5)));
}
if(tsc && tsc->data[SC_KAAHI] && tsc->data[SC_KAAHI]->val4 == INVALID_TIMER && tstatus->hp < tstatus->max_hp)
- tsc->data[SC_KAAHI]->val4 = iTimer->add_timer(tick + skill->get_time2(SL_KAAHI,tsc->data[SC_KAAHI]->val1), kaahi_heal_timer, target->id, SC_KAAHI); //Activate heal.
+ tsc->data[SC_KAAHI]->val4 = timer->add(tick + skill->get_time2(SL_KAAHI,tsc->data[SC_KAAHI]->val1), status->kaahi_heal_timer, target->id, SC_KAAHI); //Activate heal.
wd = battle->calc_attack(BF_WEAPON, src, target, 0, 0, flag);
if( sc && sc->count ) {
- if (sc->data[SC_EXEEDBREAK]) {
- ATK_RATER(sc->data[SC_EXEEDBREAK]->val1)
- status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER);
- }
if( sc->data[SC_SPELLFIST] ) {
if( --(sc->data[SC_SPELLFIST]->val1) >= 0 ){
struct Damage ad = battle->calc_attack(BF_MAGIC,src,target,sc->data[SC_SPELLFIST]->val3,sc->data[SC_SPELLFIST]->val4,flag|BF_SHORT);
@@ -5421,8 +5753,6 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
}else
status_change_end(src,SC_SPELLFIST,INVALID_TIMER);
}
- if( sc->data[SC_GIANTGROWTH] && (wd.flag&BF_SHORT) && rnd()%100 < sc->data[SC_GIANTGROWTH]->val2 )
- wd.damage *= 3; // Triple Damage
if( sd && sc->data[SC_FEARBREEZE] && sc->data[SC_FEARBREEZE]->val4 > 0 && sd->status.inventory[sd->equip_index[EQI_AMMO]].amount >= sc->data[SC_FEARBREEZE]->val4 && battle_config.arrow_decrement){
pc->delitem(sd,sd->equip_index[EQI_AMMO],sc->data[SC_FEARBREEZE]->val4,0,1,LOG_TYPE_CONSUME);
@@ -5445,7 +5775,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
}
}
- wd.dmotion = clif->damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2);
+ wd.dmotion = clif->damage(src, target, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2);
if (sd && sd->bonus.splash_range > 0 && damage > 0)
skill->castend_damage_id(src, target, 0, 1, tick, 0);
@@ -5454,20 +5784,26 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
if( su->group && su->group->skill_id == HT_BLASTMINE)
skill->blown(src, target, 3, -1, 0);
}
- iMap->freeblock_lock();
-
- battle->delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion, true);
+ map->freeblock_lock();
+
+ if( skill->check_shadowform(target, damage, wd.div_) ){
+ if( !status->isdead(target) )
+ skill->additional_effect(src, target, 0, 0, wd.flag, wd.dmg_lv, tick);
+ if( wd.dmg_lv > ATK_BLOCK)
+ skill->counter_additional_effect(src, target, 0, 0, wd.flag,tick);
+ }else
+ battle->delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion, true);
if( tsc ) {
if( tsc->data[SC_DEVOTION] ) {
struct status_change_entry *sce = tsc->data[SC_DEVOTION];
- struct block_list *d_bl = iMap->id2bl(sce->val1);
+ struct block_list *d_bl = map->id2bl(sce->val1);
if( d_bl && (
(d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == target->id) ||
(d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id)
) && check_distance_bl(target, d_bl, sce->val3) )
{
- clif->damage(d_bl, d_bl, iTimer->gettick(), 0, 0, damage, 0, 0, 0);
+ clif->damage(d_bl, d_bl, 0, 0, damage, 0, 0, 0);
status_fix_damage(NULL, d_bl, damage, 0);
}
else
@@ -5479,13 +5815,13 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
skill->attack(BF_MAGIC,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag);
}
} else if( tsc->data[SC_WATER_SCREEN_OPTION] && tsc->data[SC_WATER_SCREEN_OPTION]->val1 ) {
- struct block_list *e_bl = iMap->id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1);
- if( e_bl && !status_isdead(e_bl) ) {
- clif->damage(e_bl,e_bl,tick,wd.amotion,wd.dmotion,damage,wd.div_,wd.type,wd.damage2);
- status_damage(target,e_bl,damage,0,0,0);
+ struct block_list *e_bl = map->id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1);
+ if( e_bl && !status->isdead(e_bl) ) {
+ clif->damage(e_bl,e_bl,wd.amotion,wd.dmotion,damage,wd.div_,wd.type,wd.damage2);
+ status->damage(target,e_bl,damage,0,0,0);
// Just show damage in target.
- clif->damage(src, target, tick, wd.amotion, wd.dmotion, damage, wd.div_, wd.type, wd.damage2 );
- iMap->freeblock_unlock();
+ clif->damage(src, target, wd.amotion, wd.dmotion, damage, wd.div_, wd.type, wd.damage2 );
+ map->freeblock_unlock();
return ATK_NONE;
}
}
@@ -5502,7 +5838,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
if (skill_lv < 1) skill_lv = 1;
sp = skill->get_sp(skill_id,skill_lv) * 2 / 3;
- if (status_charge(src, 0, sp)) {
+ if (status->charge(src, 0, sp)) {
switch (skill->get_casttype(skill_id)) {
case CAST_GROUND:
skill->castend_pos2(src, target->x, target->y, skill_id, skill_lv, tick, flag);
@@ -5517,28 +5853,30 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
}
}
if (sd) {
- if( wd.flag&BF_SHORT && sc && sc->data[SC__AUTOSHADOWSPELL] && rnd()%100 < sc->data[SC__AUTOSHADOWSPELL]->val3 &&
- sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].id != 0 && sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].flag == SKILL_FLAG_PLAGIARIZED )
- {
- int r_skill = sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].id,
- r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2;
+ if( wd.flag&BF_SHORT && sc
+ && sc->data[SC__AUTOSHADOWSPELL] && rnd()%100 < sc->data[SC__AUTOSHADOWSPELL]->val3
+ && sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].id != 0
+ && sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].flag == SKILL_FLAG_PLAGIARIZED
+ ) {
+ int r_skill = sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].id;
+ int r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2;
if (r_skill != AL_HOLYLIGHT && r_skill != PR_MAGNUS) {
int type;
if( (type = skill->get_casttype(r_skill)) == CAST_GROUND ) {
int maxcount = 0;
- if( !(BL_PC&battle_config.skill_reiteration) &&
- skill->get_unit_flag(r_skill)&UF_NOREITERATION )
- type = -1;
+ if( !(BL_PC&battle_config.skill_reiteration)
+ && skill->get_unit_flag(r_skill)&UF_NOREITERATION )
+ type = -1;
- if( BL_PC&battle_config.skill_nofootset &&
- skill->get_unit_flag(r_skill)&UF_NOFOOTSET )
- type = -1;
+ if( BL_PC&battle_config.skill_nofootset
+ && skill->get_unit_flag(r_skill)&UF_NOFOOTSET )
+ type = -1;
- if( BL_PC&battle_config.land_skill_limit &&
- (maxcount = skill->get_maxcount(r_skill, r_lv)) > 0
- ) {
+ if( BL_PC&battle_config.land_skill_limit
+ && (maxcount = skill->get_maxcount(r_skill, r_lv)) > 0
+ ) {
int v;
for(v=0;v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount;v++) {
if(sd->ud.skillunit[v]->skill_id == r_skill)
@@ -5548,10 +5886,10 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
type = -1;
}
- if( type != CAST_GROUND ){
- clif->skill_fail(sd,r_skill,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
- return wd.dmg_lv;
+ if( type != CAST_GROUND ) {
+ clif->skill_fail(sd,r_skill,USESKILL_FAIL_LEVEL,0);
+ map->freeblock_unlock();
+ return wd.dmg_lv;
}
}
@@ -5584,12 +5922,14 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
}
if (tsc) {
- if (tsc->data[SC_POISONREACT] &&
- (rnd()%100 < tsc->data[SC_POISONREACT]->val3
- || sstatus->def_ele == ELE_POISON) &&
-// check_distance_bl(src, target, tstatus->rhw.range+1) && Doesn't checks range! o.O;
- status_check_skilluse(target, src, TF_POISON, 0)
- ) { //Poison React
+ if (tsc->data[SC_POISONREACT]
+ && ( rnd()%100 < tsc->data[SC_POISONREACT]->val3
+ || sstatus->def_ele == ELE_POISON
+ )
+ /* && check_distance_bl(src, target, tstatus->rhw.range+1) Doesn't check range! o.O; */
+ && status->check_skilluse(target, src, TF_POISON, 0)
+ ) {
+ //Poison React
struct status_change_entry *sce = tsc->data[SC_POISONREACT];
if (sstatus->def_ele == ELE_POISON) {
sce->val2 = 0;
@@ -5602,30 +5942,39 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
status_change_end(target, SC_POISONREACT, INVALID_TIMER);
}
}
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return wd.dmg_lv;
}
-
-int battle_check_undead(int race,int element)
+#undef ATK_RATE
+#undef ATK_RATE2
+#undef ATK_RATER
+#undef ATK_RATEL
+#undef ATK_ADDRATE
+#undef ATK_ADDRATE2
+#undef ATK_ADD
+#undef ATK_ADD2
+#undef GET_NORMAL_ATTACK
+#undef GET_NORMAL_ATTACK2
+
+bool battle_check_undead(int race,int element)
{
if(battle_config.undead_detect_type == 0) {
if(element == ELE_UNDEAD)
- return 1;
+ return true;
}
else if(battle_config.undead_detect_type == 1) {
if(race == RC_UNDEAD)
- return 1;
+ return true;
}
else {
if(element == ELE_UNDEAD || race == RC_UNDEAD)
- return 1;
+ return true;
}
- return 0;
+ return false;
}
//Returns the upmost level master starting with the given object
-struct block_list* battle_get_master(struct block_list *src)
-{
+struct block_list* battle_get_master(struct block_list *src) {
struct block_list *prev; //Used for infinite loop check (master of yourself?)
do {
prev = src;
@@ -5636,7 +5985,7 @@ struct block_list* battle_get_master(struct block_list *src)
break;
case BL_MOB:
if (((TBL_MOB*)src)->master_id)
- src = iMap->id2bl(((TBL_MOB*)src)->master_id);
+ src = map->id2bl(((TBL_MOB*)src)->master_id);
break;
case BL_HOM:
if (((TBL_HOM*)src)->master)
@@ -5652,7 +6001,7 @@ struct block_list* battle_get_master(struct block_list *src)
break;
case BL_SKILL:
if (((TBL_SKILL*)src)->group && ((TBL_SKILL*)src)->group->src_id)
- src = iMap->id2bl(((TBL_SKILL*)src)->group->src_id);
+ src = map->id2bl(((TBL_SKILL*)src)->group->src_id);
break;
}
} while (src && src != prev);
@@ -5681,6 +6030,10 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
m = target->m;
+ if (flag&BCT_ENEMY && ( map->getcell(m,src->x,src->y,CELL_CHKBASILICA) || map->getcell(m,target->x,target->y,CELL_CHKBASILICA) ) ) {
+ return -1;
+ }
+
//t_bl/s_bl hold the 'master' of the attack, while src/target are the actual
//objects involved.
if( (t_bl = battle->get_master(target)) == NULL )
@@ -5692,7 +6045,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if ( s_bl->type == BL_PC ) {
switch( t_bl->type ) {
case BL_MOB: // Source => PC, Target => MOB
- if ( pc_has_permission((TBL_PC*)s_bl, PC_PERM_DISABLE_PVM) )
+ if (pc_has_permission((TBL_PC*)s_bl, PC_PERM_DISABLE_PVM) )
return 0;
break;
case BL_PC:
@@ -5706,7 +6059,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
switch( target->type ) { // Checks on actual target
case BL_PC: {
- struct status_change* sc = status_get_sc(src);
+ struct status_change* sc = status->get_sc(src);
if (((TBL_PC*)target)->invincible_timer != INVALID_TIMER || pc_isinvisible((TBL_PC*)target))
return -1; //Cannot be targeted yet.
if( sc && sc->count ) {
@@ -5719,7 +6072,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if(((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres
(((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras
s_bl->type == BL_PC && src->type != BL_MOB) || (((TBL_MOB*)target)->special_state.ai == 4 && t_bl->id != s_bl->id)) //Zanzoe
- { //Targettable by players
+ { //Targetable by players
state |= BCT_ENEMY;
strip_enemy = 0;
}
@@ -5733,7 +6086,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
switch( battle->get_current_skill(src) ) {
case RK_DRAGONBREATH:// it can only hit traps in pvp/gvg maps
case RK_DRAGONBREATH_WATER:
- if( !map[m].flag.pvp && !map[m].flag.gvg )
+ if( !map->list[m].flag.pvp && !map->list[m].flag.gvg )
break;
case 0://you can hit them without skills
case MA_REMOVETRAP:
@@ -5746,12 +6099,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
case MS_MAGNUM:
case RA_DETONATOR:
case RA_SENSITIVEKEEN:
- case GN_CRAZYWEED_ATK:
case RK_STORMBLAST:
- case RK_PHANTOMTHRUST:
case SR_RAMPAGEBLASTER:
case NC_COLDSLOWER:
- case NC_SELFDESTRUCTION:
#ifdef RENEWAL
case KN_BOWLINGBASH:
case KN_SPEARSTAB:
@@ -5765,19 +6115,18 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
case ASC_METEORASSAULT:
case RG_RAID:
case MC_CARTREVOLUTION:
+ case HT_CLAYMORETRAP:
+ case RA_ICEBOUNDTRAP:
+ case RA_FIRINGTRAP:
#endif
state |= BCT_ENEMY;
strip_enemy = 0;
break;
default:
- if(su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD){
- state |= BCT_ENEMY;
- strip_enemy = 0;
- }else
- return 0;
+ return 0;
}
} else if (su->group->skill_id==WZ_ICEWALL ||
- su->group->skill_id == GN_WALLOFTHORN) {
+ su->group->skill_id == GN_WALLOFTHORN) {
state |= BCT_ENEMY;
strip_enemy = 0;
} else //Excepting traps and icewall, you should not be able to target skills.
@@ -5794,8 +6143,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
return 0;
} //end switch actual target
- switch( t_bl->type )
- { //Checks on target master
+ switch( t_bl->type ) { //Checks on target master
case BL_PC:
{
struct map_session_data *sd;
@@ -5803,7 +6151,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
sd = BL_CAST(BL_PC, t_bl);
if( sd->state.monster_ignore && flag&BCT_ENEMY )
- return 0; // Global inminuty only to Attacks
+ return 0; // Global immunity only to Attacks
if( sd->status.karma && s_bl->type == BL_PC && ((TBL_PC*)s_bl)->status.karma )
state |= BCT_ENEMY; // Characters with bad karma may fight amongst them
if( sd->state.killable ) {
@@ -5816,12 +6164,13 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
{
struct mob_data *md = BL_CAST(BL_MOB, t_bl);
- if( !((iMap->agit_flag || iMap->agit2_flag) && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id )
+ if( !((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle)
+ && md->guardian_data && (md->guardian_data->g || md->guardian_data->castle->guild_id) )
return 0; // Disable guardians/emperiums owned by Guilds on non-woe times.
break;
}
default: break; //other type doesn't have slave yet
- } //end switch master target
+ } //end switch master target
switch( src->type ) { //Checks on actual src type
case BL_PET:
@@ -5848,22 +6197,19 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->class_ == MOBID_EMPERIUM && flag&BCT_ENEMY)
return 0; //mercenary may not attack Emperium
break;
- } //end switch actual src
+ } //end switch actual src
- switch( s_bl->type )
- { //Checks on source master
+ switch( s_bl->type ) { //Checks on source master
case BL_PC:
{
struct map_session_data *sd = BL_CAST(BL_PC, s_bl);
- if( s_bl != t_bl )
- {
- if( sd->state.killer )
- {
+ if( s_bl != t_bl ) {
+ if( sd->state.killer ) {
state |= BCT_ENEMY; // Can kill anything
strip_enemy = 0;
- }
- else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) )
- {
+ } else if( sd->duel_group
+ && !((!battle_config.duel_allow_pvp && map->list[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m)))
+ ) {
if( t_bl->type == BL_PC && (sd->duel_group == ((TBL_PC*)t_bl)->duel_group) )
return (BCT_ENEMY&flag)?1:-1; // Duel targets can ONLY be your enemy, nothing else.
else
@@ -5879,7 +6225,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
case BL_MOB:
{
struct mob_data *md = BL_CAST(BL_MOB, s_bl);
- if( !((iMap->agit_flag || iMap->agit2_flag) && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id )
+ if( !((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle)
+ && md->guardian_data && (md->guardian_data->g || md->guardian_data->castle->guild_id) )
return 0; // Disable guardians/emperium owned by Guilds on non-woe times.
if( !md->special_state.ai )
@@ -5900,11 +6247,11 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
break;
}
default:
- //Need some sort of default behaviour for unhandled types.
+ //Need some sort of default behavior for unhandled types.
if (t_bl->type != s_bl->type)
state |= BCT_ENEMY;
break;
- } //end switch on src master
+ } //end switch on src master
if( (flag&BCT_ALL) == BCT_ALL )
{ //All actually stands for all attackable chars
@@ -5924,32 +6271,37 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
return (flag&state)?1:-1;
}
- if( map_flag_vs(m) )
- { //Check rivalry settings.
+ if( map_flag_vs(m) ) {
+ //Check rivalry settings.
int sbg_id = 0, tbg_id = 0;
- if( map[m].flag.battleground )
- {
- sbg_id = bg_team_get_id(s_bl);
- tbg_id = bg_team_get_id(t_bl);
+ if( map->list[m].flag.battleground ) {
+ sbg_id = bg->team_get_id(s_bl);
+ tbg_id = bg->team_get_id(t_bl);
}
- if( flag&(BCT_PARTY|BCT_ENEMY) )
- {
- int s_party = status_get_party_id(s_bl);
- if( s_party && s_party == status_get_party_id(t_bl) && !(map[m].flag.pvp && map[m].flag.pvp_noparty) && !(map_flag_gvg(m) && map[m].flag.gvg_noparty) && (!map[m].flag.battleground || sbg_id == tbg_id) )
+ if( flag&(BCT_PARTY|BCT_ENEMY) ) {
+ int s_party = status->get_party_id(s_bl);
+ int s_guild = status->get_guild_id(s_bl);
+
+ if( s_party && s_party == status->get_party_id(t_bl)
+ && !(map->list[m].flag.pvp && map->list[m].flag.pvp_noparty)
+ && !(map_flag_gvg(m) && map->list[m].flag.gvg_noparty && !( s_guild && s_guild == status->get_guild_id(t_bl) ))
+ && (!map->list[m].flag.battleground || sbg_id == tbg_id) )
state |= BCT_PARTY;
else
state |= BCT_ENEMY;
}
- if( flag&(BCT_GUILD|BCT_ENEMY) )
- {
- int s_guild = status_get_guild_id(s_bl);
- int t_guild = status_get_guild_id(t_bl);
- if( !(map[m].flag.pvp && map[m].flag.pvp_noguild) && s_guild && t_guild && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild->isallied(s_guild, t_guild))) && (!map[m].flag.battleground || sbg_id == tbg_id) )
+ if( flag&(BCT_GUILD|BCT_ENEMY) ) {
+ int s_guild = status->get_guild_id(s_bl);
+ int t_guild = status->get_guild_id(t_bl);
+ if( !(map->list[m].flag.pvp && map->list[m].flag.pvp_noguild)
+ && s_guild && t_guild
+ && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild->isallied(s_guild, t_guild)))
+ && (!map->list[m].flag.battleground || sbg_id == tbg_id) )
state |= BCT_GUILD;
else
state |= BCT_ENEMY;
}
- if( state&BCT_ENEMY && map[m].flag.battleground && sbg_id && sbg_id == tbg_id )
+ if( state&BCT_ENEMY && map->list[m].flag.battleground && sbg_id && sbg_id == tbg_id )
state &= ~BCT_ENEMY;
if( state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) && s_bl->type == BL_PC && t_bl->type == BL_PC )
@@ -5959,24 +6311,22 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
(sd->class_&MAPID_UPPERMASK) == MAPID_NOVICE ||
(sd2->class_&MAPID_UPPERMASK) == MAPID_NOVICE ||
(int)sd->status.base_level < battle_config.pk_min_level ||
- (int)sd2->status.base_level < battle_config.pk_min_level ||
+ (int)sd2->status.base_level < battle_config.pk_min_level ||
(battle_config.pk_level_range && abs((int)sd->status.base_level - (int)sd2->status.base_level) > battle_config.pk_level_range)
)
state &= ~BCT_ENEMY;
}
- }//end map_flag_vs chk rivality
+ }//end map_flag_vs chk rivality
else
{ //Non pvp/gvg, check party/guild settings.
- if( flag&BCT_PARTY || state&BCT_ENEMY )
- {
- int s_party = status_get_party_id(s_bl);
- if(s_party && s_party == status_get_party_id(t_bl))
+ if( flag&BCT_PARTY || state&BCT_ENEMY ) {
+ int s_party = status->get_party_id(s_bl);
+ if(s_party && s_party == status->get_party_id(t_bl))
state |= BCT_PARTY;
}
- if( flag&BCT_GUILD || state&BCT_ENEMY )
- {
- int s_guild = status_get_guild_id(s_bl);
- int t_guild = status_get_guild_id(t_bl);
+ if( flag&BCT_GUILD || state&BCT_ENEMY ) {
+ int s_guild = status->get_guild_id(s_bl);
+ int t_guild = status->get_guild_id(t_bl);
if(s_guild && t_guild && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild->isallied(s_guild, t_guild))))
state |= BCT_GUILD;
}
@@ -5992,7 +6342,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
}
/*==========================================
* Check if can attack from this range
- * Basic check then calling path_search for obstacle etc..
+ * Basic check then calling path->search for obstacle etc..
*------------------------------------------*/
bool battle_check_range(struct block_list *src, struct block_list *bl, int range)
{
@@ -6006,7 +6356,7 @@ bool battle_check_range(struct block_list *src, struct block_list *bl, int range
#ifndef CIRCULAR_AREA
if( src->type == BL_PC ) { // Range for players' attacks and skills should always have a circular check. [Angezerus]
int dx = src->x - bl->x, dy = src->y - bl->y;
- if( !check_distance(dx, dy, range) )
+ if( !path->check_distance(dx, dy, range) )
return false;
} else
#endif
@@ -6017,12 +6367,12 @@ bool battle_check_range(struct block_list *src, struct block_list *bl, int range
return true; // No need for path checking.
if( d > AREA_SIZE )
- return false; // Avoid targetting objects beyond your range of sight.
+ return false; // Avoid targeting objects beyond your range of sight.
- return path_search_long(NULL,src->m,src->x,src->y,bl->x,bl->y,CELL_CHKWALL);
+ return path->search_long(NULL,src->m,src->x,src->y,bl->x,bl->y,CELL_CHKWALL);
}
-static const struct _battle_data {
+static const struct battle_data {
const char* str;
int* val;
int defval;
@@ -6287,7 +6637,6 @@ static const struct _battle_data {
{ "mobs_level_up_exp_rate", &battle_config.mobs_level_up_exp_rate, 1, 1, INT_MAX, },
{ "pk_min_level", &battle_config.pk_min_level, 55, 1, INT_MAX, },
{ "skill_steal_max_tries", &battle_config.skill_steal_max_tries, 0, 0, UCHAR_MAX, },
- { "finding_ore_rate", &battle_config.finding_ore_rate, 100, 0, INT_MAX, },
{ "exp_calc_type", &battle_config.exp_calc_type, 0, 0, 1, },
{ "exp_bonus_attacker", &battle_config.exp_bonus_attacker, 25, 0, INT_MAX, },
{ "exp_bonus_max_attacker", &battle_config.exp_bonus_max_attacker, 12, 2, INT_MAX, },
@@ -6323,7 +6672,7 @@ static const struct _battle_data {
{ "duel_time_interval", &battle_config.duel_time_interval, 60, 0, INT_MAX, },
{ "duel_only_on_same_map", &battle_config.duel_only_on_same_map, 0, 0, 1, },
{ "skip_teleport_lv1_menu", &battle_config.skip_teleport_lv1_menu, 0, 0, 1, },
- { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, 100, 1, INT_MAX, },
+ { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, 100, 1, INT_MAX, },
{ "allow_skill_without_day", &battle_config.allow_skill_without_day, 0, 0, 1, },
{ "allow_es_magic_player", &battle_config.allow_es_magic_pc, 0, 0, 1, },
{ "skill_caster_check", &battle_config.skill_caster_check, 1, 0, 1, },
@@ -6365,6 +6714,7 @@ static const struct _battle_data {
{ "invincible.nodamage", &battle_config.invincible_nodamage, 0, 0, 1, },
{ "mob_slave_keep_target", &battle_config.mob_slave_keep_target, 0, 0, 1, },
{ "autospell_check_range", &battle_config.autospell_check_range, 0, 0, 1, },
+ { "knockback_left", &battle_config.knockback_left, 1, 0, 1, },
{ "client_reshuffle_dice", &battle_config.client_reshuffle_dice, 0, 0, 1, },
{ "client_sort_storage", &battle_config.client_sort_storage, 0, 0, 1, },
{ "feature.buying_store", &battle_config.feature_buying_store, 1, 0, 1, },
@@ -6375,14 +6725,16 @@ static const struct _battle_data {
{ "cashshop_show_points", &battle_config.cashshop_show_points, 0, 0, 1, },
{ "mail_show_status", &battle_config.mail_show_status, 0, 0, 2, },
{ "client_limit_unit_lv", &battle_config.client_limit_unit_lv, 0, 0, BL_ALL, },
+ { "client_emblem_max_blank_percent", &battle_config.client_emblem_max_blank_percent, 100, 0, 100, },
// BattleGround Settings
{ "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, },
{ "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, },
/**
* rAthena
**/
- { "max_third_parameter", &battle_config.max_third_parameter, 120, 10, 10000, },
- { "max_baby_third_parameter", &battle_config.max_baby_third_parameter, 108, 10, 10000, },
+ { "max_third_parameter", &battle_config.max_third_parameter, 130, 10, 10000, },
+ { "max_baby_third_parameter", &battle_config.max_baby_third_parameter, 117, 10, 10000, },
+ { "max_extended_parameter", &battle_config.max_extended_parameter, 125, 10, 10000, },
{ "atcommand_max_stat_bypass", &battle_config.atcommand_max_stat_bypass, 0, 0, 100, },
{ "skill_amotion_leniency", &battle_config.skill_amotion_leniency, 90, 0, 300 },
{ "mvp_tomb_enabled", &battle_config.mvp_tomb_enabled, 1, 0, 1 },
@@ -6391,16 +6743,28 @@ static const struct _battle_data {
{ "atcommand_mobinfo_type", &battle_config.atcommand_mobinfo_type, 0, 0, 1 },
{ "homunculus_max_level", &battle_config.hom_max_level, 99, 0, MAX_LEVEL, },
{ "homunculus_S_max_level", &battle_config.hom_S_max_level, 150, 0, MAX_LEVEL, },
- { "mob_size_influence", &battle_config.mob_size_influence, 0, 0, 1, },
+ { "mob_size_influence", &battle_config.mob_size_influence, 0, 0, 1, },
+ { "bowling_bash_area", &battle_config.bowling_bash_area, 0, 0, 20, },
/**
* Hercules
**/
{ "skill_trap_type", &battle_config.skill_trap_type, 0, 0, 1, },
{ "item_restricted_consumption_type", &battle_config.item_restricted_consumption_type,1, 0, 1, },
- { "max_walk_path", &battle_config.max_walk_path, 17, 1, MAX_WALKPATH, },
- { "item_enabled_npc", &battle_config.item_enabled_npc, 1, 0, 1, },
- { "gm_ignore_warpable_area", &battle_config.gm_ignore_warpable_area, 0, 2, 100, },
- { "packet_obfuscation", &battle_config.packet_obfuscation, 1, 0, 3, },
+ { "max_walk_path", &battle_config.max_walk_path, 17, 1, MAX_WALKPATH, },
+ { "item_enabled_npc", &battle_config.item_enabled_npc, 1, 0, 1, },
+ { "gm_ignore_warpable_area", &battle_config.gm_ignore_warpable_area, 0, 2, 100, },
+ { "packet_obfuscation", &battle_config.packet_obfuscation, 1, 0, 3, },
+ { "client_accept_chatdori", &battle_config.client_accept_chatdori, 0, 0, INT_MAX, },
+ { "snovice_call_type", &battle_config.snovice_call_type, 0, 0, 1, },
+ { "guild_notice_changemap", &battle_config.guild_notice_changemap, 2, 0, 2, },
+ { "feature.banking", &battle_config.feature_banking, 1, 0, 1, },
+ { "feature.auction", &battle_config.feature_auction, 0, 0, 2, },
+ { "idletime_criteria", &battle_config.idletime_criteria, 0x25, 1, INT_MAX, },
+
+ { "mon_trans_disable_in_gvg", &battle_config.mon_trans_disable_in_gvg, 0, 0, 1, },
+ { "case_sensitive_aegisnames", &battle_config.case_sensitive_aegisnames, 1, 0, 1, },
+ { "guild_castle_invite", &battle_config.guild_castle_invite, 0, 0, 1, },
+ { "guild_castle_expulsion", &battle_config.guild_castle_expulsion, 0, 0, 1, },
};
#ifndef STATS_OPT_OUT
/**
@@ -6409,8 +6773,6 @@ static const struct _battle_data {
void Hercules_report(char* date, char *time_c) {
int i, bd_size = ARRAYLENGTH(battle_data);
unsigned int config = 0;
- const char *svn = get_svn_revision();
- const char *git = get_git_hash();
char timestring[25];
time_t curtime;
char* buf;
@@ -6418,7 +6780,7 @@ void Hercules_report(char* date, char *time_c) {
enum config_table {
C_CIRCULAR_AREA = 0x0001,
C_CELLNOSTACK = 0x0002,
- C_CONSOLE_INPUT = 0x0004,
+ C_CONSOLE_INPUT = 0x0004,
C_SCRIPT_CALLFUNC_CHECK = 0x0008,
C_OFFICIAL_WALKPATH = 0x0010,
C_RENEWAL = 0x0020,
@@ -6429,12 +6791,15 @@ void Hercules_report(char* date, char *time_c) {
C_RENEWAL_EDP = 0x0400,
C_RENEWAL_ASPD = 0x0800,
C_SECURE_NPCTIMEOUT = 0x1000,
- C_SQL_DBS = 0x2000,
+ C_SQL_DB_ITEM = 0x2000,
C_SQL_LOGS = 0x4000,
- C_MEMWATCH = 0x8000,
- C_DMALLOC = 0x10000,
- C_GCOLLECT = 0x20000,
- C_SEND_SHORTLIST = 0x40000,
+ C_MEMWATCH = 0x8000,
+ C_DMALLOC = 0x10000,
+ C_GCOLLECT = 0x20000,
+ C_SEND_SHORTLIST = 0x40000,
+ C_SQL_DB_MOB = 0x80000,
+ C_SQL_DB_MOBSKILL = 0x100000,
+ C_PACKETVER_RE = 0x200000,
};
/* we get the current time */
@@ -6492,10 +6857,18 @@ void Hercules_report(char* date, char *time_c) {
#ifdef SECURE_NPCTIMEOUT
config |= C_SECURE_NPCTIMEOUT;
#endif
+
+#ifdef PACKETVER_RE
+ config |= C_PACKETVER_RE;
+#endif
/* non-define part */
- if( iMap->db_use_sqldbs )
- config |= C_SQL_DBS;
+ if( map->db_use_sql_item_db )
+ config |= C_SQL_DB_ITEM;
+ if( map->db_use_sql_mob_db )
+ config |= C_SQL_DB_MOB;
+ if( map->db_use_sql_mob_skill_db )
+ config |= C_SQL_DB_MOBSKILL;
if( logs->config.sql_logs )
config |= C_SQL_LOGS;
@@ -6516,37 +6889,47 @@ void Hercules_report(char* date, char *time_c) {
#define BFLAG_LENGTH 35
- CREATE(buf, char, 6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) + 1 );
+ CREATE(buf, char, 262 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) + 1 );
/* build packet */
WBUFW(buf,0) = 0x3000;
- WBUFW(buf,2) = 6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) );
- WBUFW(buf,4) = 0x9e;
+ WBUFW(buf,2) = 262 + ( bd_size * ( BFLAG_LENGTH + 4 ) );
+ WBUFW(buf,4) = 0x9f;
safestrncpy((char*)WBUFP(buf,6), date, 12);
- safestrncpy((char*)WBUFP(buf,6 + 12), time_c, 9);
- safestrncpy((char*)WBUFP(buf,6 + 12 + 9), timestring, 24);
-
- safestrncpy((char*)WBUFP(buf,6 + 12 + 9 + 24), git[0] != HERC_UNKNOWN_VER ? git : svn[0] != HERC_UNKNOWN_VER ? svn : "Unknown", 41);
- WBUFL(buf,6 + 12 + 9 + 24 + 41) = iMap->getusers();
-
- WBUFL(buf,6 + 12 + 9 + 24 + 41 + 4) = config;
- WBUFL(buf,6 + 12 + 9 + 24 + 41 + 4 + 4) = bd_size;
-
+ safestrncpy((char*)WBUFP(buf,18), time_c, 9);
+ safestrncpy((char*)WBUFP(buf,27), timestring, 24);
+
+ safestrncpy((char*)WBUFP(buf,51), sysinfo->platform(), 16);
+ safestrncpy((char*)WBUFP(buf,67), sysinfo->osversion(), 50);
+ safestrncpy((char*)WBUFP(buf,117), sysinfo->cpu(), 32);
+ WBUFL(buf,149) = sysinfo->cpucores();
+ safestrncpy((char*)WBUFP(buf,153), sysinfo->arch(), 8);
+ WBUFB(buf,161) = sysinfo->vcstypeid();
+ WBUFB(buf,162) = sysinfo->is64bit();
+ safestrncpy((char*)WBUFP(buf,163), sysinfo->vcsrevision_src(), 41);
+ safestrncpy((char*)WBUFP(buf,204), sysinfo->vcsrevision_scripts(), 41);
+ WBUFB(buf,245) = (sysinfo->is_superuser()? 1 : 0);
+ WBUFL(buf,246) = map->getusers();
+
+ WBUFL(buf,250) = config;
+ WBUFL(buf,254) = PACKETVER;
+
+ WBUFL(buf,258) = bd_size;
for( i = 0; i < bd_size; i++ ) {
- safestrncpy((char*)WBUFP(buf,6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( i * ( BFLAG_LENGTH + 4 ) ) ), battle_data[i].str, 35);
- WBUFL(buf,6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + BFLAG_LENGTH + ( i * ( BFLAG_LENGTH + 4 ) ) ) = *battle_data[i].val;
+ safestrncpy((char*)WBUFP(buf,262 + ( i * ( BFLAG_LENGTH + 4 ) ) ), battle_data[i].str, BFLAG_LENGTH);
+ WBUFL(buf,262 + BFLAG_LENGTH + ( i * ( BFLAG_LENGTH + 4 ) ) ) = *battle_data[i].val;
}
- chrif_send_report(buf, 6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) );
+ chrif->send_report(buf, 262 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) );
aFree(buf);
#undef BFLAG_LENGTH
}
-static int Hercules_report_timer(int tid, unsigned int tick, int id, intptr_t data) {
- if( chrif_isconnected() ) {/* char server relays it, so it must be online. */
+static int Hercules_report_timer(int tid, int64 tick, int id, intptr_t data) {
+ if( chrif->isconnected() ) {/* char server relays it, so it must be online. */
Hercules_report(__DATE__,__TIME__);
}
return 0;
@@ -6559,8 +6942,11 @@ int battle_set_value(const char* w1, const char* w2)
int i;
ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0);
- if (i == ARRAYLENGTH(battle_data))
+ if (i == ARRAYLENGTH(battle_data)) {
+ if( HPM->parseConf(w1,w2,HPCT_BATTLE) ) /* if plugin-owned, succeed */
+ return 1;
return 0; // not found
+ }
if (val < battle_data[i].min || val > battle_data[i].max)
{
@@ -6622,6 +7008,22 @@ void battle_adjust_conf(void) {
battle_config.feature_search_stores = 0;
}
#endif
+
+#if PACKETVER < 20130724
+ if( battle_config.feature_banking ) {
+ ShowWarning("conf/battle/feature.conf banking is enabled but it requires PACKETVER 2013-07-24 or newer, disabling...\n");
+ battle_config.feature_banking = 0;
+ }
+#endif
+
+#if PACKETVER > 20120000 && PACKETVER < 20130515 /* exact date (when it started) not known */
+ if( battle_config.feature_auction == 1 ) {
+ ShowWarning("conf/battle/feature.conf:feature.auction is enabled but it is not stable on PACKETVER "EXPAND_AND_QUOTE(PACKETVER)", disabling...\n");
+ ShowWarning("conf/battle/feature.conf:feature.auction change value to '2' to silence this warning and maintain it enabled\n");
+ battle_config.feature_auction = 0;
+ }
+#endif
+
#ifndef CELL_NOSTACK
if (battle_config.cell_stack_limit != 1)
@@ -6671,19 +7073,22 @@ int battle_config_read(const char* cfgName)
return 0;
}
-void do_init_battle(void) {
- delay_damage_ers = ers_new(sizeof(struct delay_damage),"battle.c::delay_damage_ers",ERS_OPT_CLEAR);
- iTimer->add_timer_func_list(battle_delay_damage_sub, "battle_delay_damage_sub");
+void do_init_battle(bool minimal) {
+ if (minimal)
+ return;
+
+ battle->delay_damage_ers = ers_new(sizeof(struct delay_damage),"battle.c::delay_damage_ers",ERS_OPT_CLEAR);
+ timer->add_func_list(battle->delay_damage_sub, "battle_delay_damage_sub");
#ifndef STATS_OPT_OUT
- iTimer->add_timer_func_list(Hercules_report_timer, "Hercules_report_timer");
- iTimer->add_timer_interval(iTimer->gettick()+30000, Hercules_report_timer, 0, 0, 60000 * 30);
+ timer->add_func_list(Hercules_report_timer, "Hercules_report_timer");
+ timer->add_interval(timer->gettick()+30000, Hercules_report_timer, 0, 0, 60000 * 30);
#endif
}
void do_final_battle(void) {
- ers_destroy(delay_damage_ers);
+ ers_destroy(battle->delay_damage_ers);
}
/* initialize the interface */
@@ -6692,6 +7097,9 @@ void battle_defaults(void) {
battle->bc = &battle_config;
+ memset(battle->attr_fix_table, 0, sizeof(battle->attr_fix_table));
+ battle->delay_damage_ers = NULL;
+
battle->init = do_init_battle;
battle->final = do_final_battle;
@@ -6699,25 +7107,21 @@ void battle_defaults(void) {
battle->calc_damage = battle_calc_damage;
battle->calc_gvg_damage = battle_calc_gvg_damage;
battle->calc_bg_damage = battle_calc_bg_damage;
- battle->calc_base_damage = battle_calc_base_damage;
- battle->calc_misc_attack = battle_calc_misc_attack;
- battle->calc_magic_attack = battle_calc_magic_attack;
battle->weapon_attack = battle_weapon_attack;
+ battle->calc_weapon_attack = battle_calc_weapon_attack;
battle->delay_damage = battle_delay_damage;
battle->drain = battle_drain;
- battle->calc_return_damage = battle_calc_return_damage;
- battle->calc_weapon_attack = battle_calc_weapon_attack;
-#ifdef RENEWAL
- battle->calc_weapon_damage = battle_calc_weapon_damage;
-#endif
- battle->calc_defense = battle_calc_defense;
+ battle->reflect_damage = battle_reflect_damage;
battle->attr_ratio = battle_attr_ratio;
battle->attr_fix = battle_attr_fix;
battle->calc_cardfix = battle_calc_cardfix;
battle->calc_elefix = battle_calc_elefix;
battle->calc_masteryfix = battle_calc_masteryfix;
+ battle->calc_chorusbonus = battle_calc_chorusbonus;
battle->calc_skillratio = battle_calc_skillratio;
battle->calc_sizefix = battle_calc_sizefix;
+ battle->calc_weapon_damage = battle_calc_weapon_damage;
+ battle->calc_defense = battle_calc_defense;
battle->get_master = battle_get_master;
battle->get_targeted = battle_gettargeted;
battle->get_enemy = battle_getenemy;
@@ -6733,6 +7137,10 @@ void battle_defaults(void) {
battle->delay_damage_sub = battle_delay_damage_sub;
battle->blewcount_bonus = battle_blewcount_bonus;
battle->range_type = battle_range_type;
+ battle->calc_base_damage = battle_calc_base_damage;
+ battle->calc_base_damage2 = battle_calc_base_damage2;
+ battle->calc_misc_attack = battle_calc_misc_attack;
+ battle->calc_magic_attack = battle_calc_magic_attack;
battle->adjust_skill_damage = battle_adjust_skill_damage;
battle->add_mastery = battle_addmastery;
battle->calc_drain = battle_calc_drain;
diff --git a/src/map/battle.h b/src/map/battle.h
index 7d41a02c5..dfa156796 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -2,8 +2,11 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _BATTLE_H_
-#define _BATTLE_H_
+#ifndef MAP_BATTLE_H
+#define MAP_BATTLE_H
+
+#include "map.h" //ELE_MAX
+#include "../common/cbasetypes.h"
/**
* Declarations
@@ -18,14 +21,14 @@ struct status_data;
/**
* Defines
**/
-#define MIN_HAIR_STYLE battle_config.min_hair_style
-#define MAX_HAIR_STYLE battle_config.max_hair_style
-#define MIN_HAIR_COLOR battle_config.min_hair_color
-#define MAX_HAIR_COLOR battle_config.max_hair_color
-#define MIN_CLOTH_COLOR battle_config.min_cloth_color
-#define MAX_CLOTH_COLOR battle_config.max_cloth_color
+#define MIN_HAIR_STYLE (battle->bc->min_hair_style)
+#define MAX_HAIR_STYLE (battle->bc->max_hair_style)
+#define MIN_HAIR_COLOR (battle->bc->min_hair_color)
+#define MAX_HAIR_COLOR (battle->bc->max_hair_color)
+#define MIN_CLOTH_COLOR (battle->bc->min_cloth_color)
+#define MAX_CLOTH_COLOR (battle->bc->max_cloth_color)
-#define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru]
+#define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru]
/**
* Enumerations
@@ -55,28 +58,30 @@ typedef enum damage_lv {
} damage_lv;
enum e_battle_check_target { //New definitions [Skotlex]
- BCT_NOONE = 0x000000,
- BCT_SELF = 0x010000,
- BCT_ENEMY = 0x020000,
- BCT_PARTY = 0x040000,
- BCT_GUILD = 0x080000,
- BCT_NEUTRAL = 0x100000,
- BCT_SAMEGUILD = 0x200000, // No Guild Allies
-
- BCT_NOGUILD = 0x170000, // This should be (~BCT_GUILD&BCT_ALL)
- BCT_NOPARTY = 0x1b0000, // This should be (~BCT_PARTY&BCT_ALL)
- BCT_NOENEMY = 0x1d0000, // This should be (~BCT_ENEMY&BCT_ALL)
+ BCT_NOONE = 0x000000,
+ BCT_SELF = 0x010000,
+ BCT_ENEMY = 0x020000,
+ BCT_PARTY = 0x040000,
+ BCT_GUILDALLY = 0x080000, // Only allies, NOT guildmates
+ BCT_NEUTRAL = 0x100000,
+ BCT_SAMEGUILD = 0x200000, // No Guild Allies
+
+ BCT_GUILD = 0x280000, // Guild AND allies (BCT_SAMEGUILD|BCT_GUILDALLY)
- BCT_ALL = 0x1f0000, // Sum of BCT_NOONE to BCT_NEUTRAL
+ BCT_NOGUILD = 0x170000, // This should be (~BCT_GUILD&BCT_ALL)
+ BCT_NOPARTY = 0x3b0000, // This should be (~BCT_PARTY&BCT_ALL)
+ BCT_NOENEMY = 0x3d0000, // This should be (~BCT_ENEMY&BCT_ALL)
+
+ BCT_ALL = 0x3f0000, // Sum of BCT_NOONE to BCT_SAMEGUILD
};
/**
* Structures
**/
-// dammage structure
+// damage structure
struct Damage {
- int damage,damage2; //right, left dmg
+ int64 damage,damage2; //right, left dmg
int type,div_; //chk clif_damage for type @TODO add an enum ? ; nb of hit
int amotion,dmotion;
int blewcount; //nb of knockback
@@ -325,7 +330,6 @@ struct Battle_Config {
int mobs_level_up_exp_rate; // [Valaris]
int pk_min_level; // [celest]
int skill_steal_max_tries; //max steal skill tries on a mob. if 0, then w/o limit [Lupus]
- int finding_ore_rate; // orn
int exp_calc_type;
int exp_bonus_attacker;
int exp_bonus_max_attacker;
@@ -412,6 +416,7 @@ struct Battle_Config {
int invincible_nodamage;
int mob_slave_keep_target;
int autospell_check_range; //Enable range check for autospell bonus. [L0ne_W0lf]
+ int knockback_left;
int client_reshuffle_dice; // Reshuffle /dice
int client_sort_storage;
int feature_buying_store;
@@ -422,6 +427,7 @@ struct Battle_Config {
int cashshop_show_points;
int mail_show_status;
int client_limit_unit_lv;
+ int client_emblem_max_blank_percent;
int hom_max_level;
int hom_S_max_level;
@@ -432,6 +438,7 @@ struct Battle_Config {
// rAthena
int max_third_parameter;
int max_baby_third_parameter;
+ int max_extended_parameter;
int atcommand_max_stat_bypass;
int max_third_aspd;
int vcast_stat_scale;
@@ -439,28 +446,65 @@ struct Battle_Config {
int mvp_tomb_enabled;
int atcommand_suggestions_enabled;
- int min_npc_vendchat_distance;
+ int min_npc_vendchat_distance;
int atcommand_mobinfo_type;
int mob_size_influence; // Enable modifications on earned experience, drop rates and monster status depending on monster size. [mkbu95]
-
+ int bowling_bash_area;
+
/** Hercules **/
int skill_trap_type;
int item_restricted_consumption_type;
int max_walk_path;
int item_enabled_npc;
int packet_obfuscation;
-
+ int idletime_criteria;
int gm_ignore_warpable_area;
-} battle_config;
+ int client_accept_chatdori; // [Ai4rei/Mirei]
+ int snovice_call_type;
+ int guild_notice_changemap;
+
+ int feature_banking;
+ int feature_auction;
+ int mon_trans_disable_in_gvg;
-/**
- * Vars
- **/
-//attribute table
-extern int attr_fix_table[4][10][10];
+ int case_sensitive_aegisnames;
+ int guild_castle_invite;
+ int guild_castle_expulsion;
+};
+
+extern struct Battle_Config battle_config;
+
+/* criteria for battle_config.idletime_critera */
+enum e_battle_config_idletime {
+ BCIDLE_WALK = 0x001,
+ BCIDLE_USESKILLTOID = 0x002,
+ BCIDLE_USESKILLTOPOS = 0x004,
+ BCIDLE_USEITEM = 0x008,
+ BCIDLE_ATTACK = 0x010,
+ BCIDLE_CHAT = 0x020,
+ BCIDLE_SIT = 0x040,
+ BCIDLE_EMOTION = 0x080,
+ BCIDLE_DROPITEM = 0x100,
+ BCIDLE_ATCOMMAND = 0x200,
+};
+
+// Damage delayed info
+struct delay_damage {
+ int src_id;
+ int target_id;
+ int64 damage;
+ int delay;
+ unsigned short distance;
+ uint16 skill_lv;
+ uint16 skill_id;
+ enum damage_lv dmg_lv;
+ unsigned short attack_type;
+ bool additional_effects;
+ enum bl_type src_type;
+};
/**
* Battle.c Interface
@@ -468,48 +512,51 @@ extern int attr_fix_table[4][10][10];
struct battle_interface {
/* */
struct Battle_Config *bc;
+ /* */
+ int attr_fix_table[4][ELE_MAX][ELE_MAX];
+ struct eri *delay_damage_ers; //For battle delay damage structures.
/* init */
- void (*init) (void);
+ void (*init) (bool minimal);
/* final */
void (*final) (void);
/* damage calculation */
struct Damage (*calc_attack) (int attack_type, struct block_list *bl, struct block_list *target, uint16 skill_id, uint16 skill_lv, int count);
/* generic final damage calculation */
- int (*calc_damage) (struct block_list *src, struct block_list *bl, struct Damage *d, int damage, uint16 skill_id, uint16 skill_lv);
+ int64 (*calc_damage) (struct block_list *src, struct block_list *bl, struct Damage *d, int64 damage, uint16 skill_id, uint16 skill_lv);
/* gvg final damage calculation */
- int (*calc_gvg_damage) (struct block_list *src, struct block_list *bl, int damage, int div_, uint16 skill_id, uint16 skill_lv, int flag);
+ int64 (*calc_gvg_damage) (struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag);
/* battlegrounds final damage calculation */
- int (*calc_bg_damage) (struct block_list *src, struct block_list *bl, int damage, int div_, uint16 skill_id, uint16 skill_lv, int flag);
+ int64 (*calc_bg_damage) (struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag);
/* normal weapon attack */
- enum damage_lv (*weapon_attack) (struct block_list *bl, struct block_list *target, unsigned int tick, int flag);
+ enum damage_lv (*weapon_attack) (struct block_list *bl, struct block_list *target, int64 tick, int flag);
/* calculate weapon attack */
struct Damage (*calc_weapon_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag);
/* delays damage or skills by a timer */
- int (*delay_damage) (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects);
+ int (*delay_damage) (int64 tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects);
/* drain damage */
- void (*drain) (struct map_session_data *sd, struct block_list *tbl, int rdamage, int ldamage, int race, int boss);
- /* damage return/reflect */
- int (*calc_return_damage) (struct block_list *bl, struct block_list *src, int *, int flag, uint16 skill_id, int*);
+ void (*drain) (struct map_session_data *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int boss);
+ /* damage reflect */
+ void (*reflect_damage) (struct block_list *target, struct block_list *src, struct Damage *wd,uint16 skill_id);
/* attribute rate */
int (*attr_ratio) (int atk_elem, int def_type, int def_lv);
/* applies attribute modifiers */
- int (*attr_fix) (struct block_list *src, struct block_list *target, int damage, int atk_elem, int def_type, int def_lv);
+ int64 (*attr_fix) (struct block_list *src, struct block_list *target, int64 damage, int atk_elem, int def_type, int def_lv);
/* applies card modifiers */
- int (*calc_cardfix) (int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int damage, int left, int flag);
- /* applies element modifiers */
- int (*calc_elefix) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag);
- /* applies mastery modifiers */
- int (*calc_masteryfix) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int div, bool left, bool weapon);
- /* applies skill modifiers */
+ int64 (*calc_cardfix) (int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int left, int flag);
+ /* applies element modifiers */
+ int64 (*calc_elefix) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag);
+ /* applies mastery modifiers */
+ int64 (*calc_masteryfix) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int div, bool left, bool weapon);
+ /* calculates chorus bonus */
+ int (*calc_chorusbonus) (struct map_session_data *sd);
+ /* applies skill modifiers */
int (*calc_skillratio) (int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int skillratio, int flag);
/* applies size modifiers */
- int (*calc_sizefix) (struct map_session_data *sd, int damage, int type, int size, bool ignore);
-#ifdef RENEWAL
+ int64 (*calc_sizefix) (struct map_session_data *sd, int64 damage, int type, int size, bool ignore);
/* get weapon damage */
- int (*calc_weapon_damage) (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2);
-#endif
+ int64 (*calc_weapon_damage) (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2);
/* applies defense reductions */
- int (*calc_defense) (int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int flag, int pdef);
+ int64 (*calc_defense) (int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int flag, int pdef);
/* get master (who does this unit respond to?) */
struct block_list *(*get_master) (struct block_list *src);
/* returns a random unit who is targeting this unit */
@@ -521,31 +568,27 @@ struct battle_interface {
/* the current skill being processed/casted by this unit */
int (*get_current_skill) (struct block_list *bl);
/* is either this race or element enough to be considered undead? */
- int (*check_undead) (int race,int element);
+ bool (*check_undead) (int race,int element);
/* check if src and target are part of flag (e.g. enemies or allies) */
int (*check_target) (struct block_list *src, struct block_list *target,int flag);
/* is src and bl within range? */
bool (*check_range) (struct block_list *src,struct block_list *bl,int range);
- /* consume amo for this skill and lv */
- void (*consume_ammo) (struct map_session_data* sd, int skill, int lv);
+ /* consume ammo for this skill and lv */
+ void (*consume_ammo) (struct map_session_data* sd, int skill_id, int lv);
int (*get_targeted_sub) (struct block_list *bl, va_list ap);
int (*get_enemy_sub) (struct block_list *bl, va_list ap);
int (*get_enemy_area_sub) (struct block_list *bl, va_list ap);
- int (*delay_damage_sub) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*delay_damage_sub) (int tid, int64 tick, int id, intptr_t data);
int (*blewcount_bonus) (struct map_session_data *sd, uint16 skill_id);
/* skill range criteria */
int (*range_type) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv);
- int (*calc_base_damage)
-#ifdef RENEWAL
- (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2);
-#else
- (struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag);
-#endif
+ int64 (*calc_base_damage) (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2);
+ int64 (*calc_base_damage2) (struct status_data *st, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag);
struct Damage (*calc_misc_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag);
struct Damage (*calc_magic_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag);
int (*adjust_skill_damage) (int m, unsigned short skill_id);
- int (*add_mastery) (struct map_session_data *sd,struct block_list *target,int dmg,int type);
- int (*calc_drain) (int damage, int rate, int per);
+ int64 (*add_mastery) (struct map_session_data *sd,struct block_list *target,int64 dmg,int type);
+ int (*calc_drain) (int64 damage, int rate, int per);
/* - battle_config */
int (*config_read) (const char *cfgName);
void (*config_set_defaults) (void);
@@ -556,10 +599,10 @@ struct battle_interface {
/* picks a random enemy within the specified range */
struct block_list* (*get_enemy_area) (struct block_list *src, int x, int y, int range, int type, int ignore_id);
/* damages area, originally for royal guard's reflect damage */
- int (*damage_area) ( struct block_list *bl, va_list ap);
-} battle_s;
+ int (*damage_area) (struct block_list *bl, va_list ap);
+};
struct battle_interface *battle;
void battle_defaults(void);
-#endif /* _BATTLE_H_ */
+#endif /* MAP_BATTLE_H */
diff --git a/src/map/battleground.c b/src/map/battleground.c
index 64bc25269..f7131513d 100644
--- a/src/map/battleground.c
+++ b/src/map/battleground.c
@@ -2,179 +2,204 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/timer.h"
-#include "../common/malloc.h"
-#include "../common/nullpo.h"
-#include "../common/showmsg.h"
-#include "../common/socket.h"
-#include "../common/strlib.h"
-#include "../common/conf.h"
+#define HERCULES_CORE
#include "battleground.h"
+
+#include <stdio.h>
+#include <string.h>
+
#include "battle.h"
#include "clif.h"
+#include "homunculus.h"
#include "map.h"
+#include "mapreg.h"
+#include "mercenary.h"
+#include "mob.h" // struct mob_data
#include "npc.h"
-#include "pc.h"
#include "party.h"
+#include "pc.h"
#include "pet.h"
-#include "homunculus.h"
-#include "mercenary.h"
-
-#include <string.h>
-#include <stdio.h>
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
-static DBMap* bg_team_db; // int bg_id -> struct battleground_data*
-static unsigned int bg_team_counter = 0; // Next bg_id
+struct battleground_interface bg_s;
-struct battleground_data* bg_team_search(int bg_id) { // Search a BG Team using bg_id
+/// Search a BG Team using bg_id
+struct battleground_data* bg_team_search(int bg_id) {
if( !bg_id ) return NULL;
- return (struct battleground_data *)idb_get(bg_team_db, bg_id);
+ return (struct battleground_data *)idb_get(bg->team_db, bg_id);
}
-struct map_session_data* bg_getavailablesd(struct battleground_data *bg) {
+struct map_session_data* bg_getavailablesd(struct battleground_data *bgd) {
int i;
- nullpo_retr(NULL, bg);
- ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd != NULL);
- return( i < MAX_BG_MEMBERS ) ? bg->members[i].sd : NULL;
+ nullpo_retr(NULL, bgd);
+ ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd != NULL);
+ return( i < MAX_BG_MEMBERS ) ? bgd->members[i].sd : NULL;
}
-int bg_team_delete(int bg_id)
-{ // Deletes BG Team from db
+/// Deletes BG Team from db
+bool bg_team_delete(int bg_id) {
int i;
struct map_session_data *sd;
- struct battleground_data *bg = bg_team_search(bg_id);
+ struct battleground_data *bgd = bg->team_search(bg_id);
- if( bg == NULL ) return 0;
- for( i = 0; i < MAX_BG_MEMBERS; i++ )
- {
- if( (sd = bg->members[i].sd) == NULL )
+ if( bgd == NULL ) return false;
+ for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
+ if( (sd = bgd->members[i].sd) == NULL )
continue;
- bg_send_dot_remove(sd);
+ bg->send_dot_remove(sd);
sd->bg_id = 0;
}
- idb_remove(bg_team_db, bg_id);
- return 1;
+ idb_remove(bg->team_db, bg_id);
+ return true;
}
-int bg_team_warp(int bg_id, unsigned short mapindex, short x, short y)
-{ // Warps a Team
+/// Warps a Team
+bool bg_team_warp(int bg_id, unsigned short map_index, short x, short y) {
int i;
- struct battleground_data *bg = bg_team_search(bg_id);
- if( bg == NULL ) return 0;
+ struct battleground_data *bgd = bg->team_search(bg_id);
+ if( bgd == NULL ) return false;
for( i = 0; i < MAX_BG_MEMBERS; i++ )
- if( bg->members[i].sd != NULL ) pc->setpos(bg->members[i].sd, mapindex, x, y, CLR_TELEPORT);
- return 1;
+ if( bgd->members[i].sd != NULL ) pc->setpos(bgd->members[i].sd, map_index, x, y, CLR_TELEPORT);
+ return true;
}
-int bg_send_dot_remove(struct map_session_data *sd)
-{
+void bg_send_dot_remove(struct map_session_data *sd) {
if( sd && sd->bg_id )
clif->bg_xy_remove(sd);
- return 0;
}
-int bg_team_join(int bg_id, struct map_session_data *sd)
-{ // Player joins team
+/// Player joins team
+bool bg_team_join(int bg_id, struct map_session_data *sd) {
int i;
- struct battleground_data *bg = bg_team_search(bg_id);
+ struct battleground_data *bgd = bg->team_search(bg_id);
struct map_session_data *pl_sd;
- if( bg == NULL || sd == NULL || sd->bg_id ) return 0;
+ if( bgd == NULL || sd == NULL || sd->bg_id ) return false;
- ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == NULL);
- if( i == MAX_BG_MEMBERS ) return 0; // No free slots
+ ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd == NULL);
+ if( i == MAX_BG_MEMBERS ) return false; // No free slots
sd->bg_id = bg_id;
- bg->members[i].sd = sd;
- bg->members[i].x = sd->bl.x;
- bg->members[i].y = sd->bl.y;
- bg->count++;
+ bgd->members[i].sd = sd;
+ bgd->members[i].x = sd->bl.x;
+ bgd->members[i].y = sd->bl.y;
+ /* populate 'where i came from' */
+ if(map->list[sd->bl.m].flag.nosave || map->list[sd->bl.m].instance_id >= 0) {
+ struct map_data *m=&map->list[sd->bl.m];
+ if(m->save.map)
+ memcpy(&bgd->members[i].source,&m->save,sizeof(struct point));
+ else
+ memcpy(&bgd->members[i].source,&sd->status.save_point,sizeof(struct point));
+ } else
+ memcpy(&bgd->members[i].source,&sd->status.last_point,sizeof(struct point));
+ bgd->count++;
guild->send_dot_remove(sd);
for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
- if( (pl_sd = bg->members[i].sd) != NULL && pl_sd != sd )
+ if( (pl_sd = bgd->members[i].sd) != NULL && pl_sd != sd )
clif->hpmeter_single(sd->fd, pl_sd->bl.id, pl_sd->battle_status.hp, pl_sd->battle_status.max_hp);
}
clif->bg_hp(sd);
clif->bg_xy(sd);
- return 1;
+ return true;
}
-int bg_team_leave(struct map_session_data *sd, int flag)
-{ // Single Player leaves team
+/// Single Player leaves team
+int bg_team_leave(struct map_session_data *sd, enum bg_team_leave_type flag) {
int i, bg_id;
- struct battleground_data *bg;
+ struct battleground_data *bgd;
char output[128];
if( sd == NULL || !sd->bg_id )
return 0;
-
- bg_send_dot_remove(sd);
+ bg->send_dot_remove(sd);
bg_id = sd->bg_id;
sd->bg_id = 0;
- if( (bg = bg_team_search(bg_id)) == NULL )
+ if( (bgd = bg->team_search(bg_id)) == NULL )
return 0;
- ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == sd);
- if( i < MAX_BG_MEMBERS ) // Removes member from BG
- memset(&bg->members[i], 0, sizeof(bg->members[0]));
- bg->count--;
-
- if( flag )
- sprintf(output, "Server : %s has quit the game...", sd->status.name);
- else
- sprintf(output, "Server : %s is leaving the battlefield...", sd->status.name);
- clif->bg_message(bg, 0, "Server", output, strlen(output) + 1);
+ ARR_FIND(0, MAX_BG_MEMBERS, i, bgd->members[i].sd == sd);
+ if( i < MAX_BG_MEMBERS ) { // Removes member from BG
+ if( sd->bg_queue.arena ) {
+ bg->queue_pc_cleanup(sd);
+ pc->setpos(sd,bgd->members[i].source.map, bgd->members[i].source.x, bgd->members[i].source.y, CLR_OUTSIGHT);
+ }
+ memset(&bgd->members[i], 0, sizeof(bgd->members[0]));
+ }
- if( bg->logout_event[0] && flag )
- npc_event(sd, bg->logout_event, 0);
+ if( --bgd->count != 0 ) {
+ switch( flag ) {
+ default:
+ case BGTL_QUIT:
+ sprintf(output, "Server : %s has quit the game...", sd->status.name);
+ break;
+ case BGTL_LEFT:
+ sprintf(output, "Server : %s is leaving the battlefield...", sd->status.name);
+ break;
+ case BGTL_AFK:
+ sprintf(output, "Server : %s has been afk-kicked from the battlefield...", sd->status.name);
+ break;
+ }
+ clif->bg_message(bgd, 0, "Server", output, strlen(output) + 1);
+ }
- return bg->count;
+ if( bgd->logout_event[0] && flag )
+ npc->event(sd, bgd->logout_event, 0);
+
+ if( sd->bg_queue.arena ) {
+ bg->queue_pc_cleanup(sd);
+ }
+
+ return bgd->count;
}
-int bg_member_respawn(struct map_session_data *sd)
-{ // Respawn after killed
- struct battleground_data *bg;
- if( sd == NULL || !pc_isdead(sd) || !sd->bg_id || (bg = bg_team_search(sd->bg_id)) == NULL )
- return 0;
- if( bg->mapindex == 0 )
- return 0; // Respawn not handled by Core
- pc->setpos(sd, bg->mapindex, bg->x, bg->y, CLR_OUTSIGHT);
- status_revive(&sd->bl, 1, 100);
-
- return 1; // Warped
+/// Respawn after killed
+bool bg_member_respawn(struct map_session_data *sd) {
+ struct battleground_data *bgd;
+ if( sd == NULL || !pc_isdead(sd) || !sd->bg_id || (bgd = bg->team_search(sd->bg_id)) == NULL )
+ return false;
+ if( bgd->mapindex == 0 )
+ return false; // Respawn not handled by Core
+ pc->setpos(sd, bgd->mapindex, bgd->x, bgd->y, CLR_OUTSIGHT);
+ status->revive(&sd->bl, 1, 100);
+
+ return true; // Warped
}
-int bg_create(unsigned short mapindex, short rx, short ry, const char *ev, const char *dev) {
- struct battleground_data *bg;
- bg_team_counter++;
+int bg_create(unsigned short map_index, short rx, short ry, const char *ev, const char *dev) {
+ struct battleground_data *bgd;
+ bg->team_counter++;
- CREATE(bg, struct battleground_data, 1);
- bg->bg_id = bg_team_counter;
- bg->count = 0;
- bg->mapindex = mapindex;
- bg->x = rx;
- bg->y = ry;
- safestrncpy(bg->logout_event, ev, sizeof(bg->logout_event));
- safestrncpy(bg->die_event, dev, sizeof(bg->die_event));
+ CREATE(bgd, struct battleground_data, 1);
+ bgd->bg_id = bg->team_counter;
+ bgd->count = 0;
+ bgd->mapindex = map_index;
+ bgd->x = rx;
+ bgd->y = ry;
+ safestrncpy(bgd->logout_event, ev, sizeof(bgd->logout_event));
+ safestrncpy(bgd->die_event, dev, sizeof(bgd->die_event));
- memset(&bg->members, 0, sizeof(bg->members));
- idb_put(bg_team_db, bg_team_counter, bg);
+ memset(&bgd->members, 0, sizeof(bgd->members));
+ idb_put(bg->team_db, bg->team_counter, bgd);
- return bg->bg_id;
+ return bgd->bg_id;
}
-int bg_team_get_id(struct block_list *bl)
-{
+int bg_team_get_id(struct block_list *bl) {
nullpo_ret(bl);
- switch( bl->type )
- {
+ switch( bl->type ) {
case BL_PC:
return ((TBL_PC*)bl)->bg_id;
case BL_PET:
@@ -185,7 +210,7 @@ int bg_team_get_id(struct block_list *bl)
{
struct map_session_data *msd;
struct mob_data *md = (TBL_MOB*)bl;
- if( md->special_state.ai && (msd = iMap->id2sd(md->master_id)) != NULL )
+ if( md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL )
return msd->bg_id;
return md->bg_id;
}
@@ -204,97 +229,124 @@ int bg_team_get_id(struct block_list *bl)
return 0;
}
-int bg_send_message(struct map_session_data *sd, const char *mes, int len)
-{
- struct battleground_data *bg;
+bool bg_send_message(struct map_session_data *sd, const char *mes, int len) {
+ struct battleground_data *bgd;
nullpo_ret(sd);
- if( sd->bg_id == 0 || (bg = bg_team_search(sd->bg_id)) == NULL )
- return 0;
- clif->bg_message(bg, sd->bl.id, sd->status.name, mes, len);
- return 0;
+ if( sd->bg_id == 0 || (bgd = bg->team_search(sd->bg_id)) == NULL )
+ return false; // Couldn't send message
+ clif->bg_message(bgd, sd->bl.id, sd->status.name, mes, len);
+ return true;
}
/**
* @see DBApply
*/
-int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap)
-{
- struct battleground_data *bg = DB->data2ptr(data);
+int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap) {
+ struct battleground_data *bgd = DB->data2ptr(data);
struct map_session_data *sd;
int i;
- nullpo_ret(bg);
+ nullpo_ret(bgd);
for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
- if( (sd = bg->members[i].sd) == NULL )
+ if( (sd = bgd->members[i].sd) == NULL )
continue;
- if( sd->bl.x != bg->members[i].x || sd->bl.y != bg->members[i].y ) { // xy update
- bg->members[i].x = sd->bl.x;
- bg->members[i].y = sd->bl.y;
+ if( sd->bl.x != bgd->members[i].x || sd->bl.y != bgd->members[i].y ) { // xy update
+ bgd->members[i].x = sd->bl.x;
+ bgd->members[i].y = sd->bl.y;
clif->bg_xy(sd);
}
}
return 0;
}
-int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) {
- bg_team_db->foreach(bg_team_db, bg_send_xy_timer_sub, tick);
+int bg_send_xy_timer(int tid, int64 tick, int id, intptr_t data) {
+ bg->team_db->foreach(bg->team_db, bg->send_xy_timer_sub, tick);
return 0;
}
+
+enum bg_queue_types bg_str2teamtype (const char *str) {
+ char temp[200], *parse;
+ enum bg_queue_types type = BGQT_INVALID;
+
+ safestrncpy(temp, str, 200);
+
+ parse = strtok(temp,"|");
+
+ while (parse != NULL) {
+ normalize_name(parse," ");
+ if( strcmpi(parse,"all") == 0 )
+ type |= BGQT_INDIVIDUAL|BGQT_PARTY|BGQT_GUILD;
+ else if( strcmpi(parse,"party") == 0 )
+ type |= BGQT_PARTY;
+ else if( strcmpi(parse,"guild") == 0 )
+ type |= BGQT_GUILD;
+ else if( strcmpi(parse,"solo") == 0 )
+ type |= BGQT_INDIVIDUAL;
+ else {
+ ShowError("bg_str2teamtype: '%s' unknown type, skipping...\n",parse);
+ }
+ parse = strtok(NULL,"|");
+ }
+
+ return type;
+}
+
void bg_config_read(void) {
config_t bg_conf;
config_setting_t *data = NULL;
const char *config_filename = "conf/battlegrounds.conf"; // FIXME hardcoded name
- if (conf_read_file(&bg_conf, config_filename))
+ if (libconfig->read_file(&bg_conf, config_filename))
return;
- data = config_lookup(&bg_conf, "battlegrounds");
+ data = libconfig->lookup(&bg_conf, "battlegrounds");
if (data != NULL) {
- config_setting_t *settings = config_setting_get_elem(data, 0);
+ config_setting_t *settings = libconfig->setting_get_elem(data, 0);
config_setting_t *arenas;
const char *delay_var;
- int i, arena_count = 0, total = 0, offline = 0;
+ int i, arena_count = 0, offline = 0;
- if( !config_setting_lookup_string(settings, "global_delay_var", &delay_var) )
+ if( !libconfig->setting_lookup_string(settings, "global_delay_var", &delay_var) )
delay_var = "BG_Delay_Tick";
safestrncpy(bg->gdelay_var, delay_var, BG_DELAY_VAR_LENGTH);
- config_setting_lookup_int(settings, "maximum_afk_seconds", &bg->mafksec);
-
- config_setting_lookup_bool(settings, "feature_off", &offline);
-
+ libconfig->setting_lookup_int(settings, "maximum_afk_seconds", &bg->mafksec);
+
+ libconfig->setting_lookup_bool(settings, "feature_off", &offline);
+
if( offline == 0 )
bg->queue_on = true;
- if( (arenas = config_setting_get_member(settings, "arenas")) != NULL ) {
- arena_count = config_setting_length(arenas);
+ if( (arenas = libconfig->setting_get_member(settings, "arenas")) != NULL ) {
+ arena_count = libconfig->setting_length(arenas);
CREATE( bg->arena, struct bg_arena *, arena_count );
for(i = 0; i < arena_count; i++) {
- config_setting_t *arena = config_setting_get_elem(arenas, i);
+ config_setting_t *arena = libconfig->setting_get_elem(arenas, i);
config_setting_t *reward;
- const char *aName, *aEvent, *aDelayVar;
+ const char *aName, *aEvent, *aDelayVar, *aTeamTypes;
int minLevel = 0, maxLevel = 0;
int prizeWin, prizeLoss, prizeDraw;
int minPlayers, maxPlayers, minTeamPlayers;
int maxDuration;
- int fillup_duration, pregame_duration;
+ int fillup_duration = 0, pregame_duration = 0;
+ enum bg_queue_types allowedTypes;
bg->arena[i] = NULL;
- if( !config_setting_lookup_string(arena, "name", &aName) ) {
+ if( !libconfig->setting_lookup_string(arena, "name", &aName) ) {
ShowError("bg_config_read: failed to find 'name' for arena #%d\n",i);
continue;
}
- if( !config_setting_lookup_string(arena, "event", &aEvent) ) {
+ if( !libconfig->setting_lookup_string(arena, "event", &aEvent) ) {
ShowError("bg_config_read: failed to find 'event' for arena #%d\n",i);
continue;
}
- config_setting_lookup_int(arena, "minLevel", &minLevel);
- config_setting_lookup_int(arena, "maxLevel", &maxLevel);
+ libconfig->setting_lookup_int(arena, "minLevel", &minLevel);
+ libconfig->setting_lookup_int(arena, "maxLevel", &maxLevel);
if( minLevel < 0 ) {
ShowWarning("bg_config_read: invalid %d value for arena '%s' minLevel\n",minLevel,aName);
@@ -305,14 +357,14 @@ void bg_config_read(void) {
maxLevel = MAX_LEVEL;
}
- if( !(reward = config_setting_get_member(settings, "reward")) ) {
+ if( !(reward = libconfig->setting_get_member(arena, "reward")) ) {
ShowError("bg_config_read: failed to find 'reward' for arena '%s'/#%d\n",aName,i);
continue;
}
- config_setting_lookup_int(reward, "win", &prizeWin);
- config_setting_lookup_int(reward, "loss", &prizeLoss);
- config_setting_lookup_int(reward, "draw", &prizeDraw);
+ libconfig->setting_lookup_int(reward, "win", &prizeWin);
+ libconfig->setting_lookup_int(reward, "loss", &prizeLoss);
+ libconfig->setting_lookup_int(reward, "draw", &prizeDraw);
if( prizeWin < 0 ) {
ShowWarning("bg_config_read: invalid %d value for arena '%s' reward:win\n",prizeWin,aName);
@@ -327,9 +379,9 @@ void bg_config_read(void) {
prizeDraw = 0;
}
- config_setting_lookup_int(arena, "minPlayers", &minPlayers);
- config_setting_lookup_int(arena, "maxPlayers", &maxPlayers);
- config_setting_lookup_int(arena, "minTeamPlayers", &minTeamPlayers);
+ libconfig->setting_lookup_int(arena, "minPlayers", &minPlayers);
+ libconfig->setting_lookup_int(arena, "maxPlayers", &maxPlayers);
+ libconfig->setting_lookup_int(arena, "minTeamPlayers", &minTeamPlayers);
if( minPlayers < 0 ) {
ShowWarning("bg_config_read: invalid %d value for arena '%s' minPlayers\n",minPlayers,aName);
@@ -344,20 +396,26 @@ void bg_config_read(void) {
minTeamPlayers = 0;
}
- if( !config_setting_lookup_string(arena, "delay_var", &aDelayVar) ) {
+ if( !libconfig->setting_lookup_string(arena, "delay_var", &aDelayVar) ) {
ShowError("bg_config_read: failed to find 'delay_var' for arena '%s'/#%d\n",aName,i);
continue;
}
- config_setting_lookup_int(arena, "maxDuration", &maxDuration);
+
+ if( !libconfig->setting_lookup_string(arena, "allowedTypes", &aTeamTypes) ) {
+ ShowError("bg_config_read: failed to find 'allowedTypes' for arena '%s'/#%d\n",aName,i);
+ continue;
+ }
+
+ libconfig->setting_lookup_int(arena, "maxDuration", &maxDuration);
if( maxDuration < 0 ) {
ShowWarning("bg_config_read: invalid %d value for arena '%s' maxDuration\n",maxDuration,aName);
maxDuration = 30;
}
- config_setting_lookup_int(arena, "fillDuration", &fillup_duration);
- config_setting_lookup_int(arena, "pGameDuration", &pregame_duration);
+ libconfig->setting_lookup_int(arena, "fillDuration", &fillup_duration);
+ libconfig->setting_lookup_int(arena, "pGameDuration", &pregame_duration);
if( fillup_duration < 20 ) {
ShowWarning("bg_config_read: invalid %d value for arena '%s' fillDuration, minimum has to be 20, defaulting to 20.\n",fillup_duration,aName);
@@ -369,6 +427,7 @@ void bg_config_read(void) {
pregame_duration = 20;
}
+ allowedTypes = bg->str2teamtype(aTeamTypes);
CREATE( bg->arena[i], struct bg_arena, 1 );
@@ -385,19 +444,19 @@ void bg_config_read(void) {
bg->arena[i]->min_team_players = minTeamPlayers;
safestrncpy(bg->arena[i]->delay_var, aDelayVar, NAME_LENGTH);
bg->arena[i]->maxDuration = maxDuration;
- bg->arena[i]->queue_id = -1;
+ bg->arena[i]->queue_id = script->queue_create();
bg->arena[i]->begin_timer = INVALID_TIMER;
bg->arena[i]->fillup_timer = INVALID_TIMER;
bg->arena[i]->pregame_duration = pregame_duration;
bg->arena[i]->fillup_duration = fillup_duration;
-
- total++;
+ bg->arena[i]->ongoing = false;
+ bg->arena[i]->allowed_types = allowedTypes;
+
}
bg->arenas = arena_count;
}
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' arenas in '"CL_WHITE"%s"CL_RESET"'.\n", total, config_filename);
- config_destroy(&bg_conf);
+ libconfig->destroy(&bg_conf);
}
}
struct bg_arena *bg_name2arena (char *name) {
@@ -411,20 +470,55 @@ struct bg_arena *bg_name2arena (char *name) {
int bg_id2pos ( int queue_id, int account_id ) {
struct hQueue *queue = script->queue(queue_id);
if( queue ) {
- int i;
- for(i = 0; i < queue->items; i++ ) {
- if( queue->item[i] == account_id ) {
- return i;
+ int i, pos = 1;
+ for(i = 0; i < queue->size; i++ ) {
+ if( queue->item[i] > 0 ) {
+ if( queue->item[i] == account_id ) {
+ return pos;
+ }
+ pos++;
}
}
}
return 0;
}
+void bg_queue_ready_ack (struct bg_arena *arena, struct map_session_data *sd, bool response) {
+ if( arena->begin_timer == INVALID_TIMER || !sd->bg_queue.arena || sd->bg_queue.arena != arena ) {
+ bg->queue_pc_cleanup(sd);
+ return;
+ }
+ if( !response )
+ bg->queue_pc_cleanup(sd);
+ else {
+ struct hQueue *queue = &script->hq[arena->queue_id];
+ int i, count = 0;
+ sd->bg_queue.ready = 1;
+
+ for( i = 0; i < queue->size; i++ ) {
+ if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) {
+ if( sd->bg_queue.ready == 1 )
+ count++;
+ }
+ }
+ /* check if all are ready then cancel timer, and start game */
+ if( count == queue->items ) {
+ timer->delete(arena->begin_timer,bg->begin_timer);
+ arena->begin_timer = INVALID_TIMER;
+ bg->begin(arena);
+ }
+
+ }
+
+}
void bg_queue_player_cleanup(struct map_session_data *sd) {
if ( sd->bg_queue.client_has_bg_data ) {
- clif->bgqueue_notice_delete(sd,BGQND_CLOSEWINDOW, sd->bg_queue.arena->id);
+ if( sd->bg_queue.arena )
+ clif->bgqueue_notice_delete(sd,BGQND_CLOSEWINDOW,sd->bg_queue.arena->name);
+ else
+ clif->bgqueue_notice_delete(sd,BGQND_FAIL_NOT_QUEUING,bg->arena[0]->name);
}
- script->queue_remove(sd->bg_queue.arena->queue_id,sd->status.account_id);
+ if( sd->bg_queue.arena )
+ script->queue_remove(sd->bg_queue.arena->queue_id,sd->status.account_id);
sd->bg_queue.arena = NULL;
sd->bg_queue.ready = 0;
sd->bg_queue.client_has_bg_data = 0;
@@ -432,49 +526,116 @@ void bg_queue_player_cleanup(struct map_session_data *sd) {
}
void bg_match_over(struct bg_arena *arena, bool canceled) {
struct hQueue *queue = &script->hq[arena->queue_id];
- int i;//, count = 0;
-
- /* if( !canceled ) <check time/score> */
+ int i;
- for( i = 0; i < queue->items; i++ ) {
+ if( !arena->ongoing )
+ return;
+ arena->ongoing = false;
+
+ for( i = 0; i < queue->size; i++ ) {
struct map_session_data * sd = NULL;
- if( ( sd = iMap->id2sd(queue->item[i]) ) ) {
- bg->queue_pc_cleanup(sd);
- clif->colormes(sd->fd,COLOR_RED,"BG Match Cancelled: not enough players");
+ if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) {
+ if( sd->bg_queue.arena ) {
+ bg->team_leave(sd, 0);
+ bg->queue_pc_cleanup(sd);
+ }
+ if( canceled )
+ clif->colormes(sd->fd,COLOR_RED,"BG Match Canceled: not enough players");
+ else {
+ pc_setglobalreg(sd, script->add_str(arena->delay_var), (unsigned int)time(NULL));
+ }
}
}
- bg->arena[i]->begin_timer = INVALID_TIMER;
- bg->arena[i]->fillup_timer = INVALID_TIMER;
+ arena->begin_timer = INVALID_TIMER;
+ arena->fillup_timer = INVALID_TIMER;
/* reset queue */
+ script->queue_clear(arena->queue_id);
}
void bg_begin(struct bg_arena *arena) {
struct hQueue *queue = &script->hq[arena->queue_id];
int i, count = 0;
-
- for( i = 0; i < queue->items; i++ ) {
+
+ for( i = 0; i < queue->size; i++ ) {
struct map_session_data * sd = NULL;
- if( ( sd = iMap->id2sd(queue->item[i]) ) ) {
+ if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) {
if( sd->bg_queue.ready == 1 )
count++;
else
bg->queue_pc_cleanup(sd);
}
}
+ /* TODO/FIXME? I *think* it should check what kind of queue the player used, then check if his party/guild
+ * (his team) still meet the join criteria (sort of what bg->can_queue does)
+ */
if( count < arena->min_players ) {
- bg_match_over(arena,true);
+ bg->match_over(arena,true);
} else {
- ;
- /* we split evenly? */
- /* but if a party of say 10 joins, it cant be split evenly unless by luck there are 10 soloers in the queue besides them */
- /* not sure how to split T_T needs more info */
+ arena->ongoing = true;
+
+ if( bg->afk_timer_id == INVALID_TIMER && bg->mafksec > 0 )
+ bg->afk_timer_id = timer->add(timer->gettick()+10000,bg->afk_timer,0,0);
+
+ /* TODO: make this a arena-independent var? or just .@? */
+ mapreg->setreg(script->add_str("$@bg_queue_id"),arena->queue_id);
+ mapreg->setregstr(script->add_str("$@bg_delay_var$"),bg->gdelay_var);
+
+ count = 0;
+ for( i = 0; i < queue->size; i++ ) {
+ struct map_session_data * sd = NULL;
+
+ if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) {
+ if( sd->bg_queue.ready == 1 ) {
+
+ mapreg->setreg(reference_uid(script->add_str("$@bg_member"), count), sd->status.account_id);
+
+ mapreg->setreg(reference_uid(script->add_str("$@bg_member_group"), count),
+ sd->bg_queue.type == BGQT_GUILD ? sd->status.guild_id :
+ sd->bg_queue.type == BGQT_PARTY ? sd->status.party_id :
+ 0
+ );
+ mapreg->setreg(reference_uid(script->add_str("$@bg_member_type"), count),
+ sd->bg_queue.type == BGQT_GUILD ? 1 :
+ sd->bg_queue.type == BGQT_PARTY ? 2 :
+ 0
+ );
+ count++;
+ }
+ }
+ }
+ mapreg->setreg(script->add_str("$@bg_member_size"),count);
+
+ npc->event_do(arena->npc_event);
}
}
-int bg_begin_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int bg_begin_timer(int tid, int64 tick, int id, intptr_t data) {
bg->begin(bg->arena[id]);
+ bg->arena[id]->begin_timer = INVALID_TIMER;
+ return 0;
+}
+
+int bg_afk_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct s_mapiterator* iter;
+ struct map_session_data* sd;
+ int count = 0;
+
+ iter = mapit_getallusers();
+ for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) {
+ if( !sd->bg_queue.arena || !sd->bg_id )
+ continue;
+ if( DIFF_TICK(sockt->last_tick, sd->idletime) > bg->mafksec )
+ bg->team_leave(sd,BGTL_AFK);
+ count++;
+ }
+ mapit->free(iter);
+
+ if( count )
+ bg->afk_timer_id = timer->add(timer->gettick()+10000,bg->afk_timer,0,0);
+ else
+ bg->afk_timer_id = INVALID_TIMER;
return 0;
}
@@ -482,31 +643,31 @@ void bg_queue_pregame(struct bg_arena *arena) {
struct hQueue *queue = &script->hq[arena->queue_id];
int i;
- for( i = 0; i < queue->items; i++ ) {
+ for( i = 0; i < queue->size; i++ ) {
struct map_session_data * sd = NULL;
- if( ( sd = iMap->id2sd(queue->item[i]) ) ) {
+ if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) {
clif->bgqueue_battlebegins(sd,arena->id,SELF);
}
}
- arena->begin_timer = iTimer->add_timer( iTimer->gettick() + (arena->pregame_duration*1000), bg->begin_timer, arena->id, 0 );
+ arena->begin_timer = timer->add( timer->gettick() + (arena->pregame_duration*1000), bg->begin_timer, arena->id, 0 );
}
-int bg_fillup_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int bg_fillup_timer(int tid, int64 tick, int id, intptr_t data) {
bg->queue_pregame(bg->arena[id]);
+ bg->arena[id]->fillup_timer = INVALID_TIMER;
return 0;
}
void bg_queue_check(struct bg_arena *arena) {
int count = script->hq[arena->queue_id].items;
-
if( count == arena->max_players ) {
if( arena->fillup_timer != INVALID_TIMER ) {
- iTimer->delete_timer(arena->fillup_timer,bg_fillup_timer);
+ timer->delete(arena->fillup_timer,bg->fillup_timer);
arena->fillup_timer = INVALID_TIMER;
}
bg->queue_pregame(arena);
} else if( count >= arena->min_players && arena->fillup_timer == INVALID_TIMER ) {
- arena->fillup_timer = iTimer->add_timer( iTimer->gettick() + (arena->fillup_duration*1000), bg->fillup_timer, arena->id, 0 );
+ arena->fillup_timer = timer->add( timer->gettick() + (arena->fillup_duration*1000), bg->fillup_timer, arena->id, 0 );
}
}
void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type) {
@@ -514,7 +675,7 @@ void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_q
struct hQueue *queue;
int i, count = 0;
- if( arena->begin_timer != INVALID_TIMER ) {
+ if( arena->begin_timer != INVALID_TIMER || arena->ongoing ) {
clif->bgqueue_ack(sd,BGQA_FAIL_QUEUING_FINISHED,arena->id);
return;
}
@@ -545,11 +706,11 @@ void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_q
break;
}
- if( !(queue = script->queue(arena->queue_id)) || (queue->items+count) >= arena->max_players ) {
+ if( !(queue = script->queue(arena->queue_id)) || (queue->items+count) > arena->max_players ) {
clif->bgqueue_ack(sd,BGQA_FAIL_PPL_OVERAMOUNT,arena->id);
return;
}
-
+
switch( type ) {
case BGQT_INDIVIDUAL:
sd->bg_queue.type = type;
@@ -585,14 +746,19 @@ void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_q
}
break;
}
-
+
clif->bgqueue_ack(sd,BGQA_SUCCESS,arena->id);
+ bg->queue_check(arena);
}
enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type) {
int tick;
unsigned int tsec;
- if ( sd->status.base_level > arena->max_level || sd->status.base_level < arena->max_level )
+
+ if( !(arena->allowed_types & type) )
+ return BGQA_FAIL_TYPE_INVALID;
+
+ if ( sd->status.base_level > arena->max_level || sd->status.base_level < arena->min_level )
return BGQA_FAIL_LEVEL_INCORRECT;
if ( !(sd->class_&JOBL_2) ) /* TODO: maybe make this a per-arena setting, so users may make custom arenas like baby-only,whatever. */
@@ -600,7 +766,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
tsec = (unsigned int)time(NULL);
- if ( ( tick = pc_readglobalreg(sd, bg->gdelay_var) ) && tsec < tick ) {
+ if ( ( tick = pc_readglobalreg(sd, script->add_str(bg->gdelay_var)) ) && tsec < tick ) {
char response[100];
if( (tick-tsec) > 60 )
sprintf(response, "You are a deserter! Wait %d minute(s) before you can apply again",(tick-tsec)/60);
@@ -610,7 +776,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
return BGQA_FAIL_DESERTER;
}
- if ( ( tick = pc_readglobalreg(sd, arena->cooldown_variable) ) && tsec < tick ) {
+ if ( ( tick = pc_readglobalreg(sd, script->add_str(arena->delay_var)) ) && tsec < tick ) {
char response[100];
if( (tick-tsec) > 60 )
sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %d minute(s)",(tick-tsec)/60);
@@ -622,7 +788,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
if( sd->bg_queue.arena != NULL )
return BGQA_DUPLICATE_REQUEST;
-
+
switch(type) {
case BGQT_GUILD:
if( !sd->guild || !sd->state.gmaster_flag )
@@ -689,16 +855,20 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
return BGQA_SUCCESS;
}
-void do_init_battleground(void) {
- bg_team_db = idb_alloc(DB_OPT_RELEASE_DATA);
- iTimer->add_timer_func_list(bg_send_xy_timer, "bg_send_xy_timer");
- iTimer->add_timer_interval(iTimer->gettick() + battle_config.bg_update_interval, bg_send_xy_timer, 0, 0, battle_config.bg_update_interval);
+void do_init_battleground(bool minimal) {
+ if (minimal)
+ return;
+
+ bg->team_db = idb_alloc(DB_OPT_RELEASE_DATA);
+ timer->add_func_list(bg->send_xy_timer, "bg_send_xy_timer");
+ timer->add_interval(timer->gettick() + battle_config.bg_update_interval, bg->send_xy_timer, 0, 0, battle_config.bg_update_interval);
+ bg->config_read();
}
void do_final_battleground(void) {
int i;
- bg_team_db->destroy(bg_team_db, NULL);
+ db_destroy(bg->team_db);
for( i = 0; i < bg->arenas; i++ ) {
if( bg->arena[i] )
@@ -714,9 +884,16 @@ void battleground_defaults(void) {
bg->queue_on = false;
bg->mafksec = 0;
+ bg->afk_timer_id = INVALID_TIMER;
bg->arena = NULL;
bg->arenas = 0;
/* */
+ bg->team_db = NULL;
+ bg->team_counter = 0;
+ /* */
+ bg->init = do_init_battleground;
+ bg->final = do_final_battleground;
+ /* */
bg->name2arena = bg_name2arena;
bg->queue_add = bg_queue_add;
bg->can_queue = bg_canqueue;
@@ -726,6 +903,25 @@ void battleground_defaults(void) {
bg->begin_timer = bg_begin_timer;
bg->queue_pregame = bg_queue_pregame;
bg->fillup_timer = bg_fillup_timer;
+ bg->queue_ready_ack = bg_queue_ready_ack;
+ bg->match_over = bg_match_over;
+ bg->queue_check = bg_queue_check;
+ bg->team_search = bg_team_search;
+ bg->getavailablesd = bg_getavailablesd;
+ bg->team_delete = bg_team_delete;
+ bg->team_warp = bg_team_warp;
+ bg->send_dot_remove = bg_send_dot_remove;
+ bg->team_join = bg_team_join;
+ bg->team_leave = bg_team_leave;
+ bg->member_respawn = bg_member_respawn;
+ bg->create = bg_create;
+ bg->team_get_id = bg_team_get_id;
+ bg->send_message = bg_send_message;
+ bg->send_xy_timer_sub = bg_send_xy_timer_sub;
+ bg->send_xy_timer = bg_send_xy_timer;
+ bg->afk_timer = bg_afk_timer;
+ /* */
+ bg->str2teamtype = bg_str2teamtype;
/* */
bg->config_read = bg_config_read;
}
diff --git a/src/map/battleground.h b/src/map/battleground.h
index 8fe9f3b77..c1d3be054 100644
--- a/src/map/battleground.h
+++ b/src/map/battleground.h
@@ -2,11 +2,12 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _BATTLEGROUND_H_
-#define _BATTLEGROUND_H_
+#ifndef MAP_BATTLEGROUND_H
+#define MAP_BATTLEGROUND_H
-#include "../common/mmo.h" // struct party
+#include "clif.h"
#include "guild.h"
+#include "../common/mmo.h" // struct party
/**
* Defines
@@ -18,16 +19,24 @@
* Enumerations
**/
enum bg_queue_types {
- BGQT_INVALID,
- BGQT_INDIVIDUAL,
- BGQT_PARTY,
- BGQT_GUILD
+ BGQT_INVALID = 0x0,
+ BGQT_INDIVIDUAL = 0x1,
+ BGQT_PARTY = 0x2,
+ /* yup no 0x3 */
+ BGQT_GUILD = 0x4,
+};
+
+enum bg_team_leave_type {
+ BGTL_LEFT = 0x0,
+ BGTL_QUIT = 0x1,
+ BGTL_AFK = 0x2,
};
struct battleground_member_data {
unsigned short x, y;
struct map_session_data *sd;
unsigned afk : 1;
+ struct point source;/* where did i come from before i join? */
};
struct battleground_data {
@@ -41,22 +50,6 @@ struct battleground_data {
char die_event[EVENT_NAME_LENGTH];
};
-void do_init_battleground(void);
-void do_final_battleground(void);
-
-struct battleground_data* bg_team_search(int bg_id);
-int bg_send_dot_remove(struct map_session_data *sd);
-int bg_team_get_id(struct block_list *bl);
-struct map_session_data* bg_getavailablesd(struct battleground_data *bg);
-
-int bg_create(unsigned short mapindex, short rx, short ry, const char *ev, const char *dev);
-int bg_team_join(int bg_id, struct map_session_data *sd);
-int bg_team_delete(int bg_id);
-int bg_team_leave(struct map_session_data *sd, int flag);
-int bg_team_warp(int bg_id, unsigned short mapindex, short x, short y);
-int bg_member_respawn(struct map_session_data *sd);
-int bg_send_message(struct map_session_data *sd, const char *mes, int len);
-
struct bg_arena {
char name[NAME_LENGTH];
unsigned char id;
@@ -66,7 +59,6 @@ struct bg_arena {
short min_players;
short max_players;
short min_team_players;
- char cooldown_variable[NAME_LENGTH];
char delay_var[NAME_LENGTH];
unsigned short maxDuration;
int queue_id;
@@ -75,33 +67,59 @@ struct bg_arena {
int game_timer;
unsigned short fillup_duration;
unsigned short pregame_duration;
+ bool ongoing;
+ enum bg_queue_types allowed_types;
};
-/* battleground.c interface (incomplete) */
struct battleground_interface {
bool queue_on;
/* */
- int mafksec;
+ int mafksec, afk_timer_id;
char gdelay_var[BG_DELAY_VAR_LENGTH];
/* */
struct bg_arena **arena;
unsigned char arenas;
/* */
+ DBMap *team_db; // int bg_id -> struct battleground_data*
+ unsigned int team_counter; // Next bg_id
+ /* */
+ void (*init) (bool minimal);
+ void (*final) (void);
+ /* */
struct bg_arena *(*name2arena) (char *name);
void (*queue_add) (struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type);
enum BATTLEGROUNDS_QUEUE_ACK (*can_queue) (struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type);
int (*id2pos) (int queue_id, int account_id);
void (*queue_pc_cleanup) (struct map_session_data *sd);
void (*begin) (struct bg_arena *arena);
- int (*begin_timer) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*begin_timer) (int tid, int64 tick, int id, intptr_t data);
void (*queue_pregame) (struct bg_arena *arena);
- int (*fillup_timer) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*fillup_timer) (int tid, int64 tick, int id, intptr_t data);
+ void (*queue_ready_ack) (struct bg_arena *arena, struct map_session_data *sd, bool response);
+ void (*match_over) (struct bg_arena *arena, bool canceled);
+ void (*queue_check) (struct bg_arena *arena);
+ struct battleground_data* (*team_search) (int bg_id);
+ struct map_session_data* (*getavailablesd) (struct battleground_data *bgd);
+ bool (*team_delete) (int bg_id);
+ bool (*team_warp) (int bg_id, unsigned short map_index, short x, short y);
+ void (*send_dot_remove) (struct map_session_data *sd);
+ bool (*team_join) (int bg_id, struct map_session_data *sd);
+ int (*team_leave) (struct map_session_data *sd, enum bg_team_leave_type flag);
+ bool (*member_respawn) (struct map_session_data *sd);
+ int (*create) (unsigned short map_index, short rx, short ry, const char *ev, const char *dev);
+ int (*team_get_id) (struct block_list *bl);
+ bool (*send_message) (struct map_session_data *sd, const char *mes, int len);
+ int (*send_xy_timer_sub) (DBKey key, DBData *data, va_list ap);
+ int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*afk_timer) (int tid, int64 tick, int id, intptr_t data);
+ /* */
+ enum bg_queue_types (*str2teamtype) (const char *str);
/* */
void (*config_read) (void);
-} bg_s;
+};
struct battleground_interface *bg;
void battleground_defaults(void);
-#endif /* _BATTLEGROUND_H_ */
+#endif /* MAP_BATTLEGROUND_H */
diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c
index 764b51015..626d102a3 100644
--- a/src/map/buyingstore.c
+++ b/src/map/buyingstore.c
@@ -2,50 +2,29 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/db.h" // ARR_FIND
-#include "../common/showmsg.h" // ShowWarning
-#include "../common/socket.h" // RBUF*
-#include "../common/strlib.h" // safestrncpy
+#define HERCULES_CORE
+
+#include "buyingstore.h" // struct s_buyingstore
+
#include "atcommand.h" // msg_txt
#include "battle.h" // battle_config.*
-#include "buyingstore.h" // struct s_buyingstore
+#include "chrif.h"
#include "clif.h" // clif->buyingstore_*
#include "log.h" // log_pick_pc, log_zeny
#include "pc.h" // struct map_session_data
-#include "chrif.h"
-
-
-/// constants (client-side restrictions)
-#define BUYINGSTORE_MAX_PRICE 99990000
-#define BUYINGSTORE_MAX_AMOUNT 9999
-
-
-/// failure constants for clif functions
-enum e_buyingstore_failure
-{
- BUYINGSTORE_CREATE = 1, // "Failed to open buying store."
- BUYINGSTORE_CREATE_OVERWEIGHT = 2, // "Total amount of then possessed items exceeds the weight limit by %d. Please re-enter."
- BUYINGSTORE_TRADE_BUYER_ZENY = 3, // "All items within the buy limit were purchased."
- BUYINGSTORE_TRADE_BUYER_NO_ITEMS = 4, // "All items were purchased."
- BUYINGSTORE_TRADE_SELLER_FAILED = 5, // "The deal has failed."
- BUYINGSTORE_TRADE_SELLER_COUNT = 6, // "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy."
- BUYINGSTORE_TRADE_SELLER_ZENY = 7, // "The trade failed, because the buyer is lacking required balance."
- BUYINGSTORE_CREATE_NO_INFO = 8, // "No sale (purchase) information available."
-};
-
-
-static unsigned int buyingstore_nextid = 0;
-static const short buyingstore_blankslots[MAX_SLOTS] = { 0 }; // used when checking whether or not an item's card slots are blank
+#include "../common/cbasetypes.h"
+#include "../common/db.h" // ARR_FIND
+#include "../common/showmsg.h" // ShowWarning
+#include "../common/socket.h" // RBUF*
+#include "../common/strlib.h" // safestrncpy
+struct buyingstore_interface buyingstore_s;
/// Returns unique buying store id
-static unsigned int buyingstore_getuid(void)
-{
- return buyingstore_nextid++;
+unsigned int buyingstore_getuid(void) {
+ return buyingstore->nextid++;
}
-
bool buyingstore_setup(struct map_session_data* sd, unsigned char slots)
{
if( !battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0 )
@@ -58,14 +37,14 @@ bool buyingstore_setup(struct map_session_data* sd, unsigned char slots)
return false;
}
- if( map[sd->bl.m].flag.novending )
- {// custom: no vending maps
+ if( map->list[sd->bl.m].flag.novending ) {
+ // custom: no vending maps
clif->message(sd->fd, msg_txt(276)); // "You can't open a shop on this map"
return false;
}
- if( iMap->getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) )
- {// custom: no vending cells
+ if( map->getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) ) {
+ // custom: no vending cells
clif->message(sd->fd, msg_txt(204)); // "You can't open a shop on this cell."
return false;
}
@@ -100,7 +79,7 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
return;
}
- if( !pc->can_give_items(sd) )
+ if( !pc_can_give_items(sd) )
{// custom: GM is not allowed to buy (give zeny)
sd->buyingstore.slots = 0;
clif->message(sd->fd, msg_txt(246));
@@ -113,14 +92,14 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
return;
}
- if( map[sd->bl.m].flag.novending )
- {// custom: no vending maps
+ if( map->list[sd->bl.m].flag.novending ) {
+ // custom: no vending maps
clif->message(sd->fd, msg_txt(276)); // "You can't open a shop on this map"
return;
}
- if( iMap->getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) )
- {// custom: no vending cells
+ if( map->getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) ) {
+ // custom: no vending cells
clif->message(sd->fd, msg_txt(204)); // "You can't open a shop on this cell."
return;
}
@@ -137,7 +116,7 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
amount = RBUFW(itemlist,i*8+2);
price = RBUFL(itemlist,i*8+4);
- if( ( id = itemdb_exists(nameid) ) == NULL || amount == 0 )
+ if( ( id = itemdb->exists(nameid) ) == NULL || amount == 0 )
{// invalid input
break;
}
@@ -147,8 +126,9 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
break;
}
- if( !id->flag.buyingstore || !itemdb_cantrade_sub(id, pc->get_group_level(sd), pc->get_group_level(sd)) || ( idx = pc->search_inventory(sd, nameid) ) == -1 )
- {// restrictions: allowed, no character-bound items and at least one must be owned
+ if (!id->flag.buyingstore || !itemdb->cantrade_sub(id, pc_get_group_level(sd), pc_get_group_level(sd))
+ || (idx = pc->search_inventory(sd, nameid)) == INDEX_NOT_FOUND
+ ) { // restrictions: allowed, no character-bound items and at least one must be owned
break;
}
@@ -221,14 +201,14 @@ void buyingstore_open(struct map_session_data* sd, int account_id)
return;
}
- if( !pc->can_give_items(sd) )
+ if( !pc_can_give_items(sd) )
{// custom: GM is not allowed to sell
clif->message(sd->fd, msg_txt(246));
return;
}
- if( ( pl_sd = iMap->id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore )
- {// not online or not buying
+ if( ( pl_sd = map->id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore ) {
+ // not online or not buying
return;
}
@@ -259,15 +239,15 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
return;
}
- if( !pc->can_give_items(sd) )
+ if( !pc_can_give_items(sd) )
{// custom: GM is not allowed to sell
clif->message(sd->fd, msg_txt(246));
clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
return;
}
- if( ( pl_sd = iMap->id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id )
- {// not online, not buying or not same store
+ if( ( pl_sd = map->id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id ) {
+ // not online, not buying or not same store
clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0);
return;
}
@@ -314,8 +294,8 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
return;
}
- if( sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc->get_group_level(sd), pc->get_group_level(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots)) )
- {// non-tradable item
+ if( sd->status.inventory[index].expire_time || (sd->status.inventory[index].bound && !pc_can_give_bound_items(sd)) || !itemdb_cantrade(&sd->status.inventory[index], pc_get_group_level(sd), pc_get_group_level(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore->blankslots, sizeof(buyingstore->blankslots)) )
+ {// non-tradable item
clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
return;
}
@@ -383,9 +363,9 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
clif->buyingstore_update_item(pl_sd, nameid, amount);
}
- if( iMap->save_settings&128 ) {
- chrif_save(sd, 0);
- chrif_save(pl_sd, 0);
+ if( map->save_settings&128 ) {
+ chrif->save(sd, 0);
+ chrif->save(pl_sd, 0);
}
// check whether or not there is still something to buy
@@ -407,9 +387,8 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
buyingstore_close(pl_sd);
// remove auto-trader
- if( pl_sd->state.autotrade )
- {
- iMap->quit(pl_sd);
+ if( pl_sd->state.autotrade ) {
+ map->quit(pl_sd);
}
}
@@ -470,7 +449,7 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st
;
}
- if( !searchstore->result(s->search_sd, sd->buyer_id, sd->status.account_id, sd->message, it->nameid, it->amount, it->price, buyingstore_blankslots, 0) )
+ if( !searchstore->result(s->search_sd, sd->buyer_id, sd->status.account_id, sd->message, it->nameid, it->amount, it->price, buyingstore->blankslots, 0) )
{// result set full
return false;
}
@@ -481,6 +460,9 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st
void buyingstore_defaults(void) {
buyingstore = &buyingstore_s;
+ buyingstore->nextid = 0;
+ memset(buyingstore->blankslots,0,sizeof(buyingstore->blankslots));
+ /* */
buyingstore->setup = buyingstore_setup;
buyingstore->create = buyingstore_create;
buyingstore->close = buyingstore_close;
@@ -488,5 +470,6 @@ void buyingstore_defaults(void) {
buyingstore->trade = buyingstore_trade;
buyingstore->search = buyingstore_search;
buyingstore->searchall = buyingstore_searchall;
+ buyingstore->getuid = buyingstore_getuid;
}
diff --git a/src/map/buyingstore.h b/src/map/buyingstore.h
index a416317be..c981cc444 100644
--- a/src/map/buyingstore.h
+++ b/src/map/buyingstore.h
@@ -2,13 +2,46 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _BUYINGSTORE_H_
-#define _BUYINGSTORE_H_
+#ifndef MAP_BUYINGSTORE_H
+#define MAP_BUYINGSTORE_H
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h" // MAX_SLOTS
+
+struct map_session_data;
+
+/**
+ * Declarations
+ **/
struct s_search_store_search;
+/**
+ * Defines
+ **/
#define MAX_BUYINGSTORE_SLOTS 5
+/// constants (client-side restrictions)
+#define BUYINGSTORE_MAX_PRICE 99990000
+#define BUYINGSTORE_MAX_AMOUNT 9999
+
+/**
+ * Enumerations
+ **/
+/// failure constants for clif functions
+enum e_buyingstore_failure {
+ BUYINGSTORE_CREATE = 1, // "Failed to open buying store."
+ BUYINGSTORE_CREATE_OVERWEIGHT = 2, // "Total amount of then possessed items exceeds the weight limit by %d. Please re-enter."
+ BUYINGSTORE_TRADE_BUYER_ZENY = 3, // "All items within the buy limit were purchased."
+ BUYINGSTORE_TRADE_BUYER_NO_ITEMS = 4, // "All items were purchased."
+ BUYINGSTORE_TRADE_SELLER_FAILED = 5, // "The deal has failed."
+ BUYINGSTORE_TRADE_SELLER_COUNT = 6, // "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy."
+ BUYINGSTORE_TRADE_SELLER_ZENY = 7, // "The trade failed, because the buyer is lacking required balance."
+ BUYINGSTORE_CREATE_NO_INFO = 8, // "No sale (purchase) information available."
+};
+
+/**
+ * Structures
+ **/
struct s_buyingstore_item {
int price;
unsigned short amount;
@@ -21,7 +54,13 @@ struct s_buyingstore {
unsigned char slots;
};
+/**
+ * Interface
+ **/
struct buyingstore_interface {
+ unsigned int nextid;
+ short blankslots[MAX_SLOTS]; // used when checking whether or not an item's card slots are blank
+ /* */
bool (*setup) (struct map_session_data* sd, unsigned char slots);
void (*create) (struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count);
void (*close) (struct map_session_data* sd);
@@ -29,10 +68,11 @@ struct buyingstore_interface {
void (*trade) (struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count);
bool (*search) (struct map_session_data* sd, unsigned short nameid);
bool (*searchall) (struct map_session_data* sd, const struct s_search_store_search* s);
-} buyingstore_s;
+ unsigned int (*getuid) (void);
+};
struct buyingstore_interface *buyingstore;
void buyingstore_defaults (void);
-#endif // _BUYINGSTORE_H_
+#endif // MAP_BUYINGSTORE_H
diff --git a/src/map/chat.c b/src/map/chat.c
index c0452f2c5..cd7b5f811 100644
--- a/src/map/chat.c
+++ b/src/map/chat.c
@@ -1,12 +1,14 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
+
+#define HERCULES_CORE
+
+#include "chat.h"
+
+#include <stdio.h>
+#include <string.h>
-#include "../common/cbasetypes.h"
-#include "../common/malloc.h"
-#include "../common/nullpo.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
-#include "../common/mmo.h"
#include "atcommand.h" // msg_txt()
#include "battle.h" // struct battle_config
#include "clif.h"
@@ -14,21 +16,23 @@
#include "npc.h" // npc_event_do()
#include "pc.h"
#include "skill.h" // ext_skill_unit_onplace()
-#include "chat.h"
-
-#include <stdio.h>
-#include <string.h>
-
+#include "../common/cbasetypes.h"
+#include "../common/malloc.h"
+#include "../common/mmo.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
-int chat_triggerevent(struct chat_data *cd); // forward declaration
+struct chat_interface chat_s;
/// Initializes a chatroom object (common functionality for both pc and npc chatrooms).
/// Returns a chatroom object on success, or NULL on failure.
-static struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl)
+struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl)
{
struct chat_data* cd;
nullpo_retr(NULL, bl);
+ /* Given the overhead and the numerous instances (npc allocated or otherwise) wouldn't it be beneficial to have it use ERS? [Ind] */
cd = (struct chat_data *) aMalloc(sizeof(struct chat_data));
safestrncpy(cd->title, title, sizeof(cd->title));
@@ -44,21 +48,20 @@ static struct chat_data* chat_createchat(struct block_list* bl, const char* titl
cd->owner = bl;
safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event));
- cd->bl.id = iMap->get_new_object_id();
+ cd->bl.id = map->get_new_object_id();
cd->bl.m = bl->m;
cd->bl.x = bl->x;
cd->bl.y = bl->y;
cd->bl.type = BL_CHAT;
cd->bl.next = cd->bl.prev = NULL;
- if( cd->bl.id == 0 )
- {
+ if( cd->bl.id == 0 ) {
aFree(cd);
- cd = NULL;
+ return NULL;
}
- iMap->addiddb(&cd->bl);
-
+ map->addiddb(&cd->bl);
+
if( bl->type != BL_NPC )
cd->kick_list = idb_alloc(DB_OPT_BASE);
@@ -68,34 +71,31 @@ static struct chat_data* chat_createchat(struct block_list* bl, const char* titl
/*==========================================
* player chatroom creation
*------------------------------------------*/
-int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub)
-{
+bool chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub) {
struct chat_data* cd;
nullpo_ret(sd);
if( sd->chatID )
- return 0; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex]
+ return false; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex]
if( sd->state.vending || sd->state.buyingstore )
{// not chat, when you already have a store open
- return 0;
+ return false;
}
- if( map[sd->bl.m].flag.nochat )
- {
+ if( map->list[sd->bl.m].flag.nochat ) {
clif->message(sd->fd, msg_txt(281));
- return 0; //Can't create chatrooms on this map.
+ return false; //Can't create chatrooms on this map.
}
- if( iMap->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOCHAT) )
- {
- clif->message (sd->fd, msg_txt(665));
- return 0;
+ if( map->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOCHAT) ) {
+ clif->message (sd->fd, msg_txt(865)); // "Can't create chat rooms in this area."
+ return false;
}
pc_stop_walking(sd,1);
- cd = chat_createchat(&sd->bl, title, pass, limit, pub, 0, "", 0, 1, MAX_LEVEL);
+ cd = chat->create(&sd->bl, title, pass, limit, pub, 0, "", 0, 1, MAX_LEVEL);
if( cd ) {
cd->users = 1;
cd->usersd[0] = sd;
@@ -103,51 +103,51 @@ int chat_createpcchat(struct map_session_data* sd, const char* title, const char
pc_stop_attack(sd);
clif->createchat(sd,0);
clif->dispchat(cd,0);
- } else
- clif->createchat(sd,1);
+ return true;
+ }
+ clif->createchat(sd,1); // 1 = Room limit exceeded
- return 0;
+ return false;
}
/*==========================================
* join an existing chatroom
*------------------------------------------*/
-int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass)
-{
+bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) {
struct chat_data* cd;
nullpo_ret(sd);
- cd = (struct chat_data*)iMap->id2bl(chatid);
+ cd = (struct chat_data*)map->id2bl(chatid);
if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chatID || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit )
{
- clif->joinchatfail(sd,0);
- return 0;
+ clif->joinchatfail(sd,0); // room full
+ return false;
}
if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !pc_has_permission(sd, PC_PERM_JOIN_ALL_CHAT) )
{
- clif->joinchatfail(sd,1);
- return 0;
+ clif->joinchatfail(sd,1); // wrong password
+ return false;
}
if( sd->status.base_level < cd->minLvl || sd->status.base_level > cd->maxLvl ) {
if(sd->status.base_level < cd->minLvl)
- clif->joinchatfail(sd,5);
+ clif->joinchatfail(sd,5); // too low level
else
- clif->joinchatfail(sd,6);
+ clif->joinchatfail(sd,6); // too high level
- return 0;
+ return false;
}
if( sd->status.zeny < cd->zeny ) {
- clif->joinchatfail(sd,4);
- return 0;
+ clif->joinchatfail(sd,4); // not enough zeny
+ return false;
}
if( cd->owner->type != BL_NPC && idb_exists(cd->kick_list,sd->status.char_id) ) {
- clif->joinchatfail(sd,2);//You have been kicked out of the room.
- return 0;
+ clif->joinchatfail(sd,2); // You have been kicked out of the room.
+ return false;
}
pc_stop_walking(sd,1);
@@ -157,38 +157,41 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass)
pc_setchatid(sd,cd->bl.id);
clif->joinchatok(sd, cd); //To the person who newly joined the list of all
- clif->addchat(cd, sd); //Reports To the person who already in the chat
- clif->dispchat(cd, 0); //Reported number of changes to the people around
+ clif->addchat(cd, sd); //Reports To the person who already in the chat
+ clif->dispchat(cd, 0); //Reported number of changes to the people around
- chat_triggerevent(cd); //Event
+ chat->trigger_event(cd); //Event
- return 0;
+ return true;
}
/*==========================================
- * leave a chatroom
+ * Leave a chatroom
+ * Return
+ * 0: User not found in chatroom/Missing data
+ * 1: Success
+ * 2: Chat room deleted (chat room empty)
+ * 3: Owner changed (Owner left and a new one as assigned)
*------------------------------------------*/
-int chat_leavechat(struct map_session_data* sd, bool kicked)
-{
+int chat_leavechat(struct map_session_data* sd, bool kicked) {
struct chat_data* cd;
int i;
int leavechar;
- nullpo_retr(1, sd);
+ nullpo_retr(0, sd);
- cd = (struct chat_data*)iMap->id2bl(sd->chatID);
- if( cd == NULL )
- {
+ cd = (struct chat_data*)map->id2bl(sd->chatID);
+ if( cd == NULL ) {
pc_setchatid(sd, 0);
- return 1;
+ return 0;
}
ARR_FIND( 0, cd->users, i, cd->usersd[i] == sd );
if ( i == cd->users )
{ // Not found in the chatroom?
pc_setchatid(sd, 0);
- return -1;
+ return 0;
}
clif->leavechat(cd, sd, kicked);
@@ -202,61 +205,63 @@ int chat_leavechat(struct map_session_data* sd, bool kicked)
if( cd->users == 0 && cd->owner->type == BL_PC ) { // Delete empty chatroom
- struct skill_unit* unit;
- struct skill_unit_group* group;
+ struct skill_unit* su;
+ struct skill_unit_group* group;
clif->clearchat(cd, 0);
db_destroy(cd->kick_list);
- iMap->deliddb(&cd->bl);
- iMap->delblock(&cd->bl);
- iMap->freeblock(&cd->bl);
+ map->deliddb(&cd->bl);
+ map->delblock(&cd->bl);
+ map->freeblock(&cd->bl);
- unit = iMap->find_skill_unit_oncell(&sd->bl, sd->bl.x, sd->bl.y, AL_WARP, NULL, 0);
- group = (unit != NULL) ? unit->group : NULL;
+ su = map->find_skill_unit_oncell(&sd->bl, sd->bl.x, sd->bl.y, AL_WARP, NULL, 0);
+ group = (su != NULL) ? su->group : NULL;
if (group != NULL)
- skill->unit_onplace(unit, &sd->bl, group->tick);
+ skill->unit_onplace(su, &sd->bl, group->tick);
- return 1;
+ return 2;
}
- if( leavechar == 0 && cd->owner->type == BL_PC )
- { // Set and announce new owner
+ if( leavechar == 0 && cd->owner->type == BL_PC ) {
+ // Set and announce new owner
cd->owner = (struct block_list*) cd->usersd[0];
clif->changechatowner(cd, cd->usersd[0]);
clif->clearchat(cd, 0);
//Adjust Chat location after owner has been changed.
- iMap->delblock( &cd->bl );
+ map->delblock( &cd->bl );
cd->bl.x=cd->usersd[0]->bl.x;
cd->bl.y=cd->usersd[0]->bl.y;
- iMap->addblock( &cd->bl );
+ map->addblock( &cd->bl );
clif->dispchat(cd,0);
+ return 3; // Owner changed
}
- else
- clif->dispchat(cd,0); // refresh chatroom
+ clif->dispchat(cd,0); // refresh chatroom
- return 0;
+ return 1;
}
/*==========================================
- * change a chatroom's owner
+ * Change a chatroom's owner
+ * Return
+ * 0: User not found/Missing data
+ * 1: Success
*------------------------------------------*/
-int chat_changechatowner(struct map_session_data* sd, const char* nextownername)
-{
+bool chat_changechatowner(struct map_session_data* sd, const char* nextownername) {
struct chat_data* cd;
struct map_session_data* tmpsd;
int i;
- nullpo_retr(1, sd);
+ nullpo_ret(sd);
- cd = (struct chat_data*)iMap->id2bl(sd->chatID);
+ cd = (struct chat_data*)map->id2bl(sd->chatID);
if( cd == NULL || (struct block_list*) sd != cd->owner )
- return 1;
+ return false;
ARR_FIND( 1, cd->users, i, strncmp(cd->usersd[i]->status.name, nextownername, NAME_LENGTH) == 0 );
if( i == cd->users )
- return -1; // name not found
+ return false; // name not found
// erase temporarily
clif->clearchat(cd,0);
@@ -271,29 +276,31 @@ int chat_changechatowner(struct map_session_data* sd, const char* nextownername)
cd->usersd[0] = tmpsd;
// set the new chatroom position
- iMap->delblock( &cd->bl );
+ map->delblock( &cd->bl );
cd->bl.x = cd->owner->x;
cd->bl.y = cd->owner->y;
- iMap->addblock( &cd->bl );
+ map->addblock( &cd->bl );
// and display again
clif->dispchat(cd,0);
- return 0;
+ return true;
}
/*==========================================
- * change a chatroom's status (title, etc)
+ * Change a chatroom's status (title, etc)
+ * Return
+ * 0: Missing data
+ * 1: Success
*------------------------------------------*/
-int chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub)
-{
+bool chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub) {
struct chat_data* cd;
- nullpo_retr(1, sd);
+ nullpo_ret(sd);
- cd = (struct chat_data*)iMap->id2bl(sd->chatID);
+ cd = (struct chat_data*)map->id2bl(sd->chatID);
if( cd==NULL || (struct block_list *)sd != cd->owner )
- return 1;
+ return false;
safestrncpy(cd->title, title, CHATROOM_TITLE_SIZE);
safestrncpy(cd->pass, pass, CHATROOM_PASS_SIZE);
@@ -303,122 +310,161 @@ int chat_changechatstatus(struct map_session_data* sd, const char* title, const
clif->changechatstatus(cd);
clif->dispchat(cd,0);
- return 0;
+ return true;
}
/*==========================================
- * kick an user from a chatroom
+ * Kick an user from a chatroom
+ * Return:
+ * 0: User cannot be kicked (is gm)/Missing data
+ * 1: Success
*------------------------------------------*/
-int chat_kickchat(struct map_session_data* sd, const char* kickusername)
-{
+bool chat_kickchat(struct map_session_data* sd, const char* kickusername) {
struct chat_data* cd;
int i;
- nullpo_retr(1, sd);
+ nullpo_ret(sd);
- cd = (struct chat_data *)iMap->id2bl(sd->chatID);
+ cd = (struct chat_data *)map->id2bl(sd->chatID);
if( cd==NULL || (struct block_list *)sd != cd->owner )
- return -1;
+ return false;
ARR_FIND( 0, cd->users, i, strncmp(cd->usersd[i]->status.name, kickusername, NAME_LENGTH) == 0 );
- if( i == cd->users )
- return -1;
+ if( i == cd->users ) // User not found
+ return false;
if (pc_has_permission(cd->usersd[i], PC_PERM_NO_CHAT_KICK))
- return 0; //gm kick protection [Valaris]
+ return false; //gm kick protection [Valaris]
- idb_put(cd->kick_list,cd->usersd[i]->status.char_id,(void*)1);
+ idb_iput(cd->kick_list,cd->usersd[i]->status.char_id,1);
- chat_leavechat(cd->usersd[i],1);
- return 0;
+ chat->leave(cd->usersd[i],1);
+ return true;
}
-/// Creates a chat room for the npc.
-int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl)
+/*==========================================
+ * Creates a chat room for the npc
+ *------------------------------------------*/
+bool chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl)
{
struct chat_data* cd;
nullpo_ret(nd);
if( nd->chat_id ) {
ShowError("chat_createnpcchat: npc '%s' already has a chatroom, cannot create new one!\n", nd->exname);
- return 0;
+ return false;
}
if( zeny > MAX_ZENY || maxLvl > MAX_LEVEL ) {
ShowError("chat_createnpcchat: npc '%s' has a required lvl or amount of zeny over the max limit!\n", nd->exname);
- return 0;
+ return false;
}
- cd = chat_createchat(&nd->bl, title, "", limit, pub, trigger, ev, zeny, minLvl, maxLvl);
+ cd = chat->create(&nd->bl, title, "", limit, pub, trigger, ev, zeny, minLvl, maxLvl);
if( cd ) {
nd->chat_id = cd->bl.id;
clif->dispchat(cd,0);
+ return true;
}
- return 0;
+ return false;
}
-/// Removes the chatroom from the npc.
-int chat_deletenpcchat(struct npc_data* nd)
-{
+/*==========================================
+ * Removes the chatroom from the npc.
+ * Return:
+ * 0: Missing data
+ * 1: Success
+ *------------------------------------------*/
+bool chat_deletenpcchat(struct npc_data* nd) {
struct chat_data *cd;
nullpo_ret(nd);
- cd = (struct chat_data*)iMap->id2bl(nd->chat_id);
+ cd = (struct chat_data*)map->id2bl(nd->chat_id);
if( cd == NULL )
- return 0;
+ return false;
- chat_npckickall(cd);
+ chat->npc_kick_all(cd);
clif->clearchat(cd, 0);
- iMap->deliddb(&cd->bl);
- iMap->delblock(&cd->bl);
- iMap->freeblock(&cd->bl);
+ map->deliddb(&cd->bl);
+ map->delblock(&cd->bl);
+ map->freeblock(&cd->bl);
nd->chat_id = 0;
- return 0;
+ return true;
}
/*==========================================
* Trigger npc event when we enter the chatroom
+ * Return
+ * 0: Couldn't trigger / Missing data
+ * 1: Success
*------------------------------------------*/
-int chat_triggerevent(struct chat_data *cd)
+bool chat_triggerevent(struct chat_data *cd)
{
nullpo_ret(cd);
if( cd->users >= cd->trigger && cd->npc_event[0] )
- npc_event_do(cd->npc_event);
- return 0;
+ {
+ npc->event_do(cd->npc_event);
+ return true;
+ }
+ return false;
}
/// Enables the event of the chat room.
/// At most, 127 users are needed to trigger the event.
-int chat_enableevent(struct chat_data* cd)
+bool chat_enableevent(struct chat_data* cd)
{
nullpo_ret(cd);
cd->trigger &= 0x7f;
- chat_triggerevent(cd);
- return 0;
+ chat->trigger_event(cd);
+ return true;
}
/// Disables the event of the chat room
-int chat_disableevent(struct chat_data* cd)
+bool chat_disableevent(struct chat_data* cd)
{
nullpo_ret(cd);
cd->trigger |= 0x80;
- return 0;
+ return true;
}
/// Kicks all the users from the chat room.
-int chat_npckickall(struct chat_data* cd)
+bool chat_npckickall(struct chat_data* cd)
{
nullpo_ret(cd);
while( cd->users > 0 )
- chat_leavechat(cd->usersd[cd->users-1],0);
+ chat->leave(cd->usersd[cd->users-1],0);
- return 0;
+ return true;
+}
+
+/*=====================================
+* Default Functions : chat.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+void chat_defaults(void) {
+ chat = &chat_s;
+
+ /* funcs */
+ chat->create_pc_chat = chat_createpcchat;
+ chat->join = chat_joinchat;
+ chat->leave = chat_leavechat;
+ chat->change_owner = chat_changechatowner;
+ chat->change_status = chat_changechatstatus;
+ chat->kick = chat_kickchat;
+ chat->create_npc_chat = chat_createnpcchat;
+ chat->delete_npc_chat = chat_deletenpcchat;
+ chat->enable_event = chat_enableevent;
+ chat->disable_event = chat_disableevent;
+ chat->npc_kick_all = chat_npckickall;
+ chat->trigger_event = chat_triggerevent;
+ chat->create = chat_createchat;
}
diff --git a/src/map/chat.h b/src/map/chat.h
index cb2e6ecd9..e055c04ed 100644
--- a/src/map/chat.h
+++ b/src/map/chat.h
@@ -1,17 +1,23 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _CHAT_H_
-#define _CHAT_H_
+#ifndef MAP_CHAT_H
+#define MAP_CHAT_H
#include "map.h" // struct block_list, CHATROOM_TITLE_SIZE
-struct map_session_data;
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+
struct chat_data;
+struct map_session_data;
+struct npc_data;
+#define MAX_CHAT_USERS 20
struct chat_data {
struct block_list bl; // data for this map object
- char title[CHATROOM_TITLE_SIZE]; // room title
+ char title[CHATROOM_TITLE_SIZE]; // room title
char pass[CHATROOM_PASS_SIZE]; // password
bool pub; // private/public flag
uint8 users; // current user count
@@ -20,24 +26,38 @@ struct chat_data {
uint32 zeny; // required zeny to join
uint32 minLvl; // minimum base level to join
uint32 maxLvl; // maximum base level allowed to join
- struct map_session_data* usersd[20];
+ struct map_session_data* usersd[MAX_CHAT_USERS];
struct block_list* owner;
char npc_event[EVENT_NAME_LENGTH];
+ /* isn't this a waste? there is a enormous overhead, wouldn't something like skill_blockpc_start be better here? [Ind] */
DBMap* kick_list; //DBMap of users who were kicked from this chat
};
+/*=====================================
+* Interface : chat.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+struct chat_interface {
+
+ /* funcs */
+ bool (*create_pc_chat) (struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub);
+ bool (*join) (struct map_session_data* sd, int chatid, const char* pass);
+ int (*leave) (struct map_session_data* sd, bool kicked);
+ bool (*change_owner) (struct map_session_data* sd, const char* nextownername);
+ bool (*change_status) (struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub);
+ bool (*kick) (struct map_session_data* sd, const char* kickusername);
+ bool (*create_npc_chat) (struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl);
+ bool (*delete_npc_chat) (struct npc_data* nd);
+ bool (*enable_event) (struct chat_data* cd);
+ bool (*disable_event) (struct chat_data* cd);
+ bool (*npc_kick_all) (struct chat_data* cd);
+ bool (*trigger_event) (struct chat_data *cd);
+ struct chat_data* (*create) (struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl);
+};
-int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub);
-int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass);
-int chat_leavechat(struct map_session_data* sd, bool kicked);
-int chat_changechatowner(struct map_session_data* sd, const char* nextownername);
-int chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub);
-int chat_kickchat(struct map_session_data* sd, const char* kickusername);
+struct chat_interface *chat;
-int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl);
-int chat_deletenpcchat(struct npc_data* nd);
-int chat_enableevent(struct chat_data* cd);
-int chat_disableevent(struct chat_data* cd);
-int chat_npckickall(struct chat_data* cd);
+void chat_defaults(void);
-#endif /* _CHAT_H_ */
+#endif /* MAP_CHAT_H */
diff --git a/src/map/chrif.c b/src/map/chrif.c
index 6e076e6d8..4c8cd747b 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -2,14 +2,16 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/malloc.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
-#include "../common/ers.h"
+#define HERCULES_CORE
+
+#include "../config/core.h" // AUTOTRADE_PERSISTENCY, STATS_OPT_OUT
+#include "chrif.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
#include "map.h"
#include "battle.h"
@@ -24,29 +26,19 @@
#include "instance.h"
#include "mercenary.h"
#include "elemental.h"
-#include "chrif.h"
#include "quest.h"
#include "storage.h"
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <time.h>
-
-static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_t data);
-
-static struct eri *auth_db_ers; //For reutilizing player login structures.
-static DBMap* auth_db; // int id -> struct auth_node*
-
-static const int packet_len_table[0x3d] = { // U - used, F - free
- 60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
- 6,-1,18, 7,-1,39,30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
- 6,30, -1, 0,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
- 11,10,10, 0,11, 0,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, F->2b15, U->2b16, U->2b17
- 2,10, 2,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
- -1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27
-};
+struct chrif_interface chrif_s;
//Used Packets:
//2af8: Outgoing, chrif_connect -> 'connect to charserver / auth @ charserver'
@@ -56,14 +48,14 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
//2afc: Outgoing, chrif_scdata_request -> request sc_data for pc->authok'ed char. <- new command reuses previous one.
//2afd: Incoming, chrif_authok -> 'client authentication ok'
//2afe: Outgoing, send_usercount_tochar -> 'sends player count of this map server to charserver'
-//2aff: Outgoing, send_users_tochar -> 'sends all actual connected character ids to charserver'
-//2b00: Incoming, iMap->setusers -> 'set the actual usercount? PACKET.2B COUNT.L.. ?' (not sure)
+//2aff: Outgoing, chrif_send_users_tochar -> 'sends all actual connected character ids to charserver'
+//2b00: Incoming, map_setusers -> 'set the actual usercount? PACKET.2B COUNT.L.. ?' (not sure)
//2b01: Outgoing, chrif_save -> 'charsave of char XY account XY (complete struct)'
//2b02: Outgoing, chrif_charselectreq -> 'player returns from ingame to charserver to select another char.., this packets includes sessid etc' ? (not 100% sure)
//2b03: Incoming, clif_charselectok -> '' (i think its the packet after enterworld?) (not sure)
//2b04: Incoming, chrif_recvmap -> 'getting maps from charserver of other mapserver's'
//2b05: Outgoing, chrif_changemapserver -> 'Tell the charserver the mapchange / quest for ok...'
-//2b06: Incoming, chrif_changemapserverack -> 'awnser of 2b05, ok/fail, data: dunno^^'
+//2b06: Incoming, chrif_changemapserverack -> 'answer of 2b05, ok/fail, data: dunno^^'
//2b07: Outgoing, chrif_removefriend -> 'Tell charserver to remove friend_id from char_id friend list'
//2b08: Outgoing, chrif_searchcharid -> '...'
//2b09: Incoming, map_addchariddb -> 'Adds a name to the nick db'
@@ -87,7 +79,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
//2b1b: Incoming, chrif_recvfamelist -> 'Receive fame ranking lists'
//2b1c: Outgoing, chrif_save_scdata -> 'Send sc_data of player for saving.'
//2b1d: Incoming, chrif_load_scdata -> 'received sc_data of player for loading.'
-//2b1e: Incoming, chrif_update_ip -> 'Reqest forwarded from char-server for interserver IP sync.' [Lance]
+//2b1e: Incoming, chrif_update_ip -> 'Request forwarded from char-server for interserver IP sync.' [Lance]
//2b1f: Incoming, chrif_disconnectplayer -> 'disconnects a player (aid X) with the message XY ... 0x81 ..' [Sirius]
//2b20: Incoming, chrif_removemap -> 'remove maps of a server (sample: its going offline)' [Sirius]
//2b21: Incoming, chrif_save_ack. Returned after a character has been "final saved" on the char-server. [Skotlex]
@@ -98,23 +90,8 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
//2b26: Outgoing, chrif_authreq -> 'client authentication request'
//2b27: Incoming, chrif_authfail -> 'client authentication failed'
-int chrif_connected = 0;
-int char_fd = -1;
-int srvinfo;
-static char char_ip_str[128];
-static uint32 char_ip = 0;
-static uint16 char_port = 6121;
-static char userid[NAME_LENGTH], passwd[NAME_LENGTH];
-static int chrif_state = 0;
-int other_mapserver_count=0; //Holds count of how many other map servers are online (apart of this instance) [Skotlex]
-
-//Interval at which map server updates online listing. [Valaris]
-#define CHECK_INTERVAL 3600000
-//Interval at which map server sends number of connected users. [Skotlex]
-#define UPDATE_INTERVAL 10000
//This define should spare writing the check in every function. [Skotlex]
-#define chrif_check(a) { if(!chrif_isconnected()) return a; }
-
+#define chrif_check(a) do { if(!chrif->isconnected()) return a; } while(0)
/// Resets all the data.
void chrif_reset(void) {
@@ -122,45 +99,49 @@ void chrif_reset(void) {
exit(EXIT_FAILURE);
}
-
/// Checks the conditions for the server to stop.
/// Releases the cookie when all characters are saved.
/// If all the conditions are met, it stops the core loop.
void chrif_check_shutdown(void) {
if( runflag != MAPSERVER_ST_SHUTDOWN )
return;
- if( auth_db->size(auth_db) > 0 )
+ if( db_size(chrif->auth_db) > 0 )
return;
runflag = CORE_ST_STOP;
}
struct auth_node* chrif_search(int account_id) {
- return (struct auth_node*)idb_get(auth_db, account_id);
+ return (struct auth_node*)idb_get(chrif->auth_db, account_id);
}
struct auth_node* chrif_auth_check(int account_id, int char_id, enum sd_state state) {
- struct auth_node *node = chrif_search(account_id);
+ struct auth_node *node = chrif->search(account_id);
return ( node && node->char_id == char_id && node->state == state ) ? node : NULL;
}
bool chrif_auth_delete(int account_id, int char_id, enum sd_state state) {
struct auth_node *node;
-
- if ( (node = chrif_auth_check(account_id, char_id, state) ) ) {
+
+ if ( (node = chrif->auth_check(account_id, char_id, state) ) ) {
int fd = node->sd ? node->sd->fd : node->fd;
if ( session[fd] && session[fd]->session_data == node->sd )
session[fd]->session_data = NULL;
- if ( node->char_dat )
- aFree(node->char_dat);
-
- if ( node->sd )
+ if ( node->sd ) {
+
+ if( node->sd->regs.vars )
+ node->sd->regs.vars->destroy(node->sd->regs.vars, script->reg_destroy);
+
+ if( node->sd->regs.arrays )
+ node->sd->regs.arrays->destroy(node->sd->regs.arrays, script->array_free_db);
+
aFree(node->sd);
+ }
- ers_free(auth_db_ers, node);
- idb_remove(auth_db,account_id);
+ ers_free(chrif->auth_db_ers, node);
+ idb_remove(chrif->auth_db,account_id);
return true;
}
@@ -168,13 +149,13 @@ bool chrif_auth_delete(int account_id, int char_id, enum sd_state state) {
}
//Moves the sd character to the auth_db structure.
-static bool chrif_sd_to_auth(TBL_PC* sd, enum sd_state state) {
+bool chrif_sd_to_auth(TBL_PC* sd, enum sd_state state) {
struct auth_node *node;
- if ( chrif_search(sd->status.account_id) )
+ if ( chrif->search(sd->status.account_id) )
return false; //Already exists?
- node = ers_alloc(auth_db_ers, struct auth_node);
+ node = ers_alloc(chrif->auth_db_ers, struct auth_node);
memset(node, 0, sizeof(struct auth_node));
@@ -185,17 +166,17 @@ static bool chrif_sd_to_auth(TBL_PC* sd, enum sd_state state) {
node->sex = sd->status.sex;
node->fd = sd->fd;
node->sd = sd; //Data from logged on char.
- node->node_created = iTimer->gettick(); //timestamp for node timeouts
+ node->node_created = timer->gettick(); //timestamp for node timeouts
node->state = state;
sd->state.active = 0;
- idb_put(auth_db, node->account_id, node);
+ idb_put(chrif->auth_db, node->account_id, node);
return true;
}
-static bool chrif_auth_logout(TBL_PC* sd, enum sd_state state) {
+bool chrif_auth_logout(TBL_PC* sd, enum sd_state state) {
if(sd->fd && state == ST_LOGOUT) { //Disassociate player, and free it after saving ack returns. [Skotlex]
//fd info must not be lost for ST_MAPCHANGE as a final packet needs to be sent to the player.
@@ -204,33 +185,33 @@ static bool chrif_auth_logout(TBL_PC* sd, enum sd_state state) {
sd->fd = 0;
}
- return chrif_sd_to_auth(sd, state);
+ return chrif->sd_to_auth(sd, state);
}
bool chrif_auth_finished(TBL_PC* sd) {
- struct auth_node *node= chrif_search(sd->status.account_id);
+ struct auth_node *node= chrif->search(sd->status.account_id);
if ( node && node->sd == sd && node->state == ST_LOGIN ) {
node->sd = NULL;
- return chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN);
+ return chrif->auth_delete(node->account_id, node->char_id, ST_LOGIN);
}
return false;
}
// sets char-server's user id
void chrif_setuserid(char *id) {
- memcpy(userid, id, NAME_LENGTH);
+ memcpy(chrif->userid, id, NAME_LENGTH);
}
// sets char-server's password
void chrif_setpasswd(char *pwd) {
- memcpy(passwd, pwd, NAME_LENGTH);
+ memcpy(chrif->passwd, pwd, NAME_LENGTH);
}
// security check, prints warning if using default password
void chrif_checkdefaultlogin(void) {
- if (strcmp(userid, "s1")==0 && strcmp(passwd, "p1")==0) {
+ if (strcmp(chrif->userid, "s1")==0 && strcmp(chrif->passwd, "p1")==0) {
ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n");
ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n");
ShowNotice("and then edit your user/password in conf/map-server.conf (or conf/import/map_conf.txt)\n");
@@ -238,30 +219,29 @@ void chrif_checkdefaultlogin(void) {
}
// sets char-server's ip address
-int chrif_setip(const char* ip) {
+bool chrif_setip(const char* ip) {
char ip_str[16];
- if ( !( char_ip = host2ip(ip) ) ) {
+ if ( !( chrif->ip = host2ip(ip) ) ) {
ShowWarning("Failed to Resolve Char Server Address! (%s)\n", ip);
-
- return 0;
+ return false;
}
- safestrncpy(char_ip_str, ip, sizeof(char_ip_str));
+ safestrncpy(chrif->ip_str, ip, sizeof(chrif->ip_str));
- ShowInfo("Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(char_ip, ip_str));
+ ShowInfo("Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(chrif->ip, ip_str));
- return 1;
+ return true;
}
// sets char-server's port number
void chrif_setport(uint16 port) {
- char_port = port;
+ chrif->port = port;
}
// says whether the char-server is connected or not
int chrif_isconnected(void) {
- return (char_fd > 0 && session[char_fd] != NULL && chrif_state == 2);
+ return (chrif->fd > 0 && session[chrif->fd] != NULL && chrif->state == 2);
}
/*==========================================
@@ -269,76 +249,70 @@ int chrif_isconnected(void) {
* Flag = 1: Character is quitting
* Flag = 2: Character is changing map-servers
*------------------------------------------*/
-int chrif_save(struct map_session_data *sd, int flag) {
- nullpo_retr(-1, sd);
+bool chrif_save(struct map_session_data *sd, int flag) {
+ nullpo_ret(sd);
pc->makesavestatus(sd);
if (flag && sd->state.active) { //Store player data which is quitting
//FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex]
- if ( chrif_isconnected() )
- chrif_save_scdata(sd);
- if ( !chrif_auth_logout(sd,flag == 1 ? ST_LOGOUT : ST_MAPCHANGE) )
+ if ( chrif->isconnected() )
+ chrif->save_scdata(sd);
+ if ( !chrif->auth_logout(sd,flag == 1 ? ST_LOGOUT : ST_MAPCHANGE) )
ShowError("chrif_save: Failed to set up player %d:%d for proper quitting!\n", sd->status.account_id, sd->status.char_id);
}
- chrif_check(-1); //Character is saved on reconnect.
+ chrif_check(false); //Character is saved on reconnect.
//For data sync
if (sd->state.storage_flag == 2)
- storage_guild_storagesave(sd->status.account_id, sd->status.guild_id, flag);
+ gstorage->save(sd->status.account_id, sd->status.guild_id, flag);
if (flag)
sd->state.storage_flag = 0; //Force close it.
- //Saving of registry values.
- if (sd->state.reg_dirty&4)
- intif_saveregistry(sd, 3); //Save char regs
- if (sd->state.reg_dirty&2)
- intif_saveregistry(sd, 2); //Save account regs
- if (sd->state.reg_dirty&1)
- intif_saveregistry(sd, 1); //Save account2 regs
-
- WFIFOHEAD(char_fd, sizeof(sd->status) + 13);
- WFIFOW(char_fd,0) = 0x2b01;
- WFIFOW(char_fd,2) = sizeof(sd->status) + 13;
- WFIFOL(char_fd,4) = sd->status.account_id;
- WFIFOL(char_fd,8) = sd->status.char_id;
- WFIFOB(char_fd,12) = (flag==1)?1:0; //Flag to tell char-server this character is quitting.
- memcpy(WFIFOP(char_fd,13), &sd->status, sizeof(sd->status));
- WFIFOSET(char_fd, WFIFOW(char_fd,2));
+ //Saving of registry values.
+ if (sd->vars_dirty)
+ intif->saveregistry(sd);
+
+ WFIFOHEAD(chrif->fd, sizeof(sd->status) + 13);
+ WFIFOW(chrif->fd,0) = 0x2b01;
+ WFIFOW(chrif->fd,2) = sizeof(sd->status) + 13;
+ WFIFOL(chrif->fd,4) = sd->status.account_id;
+ WFIFOL(chrif->fd,8) = sd->status.char_id;
+ WFIFOB(chrif->fd,12) = (flag==1)?1:0; //Flag to tell char-server this character is quitting.
+ memcpy(WFIFOP(chrif->fd,13), &sd->status, sizeof(sd->status));
+ WFIFOSET(chrif->fd, WFIFOW(chrif->fd,2));
if( sd->status.pet_id > 0 && sd->pd )
- intif_save_petdata(sd->status.account_id,&sd->pd->pet);
+ intif->save_petdata(sd->status.account_id,&sd->pd->pet);
if( sd->hd && homun_alive(sd->hd) )
homun->save(sd->hd);
- if( sd->md && mercenary_get_lifetime(sd->md) > 0 )
- mercenary_save(sd->md);
- if( sd->ed && elemental_get_lifetime(sd->ed) > 0 )
- elemental_save(sd->ed);
+ if( sd->md && mercenary->get_lifetime(sd->md) > 0 )
+ mercenary->save(sd->md);
+ if( sd->ed && elemental->get_lifetime(sd->ed) > 0 )
+ elemental->save(sd->ed);
if( sd->save_quest )
- intif_quest_save(sd);
+ intif->quest_save(sd);
- return 0;
+ return true;
}
// connects to char-server (plaintext)
-int chrif_connect(int fd) {
- ShowStatus("Logging in to char server...\n", char_fd);
+void chrif_connect(int fd) {
+ ShowStatus("Logging in to char server...\n");
WFIFOHEAD(fd,60);
WFIFOW(fd,0) = 0x2af8;
- memcpy(WFIFOP(fd,2), userid, NAME_LENGTH);
- memcpy(WFIFOP(fd,26), passwd, NAME_LENGTH);
+ memcpy(WFIFOP(fd,2), chrif->userid, NAME_LENGTH);
+ memcpy(WFIFOP(fd,26), chrif->passwd, NAME_LENGTH);
WFIFOL(fd,50) = 0;
WFIFOL(fd,54) = htonl(clif->map_ip);
WFIFOW(fd,58) = htons(clif->map_port);
WFIFOSET(fd,60);
-
- return 0;
}
// sends maps to char-server
-int chrif_sendmap(int fd) {
+void chrif_sendmap(int fd) {
int i;
ShowStatus("Sending maps to char server...\n");
@@ -347,108 +321,102 @@ int chrif_sendmap(int fd) {
WFIFOHEAD(fd, 4 + instance->start_id * 4);
WFIFOW(fd,0) = 0x2afa;
for(i = 0; i < instance->start_id; i++)
- WFIFOW(fd,4+i*4) = map[i].index;
+ WFIFOW(fd,4+i*4) = map_id2index(i);
WFIFOW(fd,2) = 4 + i * 4;
WFIFOSET(fd,WFIFOW(fd,2));
-
- return 0;
}
// receive maps from some other map-server (relayed via char-server)
-int chrif_recvmap(int fd) {
+void chrif_recvmap(int fd) {
int i, j;
uint32 ip = ntohl(RFIFOL(fd,4));
uint16 port = ntohs(RFIFOW(fd,8));
for(i = 10, j = 0; i < RFIFOW(fd,2); i += 4, j++) {
- iMap->setipport(RFIFOW(fd,i), ip, port);
+ map->setipport(RFIFOW(fd,i), ip, port);
}
if (battle_config.etc_log)
ShowStatus("Received maps from %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j);
- other_mapserver_count++;
-
- return 0;
+ chrif->other_mapserver_count++;
}
// remove specified maps (used when some other map-server disconnects)
-int chrif_removemap(int fd) {
+void chrif_removemap(int fd) {
int i, j;
uint32 ip = RFIFOL(fd,4);
uint16 port = RFIFOW(fd,8);
for(i = 10, j = 0; i < RFIFOW(fd, 2); i += 4, j++)
- iMap->eraseipport(RFIFOW(fd, i), ip, port);
+ map->eraseipport(RFIFOW(fd, i), ip, port);
- other_mapserver_count--;
+ chrif->other_mapserver_count--;
if(battle_config.etc_log)
ShowStatus("remove map of server %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j);
-
- return 0;
}
// received after a character has been "final saved" on the char-server
-static void chrif_save_ack(int fd) {
- chrif_auth_delete(RFIFOL(fd,2), RFIFOL(fd,6), ST_LOGOUT);
- chrif_check_shutdown();
+void chrif_save_ack(int fd) {
+ chrif->auth_delete(RFIFOL(fd,2), RFIFOL(fd,6), ST_LOGOUT);
+ chrif->check_shutdown();
}
// request to move a character between mapservers
-int chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port) {
- nullpo_retr(-1, sd);
+bool chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port) {
+ nullpo_ret(sd);
- if (other_mapserver_count < 1) {//No other map servers are online!
+ if (chrif->other_mapserver_count < 1) {//No other map servers are online!
clif->authfail_fd(sd->fd, 0);
- return -1;
+ return false;
}
- chrif_check(-1);
-
- WFIFOHEAD(char_fd,35);
- WFIFOW(char_fd, 0) = 0x2b05;
- WFIFOL(char_fd, 2) = sd->bl.id;
- WFIFOL(char_fd, 6) = sd->login_id1;
- WFIFOL(char_fd,10) = sd->login_id2;
- WFIFOL(char_fd,14) = sd->status.char_id;
- WFIFOW(char_fd,18) = sd->mapindex;
- WFIFOW(char_fd,20) = sd->bl.x;
- WFIFOW(char_fd,22) = sd->bl.y;
- WFIFOL(char_fd,24) = htonl(ip);
- WFIFOW(char_fd,28) = htons(port);
- WFIFOB(char_fd,30) = sd->status.sex;
- WFIFOL(char_fd,31) = htonl(session[sd->fd]->client_addr);
- WFIFOL(char_fd,35) = sd->group_id;
- WFIFOSET(char_fd,39);
+ chrif_check(false);
+
+ WFIFOHEAD(chrif->fd,35);
+ WFIFOW(chrif->fd, 0) = 0x2b05;
+ WFIFOL(chrif->fd, 2) = sd->bl.id;
+ WFIFOL(chrif->fd, 6) = sd->login_id1;
+ WFIFOL(chrif->fd,10) = sd->login_id2;
+ WFIFOL(chrif->fd,14) = sd->status.char_id;
+ WFIFOW(chrif->fd,18) = sd->mapindex;
+ WFIFOW(chrif->fd,20) = sd->bl.x;
+ WFIFOW(chrif->fd,22) = sd->bl.y;
+ WFIFOL(chrif->fd,24) = htonl(ip);
+ WFIFOW(chrif->fd,28) = htons(port);
+ WFIFOB(chrif->fd,30) = sd->status.sex;
+ WFIFOL(chrif->fd,31) = htonl(session[sd->fd]->client_addr);
+ WFIFOL(chrif->fd,35) = sd->group_id;
+ WFIFOSET(chrif->fd,39);
- return 0;
+ return true;
}
-/// map-server change request acknowledgement (positive or negative)
+/// map-server change request acknowledgment (positive or negative)
/// R 2b06 <account_id>.L <login_id1>.L <login_id2>.L <char_id>.L <map_index>.W <x>.W <y>.W <ip>.L <port>.W
-int chrif_changemapserverack(int account_id, int login_id1, int login_id2, int char_id, short map_index, short x, short y, uint32 ip, uint16 port) {
+bool chrif_changemapserverack(int account_id, int login_id1, int login_id2, int char_id, short map_index, short x, short y, uint32 ip, uint16 port) {
struct auth_node *node;
- if ( !( node = chrif_auth_check(account_id, char_id, ST_MAPCHANGE) ) )
- return -1;
+ if ( !( node = chrif->auth_check(account_id, char_id, ST_MAPCHANGE) ) )
+ return false;
if ( !login_id1 ) {
- ShowError("map server change failed.\n");
+ ShowError("chrif_changemapserverack: map server change failed.\n");
clif->authfail_fd(node->fd, 0);
} else
clif->changemapserver(node->sd, map_index, x, y, ntohl(ip), ntohs(port));
//Player has been saved already, remove him from memory. [Skotlex]
- chrif_auth_delete(account_id, char_id, ST_MAPCHANGE);
+ chrif->auth_delete(account_id, char_id, ST_MAPCHANGE);
- return 0;
+ return (!login_id1)?false:true; // Is this the best approach here?
}
/*==========================================
*
*------------------------------------------*/
-int chrif_connectack(int fd) {
+void chrif_connectack(int fd) {
static bool char_init_done = false;
if (RFIFOB(fd,2)) {
@@ -457,52 +425,49 @@ int chrif_connectack(int fd) {
}
ShowStatus("Successfully logged on to Char Server (Connection: '"CL_WHITE"%d"CL_RESET"').\n",fd);
- chrif_state = 1;
- chrif_connected = 1;
+ chrif->state = 1;
+ chrif->connected = 1;
- chrif_sendmap(fd);
+ chrif->sendmap(fd);
- ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit"));
+ ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc->event_doall("OnInterIfInit"));
if( !char_init_done ) {
char_init_done = true;
- ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce"));
+ ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc->event_doall("OnInterIfInitOnce"));
guild->castle_map_init();
}
- socket_datasync(fd, true);
- chrif_skillid2idx(fd);
-
- return 0;
+ sockt->datasync(fd, true);
+ chrif->skillid2idx(fd);
}
/**
* @see DBApply
*/
-static int chrif_reconnect(DBKey key, DBData *data, va_list ap) {
+int chrif_reconnect(DBKey key, DBData *data, va_list ap) {
struct auth_node *node = DB->data2ptr(data);
switch (node->state) {
case ST_LOGIN:
- if ( node->sd && node->char_dat == NULL ) {//Since there is no way to request the char auth, make it fail.
+ if ( node->sd ) {//Since there is no way to request the char auth, make it fail.
pc->authfail(node->sd);
chrif_char_offline(node->sd);
- chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN);
+ chrif->auth_delete(node->account_id, node->char_id, ST_LOGIN);
}
break;
case ST_LOGOUT:
//Re-send final save
- chrif_save(node->sd, 1);
+ chrif->save(node->sd, 1);
break;
case ST_MAPCHANGE: { //Re-send map-change request.
struct map_session_data *sd = node->sd;
uint32 ip;
uint16 port;
- if( iMap->mapname2ipport(sd->mapindex,&ip,&port) == 0 )
- chrif_changemapserver(sd, ip, port);
+ if( map->mapname2ipport(sd->mapindex,&ip,&port) == 0 )
+ chrif->changemapserver(sd, ip, port);
else //too much lag/timeout is the closest explanation for this error.
clif->authfail_fd(sd->fd, 3);
-
break;
}
}
@@ -513,81 +478,88 @@ static int chrif_reconnect(DBKey key, DBData *data, va_list ap) {
/// Called when all the connection steps are completed.
void chrif_on_ready(void) {
+ static bool once = false;
ShowStatus("Map Server is now online.\n");
- chrif_state = 2;
+ chrif->state = 2;
- chrif_check_shutdown();
+ chrif->check_shutdown();
//If there are players online, send them to the char-server. [Skotlex]
- send_users_tochar();
+ chrif->send_users_tochar();
//Auth db reconnect handling
- auth_db->foreach(auth_db,chrif_reconnect);
+ chrif->auth_db->foreach(chrif->auth_db,chrif->reconnect);
//Re-save any storages that were modified in the disconnection time. [Skotlex]
- do_reconnect_storage();
+ storage->reconnect();
//Re-save any guild castles that were modified in the disconnection time.
guild->castle_reconnect(-1, 0, 0);
+
+ if( !once ) {
+#ifdef AUTOTRADE_PERSISTENCY
+ pc->autotrade_load();
+#endif
+ once = true;
+ }
}
/*==========================================
*
*------------------------------------------*/
-int chrif_sendmapack(int fd) {
+void chrif_sendmapack(int fd) {
if (RFIFOB(fd,2)) {
ShowFatalError("chrif : send map list to char server failed %d\n", RFIFOB(fd,2));
exit(EXIT_FAILURE);
}
- memcpy(iMap->wisp_server_name, RFIFOP(fd,3), NAME_LENGTH);
+ memcpy(map->wisp_server_name, RFIFOP(fd,3), NAME_LENGTH);
- chrif_on_ready();
-
- return 0;
+ chrif->on_ready();
}
/*==========================================
* Request sc_data from charserver [Skotlex]
*------------------------------------------*/
-int chrif_scdata_request(int account_id, int char_id) {
+bool chrif_scdata_request(int account_id, int char_id) {
#ifdef ENABLE_SC_SAVING
- chrif_check(-1);
+ chrif_check(false);
- WFIFOHEAD(char_fd,10);
- WFIFOW(char_fd,0) = 0x2afc;
- WFIFOL(char_fd,2) = account_id;
- WFIFOL(char_fd,6) = char_id;
- WFIFOSET(char_fd,10);
+ WFIFOHEAD(chrif->fd,10);
+ WFIFOW(chrif->fd,0) = 0x2afc;
+ WFIFOL(chrif->fd,2) = account_id;
+ WFIFOL(chrif->fd,6) = char_id;
+ WFIFOSET(chrif->fd,10);
#endif
- return 0;
+ return true;
}
/*==========================================
* Request auth confirmation
*------------------------------------------*/
-void chrif_authreq(struct map_session_data *sd) {
- struct auth_node *node= chrif_search(sd->bl.id);
-
- if( node != NULL || !chrif_isconnected() ) {
+void chrif_authreq(struct map_session_data *sd, bool hstandalone) {
+ struct auth_node *node= chrif->search(sd->bl.id);
+
+ if( node != NULL || !chrif->isconnected() ) {
set_eof(sd->fd);
return;
}
- WFIFOHEAD(char_fd,19);
- WFIFOW(char_fd,0) = 0x2b26;
- WFIFOL(char_fd,2) = sd->status.account_id;
- WFIFOL(char_fd,6) = sd->status.char_id;
- WFIFOL(char_fd,10) = sd->login_id1;
- WFIFOB(char_fd,14) = sd->status.sex;
- WFIFOL(char_fd,15) = htonl(session[sd->fd]->client_addr);
- WFIFOSET(char_fd,19);
- chrif_sd_to_auth(sd, ST_LOGIN);
+ WFIFOHEAD(chrif->fd,20);
+ WFIFOW(chrif->fd,0) = 0x2b26;
+ WFIFOL(chrif->fd,2) = sd->status.account_id;
+ WFIFOL(chrif->fd,6) = sd->status.char_id;
+ WFIFOL(chrif->fd,10) = sd->login_id1;
+ WFIFOB(chrif->fd,14) = sd->status.sex;
+ WFIFOL(chrif->fd,15) = htonl(session[sd->fd]->client_addr);
+ WFIFOB(chrif->fd,19) = hstandalone ? 1 : 0;
+ WFIFOSET(chrif->fd,20);
+ chrif->sd_to_auth(sd, ST_LOGIN);
}
/*==========================================
@@ -597,14 +569,14 @@ void chrif_authok(int fd) {
int account_id, group_id, char_id;
uint32 login_id1,login_id2;
time_t expiration_time;
- struct mmo_charstatus* status;
+ struct mmo_charstatus* charstatus;
struct auth_node *node;
bool changing_mapservers;
TBL_PC* sd;
//Check if both servers agree on the struct's size
if( RFIFOW(fd,2) - 25 != sizeof(struct mmo_charstatus) ) {
- ShowError("chrif_authok: Data size mismatch! %d != %d\n", RFIFOW(fd,2) - 25, sizeof(struct mmo_charstatus));
+ ShowError("chrif_authok: Data size mismatch! %d != %"PRIuS"\n", RFIFOW(fd,2) - 25, sizeof(struct mmo_charstatus));
return;
}
@@ -614,15 +586,15 @@ void chrif_authok(int fd) {
expiration_time = (time_t)(int32)RFIFOL(fd,16);
group_id = RFIFOL(fd,20);
changing_mapservers = (RFIFOB(fd,24));
- status = (struct mmo_charstatus*)RFIFOP(fd,25);
- char_id = status->char_id;
+ charstatus = (struct mmo_charstatus*)RFIFOP(fd,25);
+ char_id = charstatus->char_id;
//Check if we don't already have player data in our server
//Causes problems if the currently connected player tries to quit or this data belongs to an already connected player which is trying to re-auth.
- if ( ( sd = iMap->id2sd(account_id) ) != NULL )
+ if ( ( sd = map->id2sd(account_id) ) != NULL )
return;
-
- if ( ( node = chrif_search(account_id) ) == NULL )
+
+ if ( ( node = chrif->search(account_id) ) == NULL )
return; // should not happen
if ( node->state != ST_LOGIN )
@@ -632,7 +604,7 @@ void chrif_authok(int fd) {
/*
//When we receive double login info and the client has not connected yet,
//discard the older one and keep the new one.
- chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN);
+ chrif->auth_delete(node->account_id, node->char_id, ST_LOGIN);
*/
return; // should not happen
}
@@ -640,19 +612,18 @@ void chrif_authok(int fd) {
sd = node->sd;
if( runflag == MAPSERVER_ST_RUNNING &&
- node->char_dat == NULL &&
node->account_id == account_id &&
node->char_id == char_id &&
node->login_id1 == login_id1 )
{ //Auth Ok
- if (pc->authok(sd, login_id2, expiration_time, group_id, status, changing_mapservers))
+ if (pc->authok(sd, login_id2, expiration_time, group_id, charstatus, changing_mapservers))
return;
} else { //Auth Failed
pc->authfail(sd);
}
chrif_char_offline(sd); //Set him offline, the char server likely has it set as online already.
- chrif_auth_delete(account_id, char_id, ST_LOGIN);
+ chrif->auth_delete(account_id, char_id, ST_LOGIN);
}
// client authentication failed
@@ -667,7 +638,7 @@ void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used (
login_id1 = RFIFOL(fd,10);
sex = RFIFOB(fd,14);
- node = chrif_search(account_id);
+ node = chrif->search(account_id);
if( node != NULL &&
node->account_id == account_id &&
@@ -677,7 +648,7 @@ void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used (
node->state == ST_LOGIN )
{// found a match
clif->authfail_fd(node->fd, 0);
- chrif_auth_delete(account_id, char_id, ST_LOGIN);
+ chrif->auth_delete(account_id, char_id, ST_LOGIN);
}
}
@@ -690,18 +661,18 @@ int auth_db_cleanup_sub(DBKey key, DBData *data, va_list ap) {
struct auth_node *node = DB->data2ptr(data);
const char* states[] = { "Login", "Logout", "Map change" };
- if(DIFF_TICK(iTimer->gettick(),node->node_created)>60000) {
+ if(DIFF_TICK(timer->gettick(),node->node_created)>60000) {
switch (node->state) {
case ST_LOGOUT:
//Re-save attempt (->sd should never be null here).
- node->node_created = iTimer->gettick(); //Refresh tick (avoid char-server load if connection is really bad)
- chrif_save(node->sd, 1);
+ node->node_created = timer->gettick(); //Refresh tick (avoid char-server load if connection is really bad)
+ chrif->save(node->sd, 1);
break;
default:
//Clear data. any connected players should have timed out by now.
ShowInfo("auth_db: Node (state %s) timed out for %d:%d\n", states[node->state], node->account_id, node->char_id);
- chrif_char_offline_nsd(node->account_id, node->char_id);
- chrif_auth_delete(node->account_id, node->char_id, node->state);
+ chrif->char_offline_nsd(node->account_id, node->char_id);
+ chrif->auth_delete(node->account_id, node->char_id, node->state);
break;
}
return 1;
@@ -709,150 +680,156 @@ int auth_db_cleanup_sub(DBKey key, DBData *data, va_list ap) {
return 0;
}
-int auth_db_cleanup(int tid, unsigned int tick, int id, intptr_t data) {
+int auth_db_cleanup(int tid, int64 tick, int id, intptr_t data) {
chrif_check(0);
- auth_db->foreach(auth_db, auth_db_cleanup_sub);
+ chrif->auth_db->foreach(chrif->auth_db, chrif->auth_db_cleanup_sub);
return 0;
}
/*==========================================
- *
+ * Request char selection
*------------------------------------------*/
-int chrif_charselectreq(struct map_session_data* sd, uint32 s_ip) {
- nullpo_retr(-1, sd);
+bool chrif_charselectreq(struct map_session_data* sd, uint32 s_ip) {
+ nullpo_ret(sd);
- if( !sd || !sd->bl.id || !sd->login_id1 )
- return -1;
+ if( !sd->bl.id || !sd->login_id1 )
+ return false;
- chrif_check(-1);
+ chrif_check(false);
- WFIFOHEAD(char_fd,18);
- WFIFOW(char_fd, 0) = 0x2b02;
- WFIFOL(char_fd, 2) = sd->bl.id;
- WFIFOL(char_fd, 6) = sd->login_id1;
- WFIFOL(char_fd,10) = sd->login_id2;
- WFIFOL(char_fd,14) = htonl(s_ip);
- WFIFOSET(char_fd,18);
+ WFIFOHEAD(chrif->fd,22);
+ WFIFOW(chrif->fd, 0) = 0x2b02;
+ WFIFOL(chrif->fd, 2) = sd->bl.id;
+ WFIFOL(chrif->fd, 6) = sd->login_id1;
+ WFIFOL(chrif->fd,10) = sd->login_id2;
+ WFIFOL(chrif->fd,14) = htonl(s_ip);
+ WFIFOL(chrif->fd,18) = sd->group_id;
+ WFIFOSET(chrif->fd,22);
- return 0;
+ return true;
}
/*==========================================
* Search Char trough id on char serv
*------------------------------------------*/
-int chrif_searchcharid(int char_id) {
+bool chrif_searchcharid(int char_id) {
if( !char_id )
- return -1;
+ return false;
- chrif_check(-1);
+ chrif_check(false);
- WFIFOHEAD(char_fd,6);
- WFIFOW(char_fd,0) = 0x2b08;
- WFIFOL(char_fd,2) = char_id;
- WFIFOSET(char_fd,6);
+ WFIFOHEAD(chrif->fd,6);
+ WFIFOW(chrif->fd,0) = 0x2b08;
+ WFIFOL(chrif->fd,2) = char_id;
+ WFIFOSET(chrif->fd,6);
- return 0;
+ return true;
}
/*==========================================
* Change Email
*------------------------------------------*/
-int chrif_changeemail(int id, const char *actual_email, const char *new_email) {
+bool chrif_changeemail(int id, const char *actual_email, const char *new_email) {
if (battle_config.etc_log)
ShowInfo("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n", id, actual_email, new_email);
- chrif_check(-1);
+ chrif_check(false);
- WFIFOHEAD(char_fd,86);
- WFIFOW(char_fd,0) = 0x2b0c;
- WFIFOL(char_fd,2) = id;
- memcpy(WFIFOP(char_fd,6), actual_email, 40);
- memcpy(WFIFOP(char_fd,46), new_email, 40);
- WFIFOSET(char_fd,86);
+ WFIFOHEAD(chrif->fd,86);
+ WFIFOW(chrif->fd,0) = 0x2b0c;
+ WFIFOL(chrif->fd,2) = id;
+ memcpy(WFIFOP(chrif->fd,6), actual_email, 40);
+ memcpy(WFIFOP(chrif->fd,46), new_email, 40);
+ WFIFOSET(chrif->fd,86);
- return 0;
+ return true;
}
/*==========================================
* S 2b0e <accid>.l <name>.24B <type>.w { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w }
* Send an account modification request to the login server (via char server).
* type of operation:
- * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex (use next function for 5)
+ * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex (use next function for 5), 6: charban
*------------------------------------------*/
-int chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second) {
-
- chrif_check(-1);
-
- WFIFOHEAD(char_fd,44);
- WFIFOW(char_fd,0) = 0x2b0e;
- WFIFOL(char_fd,2) = acc;
- safestrncpy((char*)WFIFOP(char_fd,6), character_name, NAME_LENGTH);
- WFIFOW(char_fd,30) = operation_type;
-
- if ( operation_type == 2 ) {
- WFIFOW(char_fd,32) = year;
- WFIFOW(char_fd,34) = month;
- WFIFOW(char_fd,36) = day;
- WFIFOW(char_fd,38) = hour;
- WFIFOW(char_fd,40) = minute;
- WFIFOW(char_fd,42) = second;
+bool chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second) {
+
+ chrif_check(false);
+
+ WFIFOHEAD(chrif->fd,44);
+ WFIFOW(chrif->fd,0) = 0x2b0e;
+ WFIFOL(chrif->fd,2) = acc;
+ safestrncpy((char*)WFIFOP(chrif->fd,6), character_name, NAME_LENGTH);
+ WFIFOW(chrif->fd,30) = operation_type;
+
+ if ( operation_type == 2 || operation_type == 6 ) {
+ WFIFOW(chrif->fd,32) = year;
+ WFIFOW(chrif->fd,34) = month;
+ WFIFOW(chrif->fd,36) = day;
+ WFIFOW(chrif->fd,38) = hour;
+ WFIFOW(chrif->fd,40) = minute;
+ WFIFOW(chrif->fd,42) = second;
}
- WFIFOSET(char_fd,44);
- return 0;
+ WFIFOSET(chrif->fd,44);
+ return true;
}
-int chrif_changesex(struct map_session_data *sd) {
- chrif_check(-1);
+bool chrif_changesex(struct map_session_data *sd) {
+ chrif_check(false);
- WFIFOHEAD(char_fd,44);
- WFIFOW(char_fd,0) = 0x2b0e;
- WFIFOL(char_fd,2) = sd->status.account_id;
- safestrncpy((char*)WFIFOP(char_fd,6), sd->status.name, NAME_LENGTH);
- WFIFOW(char_fd,30) = 5;
- WFIFOSET(char_fd,44);
+ WFIFOHEAD(chrif->fd,44);
+ WFIFOW(chrif->fd,0) = 0x2b0e;
+ WFIFOL(chrif->fd,2) = sd->status.account_id;
+ safestrncpy((char*)WFIFOP(chrif->fd,6), sd->status.name, NAME_LENGTH);
+ WFIFOW(chrif->fd,30) = 5;
+ WFIFOSET(chrif->fd,44);
- clif->message(sd->fd, msg_txt(408)); //"Need disconnection to perform change-sex request..."
+ clif->message(sd->fd, msg_txt(408)); //"Disconnecting to perform change-sex request..."
if (sd->fd)
clif->authfail_fd(sd->fd, 15);
else
- iMap->quit(sd);
- return 0;
+ map->quit(sd);
+ return true;
}
/*==========================================
* R 2b0f <accid>.l <name>.24B <type>.w <answer>.w
- * Processing a reply to chrif_char_ask_name() (request to modify an account).
+ * Processing a reply to chrif->char_ask_name() (request to modify an account).
* type of operation:
- * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex
+ * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex, 6: charban, 7: charunban
* type of answer:
* 0: login-server request done
* 1: player not found
* 2: gm level too low
* 3: login-server offline
*------------------------------------------*/
-static void chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, uint16 answer) {
+bool chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, uint16 answer) {
struct map_session_data* sd;
char action[25];
char output[256];
+ bool charsrv = ( type == 6 || type == 7 ) ? true : false;
- sd = iMap->id2sd(acc);
+ sd = map->id2sd(acc);
if( acc < 0 || sd == NULL ) {
ShowError("chrif_char_ask_name_answer failed - player not online.\n");
- return;
+ return false;
}
+ /* re-use previous msg_txt */
+ if( type == 6 ) type = 2;
+ if( type == 7 ) type = 4;
+
if( type > 0 && type <= 5 )
snprintf(action,25,"%s",msg_txt(427+type)); //block|ban|unblock|unban|change the sex of
else
snprintf(action,25,"???");
switch( answer ) {
- case 0 : sprintf(output, msg_txt(424), action, NAME_LENGTH, player_name); break;
+ case 0 : sprintf(output, msg_txt(charsrv?434:424), action, NAME_LENGTH, player_name); break;
case 1 : sprintf(output, msg_txt(425), NAME_LENGTH, player_name); break;
case 2 : sprintf(output, msg_txt(426), action, NAME_LENGTH, player_name); break;
case 3 : sprintf(output, msg_txt(427), action, NAME_LENGTH, player_name); break;
@@ -860,115 +837,76 @@ static void chrif_char_ask_name_answer(int acc, const char* player_name, uint16
}
clif->message(sd->fd, output);
+ return true;
}
/*==========================================
* Request char server to change sex of char (modified by Yor)
*------------------------------------------*/
-int chrif_changedsex(int fd) {
- int acc, sex;
- struct map_session_data *sd;
-
- acc = RFIFOL(fd,2);
- sex = RFIFOL(fd,6);
+void chrif_changedsex(int fd) {
+ int acc = RFIFOL(fd,2);
+ //int sex = RFIFOL(fd,6); // Dead store. Uncomment if needed again.
if ( battle_config.etc_log )
ShowNotice("chrif_changedsex %d.\n", acc);
-
- sd = iMap->id2sd(acc);
- if ( sd ) { //Normally there should not be a char logged on right now!
- if ( sd->status.sex == sex )
- return 0; //Do nothing? Likely safe.
- sd->status.sex = !sd->status.sex;
-
- // reset skill of some job
- if ((sd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER) {
- int i, idx = 0;
- // remove specifical skills of Bard classes
- for(i = 315; i <= 322; i++) {
- idx = skill->get_index(i);
- if (sd->status.skill[idx].id > 0 && sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) {
- sd->status.skill_point += sd->status.skill[idx].lv;
- sd->status.skill[idx].id = 0;
- sd->status.skill[idx].lv = 0;
- }
- }
- // remove specifical skills of Dancer classes
- for(i = 323; i <= 330; i++) {
- idx = skill->get_index(i);
- if (sd->status.skill[idx].id > 0 && sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) {
- sd->status.skill_point += sd->status.skill[idx].lv;
- sd->status.skill[idx].id = 0;
- sd->status.skill[idx].lv = 0;
- }
- }
- clif->updatestatus(sd, SP_SKILLPOINT);
- // change job if necessary
- if (sd->status.sex) //Changed from Dancer
- sd->status.class_ -= 1;
- else //Changed from Bard
- sd->status.class_ += 1;
- //sd->class_ needs not be updated as both Dancer/Bard are the same.
- }
- // save character
- sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
- // do same modify in login-server for the account, but no in char-server (it ask again login_id1 to login, and don't remember it)
- clif->message(sd->fd, msg_txt(409)); //"Your sex has been changed (need disconnection by the server)..."
- set_eof(sd->fd); // forced to disconnect for the change
- iMap->quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X]
- }
- return 0;
+
+ // Path to activate this response:
+ // Map(start) (0x2b0e) -> Char(0x2727) -> Login
+ // Login(0x2723) [ALL] -> Char (0x2b0d)[ALL] -> Map (HERE)
+ // Char will usually be "logged in" despite being forced to log-out in the beginning
+ // of this process, but there's no need to perform map-server specific response
+ // as everything should been changed through char-server [Panikon]
}
/*==========================================
* Request Char Server to Divorce Players
*------------------------------------------*/
-int chrif_divorce(int partner_id1, int partner_id2) {
- chrif_check(-1);
+bool chrif_divorce(int partner_id1, int partner_id2) {
+ chrif_check(false);
- WFIFOHEAD(char_fd,10);
- WFIFOW(char_fd,0) = 0x2b11;
- WFIFOL(char_fd,2) = partner_id1;
- WFIFOL(char_fd,6) = partner_id2;
- WFIFOSET(char_fd,10);
+ WFIFOHEAD(chrif->fd,10);
+ WFIFOW(chrif->fd,0) = 0x2b11;
+ WFIFOL(chrif->fd,2) = partner_id1;
+ WFIFOL(chrif->fd,6) = partner_id2;
+ WFIFOSET(chrif->fd,10);
- return 0;
+ return true;
}
/*==========================================
* Divorce players
* only used if 'partner_id' is offline
*------------------------------------------*/
-int chrif_divorceack(int char_id, int partner_id) {
+bool chrif_divorceack(int char_id, int partner_id) {
struct map_session_data* sd;
int i;
if( !char_id || !partner_id )
- return 0;
+ return false;
- if( ( sd = iMap->charid2sd(char_id) ) != NULL && sd->status.partner_id == partner_id ) {
+ if( ( sd = map->charid2sd(char_id) ) != NULL && sd->status.partner_id == partner_id ) {
sd->status.partner_id = 0;
for(i = 0; i < MAX_INVENTORY; i++)
if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F)
pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER);
}
- if( ( sd = iMap->charid2sd(partner_id) ) != NULL && sd->status.partner_id == char_id ) {
+ if( ( sd = map->charid2sd(partner_id) ) != NULL && sd->status.partner_id == char_id ) {
sd->status.partner_id = 0;
for(i = 0; i < MAX_INVENTORY; i++)
if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F)
pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER);
}
- return 0;
+ return true;
}
/*==========================================
* Removes Baby from parents
*------------------------------------------*/
-int chrif_deadopt(int father_id, int mother_id, int child_id) {
+void chrif_deadopt(int father_id, int mother_id, int child_id) {
struct map_session_data* sd;
int idx = skill->get_index(WE_CALLBABY);
- if( father_id && ( sd = iMap->charid2sd(father_id) ) != NULL && sd->status.child == child_id ) {
+ if( father_id && ( sd = map->charid2sd(father_id) ) != NULL && sd->status.child == child_id ) {
sd->status.child = 0;
sd->status.skill[idx].id = 0;
sd->status.skill[idx].lv = 0;
@@ -976,7 +914,7 @@ int chrif_deadopt(int father_id, int mother_id, int child_id) {
clif->deleteskill(sd,WE_CALLBABY);
}
- if( mother_id && ( sd = iMap->charid2sd(mother_id) ) != NULL && sd->status.child == child_id ) {
+ if( mother_id && ( sd = map->charid2sd(mother_id) ) != NULL && sd->status.child == child_id ) {
sd->status.child = 0;
sd->status.skill[idx].id = 0;
sd->status.skill[idx].lv = 0;
@@ -984,49 +922,54 @@ int chrif_deadopt(int father_id, int mother_id, int child_id) {
clif->deleteskill(sd,WE_CALLBABY);
}
- return 0;
}
/*==========================================
- * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor]
+ * Disconnection of a player (account or char has been banned of has a status, from login or char server) by [Yor]
*------------------------------------------*/
-int chrif_accountban(int fd) {
- int acc;
+void chrif_idbanned(int fd) {
+ int id;
struct map_session_data *sd;
- acc = RFIFOL(fd,2);
+ id = RFIFOL(fd,2);
if ( battle_config.etc_log )
- ShowNotice("chrif_accountban %d.\n", acc);
+ ShowNotice("chrif_idbanned %d.\n", id);
- sd = iMap->id2sd(acc);
+ sd = ( RFIFOB(fd,6) == 2 ) ? map->charid2sd(id) : map->id2sd(id);
- if ( acc < 0 || sd == NULL ) {
- ShowError("chrif_accountban failed - player not online.\n");
- return 0;
+ if ( id < 0 || sd == NULL ) {
+ /* player not online or unknown id, either way no error is necessary (since if you try to ban a offline char it still works) */
+ return;
}
sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
- if (RFIFOB(fd,6) == 0) { // 0: change of statut, 1: ban
- int ret_status = RFIFOL(fd,7); // status or final date of a banishment
- if(0<ret_status && ret_status<=9)
- clif->message(sd->fd, msg_txt(411+ret_status));
- else if(ret_status==100)
- clif->message(sd->fd, msg_txt(421));
- else
- clif->message(sd->fd, msg_txt(420)); //"Your account has not more authorised."
- } else if (RFIFOB(fd,6) == 1) { // 0: change of statut, 1: ban
+ if (RFIFOB(fd,6) == 0) { // 0: change of status
+ int ret_status = RFIFOL(fd,7); // status or final date of a banishment
+ if(0<ret_status && ret_status<=9)
+ clif->message(sd->fd, msg_txt(411+ret_status)); // Message IDs (for search convenience): 412, 413, 414, 415, 416, 417, 418, 419, 420
+ else if(ret_status==100)
+ clif->message(sd->fd, msg_txt(421));
+ else
+ clif->message(sd->fd, msg_txt(420)); //"Your account has not more authorized."
+ } else if (RFIFOB(fd,6) == 1) { // 1: ban
time_t timestamp;
char tmpstr[2048];
timestamp = (time_t)RFIFOL(fd,7); // status or final date of a banishment
strcpy(tmpstr, msg_txt(423)); //"Your account has been banished until "
strftime(tmpstr + strlen(tmpstr), 24, "%d-%m-%Y %H:%M:%S", localtime(&timestamp));
clif->message(sd->fd, tmpstr);
+ } else if (RFIFOB(fd,6) == 2) { // 2: change of status for character
+ time_t timestamp;
+ char tmpstr[2048];
+ timestamp = (time_t)RFIFOL(fd,7); // status or final date of a banishment
+ strcpy(tmpstr, msg_txt(433)); //"This character has been banned until "
+ strftime(tmpstr + strlen(tmpstr), 24, "%d-%m-%Y %H:%M:%S", localtime(&timestamp));
+ clif->message(sd->fd, tmpstr);
}
set_eof(sd->fd); // forced to disconnect for the change
- iMap->quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X]
- return 0;
+ map->quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X]
}
//Disconnect the player out of the game, simple packet
@@ -1035,11 +978,11 @@ int chrif_disconnectplayer(int fd) {
struct map_session_data* sd;
int account_id = RFIFOL(fd, 2);
- sd = iMap->id2sd(account_id);
+ sd = map->id2sd(account_id);
if( sd == NULL ) {
- struct auth_node* auth = chrif_search(account_id);
+ struct auth_node* auth = chrif->search(account_id);
- if( auth != NULL && chrif_auth_delete(account_id, auth->char_id, ST_LOGIN) )
+ if( auth != NULL && chrif->auth_delete(account_id, auth->char_id, ST_LOGIN) )
return 0;
return -1;
@@ -1047,7 +990,7 @@ int chrif_disconnectplayer(int fd) {
if (!sd->fd) { //No connection
if (sd->state.autotrade)
- iMap->quit(sd); //Remove it.
+ map->quit(sd); //Remove it.
//Else we don't remove it because the char should have a timer to remove the player because it force-quit before,
//and we don't want them kicking their previous instance before the 10 secs penalty time passes. [Skotlex]
return 0;
@@ -1072,45 +1015,45 @@ int chrif_updatefamelist(struct map_session_data* sd) {
chrif_check(-1);
switch(sd->class_ & MAPID_UPPERMASK) {
- case MAPID_BLACKSMITH: type = 1; break;
- case MAPID_ALCHEMIST: type = 2; break;
- case MAPID_TAEKWON: type = 3; break;
+ case MAPID_BLACKSMITH: type = RANKTYPE_BLACKSMITH; break;
+ case MAPID_ALCHEMIST: type = RANKTYPE_ALCHEMIST; break;
+ case MAPID_TAEKWON: type = RANKTYPE_TAEKWON; break;
default:
return 0;
}
- WFIFOHEAD(char_fd, 11);
- WFIFOW(char_fd,0) = 0x2b10;
- WFIFOL(char_fd,2) = sd->status.char_id;
- WFIFOL(char_fd,6) = sd->status.fame;
- WFIFOB(char_fd,10) = type;
- WFIFOSET(char_fd,11);
+ WFIFOHEAD(chrif->fd, 11);
+ WFIFOW(chrif->fd,0) = 0x2b10;
+ WFIFOL(chrif->fd,2) = sd->status.char_id;
+ WFIFOL(chrif->fd,6) = sd->status.fame;
+ WFIFOB(chrif->fd,10) = type;
+ WFIFOSET(chrif->fd,11);
return 0;
}
-int chrif_buildfamelist(void) {
- chrif_check(-1);
+bool chrif_buildfamelist(void) {
+ chrif_check(false);
- WFIFOHEAD(char_fd,2);
- WFIFOW(char_fd,0) = 0x2b1a;
- WFIFOSET(char_fd,2);
+ WFIFOHEAD(chrif->fd,2);
+ WFIFOW(chrif->fd,0) = 0x2b1a;
+ WFIFOSET(chrif->fd,2);
- return 0;
+ return true;
}
-int chrif_recvfamelist(int fd) {
+void chrif_recvfamelist(int fd) {
int num, size;
int total = 0, len = 8;
- memset (smith_fame_list, 0, sizeof(smith_fame_list));
- memset (chemist_fame_list, 0, sizeof(chemist_fame_list));
- memset (taekwon_fame_list, 0, sizeof(taekwon_fame_list));
+ memset(pc->smith_fame_list, 0, sizeof(pc->smith_fame_list));
+ memset(pc->chemist_fame_list, 0, sizeof(pc->chemist_fame_list));
+ memset(pc->taekwon_fame_list, 0, sizeof(pc->taekwon_fame_list));
size = RFIFOW(fd, 6); //Blacksmith block size
for (num = 0; len < size && num < MAX_FAME_LIST; num++) {
- memcpy(&smith_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
+ memcpy(&pc->smith_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
len += sizeof(struct fame_list);
}
@@ -1119,7 +1062,7 @@ int chrif_recvfamelist(int fd) {
size = RFIFOW(fd, 4); //Alchemist block size
for (num = 0; len < size && num < MAX_FAME_LIST; num++) {
- memcpy(&chemist_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
+ memcpy(&pc->chemist_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
len += sizeof(struct fame_list);
}
@@ -1128,15 +1071,13 @@ int chrif_recvfamelist(int fd) {
size = RFIFOW(fd, 2); //Total packet length
for (num = 0; len < size && num < MAX_FAME_LIST; num++) {
- memcpy(&taekwon_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
+ memcpy(&pc->taekwon_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
len += sizeof(struct fame_list);
}
total += num;
ShowInfo("Received Fame List of '"CL_WHITE"%d"CL_RESET"' characters.\n", total);
-
- return 0;
}
/// fame ranking update confirmation
@@ -1146,9 +1087,9 @@ int chrif_updatefamelist_ack(int fd) {
uint8 index;
switch (RFIFOB(fd,2)) {
- case 1: list = smith_fame_list; break;
- case 2: list = chemist_fame_list; break;
- case 3: list = taekwon_fame_list; break;
+ case RANKTYPE_BLACKSMITH: list = pc->smith_fame_list; break;
+ case RANKTYPE_ALCHEMIST: list = pc->chemist_fame_list; break;
+ case RANKTYPE_TAEKWON: list = pc->taekwon_fame_list; break;
default: return 0;
}
@@ -1162,31 +1103,31 @@ int chrif_updatefamelist_ack(int fd) {
return 1;
}
-int chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the player and sends it to the char-server for saving. [Skotlex]
+bool chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the player and sends it to the char-server for saving. [Skotlex]
#ifdef ENABLE_SC_SAVING
int i, count=0;
- unsigned int tick;
+ int64 tick;
struct status_change_data data;
struct status_change *sc = &sd->sc;
- const struct TimerData *timer;
+ const struct TimerData *td;
- chrif_check(-1);
- tick = iTimer->gettick();
+ chrif_check(false);
+ tick = timer->gettick();
- WFIFOHEAD(char_fd, 14 + SC_MAX*sizeof(struct status_change_data));
- WFIFOW(char_fd,0) = 0x2b1c;
- WFIFOL(char_fd,4) = sd->status.account_id;
- WFIFOL(char_fd,8) = sd->status.char_id;
+ WFIFOHEAD(chrif->fd, 14 + SC_MAX*sizeof(struct status_change_data));
+ WFIFOW(chrif->fd,0) = 0x2b1c;
+ WFIFOL(chrif->fd,4) = sd->status.account_id;
+ WFIFOL(chrif->fd,8) = sd->status.char_id;
for (i = 0; i < SC_MAX; i++) {
if (!sc->data[i])
continue;
if (sc->data[i]->timer != INVALID_TIMER) {
- timer = iTimer->get_timer(sc->data[i]->timer);
- if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0)
+ td = timer->get(sc->data[i]->timer);
+ if (td == NULL || td->func != status->change_timer || DIFF_TICK(td->tick,tick) < 0)
continue;
- data.tick = DIFF_TICK(timer->tick,tick); //Duration that is left before ending.
+ data.tick = DIFF_TICK32(td->tick,tick); //Duration that is left before ending.
} else
data.tick = -1; //Infinite duration
data.type = i;
@@ -1194,24 +1135,24 @@ int chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the
data.val2 = sc->data[i]->val2;
data.val3 = sc->data[i]->val3;
data.val4 = sc->data[i]->val4;
- memcpy(WFIFOP(char_fd,14 +count*sizeof(struct status_change_data)),
+ memcpy(WFIFOP(chrif->fd,14 +count*sizeof(struct status_change_data)),
&data, sizeof(struct status_change_data));
count++;
}
if (count == 0)
- return 0; //Nothing to save.
+ return true; //Nothing to save. | Everything was as successful as if there was something to save.
- WFIFOW(char_fd,12) = count;
- WFIFOW(char_fd,2) = 14 +count*sizeof(struct status_change_data); //Total packet size
- WFIFOSET(char_fd,WFIFOW(char_fd,2));
+ WFIFOW(chrif->fd,12) = count;
+ WFIFOW(chrif->fd,2) = 14 +count*sizeof(struct status_change_data); //Total packet size
+ WFIFOSET(chrif->fd,WFIFOW(chrif->fd,2));
#endif
- return 0;
+ return true;
}
//Retrieve and load sc_data for a player. [Skotlex]
-int chrif_load_scdata(int fd) {
+bool chrif_load_scdata(int fd) {
#ifdef ENABLE_SC_SAVING
struct map_session_data *sd;
@@ -1221,127 +1162,116 @@ int chrif_load_scdata(int fd) {
aid = RFIFOL(fd,4); //Player Account ID
cid = RFIFOL(fd,8); //Player Char ID
- sd = iMap->id2sd(aid);
+ sd = map->id2sd(aid);
if ( !sd ) {
ShowError("chrif_load_scdata: Player of AID %d not found!\n", aid);
- return -1;
+ return false;
}
if ( sd->status.char_id != cid ) {
ShowError("chrif_load_scdata: Receiving data for account %d, char id does not matches (%d != %d)!\n", aid, sd->status.char_id, cid);
- return -1;
+ return false;
}
count = RFIFOW(fd,12); //sc_count
for (i = 0; i < count; i++) {
data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data));
- status_change_start(&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 15);
+ status->change_start(NULL, &sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 15);
}
+
+ pc->scdata_received(sd);
#endif
- return 0;
+ return true;
}
/*==========================================
* Send rates to char server [Wizputer]
* S 2b16 <base rate>.L <job rate>.L <drop rate>.L
*------------------------------------------*/
-int chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate) {
- chrif_check(-1);
+bool chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate) {
+ chrif_check(false);
- WFIFOHEAD(char_fd,14);
- WFIFOW(char_fd,0) = 0x2b16;
- WFIFOL(char_fd,2) = base_rate;
- WFIFOL(char_fd,6) = job_rate;
- WFIFOL(char_fd,10) = drop_rate;
- WFIFOSET(char_fd,14);
+ WFIFOHEAD(chrif->fd,14);
+ WFIFOW(chrif->fd,0) = 0x2b16;
+ WFIFOL(chrif->fd,2) = base_rate;
+ WFIFOL(chrif->fd,6) = job_rate;
+ WFIFOL(chrif->fd,10) = drop_rate;
+ WFIFOSET(chrif->fd,14);
- return 0;
+ return true;
}
/*=========================================
- * Tell char-server charcter disconnected [Wizputer]
+ * Tell char-server character disconnected [Wizputer]
*-----------------------------------------*/
-int chrif_char_offline(struct map_session_data *sd) {
- chrif_check(-1);
-
- WFIFOHEAD(char_fd,10);
- WFIFOW(char_fd,0) = 0x2b17;
- WFIFOL(char_fd,2) = sd->status.char_id;
- WFIFOL(char_fd,6) = sd->status.account_id;
- WFIFOSET(char_fd,10);
+bool chrif_char_offline_nsd(int account_id, int char_id) {
+ chrif_check(false);
- return 0;
-}
-int chrif_char_offline_nsd(int account_id, int char_id) {
- chrif_check(-1);
-
- WFIFOHEAD(char_fd,10);
- WFIFOW(char_fd,0) = 0x2b17;
- WFIFOL(char_fd,2) = char_id;
- WFIFOL(char_fd,6) = account_id;
- WFIFOSET(char_fd,10);
+ WFIFOHEAD(chrif->fd,10);
+ WFIFOW(chrif->fd,0) = 0x2b17;
+ WFIFOL(chrif->fd,2) = char_id;
+ WFIFOL(chrif->fd,6) = account_id;
+ WFIFOSET(chrif->fd,10);
- return 0;
+ return true;
}
/*=========================================
* Tell char-server to reset all chars offline [Wizputer]
*-----------------------------------------*/
-int chrif_flush_fifo(void) {
- chrif_check(-1);
+bool chrif_flush(void) {
+ chrif_check(false);
- set_nonblocking(char_fd, 0);
+ set_nonblocking(chrif->fd, 0);
flush_fifos();
- set_nonblocking(char_fd, 1);
+ set_nonblocking(chrif->fd, 1);
- return 0;
+ return true;
}
/*=========================================
* Tell char-server to reset all chars offline [Wizputer]
*-----------------------------------------*/
-int chrif_char_reset_offline(void) {
- chrif_check(-1);
+bool chrif_char_reset_offline(void) {
+ chrif_check(false);
- WFIFOHEAD(char_fd,2);
- WFIFOW(char_fd,0) = 0x2b18;
- WFIFOSET(char_fd,2);
+ WFIFOHEAD(chrif->fd,2);
+ WFIFOW(chrif->fd,0) = 0x2b18;
+ WFIFOSET(chrif->fd,2);
- return 0;
+ return true;
}
/*=========================================
- * Tell char-server charcter is online [Wizputer]
+ * Tell char-server character is online [Wizputer]
*-----------------------------------------*/
+bool chrif_char_online(struct map_session_data *sd) {
+ chrif_check(false);
-int chrif_char_online(struct map_session_data *sd) {
- chrif_check(-1);
-
- WFIFOHEAD(char_fd,10);
- WFIFOW(char_fd,0) = 0x2b19;
- WFIFOL(char_fd,2) = sd->status.char_id;
- WFIFOL(char_fd,6) = sd->status.account_id;
- WFIFOSET(char_fd,10);
+ WFIFOHEAD(chrif->fd,10);
+ WFIFOW(chrif->fd,0) = 0x2b19;
+ WFIFOL(chrif->fd,2) = sd->status.char_id;
+ WFIFOL(chrif->fd,6) = sd->status.account_id;
+ WFIFOSET(chrif->fd,10);
- return 0;
+ return true;
}
-
/// Called when the connection to Char Server is disconnected.
void chrif_on_disconnect(void) {
- if( chrif_connected != 1 )
+ if( chrif->connected != 1 )
ShowWarning("Connection to Char Server lost.\n\n");
- chrif_connected = 0;
+ chrif->connected = 0;
- other_mapserver_count = 0; //Reset counter. We receive ALL maps from all map-servers on reconnect.
- iMap->eraseallipport();
+ chrif->other_mapserver_count = 0; //Reset counter. We receive ALL maps from all map-servers on reconnect.
+ map->eraseallipport();
//Attempt to reconnect in a second. [Skotlex]
- iTimer->add_timer(iTimer->gettick() + 1000, check_connect_char_server, 0, 0);
+ timer->add(timer->gettick() + 1000, chrif->check_connect_char_server, 0, 0);
}
@@ -1350,10 +1280,10 @@ void chrif_update_ip(int fd) {
WFIFOHEAD(fd,6);
- new_ip = host2ip(char_ip_str);
+ new_ip = host2ip(chrif->ip_str);
- if (new_ip && new_ip != char_ip)
- char_ip = new_ip; //Update char_ip
+ if (new_ip && new_ip != chrif->ip)
+ chrif->ip = new_ip; //Update chrif->ip
new_ip = clif->refresh_ip();
@@ -1365,7 +1295,7 @@ void chrif_update_ip(int fd) {
WFIFOSET(fd,6);
}
-// pings the charserver
+// pings the charserver ( since on-demand flag.ping was introduced, shouldn't this be dropped? only wasting traffic and processing [Ind])
void chrif_keepalive(int fd) {
WFIFOHEAD(fd,2);
WFIFOW(fd,0) = 0x2b23;
@@ -1377,13 +1307,16 @@ void chrif_keepalive_ack(int fd) {
void chrif_skillid2idx(int fd) {
int i, count = 0;
- if( fd == 0 ) fd = char_fd;
+ if( fd == 0 ) fd = chrif->fd;
+
+ if( !session_isValid(fd) )
+ return;
WFIFOHEAD(fd,4 + (MAX_SKILL * 4));
WFIFOW(fd,0) = 0x2b0b;
for(i = 0; i < MAX_SKILL; i++) {
- if( skill_db[i].nameid ) {
- WFIFOW(fd, 4 + (count*4)) = skill_db[i].nameid;
+ if( skill->db[i].nameid ) {
+ WFIFOW(fd, 4 + (count*4)) = skill->db[i].nameid;
WFIFOW(fd, 6 + (count*4)) = i;
count++;
}
@@ -1396,10 +1329,10 @@ void chrif_skillid2idx(int fd) {
*
*------------------------------------------*/
int chrif_parse(int fd) {
- int packet_len, cmd;
+ int packet_len, cmd, r;
// only process data from the char-server
- if ( fd != char_fd ) {
+ if ( fd != chrif->fd ) {
ShowDebug("chrif_parse: Disconnecting invalid session #%d (is not the char-server)\n", fd);
do_close(fd);
return 0;
@@ -1407,33 +1340,42 @@ int chrif_parse(int fd) {
if ( session[fd]->flag.eof ) {
do_close(fd);
- char_fd = -1;
- chrif_on_disconnect();
+ chrif->fd = -1;
+ chrif->on_disconnect();
return 0;
} else if ( session[fd]->flag.ping ) {/* we've reached stall time */
- if( DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2) ) {/* we can't wait any longer */
+ if( DIFF_TICK(sockt->last_tick, session[fd]->rdata_tick) > (sockt->stall_time * 2) ) {/* we can't wait any longer */
set_eof(fd);
return 0;
} else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */
- chrif_keepalive(fd);
+ chrif->keepalive(fd);
session[fd]->flag.ping = 2;
}
}
while ( RFIFOREST(fd) >= 2 ) {
+
+ if( HPM->packetsc[hpChrif_Parse] ) {
+ if( (r = HPM->parse_packets(fd,hpChrif_Parse)) ) {
+ if( r == 1 ) continue;
+ if( r == 2 ) return 0;
+ }
+ }
+
cmd = RFIFOW(fd,0);
- if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) {
- int r = intif_parse(fd); // Passed on to the intif
+
+ if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(chrif->packet_len_table) || chrif->packet_len_table[cmd-0x2af8] == 0) {
+ r = intif->parse(fd); // Passed on to the intif
- if (r == 1) continue; // Treated in intif
+ if (r == 1) continue; // Treated in intif
if (r == 2) return 0; // Didn't have enough data (len==-1)
- ShowWarning("chrif_parse: session #%d, intif_parse failed (unrecognized command 0x%.4x).\n", fd, cmd);
+ ShowWarning("chrif_parse: session #%d, intif->parse failed (unrecognized command 0x%.4x).\n", fd, cmd);
set_eof(fd);
return 0;
}
- if ( ( packet_len = packet_len_table[cmd-0x2af8] ) == -1) { // dynamic-length packet, second WORD holds the length
+ if ( ( packet_len = chrif->packet_len_table[cmd-0x2af8] ) == -1) { // dynamic-length packet, second WORD holds the length
if (RFIFOREST(fd) < 4)
return 0;
packet_len = RFIFOW(fd,2);
@@ -1445,49 +1387,48 @@ int chrif_parse(int fd) {
//ShowDebug("Received packet 0x%4x (%d bytes) from char-server (connection %d)\n", RFIFOW(fd,0), packet_len, fd);
switch(cmd) {
- case 0x2af9: chrif_connectack(fd); break;
- case 0x2afb: chrif_sendmapack(fd); break;
- case 0x2afd: chrif_authok(fd); break;
- case 0x2b00: iMap->setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break;
+ case 0x2af9: chrif->connectack(fd); break;
+ case 0x2afb: chrif->sendmapack(fd); break;
+ case 0x2afd: chrif->authok(fd); break;
+ case 0x2b00: map->setusers(RFIFOL(fd,2)); chrif->keepalive(fd); break;
case 0x2b03: clif->charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break;
- case 0x2b04: chrif_recvmap(fd); break;
- case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break;
- case 0x2b09: iMap->addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break;
- case 0x2b0a: socket_datasync(fd, false); break;
- case 0x2b0d: chrif_changedsex(fd); break;
- case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break;
- case 0x2b12: chrif_divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break;
- case 0x2b14: chrif_accountban(fd); break;
- case 0x2b1b: chrif_recvfamelist(fd); break;
- case 0x2b1d: chrif_load_scdata(fd); break;
- case 0x2b1e: chrif_update_ip(fd); break;
- case 0x2b1f: chrif_disconnectplayer(fd); break;
- case 0x2b20: chrif_removemap(fd); break;
- case 0x2b21: chrif_save_ack(fd); break;
- case 0x2b22: chrif_updatefamelist_ack(fd); break;
- case 0x2b24: chrif_keepalive_ack(fd); break;
- case 0x2b25: chrif_deadopt(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
- case 0x2b27: chrif_authfail(fd); break;
+ case 0x2b04: chrif->recvmap(fd); break;
+ case 0x2b06: chrif->changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break;
+ case 0x2b09: map->addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break;
+ case 0x2b0a: sockt->datasync(fd, false); break;
+ case 0x2b0d: chrif->changedsex(fd); break;
+ case 0x2b0f: chrif->char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break;
+ case 0x2b12: chrif->divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break;
+ case 0x2b14: chrif->idbanned(fd); break;
+ case 0x2b1b: chrif->recvfamelist(fd); break;
+ case 0x2b1d: chrif->load_scdata(fd); break;
+ case 0x2b1e: chrif->update_ip(fd); break;
+ case 0x2b1f: chrif->disconnectplayer(fd); break;
+ case 0x2b20: chrif->removemap(fd); break;
+ case 0x2b21: chrif->save_ack(fd); break;
+ case 0x2b22: chrif->updatefamelist_ack(fd); break;
+ case 0x2b24: chrif->keepalive_ack(fd); break;
+ case 0x2b25: chrif->deadopt(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
+ case 0x2b27: chrif->authfail(fd); break;
default:
ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd);
set_eof(fd);
return 0;
}
- if ( fd == char_fd ) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex]
+ if ( fd == chrif->fd ) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex]
RFIFOSKIP(fd, packet_len);
}
return 0;
}
-// unused
-int send_usercount_tochar(int tid, unsigned int tick, int id, intptr_t data) {
+int send_usercount_tochar(int tid, int64 tick, int id, intptr_t data) {
chrif_check(-1);
- WFIFOHEAD(char_fd,4);
- WFIFOW(char_fd,0) = 0x2afe;
- WFIFOW(char_fd,2) = iMap->usercount();
- WFIFOSET(char_fd,4);
+ WFIFOHEAD(chrif->fd,4);
+ WFIFOW(chrif->fd,0) = 0x2afe;
+ WFIFOW(chrif->fd,2) = map->usercount();
+ WFIFOSET(chrif->fd,4);
return 0;
}
@@ -1495,66 +1436,66 @@ int send_usercount_tochar(int tid, unsigned int tick, int id, intptr_t data) {
* timerFunction
* Send to char the number of client connected to map
*------------------------------------------*/
-int send_users_tochar(void) {
+bool send_users_tochar(void) {
int users = 0, i = 0;
struct map_session_data* sd;
struct s_mapiterator* iter;
- chrif_check(-1);
+ chrif_check(false);
- users = iMap->usercount();
+ users = map->usercount();
- WFIFOHEAD(char_fd, 6+8*users);
- WFIFOW(char_fd,0) = 0x2aff;
+ WFIFOHEAD(chrif->fd, 6+8*users);
+ WFIFOW(chrif->fd,0) = 0x2aff;
iter = mapit_getallusers();
for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) {
- WFIFOL(char_fd,6+8*i) = sd->status.account_id;
- WFIFOL(char_fd,6+8*i+4) = sd->status.char_id;
+ WFIFOL(chrif->fd,6+8*i) = sd->status.account_id;
+ WFIFOL(chrif->fd,6+8*i+4) = sd->status.char_id;
i++;
}
mapit->free(iter);
- WFIFOW(char_fd,2) = 6 + 8*users;
- WFIFOW(char_fd,4) = users;
- WFIFOSET(char_fd, 6+8*users);
+ WFIFOW(chrif->fd,2) = 6 + 8*users;
+ WFIFOW(chrif->fd,4) = users;
+ WFIFOSET(chrif->fd, 6+8*users);
- return 0;
+ return true;
}
/*==========================================
* timerFunction
- * Chk the connection to char server, (if it down)
+ * Check the connection to char server, (if it down)
*------------------------------------------*/
-static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_t data) {
+int check_connect_char_server(int tid, int64 tick, int id, intptr_t data) {
static int displayed = 0;
- if ( char_fd <= 0 || session[char_fd] == NULL ) {
+ if ( chrif->fd <= 0 || session[chrif->fd] == NULL ) {
if ( !displayed ) {
ShowStatus("Attempting to connect to Char Server. Please wait.\n");
displayed = 1;
}
- chrif_state = 0;
+ chrif->state = 0;
- if ( ( char_fd = make_connection(char_ip, char_port,NULL) ) == -1) //Attempt to connect later. [Skotlex]
+ if ( ( chrif->fd = make_connection(chrif->ip, chrif->port,NULL) ) == -1) //Attempt to connect later. [Skotlex]
return 0;
- session[char_fd]->func_parse = chrif_parse;
- session[char_fd]->flag.server = 1;
- realloc_fifo(char_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
+ session[chrif->fd]->func_parse = chrif->parse;
+ session[chrif->fd]->flag.server = 1;
+ realloc_fifo(chrif->fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
- chrif_connect(char_fd);
- chrif_connected = (chrif_state == 2);
- srvinfo = 0;
+ chrif->connect(chrif->fd);
+ chrif->connected = (chrif->state == 2);
+ chrif->srvinfo = 0;
} else {
- if (srvinfo == 0) {
- chrif_ragsrvinfo(battle_config.base_exp_rate, battle_config.job_exp_rate, battle_config.item_rate_common);
- srvinfo = 1;
+ if (chrif->srvinfo == 0) {
+ chrif->ragsrvinfo(battle_config.base_exp_rate, battle_config.job_exp_rate, battle_config.item_rate_common);
+ chrif->srvinfo = 1;
}
}
- if ( chrif_isconnected() )
+ if ( chrif->isconnected() )
displayed = 0;
return 0;
}
@@ -1562,89 +1503,254 @@ static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_
/*==========================================
* Asks char server to remove friend_id from the friend list of char_id
*------------------------------------------*/
-int chrif_removefriend(int char_id, int friend_id) {
+bool chrif_removefriend(int char_id, int friend_id) {
- chrif_check(-1);
+ chrif_check(false);
- WFIFOHEAD(char_fd,10);
- WFIFOW(char_fd,0) = 0x2b07;
- WFIFOL(char_fd,2) = char_id;
- WFIFOL(char_fd,6) = friend_id;
- WFIFOSET(char_fd,10);
+ WFIFOHEAD(chrif->fd,10);
+ WFIFOW(chrif->fd,0) = 0x2b07;
+ WFIFOL(chrif->fd,2) = char_id;
+ WFIFOL(chrif->fd,6) = friend_id;
+ WFIFOSET(chrif->fd,10);
- return 0;
+ return true;
}
void chrif_send_report(char* buf, int len) {
#ifndef STATS_OPT_OUT
- if( char_fd ) {
- WFIFOHEAD(char_fd,len + 2);
+ if( chrif->fd > 0 ) {
+ WFIFOHEAD(chrif->fd,len + 2);
- WFIFOW(char_fd,0) = 0x3008;
+ WFIFOW(chrif->fd,0) = 0x3008;
- memcpy(WFIFOP(char_fd,2), buf, len);
+ memcpy(WFIFOP(chrif->fd,2), buf, len);
- WFIFOSET(char_fd,len + 2);
+ WFIFOSET(chrif->fd,len + 2);
- flush_fifo(char_fd); /* ensure it's sent now. */
+ flush_fifo(chrif->fd); /* ensure it's sent now. */
}
#endif
}
/**
+ * Sends a single scdata for saving into char server, meant to ensure integrity of duration-less conditions
+ **/
+void chrif_save_scdata_single(int account_id, int char_id, short type, struct status_change_entry *sce) {
+
+ if( !chrif->isconnected() )
+ return;
+
+ WFIFOHEAD(chrif->fd, 28);
+
+ WFIFOW(chrif->fd, 0) = 0x2740;
+ WFIFOL(chrif->fd, 2) = account_id;
+ WFIFOL(chrif->fd, 6) = char_id;
+ WFIFOW(chrif->fd, 10) = type;
+ WFIFOL(chrif->fd, 12) = sce->val1;
+ WFIFOL(chrif->fd, 16) = sce->val2;
+ WFIFOL(chrif->fd, 20) = sce->val3;
+ WFIFOL(chrif->fd, 24) = sce->val4;
+
+ WFIFOSET(chrif->fd, 28);
+
+}
+/**
+ * Sends a single scdata deletion request into char server, meant to ensure integrity of duration-less conditions
+ **/
+void chrif_del_scdata_single(int account_id, int char_id, short type) {
+
+ if( !chrif->isconnected() ) {
+ ShowError("MAYDAY! failed to delete status %d from CID:%d/AID:%d\n",type,char_id,account_id);
+ return;
+ }
+
+
+ WFIFOHEAD(chrif->fd, 12);
+
+ WFIFOW(chrif->fd, 0) = 0x2741;
+ WFIFOL(chrif->fd, 2) = account_id;
+ WFIFOL(chrif->fd, 6) = char_id;
+ WFIFOW(chrif->fd, 10) = type;
+
+ WFIFOSET(chrif->fd, 12);
+
+}
+
+/** `
* @see DBApply
*/
int auth_db_final(DBKey key, DBData *data, va_list ap) {
struct auth_node *node = DB->data2ptr(data);
- if (node->char_dat)
- aFree(node->char_dat);
-
- if (node->sd)
+ if (node->sd) {
+
+ if( node->sd->regs.vars )
+ node->sd->regs.vars->destroy(node->sd->regs.vars, script->reg_destroy);
+
+ if( node->sd->regs.arrays )
+ node->sd->regs.arrays->destroy(node->sd->regs.arrays, script->array_free_db);
+
aFree(node->sd);
-
- ers_free(auth_db_ers, node);
-
+ }
+ ers_free(chrif->auth_db_ers, node);
+
return 0;
}
/*==========================================
* Destructor
*------------------------------------------*/
-int do_final_chrif(void) {
+void do_final_chrif(void) {
- if( char_fd != -1 ) {
- do_close(char_fd);
- char_fd = -1;
+ if( chrif->fd != -1 ) {
+ do_close(chrif->fd);
+ chrif->fd = -1;
}
- auth_db->destroy(auth_db, auth_db_final);
+ chrif->auth_db->destroy(chrif->auth_db, chrif->auth_db_final);
- ers_destroy(auth_db_ers);
-
- return 0;
+ ers_destroy(chrif->auth_db_ers);
}
/*==========================================
*
*------------------------------------------*/
-int do_init_chrif(void) {
-
- auth_db = idb_alloc(DB_OPT_BASE);
- auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE);
+void do_init_chrif(bool minimal) {
+ if (minimal)
+ return;
+
+ chrif->auth_db = idb_alloc(DB_OPT_BASE);
+ chrif->auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE);
- iTimer->add_timer_func_list(check_connect_char_server, "check_connect_char_server");
- iTimer->add_timer_func_list(auth_db_cleanup, "auth_db_cleanup");
+ timer->add_func_list(chrif->check_connect_char_server, "check_connect_char_server");
+ timer->add_func_list(chrif->auth_db_cleanup, "auth_db_cleanup");
+ timer->add_func_list(chrif->send_usercount_tochar, "send_usercount_tochar");
// establish map-char connection if not present
- iTimer->add_timer_interval(iTimer->gettick() + 1000, check_connect_char_server, 0, 0, 10 * 1000);
+ timer->add_interval(timer->gettick() + 1000, chrif->check_connect_char_server, 0, 0, 10 * 1000);
// wipe stale data for timed-out client connection requests
- iTimer->add_timer_interval(iTimer->gettick() + 1000, auth_db_cleanup, 0, 0, 30 * 1000);
+ timer->add_interval(timer->gettick() + 1000, chrif->auth_db_cleanup, 0, 0, 30 * 1000);
// send the user count every 10 seconds, to hide the charserver's online counting problem
- iTimer->add_timer_interval(iTimer->gettick() + 1000, send_usercount_tochar, 0, 0, UPDATE_INTERVAL);
-
- return 0;
+ timer->add_interval(timer->gettick() + 1000, chrif->send_usercount_tochar, 0, 0, UPDATE_INTERVAL);
+}
+
+
+/*=====================================
+* Default Functions : chrif.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+void chrif_defaults(void) {
+ const int packet_len_table[CHRIF_PACKET_LEN_TABLE_SIZE] = { // U - used, F - free
+ 60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
+ 6,-1,18, 7,-1,39,30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
+ 6,30, -1, 0,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
+ 11,10,10, 0,11, 0,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, F->2b15, U->2b16, U->2b17
+ 2,10, 2,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
+ -1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27
+ };
+
+ chrif = &chrif_s;
+
+ /* vars */
+ chrif->connected = 0;
+ chrif->other_mapserver_count = 0;
+
+ memcpy(chrif->packet_len_table,&packet_len_table,sizeof(chrif->packet_len_table));
+ chrif->fd = -1;
+ chrif->srvinfo = 0;
+ memset(chrif->ip_str,0,sizeof(chrif->ip_str));
+ chrif->ip = 0;
+ chrif->port = 6121;
+ memset(chrif->userid,0,sizeof(chrif->userid));
+ memset(chrif->passwd,0,sizeof(chrif->passwd));
+ chrif->state = 0;
+
+ /* */
+ chrif->auth_db = NULL;
+ chrif->auth_db_ers = NULL;
+ /* */
+ chrif->init = do_init_chrif;
+ chrif->final = do_final_chrif;
+
+ /* funcs */
+ chrif->setuserid = chrif_setuserid;
+ chrif->setpasswd = chrif_setpasswd;
+ chrif->checkdefaultlogin = chrif_checkdefaultlogin;
+ chrif->setip = chrif_setip;
+ chrif->setport = chrif_setport;
+
+ chrif->isconnected = chrif_isconnected;
+ chrif->check_shutdown = chrif_check_shutdown;
+
+ chrif->search = chrif_search;
+ chrif->auth_check = chrif_auth_check;
+ chrif->auth_delete = chrif_auth_delete;
+ chrif->auth_finished = chrif_auth_finished;
+
+ chrif->authreq = chrif_authreq;
+ chrif->authok = chrif_authok;
+ chrif->scdata_request = chrif_scdata_request;
+ chrif->save = chrif_save;
+ chrif->charselectreq = chrif_charselectreq;
+ chrif->changemapserver = chrif_changemapserver;
+
+ chrif->searchcharid = chrif_searchcharid;
+ chrif->changeemail = chrif_changeemail;
+ chrif->char_ask_name = chrif_char_ask_name;
+ chrif->updatefamelist = chrif_updatefamelist;
+ chrif->buildfamelist = chrif_buildfamelist;
+ chrif->save_scdata = chrif_save_scdata;
+ chrif->ragsrvinfo = chrif_ragsrvinfo;
+ chrif->char_offline_nsd = chrif_char_offline_nsd;
+ chrif->char_reset_offline = chrif_char_reset_offline;
+ chrif->send_users_tochar = send_users_tochar;
+ chrif->char_online = chrif_char_online;
+ chrif->changesex = chrif_changesex;
+ //chrif->chardisconnect = chrif_chardisconnect;
+ chrif->divorce = chrif_divorce;
+
+ chrif->removefriend = chrif_removefriend;
+ chrif->send_report = chrif_send_report;
+
+ chrif->flush = chrif_flush;
+ chrif->skillid2idx = chrif_skillid2idx;
+
+ chrif->sd_to_auth = chrif_sd_to_auth;
+ chrif->check_connect_char_server = check_connect_char_server;
+ chrif->auth_logout = chrif_auth_logout;
+ chrif->save_ack = chrif_save_ack;
+ chrif->reconnect = chrif_reconnect;
+ chrif->auth_db_cleanup_sub = auth_db_cleanup_sub;
+ chrif->char_ask_name_answer = chrif_char_ask_name_answer;
+ chrif->auth_db_final = auth_db_final;
+ chrif->send_usercount_tochar = send_usercount_tochar;
+ chrif->auth_db_cleanup = auth_db_cleanup;
+
+ chrif->connect = chrif_connect;
+ chrif->connectack = chrif_connectack;
+ chrif->sendmap = chrif_sendmap;
+ chrif->sendmapack = chrif_sendmapack;
+ chrif->recvmap = chrif_recvmap;
+ chrif->changemapserverack = chrif_changemapserverack;
+ chrif->changedsex = chrif_changedsex;
+ chrif->divorceack = chrif_divorceack;
+ chrif->idbanned = chrif_idbanned;
+ chrif->recvfamelist = chrif_recvfamelist;
+ chrif->load_scdata = chrif_load_scdata;
+ chrif->update_ip = chrif_update_ip;
+ chrif->disconnectplayer = chrif_disconnectplayer;
+ chrif->removemap = chrif_removemap;
+ chrif->updatefamelist_ack = chrif_updatefamelist_ack;
+ chrif->keepalive = chrif_keepalive;
+ chrif->keepalive_ack = chrif_keepalive_ack;
+ chrif->deadopt = chrif_deadopt;
+ chrif->authfail = chrif_authfail;
+ chrif->on_ready = chrif_on_ready;
+ chrif->on_disconnect = chrif_on_disconnect;
+ chrif->parse = chrif_parse;
+ chrif->save_scdata_single = chrif_save_scdata_single;
+ chrif->del_scdata_single = chrif_del_scdata_single;
}
-
diff --git a/src/map/chrif.h b/src/map/chrif.h
index 9c7142905..11baaf5ff 100644
--- a/src/map/chrif.h
+++ b/src/map/chrif.h
@@ -2,70 +2,156 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _CHRIF_H_
-#define _CHRIF_H_
+#ifndef MAP_CHRIF_H
+#define MAP_CHRIF_H
-#include "../common/cbasetypes.h"
#include <time.h>
+#include "map.h" //TBL_stuff
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+
+struct status_change_entry;
+
+/**
+ * Defines
+ **/
+//Interval at which map server updates online listing. [Valaris]
+#define CHECK_INTERVAL 3600000
+//Interval at which map server sends number of connected users. [Skotlex]
+#define UPDATE_INTERVAL 10000
+
+#define CHRIF_PACKET_LEN_TABLE_SIZE 0x3d
+
+/**
+ * Enumerations
+ **/
enum sd_state { ST_LOGIN, ST_LOGOUT, ST_MAPCHANGE };
+
+/**
+ * Structures
+ **/
struct auth_node {
int account_id, char_id;
int login_id1, login_id2, sex, fd;
- time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
- struct map_session_data *sd; //Data from logged on char.
- struct mmo_charstatus *char_dat; //Data from char server.
- unsigned int node_created; //timestamp for node timeouts
- enum sd_state state; //To track whether player was login in/out or changing maps.
+ time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+ struct map_session_data *sd; //Data from logged on char.
+ int64 node_created; //timestamp for node timeouts
+ enum sd_state state; //To track whether player was login in/out or changing maps.
};
-void chrif_setuserid(char* id);
-void chrif_setpasswd(char* pwd);
-void chrif_checkdefaultlogin(void);
-int chrif_setip(const char* ip);
-void chrif_setport(uint16 port);
-
-int chrif_isconnected(void);
-void chrif_check_shutdown(void);
-
-extern int chrif_connected;
-extern int other_mapserver_count;
+/*=====================================
+* Interface : chrif.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+struct chrif_interface {
-struct auth_node* chrif_search(int account_id);
-struct auth_node* chrif_auth_check(int account_id, int char_id, enum sd_state state);
-bool chrif_auth_delete(int account_id, int char_id, enum sd_state state);
-bool chrif_auth_finished(struct map_session_data* sd);
+ /* vars */
+
+ int connected;
+ int other_mapserver_count; //Holds count of how many other map servers are online (apart of this instance) [Skotlex]
-void chrif_authreq(struct map_session_data* sd);
-void chrif_authok(int fd);
-int chrif_scdata_request(int account_id, int char_id);
-int chrif_save(struct map_session_data* sd, int flag);
-int chrif_charselectreq(struct map_session_data* sd, uint32 s_ip);
-int chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port);
+ /* */
+ struct eri *auth_db_ers; //For re-utilizing player login structures.
+ DBMap* auth_db; // int id -> struct auth_node*
+ /* */
+ int packet_len_table[CHRIF_PACKET_LEN_TABLE_SIZE];
+ int fd;
+ int srvinfo;
+ char ip_str[128];
+ uint32 ip;
+ uint16 port;
+ char userid[NAME_LENGTH], passwd[NAME_LENGTH];
+ int state;
+ /* */
+ void (*init) (bool minimal);
+ void (*final) (void);
+ /* funcs */
+ void (*setuserid) (char* id);
+ void (*setpasswd) (char* pwd);
+ void (*checkdefaultlogin) (void);
+ bool (*setip) (const char* ip);
+ void (*setport) (uint16 port);
+
+ int (*isconnected) (void);
+ void (*check_shutdown) (void);
+
+ struct auth_node* (*search) (int account_id);
+ struct auth_node* (*auth_check) (int account_id, int char_id, enum sd_state state);
+ bool (*auth_delete) (int account_id, int char_id, enum sd_state state);
+ bool (*auth_finished) (struct map_session_data* sd);
+
+ void (*authreq) (struct map_session_data* sd, bool hstandalone);
+ void (*authok) (int fd);
+ bool (*scdata_request) (int account_id, int char_id);
+ bool (*save) (struct map_session_data* sd, int flag);
+ bool (*charselectreq) (struct map_session_data* sd, uint32 s_ip);
+ bool (*changemapserver) (struct map_session_data* sd, uint32 ip, uint16 port);
+
+ bool (*searchcharid) (int char_id);
+ bool (*changeemail) (int id, const char *actual_email, const char *new_email);
+ bool (*char_ask_name) (int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second);
+ int (*updatefamelist) (struct map_session_data *sd);
+ bool (*buildfamelist) (void);
+ bool (*save_scdata) (struct map_session_data *sd);
+ bool (*ragsrvinfo) (int base_rate,int job_rate, int drop_rate);
+ //int (*char_offline) (struct map_session_data *sd);
+ bool (*char_offline_nsd) (int account_id, int char_id);
+ bool (*char_reset_offline) (void);
+ bool (*send_users_tochar) (void);
+ bool (*char_online) (struct map_session_data *sd);
+ bool (*changesex) (struct map_session_data *sd);
+ //int (*chardisconnect) (struct map_session_data *sd); // FIXME: Commented out in clif.c, function does not exist
+ bool (*divorce) (int partner_id1, int partner_id2);
+
+ bool (*removefriend) (int char_id, int friend_id);
+ void (*send_report) (char* buf, int len);
+
+ bool (*flush) (void);
+ void (*skillid2idx) (int fd);
+
+ bool (*sd_to_auth) (TBL_PC* sd, enum sd_state state);
+ int (*check_connect_char_server) (int tid, int64 tick, int id, intptr_t data);
+ bool (*auth_logout) (TBL_PC* sd, enum sd_state state);
+ void (*save_ack) (int fd);
+ int (*reconnect) (DBKey key, DBData *data, va_list ap);
+ int (*auth_db_cleanup_sub) (DBKey key, DBData *data, va_list ap);
+ bool (*char_ask_name_answer) (int acc, const char* player_name, uint16 type, uint16 answer);
+ int (*auth_db_final) (DBKey key, DBData *data, va_list ap);
+ int (*send_usercount_tochar) (int tid, int64 tick, int id, intptr_t data);
+ int (*auth_db_cleanup) (int tid, int64 tick, int id, intptr_t data);
-int chrif_searchcharid(int char_id);
-int chrif_changeemail(int id, const char *actual_email, const char *new_email);
-int chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second);
-int chrif_updatefamelist(struct map_session_data *sd);
-int chrif_buildfamelist(void);
-int chrif_save_scdata(struct map_session_data *sd);
-int chrif_ragsrvinfo(int base_rate,int job_rate, int drop_rate);
-int chrif_char_offline(struct map_session_data *sd);
-int chrif_char_offline_nsd(int account_id, int char_id);
-int chrif_char_reset_offline(void);
-int send_users_tochar(void);
-int chrif_char_online(struct map_session_data *sd);
-int chrif_changesex(struct map_session_data *sd);
-int chrif_chardisconnect(struct map_session_data *sd);
-int chrif_divorce(int partner_id1, int partner_id2);
-
-int chrif_removefriend(int char_id, int friend_id);
-void chrif_send_report(char* buf, int len);
+ void (*connect) (int fd);
+ void (*connectack) (int fd);
+ void (*sendmap) (int fd);
+ void (*sendmapack) (int fd);
+ void (*recvmap) (int fd);
+ bool (*changemapserverack) (int account_id, int login_id1, int login_id2, int char_id, short map_index, short x, short y, uint32 ip, uint16 port);
+ void (*changedsex) (int fd);
+ bool (*divorceack) (int char_id, int partner_id);
+ void (*idbanned) (int fd);
+ void (*recvfamelist) (int fd);
+ bool (*load_scdata) (int fd);
+ void (*update_ip) (int fd);
+ int (*disconnectplayer) (int fd);
+ void (*removemap) (int fd);
+ int (*updatefamelist_ack) (int fd);
+ void (*keepalive)(int fd);
+ void (*keepalive_ack) (int fd);
+ void (*deadopt) (int father_id, int mother_id, int child_id);
+ void (*authfail) (int fd);
+ void (*on_ready) (void);
+ void (*on_disconnect) (void);
+ int (*parse) (int fd);
+ void (*save_scdata_single) (int account_id, int char_id, short type, struct status_change_entry *sce);
+ void (*del_scdata_single) (int account_id, int char_id, short type);
+};
-int do_final_chrif(void);
-int do_init_chrif(void);
+struct chrif_interface *chrif;
-int chrif_flush_fifo(void);
-void chrif_skillid2idx(int fd);
+void chrif_defaults(void);
+// There's no need for another function when a simple macro can do exactly the same effect
+#define chrif_char_offline(x) chrif->char_offline_nsd((x)->status.account_id,(x)->status.char_id)
-#endif /* _CHRIF_H_ */
+#endif /* MAP_CHRIF_H */
diff --git a/src/map/clif.c b/src/map/clif.c
index 73d4b6666..d9acf0792 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -2,63 +2,87 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/grfio.h"
-#include "../common/malloc.h"
-#include "../common/nullpo.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
-#include "../common/ers.h"
-#include "../common/conf.h"
+#define HERCULES_CORE
+
+#include "../config/core.h" // ANTI_MAYAP_CHEAT, RENEWAL, SECURE_NPCTIMEOUT
+#include "clif.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
-#include "map.h"
-#include "chrif.h"
-#include "pc.h"
-#include "status.h"
-#include "npc.h"
-#include "itemdb.h"
-#include "chat.h"
-#include "trade.h"
-#include "storage.h"
-#include "script.h"
-#include "skill.h"
#include "atcommand.h"
-#include "intif.h"
#include "battle.h"
#include "battleground.h"
-#include "mob.h"
-#include "party.h"
-#include "unit.h"
+#include "chat.h"
+#include "chrif.h"
+#include "elemental.h"
#include "guild.h"
-#include "vending.h"
-#include "pet.h"
#include "homunculus.h"
#include "instance.h"
-#include "mercenary.h"
-#include "elemental.h"
+#include "intif.h"
+#include "irc-bot.h"
+#include "itemdb.h"
#include "log.h"
-#include "clif.h"
#include "mail.h"
+#include "map.h"
+#include "mercenary.h"
+#include "mob.h"
+#include "npc.h"
+#include "party.h"
+#include "pc.h"
+#include "pet.h"
#include "quest.h"
-#include "packets_struct.h"
-#include "irc-bot.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <time.h>
+#include "script.h"
+#include "skill.h"
+#include "status.h"
+#include "storage.h"
+#include "trade.h"
+#include "unit.h"
+#include "vending.h"
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/ers.h"
+#include "../common/grfio.h"
+#include "../common/malloc.h"
+#include "../common/mmo.h" // NEW_CARTS
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
+struct clif_interface clif_s;
+
+/* re-usable */
+static struct packet_itemlist_normal itemlist_normal;
+static struct packet_itemlist_equip itemlist_equip;
+static struct packet_storelist_normal storelist_normal;
+static struct packet_storelist_equip storelist_equip;
+static struct packet_viewequip_ack viewequip_list;
+#if PACKETVER >= 20131223
+static struct packet_npc_market_result_ack npcmarket_result;
+static struct packet_npc_market_open npcmarket_open;
+#endif
//#define DUMP_UNKNOWN_PACKET
//#define DUMP_INVALID_PACKET
//Converts item type in case of pet eggs.
static inline int itemtype(int type) {
- return ( type == IT_PETEGG ) ? IT_WEAPON : type;
+ switch( type ) {
+#if PACKETVER >= 20080827
+ case IT_WEAPON: return IT_ARMOR;
+ case IT_ARMOR:
+ case IT_PETARMOR:
+#endif
+ case IT_PETEGG: return IT_WEAPON;
+ default: return type;
+ }
}
@@ -81,17 +105,16 @@ static inline void WBUFPOS2(uint8* p, unsigned short pos, short x0, short y0, sh
p[5] = (uint8)((sx0<<4) | (sy0&0x0f));
}
-
+#if 0 // Currently unused
static inline void WFIFOPOS(int fd, unsigned short pos, short x, short y, unsigned char dir) {
WBUFPOS(WFIFOP(fd,pos), 0, x, y, dir);
}
-
+#endif // 0
static inline void WFIFOPOS2(int fd, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0) {
WBUFPOS2(WFIFOP(fd,pos), 0, x0, y0, x1, y1, sx0, sy0);
}
-
static inline void RBUFPOS(const uint8* p, unsigned short pos, short* x, short* y, unsigned char* dir) {
p += pos;
@@ -108,7 +131,11 @@ static inline void RBUFPOS(const uint8* p, unsigned short pos, short* x, short*
}
}
+static inline void RFIFOPOS(int fd, unsigned short pos, short* x, short* y, unsigned char* dir) {
+ RBUFPOS(RFIFOP(fd,pos), 0, x, y, dir);
+}
+#if 0 // currently unused
static inline void RBUFPOS2(const uint8* p, unsigned short pos, short* x0, short* y0, short* x1, short* y1, unsigned char* sx0, unsigned char* sy0) {
p += pos;
@@ -136,19 +163,12 @@ static inline void RBUFPOS2(const uint8* p, unsigned short pos, short* x0, short
sy0[0] = ( p[5] & 0x0f ) >> 0;
}
}
-
-
-static inline void RFIFOPOS(int fd, unsigned short pos, short* x, short* y, unsigned char* dir) {
- RBUFPOS(RFIFOP(fd,pos), 0, x, y, dir);
-}
-
-
static inline void RFIFOPOS2(int fd, unsigned short pos, short* x0, short* y0, short* x1, short* y1, unsigned char* sx0, unsigned char* sy0) {
RBUFPOS2(WFIFOP(fd,pos), 0, x0, y0, x1, y1, sx0, sy0);
}
+#endif // 0
-
-//To idenfity disguised characters.
+//To identify disguised characters.
static inline bool disguised(struct block_list* bl) {
return (bool)( bl->type == BL_PC && ((TBL_PC*)bl)->disguise != -1 );
}
@@ -167,27 +187,28 @@ static inline unsigned int mes_len_check(char* mes, unsigned int len, unsigned i
/*==========================================
* Ip setting of map-server
*------------------------------------------*/
-int clif_setip(const char* ip) {
+bool clif_setip(const char* ip) {
char ip_str[16];
clif->map_ip = host2ip(ip);
- if (!clif->map_ip) {
+ if ( !clif->map_ip ) {
ShowWarning("Failed to Resolve Map Server Address! (%s)\n", ip);
- return 0;
+ return false;
}
safestrncpy(clif->map_ip_str, ip, sizeof(clif->map_ip_str));
ShowInfo("Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(clif->map_ip, ip_str));
- return 1;
+ return true;
}
-void clif_setbindip(const char* ip) {
+bool clif_setbindip(const char* ip) {
clif->bind_ip = host2ip(ip);
- if (clif->bind_ip) {
+ if ( clif->bind_ip ) {
char ip_str[16];
ShowInfo("Map Server Bind IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(clif->bind_ip, ip_str));
- } else {
- ShowWarning("Failed to Resolve Map Server Address! (%s)\n", ip);
+ return true;
}
+ ShowWarning("Failed to Resolve Map Server Address! (%s)\n", ip);
+ return false;
}
/*==========================================
@@ -214,28 +235,31 @@ uint16 clif_getport(void)
{
return clif->map_port;
}
-
+/*==========================================
+ * Updates server ip resolution and returns it
+ *------------------------------------------*/
uint32 clif_refresh_ip(void) {
uint32 new_ip;
-
+
new_ip = host2ip(clif->map_ip_str);
- if (new_ip && new_ip != clif->map_ip) {
+ if ( new_ip && new_ip != clif->map_ip ) {
clif->map_ip = new_ip;
ShowInfo("Updating IP resolution of [%s].\n", clif->map_ip_str);
return clif->map_ip;
}
return 0;
}
+
#if PACKETVER >= 20071106
static inline unsigned char clif_bl_type(struct block_list *bl) {
switch (bl->type) {
- case BL_PC: return (disguised(bl) && !pcdb_checkid(status_get_viewdata(bl)->class_))? 0x1:0x0; //PC_TYPE
+ case BL_PC: return (disguised(bl) && !pcdb_checkid(status->get_viewdata(bl)->class_))? 0x1:0x0; //PC_TYPE
case BL_ITEM: return 0x2; //ITEM_TYPE
case BL_SKILL: return 0x3; //SKILL_TYPE
case BL_CHAT: return 0x4; //UNKNOWN_TYPE
- case BL_MOB: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE
- case BL_NPC: return 0x6; //NPC_EVT_TYPE
- case BL_PET: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE
+ case BL_MOB: return pcdb_checkid(status->get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE
+ case BL_NPC: return pcdb_checkid(status->get_viewdata(bl)->class_)?0x0:0x6; //NPC_EVT_TYPE
+ case BL_PET: return pcdb_checkid(status->get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE
case BL_HOM: return 0x8; //NPC_HOM_TYPE
case BL_MER: return 0x9; //NPC_MERSOL_TYPE
case BL_ELEM: return 0xa; //NPC_ELEMENTAL_TYPE
@@ -294,8 +318,19 @@ int clif_send_sub(struct block_list *bl, va_list ap) {
}
}
break;
+/* 0x120 crashes the client when warping for this packetver range [Ind/Hercules], thanks to Judas! */
+#if PACKETVER > 20120418 && PACKETVER < 20130000
+ case AREA:
+ if( WBUFW(buf, 0) == 0x120 && sd->state.warping )
+ return 0;
+ break;
+#endif
}
+ /* unless visible, hold it here */
+ if( clif->ally_only && !sd->sc.data[SC_CLAIRVOYANCE] && !sd->special_state.intravision && battle->check_target( src_bl, &sd->bl, BCT_ENEMY ) > 0 )
+ return 0;
+
WFIFOHEAD(fd, len);
if (WFIFOP(fd,0) == buf) {
ShowError("WARNING: Invalid use of clif->send function\n");
@@ -317,12 +352,12 @@ int clif_send_sub(struct block_list *bl, va_list ap) {
* Packet Delegation (called on all packets that require data to be sent to more than one client)
* functions that are sent solely to one use whose ID it posses use WFIFOSET
*------------------------------------------*/
-int clif_send(const void* buf, int len, struct block_list* bl, enum send_target type) {
+bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target type) {
int i;
struct map_session_data *sd, *tsd;
struct party_data *p = NULL;
struct guild *g = NULL;
- struct battleground_data *bg = NULL;
+ struct battleground_data *bgd = NULL;
int x0 = 0, x1 = 0, y0 = 0, y1 = 0, fd;
struct s_mapiterator* iter;
@@ -361,12 +396,12 @@ int clif_send(const void* buf, int len, struct block_list* bl, enum send_target
clif->send (buf, len, bl, SELF);
case AREA_WOC:
case AREA_WOS:
- iMap->foreachinarea(clif->send_sub, bl->m, bl->x-AREA_SIZE, bl->y-AREA_SIZE, bl->x+AREA_SIZE, bl->y+AREA_SIZE,
+ map->foreachinarea(clif->send_sub, bl->m, bl->x-AREA_SIZE, bl->y-AREA_SIZE, bl->x+AREA_SIZE, bl->y+AREA_SIZE,
BL_PC, buf, len, bl, type);
break;
case AREA_CHAT_WOC:
- iMap->foreachinarea(clif->send_sub, bl->m, bl->x-(AREA_SIZE-5), bl->y-(AREA_SIZE-5),
- bl->x+(AREA_SIZE-5), bl->y+(AREA_SIZE-5), BL_PC, buf, len, bl, AREA_WOC);
+ map->foreachinarea(clif->send_sub, bl->m, bl->x-(AREA_SIZE-5), bl->y-(AREA_SIZE-5),
+ bl->x+(AREA_SIZE-5), bl->y+(AREA_SIZE-5), BL_PC, buf, len, bl, AREA_WOC);
break;
case CHAT:
@@ -374,7 +409,7 @@ int clif_send(const void* buf, int len, struct block_list* bl, enum send_target
{
struct chat_data *cd;
if (sd) {
- cd = (struct chat_data*)iMap->id2bl(sd->chatID);
+ cd = (struct chat_data*)map->id2bl(sd->chatID);
} else if (bl->type == BL_CHAT) {
cd = (struct chat_data*)bl;
} else break;
@@ -426,7 +461,7 @@ int clif_send(const void* buf, int len, struct block_list* bl, enum send_target
memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len);
}
- if (!iMap->enable_spy) //Skip unnecessary parsing. [Skotlex]
+ if (!map->enable_spy) //Skip unnecessary parsing. [Skotlex]
break;
iter = mapit_getallusers();
@@ -503,7 +538,7 @@ int clif_send(const void* buf, int len, struct block_list* bl, enum send_target
WFIFOSET(fd,len);
}
}
- if (!iMap->enable_spy) //Skip unnecessary parsing. [Skotlex]
+ if (!map->enable_spy) //Skip unnecessary parsing. [Skotlex]
break;
iter = mapit_getallusers();
@@ -528,9 +563,9 @@ int clif_send(const void* buf, int len, struct block_list* bl, enum send_target
case BG_SAMEMAP_WOS:
case BG:
case BG_WOS:
- if( sd && sd->bg_id && (bg = bg_team_search(sd->bg_id)) != NULL ) {
+ if( sd && sd->bg_id && (bgd = bg->team_search(sd->bg_id)) != NULL ) {
for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
- if( (sd = bg->members[i].sd) == NULL || !(fd = sd->fd) )
+ if( (sd = bgd->members[i].sd) == NULL || !(fd = sd->fd) )
continue;
if( sd->bl.id == bl->id && (type == BG_WOS || type == BG_SAMEMAP_WOS || type == BG_AREA_WOS) )
continue;
@@ -545,12 +580,28 @@ int clif_send(const void* buf, int len, struct block_list* bl, enum send_target
}
break;
+ case BG_QUEUE:
+ if( sd && sd->bg_queue.arena ) {
+ struct hQueue *queue = &script->hq[sd->bg_queue.arena->queue_id];
+
+ for( i = 0; i < queue->size; i++ ) {
+ struct map_session_data *qsd = NULL;
+
+ if( queue->item[i] > 0 && ( qsd = map->id2sd(queue->item[i]) ) ) {
+ WFIFOHEAD(qsd->fd,len);
+ memcpy(WFIFOP(qsd->fd,0), buf, len);
+ WFIFOSET(qsd->fd,len);
+ }
+ }
+ }
+ break;
+
default:
- ShowError("clif->send: Unrecognized type %d\n",type);
- return -1;
+ ShowError("clif_send: Unrecognized type %d\n",type);
+ return false;
}
- return 0;
+ return true;
}
/// Notifies the client, that it's connection attempt was accepted.
@@ -559,16 +610,16 @@ int clif_send(const void* buf, int len, struct block_list* bl, enum send_target
void clif_authok(struct map_session_data *sd)
{
struct packet_authok p;
-
+
p.PacketType = authokType;
- p.startTime = iTimer->gettick();
+ p.startTime = (unsigned int)timer->gettick();
WBUFPOS(&p.PosDir[0],0,sd->bl.x,sd->bl.y,sd->ud.dir); /* do the stupid client math */
p.xSize = p.ySize = 5; /* not-used */
#if PACKETVER >= 20080102
- p.font = sd->user_font; // FIXME: Font is currently not saved.
+ p.font = sd->status.font;
#endif
-
+
clif->send(&p,sizeof(p),&sd->bl,SELF);
}
@@ -593,7 +644,7 @@ void clif_authrefuse(int fd, uint8 error_code)
/// Notifies the client of a ban or forced disconnect (SC_NOTIFY_BAN).
/// 0081 <error code>.B
/// error code:
-/// 0 = BAN_UNFAIR
+/// 0 = BAN_UNFAIR -> "disconnected from server" -> MsgStringTable[3]
/// 1 = server closed -> MsgStringTable[4]
/// 2 = ID already logged in -> MsgStringTable[5]
/// 3 = timeout/too much lag -> MsgStringTable[241]
@@ -641,12 +692,11 @@ void clif_authfail_fd(int fd, int type)
/// type:
/// 1 = disconnect, char-select
/// ? = nothing
-void clif_charselectok(int id, uint8 ok)
-{
+void clif_charselectok(int id, uint8 ok) {
struct map_session_data* sd;
int fd;
- if ((sd = iMap->id2sd(id)) == NULL || !sd->fd)
+ if ((sd = map->id2sd(id)) == NULL || !sd->fd)
return;
fd = sd->fd;
@@ -667,20 +717,20 @@ void clif_dropflooritem(struct flooritem_data* fitem) {
if (fitem->item_data.nameid <= 0)
return;
-
+
p.PacketType = dropflooritemType;
p.ITAID = fitem->bl.id;
p.ITID = ((view = itemdb_viewid(fitem->item_data.nameid)) > 0) ? view : fitem->item_data.nameid;
#if PACKETVER >= 20130000 /* not sure date */
p.type = itemtype(itemdb_type(fitem->item_data.nameid));
#endif
- p.IsIdentified = fitem->item_data.identify;
+ p.IsIdentified = fitem->item_data.identify ? 1 : 0;
p.xPos = fitem->bl.x;
p.yPos = fitem->bl.y;
p.subX = fitem->subx;
p.subY = fitem->suby;
p.count = fitem->item_data.amount;
-
+
clif->send(&p, sizeof(p), &fitem->bl, AREA);
}
@@ -754,22 +804,23 @@ void clif_clearunit_area(struct block_list* bl, clr_type type)
/// Used to make monsters with player-sprites disappear after dying
/// like normal monsters, because the client does not remove those
/// automatically.
-int clif_clearunit_delayed_sub(int tid, unsigned int tick, int id, intptr_t data) {
+int clif_clearunit_delayed_sub(int tid, int64 tick, int id, intptr_t data) {
struct block_list *bl = (struct block_list *)data;
clif->clearunit_area(bl, (clr_type) id);
ers_free(clif->delay_clearunit_ers,bl);
return 0;
}
-void clif_clearunit_delayed(struct block_list* bl, clr_type type, unsigned int tick)
-{
+
+void clif_clearunit_delayed(struct block_list* bl, clr_type type, int64 tick) {
struct block_list *tbl = ers_alloc(clif->delay_clearunit_ers, struct block_list);
memcpy (tbl, bl, sizeof (struct block_list));
- iTimer->add_timer(tick, clif->clearunit_delayed_sub, (int)type, (intptr_t)tbl);
+ timer->add(tick, clif->clearunit_delayed_sub, (int)type, (intptr_t)tbl);
}
+/// Gets weapon view info from sd's inventory_data and points (*rhand,*lhand)
void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, unsigned short *lhand)
{
- if(sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK)) {
+ if(sd->sc.option&OPTION_COSTUME) {
*rhand = *lhand = 0;
return;
}
@@ -817,7 +868,7 @@ static int clif_setlevel_sub(int lv) {
}
static int clif_setlevel(struct block_list* bl) {
- int lv = status_get_lv(bl);
+ int lv = status->get_lv(bl);
if( battle_config.client_limit_unit_lv&bl->type )
return clif_setlevel_sub(lv);
switch( bl->type ) {
@@ -828,26 +879,85 @@ static int clif_setlevel(struct block_list* bl) {
}
return lv;
}
+/* for 'packetver < 20091103' 0x78 non-pc-looking unit handling */
+void clif_set_unit_idle2(struct block_list* bl, struct map_session_data *tsd, enum send_target target) {
+#if PACKETVER < 20091103
+ struct map_session_data* sd;
+ struct status_change* sc = status->get_sc(bl);
+ struct view_data* vd = status->get_viewdata(bl);
+ struct packet_idle_unit2 p;
+ int g_id = status->get_guild_id(bl);
+
+ sd = BL_CAST(BL_PC, bl);
+ p.PacketType = idle_unit2Type;
+#if PACKETVER >= 20071106
+ p.objecttype = clif_bl_type(bl);
+#endif
+ p.GID = bl->id;
+ p.speed = status->get_speed(bl);
+ p.bodyState = (sc) ? sc->opt1 : 0;
+ p.healthState = (sc) ? sc->opt2 : 0;
+ p.effectState = (sc) ? sc->option : bl->type == BL_NPC ? ((TBL_NPC*)bl)->option : 0;
+ p.job = vd->class_;
+ p.head = vd->hair_style;
+ p.weapon = vd->weapon;
+ p.accessory = vd->head_bottom;
+ p.shield = vd->shield;
+ p.accessory2 = vd->head_top;
+ p.accessory3 = vd->head_mid;
+ if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this?
+ p.shield = status->get_emblem_id(bl);
+ p.accessory2 = GetWord(g_id, 1);
+ p.accessory3 = GetWord(g_id, 0);
+ }
+ p.headpalette = vd->hair_color;
+ p.bodypalette = vd->cloth_color;
+ p.headDir = (sd)? sd->head_dir : 0;
+ p.GUID = g_id;
+ p.GEmblemVer = status->get_emblem_id(bl);
+ p.honor = (sd) ? sd->status.manner : 0;
+ p.virtue = (sc) ? sc->opt3 : 0;
+ p.isPKModeON = (sd && sd->status.karma) ? 1 : 0;
+ p.sex = vd->sex;
+ WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit->getdir(bl));
+ p.xSize = p.ySize = (sd) ? 5 : 0;
+ p.state = vd->dead_sit;
+ p.clevel = clif_setlevel(bl);
+
+ clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target);
+#else
+ return;
+#endif
+}
/*==========================================
* Prepares 'unit standing' packet
*------------------------------------------*/
void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enum send_target target) {
struct map_session_data* sd;
- struct status_change* sc = status_get_sc(bl);
- struct view_data* vd = status_get_viewdata(bl);
+ struct status_change* sc = status->get_sc(bl);
+ struct view_data* vd = status->get_viewdata(bl);
struct packet_idle_unit p;
- int g_id = status_get_guild_id(bl);
+ int g_id = status->get_guild_id(bl);
+
+ nullpo_retv(bl);
+#if PACKETVER < 20091103
+ if( !pcdb_checkid(vd->class_) ) {
+ clif->set_unit_idle2(bl,tsd,target);
+ return;
+ }
+#endif
+
sd = BL_CAST(BL_PC, bl);
-
+
p.PacketType = idle_unitType;
#if PACKETVER >= 20091103
p.PacketLength = sizeof(p);
p.objecttype = clif_bl_type(bl);
#endif
p.GID = bl->id;
- p.speed = status_get_speed(bl);
+ p.speed = status->get_speed(bl);
p.bodyState = (sc) ? sc->opt1 : 0;
p.healthState = (sc) ? sc->opt2 : 0;
p.effectState = (sc) ? sc->option : bl->type == BL_NPC ? ((TBL_NPC*)bl)->option : 0;
@@ -861,7 +971,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
p.accessory2 = vd->head_top;
p.accessory3 = vd->head_mid;
if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this?
- p.accessory = g_id;
+ p.accessory = status->get_emblem_id(bl);
p.accessory2 = GetWord(g_id, 1);
p.accessory3 = GetWord(g_id, 0);
}
@@ -872,19 +982,19 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
p.robe = vd->robe;
#endif
p.GUID = g_id;
- p.GEmblemVer = status_get_emblem_id(bl);
+ p.GEmblemVer = status->get_emblem_id(bl);
p.honor = (sd) ? sd->status.manner : 0;
p.virtue = (sc) ? sc->opt3 : 0;
- p.isPKModeON = (sd) ? sd->status.karma : 0;
+ p.isPKModeON = (sd && sd->status.karma) ? 1 : 0;
p.sex = vd->sex;
- WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit_getdir(bl));
+ WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit->getdir(bl));
p.xSize = p.ySize = (sd) ? 5 : 0;
p.state = vd->dead_sit;
p.clevel = clif_setlevel(bl);
#if PACKETVER >= 20080102
- p.font = (sd) ? sd->user_font : 0;
+ p.font = (sd) ? sd->status.font : 0;
#endif
-#if PACKETVER >= 20140000 //actual 20120221
+#if PACKETVER >= 20150000 //actual 20120221
if( bl->type == BL_MOB ) {
p.maxHP = status_get_max_hp(bl);
p.HP = status_get_hp(bl);
@@ -895,201 +1005,90 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
p.isBoss = 0;
}
#endif
-
+
clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target);
if( disguised(bl) ) {
-#if PACKETVER >= 20071106
- p.objecttype = pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
+#if PACKETVER >= 20091103
+ p.objecttype = pcdb_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
p.GID = -bl->id;
#else
p.GID = -bl->id;
#endif
- clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,SELF);
+ clif->send(&p,sizeof(p),bl,SELF);
}
-
+
}
-/* todo for packetver 20091103 0x7c non-pc-looking unit handling */
-int clif_spawn_unit2(struct block_list* bl, enum send_target target) {
- return 0;
- /*struct map_session_data* sd;
- struct status_change* sc = status_get_sc(bl);
- struct view_data* vd = status_get_viewdata(bl);
- unsigned char *buf = WBUFP(buffer,0);
+/* for 'packetver < 20091103' 0x7c non-pc-looking unit handling */
+void clif_spawn_unit2(struct block_list* bl, enum send_target target) {
#if PACKETVER < 20091103
- bool type = !pcdb_checkid(vd->class_);
-#endif
- unsigned short offset = 0;
-#if PACKETVER >= 20091103
- const char *name;
-#endif
+ struct map_session_data* sd;
+ struct status_change* sc = status->get_sc(bl);
+ struct view_data* vd = status->get_viewdata(bl);
+ struct packet_spawn_unit2 p;
+ int g_id = status->get_guild_id(bl);
+
sd = BL_CAST(BL_PC, bl);
-
-#if PACKETVER < 20091103
- if(type)
- WBUFW(buf,0) = 0x7c;
- else
-#endif
-#if PACKETVER < 4
- WBUFW(buf,0) = 0x79;
-#elif PACKETVER < 7
- WBUFW(buf,0) = 0x1d9;
-#elif PACKETVER < 20080102
- WBUFW(buf,0) = 0x22b;
-#elif PACKETVER < 20091103
- WBUFW(buf,0) = 0x2ed;
-#elif PACKETVER < 20101124
- WBUFW(buf,0) = 0x7f8;
-#else
- WBUFW(buf,0) = 0x858;
-#endif
-
-#if PACKETVER >= 20091103
- name = status_get_name(bl);
-#if PACKETVER < 20110111
- WBUFW(buf,2) = (spawn?62:63)+strlen(name);
-#else
- WBUFW(buf,2) = (spawn?64:65)+strlen(name);
-#endif
- WBUFB(buf,4) = clif_bl_type(bl);
- offset+=3;
- buf = WBUFP(buffer,offset);
-#elif PACKETVER >= 20071106
- if (type) { //Non-player packets
- WBUFB(buf,2) = clif_bl_type(bl);
- offset++;
- buf = WBUFP(buffer,offset);
- }
-#endif
- WBUFL(buf, 2) = bl->id;
- WBUFW(buf, 6) = status_get_speed(bl);
- WBUFW(buf, 8) = (sc)? sc->opt1 : 0;
- WBUFW(buf,10) = (sc)? sc->opt2 : 0;
-#if PACKETVER < 20091103
- if (type&&spawn) { //uses an older and different packet structure
- WBUFW(buf,12) = (sc)? sc->option : 0;
- WBUFW(buf,14) = vd->hair_style;
- WBUFW(buf,16) = vd->weapon;
- WBUFW(buf,18) = vd->head_bottom;
- WBUFW(buf,20) = vd->class_; //Pet armor (ignored by client)
- WBUFW(buf,22) = vd->shield;
- } else {
-#endif
-#if PACKETVER >= 20091103
- WBUFL(buf,12) = (sc)? sc->option : 0;
- offset+=2;
- buf = WBUFP(buffer,offset);
-#elif PACKETVER >= 7
- if (!type) {
- WBUFL(buf,12) = (sc)? sc->option : 0;
- offset+=2;
- buf = WBUFP(buffer,offset);
- } else
- WBUFW(buf,12) = (sc)? sc->option : 0;
-#else
- WBUFW(buf,12) = (sc)? sc->option : 0;
-#endif
- WBUFW(buf,14) = vd->class_;
- WBUFW(buf,16) = vd->hair_style;
- WBUFW(buf,18) = vd->weapon;
-#if PACKETVER < 4
- WBUFW(buf,20) = vd->head_bottom;
- WBUFW(buf,22) = vd->shield;
-#else
- WBUFW(buf,20) = vd->shield;
- WBUFW(buf,22) = vd->head_bottom;
-#endif
-#if PACKETVER < 20091103
- }
+
+ p.PacketType = spawn_unit2Type;
+#if PACKETVER >= 20071106
+ p.objecttype = clif_bl_type(bl);
#endif
- WBUFW(buf,24) = vd->head_top;
- WBUFW(buf,26) = vd->head_mid;
-
- if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS )
- { //The hell, why flags work like this?
- WBUFW(buf,22) = status_get_emblem_id(bl);
- WBUFW(buf,24) = GetWord(status_get_guild_id(bl), 1);
- WBUFW(buf,26) = GetWord(status_get_guild_id(bl), 0);
- }
-
- WBUFW(buf,28) = vd->hair_color;
- WBUFW(buf,30) = vd->cloth_color;
- WBUFW(buf,32) = (sd)? sd->head_dir : 0;
-#if PACKETVER < 20091103
- if (type&&spawn) { //End of packet 0x7c
- WBUFB(buf,34) = (sd)?sd->status.karma:0; // karma
- WBUFB(buf,35) = vd->sex;
- WBUFPOS(buf,36,bl->x,bl->y,unit_getdir(bl));
- WBUFB(buf,39) = 0;
- WBUFB(buf,40) = 0;
- return packet_len(0x7c);
+ p.GID = bl->id;
+ p.speed = status->get_speed(bl);
+ p.bodyState = (sc) ? sc->opt1 : 0;
+ p.healthState = (sc) ? sc->opt2 : 0;
+ p.effectState = (sc) ? sc->option : bl->type == BL_NPC ? ((TBL_NPC*)bl)->option : 0;
+ p.head = vd->hair_style;
+ p.weapon = vd->weapon;
+ p.accessory = vd->head_bottom;
+ p.job = vd->class_;
+ p.shield = vd->shield;
+ p.accessory2 = vd->head_top;
+ p.accessory3 = vd->head_mid;
+ if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this?
+ p.shield = status->get_emblem_id(bl);
+ p.accessory2 = GetWord(g_id, 1);
+ p.accessory3 = GetWord(g_id, 0);
}
-#endif
-#if PACKETVER >= 20110111
- WBUFW(buf,34) = vd->robe;
- offset+= 2;
- buf = WBUFP(buffer,offset);
-#endif
- WBUFL(buf,34) = status_get_guild_id(bl);
- WBUFW(buf,38) = status_get_emblem_id(bl);
- WBUFW(buf,40) = (sd)? sd->status.manner : 0;
-#if PACKETVER >= 20091103
- WBUFL(buf,42) = (sc)? sc->opt3 : 0;
- offset+=2;
- buf = WBUFP(buffer,offset);
-#elif PACKETVER >= 7
- if (!type) {
- WBUFL(buf,42) = (sc)? sc->opt3 : 0;
- offset+=2;
- buf = WBUFP(buffer,offset);
- } else
- WBUFW(buf,42) = (sc)? sc->opt3 : 0;
-#else
- WBUFW(buf,42) = (sc)? sc->opt3 : 0;
-#endif
- WBUFB(buf,44) = (sd)? sd->status.karma : 0;
- WBUFB(buf,45) = vd->sex;
- WBUFPOS(buf,46,bl->x,bl->y,unit_getdir(bl));
- WBUFB(buf,49) = (sd)? 5 : 0;
- WBUFB(buf,50) = (sd)? 5 : 0;
- if (!spawn) {
- WBUFB(buf,51) = vd->dead_sit;
- offset++;
- buf = WBUFP(buffer,offset);
- }
- WBUFW(buf,51) = clif_setlevel(bl);
-#if PACKETVER < 20091103
- if (type) //End for non-player packet
- return packet_len(WBUFW(buffer,0));
-#endif
-#if PACKETVER >= 20080102
- WBUFW(buf,53) = sd?sd->user_font:0;
-#endif
-#if PACKETVER >= 20091103
- memcpy((char*)WBUFP(buf,55), name, NAME_LENGTH);
- return WBUFW(buffer,2);
+ p.headpalette = vd->hair_color;
+ p.bodypalette = vd->cloth_color;
+ p.headDir = (sd)? sd->head_dir : 0;
+ p.isPKModeON = (sd && sd->status.karma) ? 1 : 0;
+ p.sex = vd->sex;
+ WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit->getdir(bl));
+ p.xSize = p.ySize = (sd) ? 5 : 0;
+
+ clif->send(&p,sizeof(p),bl,target);
#else
- return packet_len(WBUFW(buffer,0));
+ return;
#endif
- */
}
-
void clif_spawn_unit(struct block_list* bl, enum send_target target) {
struct map_session_data* sd;
- struct status_change* sc = status_get_sc(bl);
- struct view_data* vd = status_get_viewdata(bl);
+ struct status_change* sc = status->get_sc(bl);
+ struct view_data* vd = status->get_viewdata(bl);
struct packet_spawn_unit p;
- int g_id = status_get_guild_id(bl);
+ int g_id = status->get_guild_id(bl);
+
+ nullpo_retv(bl);
+
+#if PACKETVER < 20091103
+ if( !pcdb_checkid(vd->class_) ) {
+ clif->spawn_unit2(bl,target);
+ return;
+ }
+#endif
sd = BL_CAST(BL_PC, bl);
-
+
p.PacketType = spawn_unitType;
#if PACKETVER >= 20091103
p.PacketLength = sizeof(p);
p.objecttype = clif_bl_type(bl);
#endif
p.GID = bl->id;
- p.speed = status_get_speed(bl);
+ p.speed = status->get_speed(bl);
p.bodyState = (sc) ? sc->opt1 : 0;
p.healthState = (sc) ? sc->opt2 : 0;
p.effectState = (sc) ? sc->option : bl->type == BL_NPC ? ((TBL_NPC*)bl)->option : 0;
@@ -1103,10 +1102,10 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
p.accessory2 = vd->head_top;
p.accessory3 = vd->head_mid;
if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this?
- p.accessory = g_id;
+ p.accessory = status->get_emblem_id(bl);
p.accessory2 = GetWord(g_id, 1);
p.accessory3 = GetWord(g_id, 0);
- }
+ }
p.headpalette = vd->hair_color;
p.bodypalette = vd->cloth_color;
p.headDir = (sd)? sd->head_dir : 0;
@@ -1114,18 +1113,18 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
p.robe = vd->robe;
#endif
p.GUID = g_id;
- p.GEmblemVer = status_get_emblem_id(bl);
+ p.GEmblemVer = status->get_emblem_id(bl);
p.honor = (sd) ? sd->status.manner : 0;
p.virtue = (sc) ? sc->opt3 : 0;
- p.isPKModeON = (sd) ? sd->status.karma : 0;
+ p.isPKModeON = (sd && sd->status.karma) ? 1 : 0;
p.sex = vd->sex;
- WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit_getdir(bl));
+ WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit->getdir(bl));
p.xSize = p.ySize = (sd) ? 5 : 0;
p.clevel = clif_setlevel(bl);
#if PACKETVER >= 20080102
- p.font = (sd) ? sd->user_font : 0;
+ p.font = (sd) ? sd->status.font : 0;
#endif
-#if PACKETVER >= 20140000 //actual 20120221
+#if PACKETVER >= 20150000 //actual 20120221
if( bl->type == BL_MOB ) {
p.maxHP = status_get_max_hp(bl);
p.HP = status_get_hp(bl);
@@ -1137,10 +1136,11 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
}
#endif
if( disguised(bl) ) {
+ nullpo_retv(sd);
if( sd->status.class_ != sd->disguise )
clif->send(&p,sizeof(p),bl,target);
-#if PACKETVER >= 20071106
- p.objecttype = pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
+#if PACKETVER >= 20091103
+ p.objecttype = pcdb_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
p.GID = -bl->id;
#else
p.GID = -bl->id;
@@ -1156,20 +1156,24 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
*------------------------------------------*/
void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, struct unit_data* ud, enum send_target target) {
struct map_session_data* sd;
- struct status_change* sc = status_get_sc(bl);
- struct view_data* vd = status_get_viewdata(bl);
+ struct status_change* sc = status->get_sc(bl);
+ struct view_data* vd = status->get_viewdata(bl);
struct packet_unit_walking p;
- int g_id = status_get_guild_id(bl);
-
+ int g_id = status->get_guild_id(bl);
+
+ nullpo_retv(bl);
+
sd = BL_CAST(BL_PC, bl);
-
+
p.PacketType = unit_walkingType;
#if PACKETVER >= 20091103
p.PacketLength = sizeof(p);
+#endif
+#if PACKETVER >= 20071106
p.objecttype = clif_bl_type(bl);
#endif
p.GID = bl->id;
- p.speed = status_get_speed(bl);
+ p.speed = status->get_speed(bl);
p.bodyState = (sc) ? sc->opt1 : 0;
p.healthState = (sc) ? sc->opt2 : 0;
p.effectState = (sc) ? sc->option : bl->type == BL_NPC ? ((TBL_NPC*)bl)->option : 0;
@@ -1177,7 +1181,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
p.head = vd->hair_style;
p.weapon = vd->weapon;
p.accessory = vd->head_bottom;
- p.moveStartTime = iTimer->gettick();
+ p.moveStartTime = (unsigned int)timer->gettick();
#if PACKETVER < 7
p.shield = vd->shield;
#endif
@@ -1190,18 +1194,18 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
p.robe = vd->robe;
#endif
p.GUID = g_id;
- p.GEmblemVer = status_get_emblem_id(bl);
+ p.GEmblemVer = status->get_emblem_id(bl);
p.honor = (sd) ? sd->status.manner : 0;
p.virtue = (sc) ? sc->opt3 : 0;
- p.isPKModeON = (sd) ? sd->status.karma : 0;
+ p.isPKModeON = (sd && sd->status.karma) ? 1 : 0;
p.sex = vd->sex;
WBUFPOS2(&p.MoveData[0],0,bl->x,bl->y,ud->to_x,ud->to_y,8,8);
p.xSize = p.ySize = (sd) ? 5 : 0;
p.clevel = clif_setlevel(bl);
#if PACKETVER >= 20080102
- p.font = (sd) ? sd->user_font : 0;
+ p.font = (sd) ? sd->status.font : 0;
#endif
-#if PACKETVER >= 20140000 //actual 20120221
+#if PACKETVER >= 20150000 //actual 20120221
if( bl->type == BL_MOB ) {
p.maxHP = status_get_max_hp(bl);
p.HP = status_get_hp(bl);
@@ -1212,17 +1216,17 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
p.isBoss = 0;
}
#endif
-
+
clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target);
if( disguised(bl) ) {
-#if PACKETVER >= 20071106
- p.objecttype = pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
+#if PACKETVER >= 20091103
+ p.objecttype = pcdb_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
p.GID = -bl->id;
#else
p.GID = -bl->id;
-#endif
- clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,SELF);
+#endif
+ clif->send(&p,sizeof(p),bl,SELF);
}
}
@@ -1277,31 +1281,23 @@ void clif_weather_check(struct map_session_data *sd) {
int16 m = sd->bl.m;
int fd = sd->fd;
- if (map[m].flag.snow
- || map[m].flag.clouds
- || map[m].flag.fog
- || map[m].flag.fireworks
- || map[m].flag.sakura
- || map[m].flag.leaves
- || map[m].flag.clouds2) {
- if (map[m].flag.snow)
- clif->specialeffect_single(&sd->bl, 162, fd);
- if (map[m].flag.clouds)
- clif->specialeffect_single(&sd->bl, 233, fd);
- if (map[m].flag.clouds2)
- clif->specialeffect_single(&sd->bl, 516, fd);
- if (map[m].flag.fog)
- clif->specialeffect_single(&sd->bl, 515, fd);
- if (map[m].flag.fireworks) {
- clif->specialeffect_single(&sd->bl, 297, fd);
- clif->specialeffect_single(&sd->bl, 299, fd);
- clif->specialeffect_single(&sd->bl, 301, fd);
- }
- if (map[m].flag.sakura)
- clif->specialeffect_single(&sd->bl, 163, fd);
- if (map[m].flag.leaves)
- clif->specialeffect_single(&sd->bl, 333, fd);
- }
+ if (map->list[m].flag.snow)
+ clif->specialeffect_single(&sd->bl, 162, fd);
+ if (map->list[m].flag.clouds)
+ clif->specialeffect_single(&sd->bl, 233, fd);
+ if (map->list[m].flag.clouds2)
+ clif->specialeffect_single(&sd->bl, 516, fd);
+ if (map->list[m].flag.fog)
+ clif->specialeffect_single(&sd->bl, 515, fd);
+ if (map->list[m].flag.fireworks) {
+ clif->specialeffect_single(&sd->bl, 297, fd);
+ clif->specialeffect_single(&sd->bl, 299, fd);
+ clif->specialeffect_single(&sd->bl, 301, fd);
+ }
+ if (map->list[m].flag.sakura)
+ clif->specialeffect_single(&sd->bl, 163, fd);
+ if (map->list[m].flag.leaves)
+ clif->specialeffect_single(&sd->bl, 333, fd);
}
/**
* Run when the weather on a map changes, throws all players in map id 'm' to clif_weather_check function
@@ -1322,19 +1318,20 @@ void clif_weather(int16 m)
/**
* Main function to spawn a unit on the client (player/mob/pet/etc)
**/
-int clif_spawn(struct block_list *bl)
+bool clif_spawn(struct block_list *bl)
{
struct view_data *vd;
- vd = status_get_viewdata(bl);
- if( !vd || vd->class_ == INVISIBLE_CLASS )
- return 0;
+ vd = status->get_viewdata(bl);
+ if( !vd )
+ return false;
- /**
- * Hide NPC from maya purple card.
- **/
- if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->option&OPTION_INVISIBLE))
- return 0;
+ if( ( bl->type == BL_NPC
+ && !((TBL_NPC*)bl)->chat_id
+ && (((TBL_NPC*)bl)->option&OPTION_INVISIBLE) ) // Hide NPC from maya purple card.
+ || ( vd->class_ == INVISIBLE_CLASS )
+ )
+ return true; // Doesn't need to be spawned, so everything is alright
clif->spawn_unit(bl,AREA_WOS);
@@ -1351,12 +1348,12 @@ int clif_spawn(struct block_list *bl)
clif->spiritball(&sd->bl);
if(sd->state.size==SZ_BIG) // tiny/big players [Valaris]
clif->specialeffect(bl,423,AREA);
- else if(sd->state.size==SZ_MEDIUM)
+ else if(sd->state.size==SZ_SMALL)
clif->specialeffect(bl,421,AREA);
- if( sd->bg_id && map[sd->bl.m].flag.battleground )
+ if( sd->bg_id && map->list[sd->bl.m].flag.battleground )
clif->sendbgemblem_area(sd);
for( i = 0; i < sd->sc_display_count; i++ ) {
- clif->sc_load(&sd->bl, sd->bl.id,AREA,StatusIconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3);
+ clif->sc_load(&sd->bl, sd->bl.id,AREA,status->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3);
}
for(i = 1; i < 5; i++){
if( sd->charm[i] > 0 )
@@ -1371,7 +1368,7 @@ int clif_spawn(struct block_list *bl)
TBL_MOB *md = ((TBL_MOB*)bl);
if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris]
clif->specialeffect(&md->bl,423,AREA);
- else if(md->special_state.size==SZ_MEDIUM)
+ else if(md->special_state.size==SZ_SMALL)
clif->specialeffect(&md->bl,421,AREA);
}
break;
@@ -1380,7 +1377,7 @@ int clif_spawn(struct block_list *bl)
TBL_NPC *nd = ((TBL_NPC*)bl);
if( nd->size == SZ_BIG )
clif->specialeffect(&nd->bl,423,AREA);
- else if( nd->size == SZ_MEDIUM )
+ else if( nd->size == SZ_SMALL )
clif->specialeffect(&nd->bl,421,AREA);
}
break;
@@ -1389,54 +1386,54 @@ int clif_spawn(struct block_list *bl)
clif->send_petdata(NULL, (TBL_PET*)bl, 3, vd->head_bottom); // needed to display pet equip properly
break;
}
- return 0;
+ return true;
}
/// Sends information about owned homunculus to the client (ZC_PROPERTY_HOMUN). [orn]
/// 022e <name>.24B <modified>.B <level>.W <hunger>.W <intimacy>.W <equip id>.W <atk>.W <matk>.W <hit>.W <crit>.W <def>.W <mdef>.W <flee>.W <aspd>.W <hp>.W <max hp>.W <sp>.W <max sp>.W <exp>.L <max exp>.L <skill points>.W <atk range>.W
void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) {
- struct status_data *status;
+ struct status_data *hstatus;
unsigned char buf[128];
enum homun_type htype;
nullpo_retv(hd);
- status = &hd->battle_status;
+ hstatus = &hd->battle_status;
htype = homun->class2type(hd->homunculus.class_);
memset(buf,0,packet_len(0x22e));
WBUFW(buf,0)=0x22e;
memcpy(WBUFP(buf,2),hd->homunculus.name,NAME_LENGTH);
// Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true)
- WBUFB(buf,26)=(battle_config.hom_rename?0:hd->homunculus.rename_flag) | (hd->homunculus.vaporize << 1) | (hd->homunculus.hp?0:4);
+ WBUFB(buf,26)=(battle_config.hom_rename && hd->homunculus.rename_flag ? 0x1 : 0x0) | (hd->homunculus.vaporize == HOM_ST_REST ? 0x2 : 0) | (hd->homunculus.hp > 0 ? 0x4 : 0);
WBUFW(buf,27)=hd->homunculus.level;
WBUFW(buf,29)=hd->homunculus.hunger;
WBUFW(buf,31)=(unsigned short) (hd->homunculus.intimacy / 100) ;
WBUFW(buf,33)=0; // equip id
- WBUFW(buf,35)=cap_value(status->rhw.atk2+status->batk, 0, INT16_MAX);
- WBUFW(buf,37)=cap_value(status->matk_max, 0, INT16_MAX);
- WBUFW(buf,39)=status->hit;
+ WBUFW(buf,35)=cap_value(hstatus->rhw.atk2+hstatus->batk, 0, INT16_MAX);
+ WBUFW(buf,37)=cap_value(hstatus->matk_max, 0, INT16_MAX);
+ WBUFW(buf,39)=hstatus->hit;
if (battle_config.hom_setting&0x10)
- WBUFW(buf,41)=status->luk/3 + 1; //crit is a +1 decimal value! Just display purpose.[Vicious]
+ WBUFW(buf,41)=hstatus->luk/3 + 1; //crit is a +1 decimal value! Just display purpose.[Vicious]
else
- WBUFW(buf,41)=status->cri/10;
- WBUFW(buf,43)=status->def + status->vit ;
- WBUFW(buf,45)=status->mdef;
- WBUFW(buf,47)=status->flee;
- WBUFW(buf,49)=(flag)?0:status->amotion;
- if (status->max_hp > INT16_MAX) {
- WBUFW(buf,51) = status->hp/(status->max_hp/100);
+ WBUFW(buf,41)=hstatus->cri/10;
+ WBUFW(buf,43)=hstatus->def + hstatus->vit ;
+ WBUFW(buf,45)=hstatus->mdef;
+ WBUFW(buf,47)=hstatus->flee;
+ WBUFW(buf,49)=(flag)?0:hstatus->amotion;
+ if (hstatus->max_hp > INT16_MAX) {
+ WBUFW(buf,51) = hstatus->hp/(hstatus->max_hp/100);
WBUFW(buf,53) = 100;
} else {
- WBUFW(buf,51)=status->hp;
- WBUFW(buf,53)=status->max_hp;
+ WBUFW(buf,51)=hstatus->hp;
+ WBUFW(buf,53)=hstatus->max_hp;
}
- if (status->max_sp > INT16_MAX) {
- WBUFW(buf,55) = status->sp/(status->max_sp/100);
+ if (hstatus->max_sp > INT16_MAX) {
+ WBUFW(buf,55) = hstatus->sp/(hstatus->max_sp/100);
WBUFW(buf,57) = 100;
} else {
- WBUFW(buf,55)=status->sp;
- WBUFW(buf,57)=status->max_sp;
+ WBUFW(buf,55)=hstatus->sp;
+ WBUFW(buf,57)=hstatus->max_sp;
}
WBUFL(buf,59)=hd->homunculus.exp;
WBUFL(buf,63)=hd->exp_next;
@@ -1483,18 +1480,23 @@ void clif_send_homdata(struct map_session_data *sd, int state, int param)
WFIFOSET(fd,packet_len(0x230));
}
-
-int clif_homskillinfoblock(struct map_session_data *sd) { //[orn]
+/// Prepares and sends homun related information [orn]
+void clif_homskillinfoblock(struct map_session_data *sd) {
struct homun_data *hd;
- int fd = sd->fd;
- int i,j,len=4,id;
- WFIFOHEAD(fd, 4+37*MAX_HOMUNSKILL);
+ int fd;
+ int i,j;
+ int len=4,id;
+ nullpo_retv(sd);
+ fd = sd->fd;
hd = sd->hd;
+
if ( !hd )
- return 0 ;
+ return;
+ WFIFOHEAD(fd, 4+37*MAX_HOMUNSKILL);
WFIFOW(fd,0)=0x235;
+
for ( i = 0; i < MAX_HOMUNSKILL; i++){
if( (id = hd->homunculus.hskill[i].id) != 0 ){
j = id - HM_SKILLBASE;
@@ -1512,7 +1514,7 @@ int clif_homskillinfoblock(struct map_session_data *sd) { //[orn]
WFIFOW(fd,2)=len;
WFIFOSET(fd,len);
- return 0;
+ return;
}
void clif_homskillup(struct map_session_data *sd, uint16 skill_id) { //[orn]
@@ -1534,16 +1536,19 @@ void clif_homskillup(struct map_session_data *sd, uint16 skill_id) { //[orn]
WFIFOSET(fd,packet_len(0x239));
}
-int clif_hom_food(struct map_session_data *sd,int foodid,int fail) //[orn]
+void clif_hom_food(struct map_session_data *sd,int foodid,int fail) //[orn]
{
- int fd=sd->fd;
+ int fd;
+ nullpo_retv(sd);
+
+ fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x22f));
WFIFOW(fd,0)=0x22f;
WFIFOB(fd,2)=fail;
WFIFOW(fd,3)=foodid;
WFIFOSET(fd,packet_len(0x22f));
- return 0;
+ return;
}
@@ -1555,14 +1560,19 @@ void clif_walkok(struct map_session_data *sd)
WFIFOHEAD(fd, packet_len(0x87));
WFIFOW(fd,0)=0x87;
- WFIFOL(fd,2)=iTimer->gettick();
+ WFIFOL(fd,2)=(unsigned int)timer->gettick();
WFIFOPOS2(fd,6,sd->bl.x,sd->bl.y,sd->ud.to_x,sd->ud.to_y,8,8);
WFIFOSET(fd,packet_len(0x87));
}
void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *ud) {
+#ifdef ANTI_MAYAP_CHEAT
+ struct status_change *sc = NULL;
+ if( (sc = status->get_sc(bl)) && sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE|OPTION_CHASEWALK) )
+ clif->ally_only = true;
+#endif
clif->set_unit_walking(bl,NULL,ud,AREA_WOS);
if(vd->cloth_color)
@@ -1575,7 +1585,7 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u
// clif_movepc(sd);
if(sd->state.size==SZ_BIG) // tiny/big players [Valaris]
clif->specialeffect(&sd->bl,423,AREA);
- else if(sd->state.size==SZ_MEDIUM)
+ else if(sd->state.size==SZ_SMALL)
clif->specialeffect(&sd->bl,421,AREA);
}
break;
@@ -1584,7 +1594,7 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u
TBL_MOB *md = ((TBL_MOB*)bl);
if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris]
clif->specialeffect(&md->bl,423,AREA);
- else if(md->special_state.size==SZ_MEDIUM)
+ else if(md->special_state.size==SZ_SMALL)
clif->specialeffect(&md->bl,421,AREA);
}
break;
@@ -1593,6 +1603,9 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u
clif->send_petdata(NULL, (TBL_PET*)bl, 3, vd->head_bottom);
break;
}
+#ifdef ANTI_MAYAP_CHEAT
+ clif->ally_only = false;
+#endif
}
@@ -1602,10 +1615,12 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u
void clif_move(struct unit_data *ud)
{
unsigned char buf[16];
- struct view_data* vd;
- struct block_list* bl = ud->bl;
-
- vd = status_get_viewdata(bl);
+ struct view_data *vd;
+ struct block_list *bl = ud->bl;
+#ifdef ANTI_MAYAP_CHEAT
+ struct status_change *sc = NULL;
+#endif
+ vd = status->get_viewdata(bl);
if (!vd || vd->class_ == INVISIBLE_CLASS)
return; //This performance check is needed to keep GM-hidden objects from being notified to bots.
@@ -1622,28 +1637,37 @@ void clif_move(struct unit_data *ud)
clif->move2(bl, vd, ud);
return;
}
+#ifdef ANTI_MAYAP_CHEAT
+ if( (sc = status->get_sc(bl)) && sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE) )
+ clif->ally_only = true;
+#endif
WBUFW(buf,0)=0x86;
WBUFL(buf,2)=bl->id;
WBUFPOS2(buf,6,bl->x,bl->y,ud->to_x,ud->to_y,8,8);
- WBUFL(buf,12)=iTimer->gettick();
+ WBUFL(buf,12)=(unsigned int)timer->gettick();
+
clif->send(buf, packet_len(0x86), bl, AREA_WOS);
+
if (disguised(bl)) {
WBUFL(buf,2)=-bl->id;
clif->send(buf, packet_len(0x86), bl, SELF);
}
+#ifdef ANTI_MAYAP_CHEAT
+ clif->ally_only = false;
+#endif
}
/*==========================================
- * Delays the iMap->quit of a player after they are disconnected. [Skotlex]
+ * Delays the map->quit of a player after they are disconnected. [Skotlex]
*------------------------------------------*/
-int clif_delayquit(int tid, unsigned int tick, int id, intptr_t data) {
+int clif_delayquit(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd = NULL;
//Remove player from map server
- if ((sd = iMap->id2sd(id)) != NULL && sd->fd == 0) //Should be a disconnected player.
- iMap->quit(sd);
+ if ((sd = map->id2sd(id)) != NULL && sd->fd == 0) //Should be a disconnected player.
+ map->quit(sd);
return 0;
}
@@ -1652,14 +1676,14 @@ int clif_delayquit(int tid, unsigned int tick, int id, intptr_t data) {
*------------------------------------------*/
void clif_quitsave(int fd,struct map_session_data *sd) {
if (!battle_config.prevent_logout ||
- DIFF_TICK(iTimer->gettick(), sd->canlog_tick) > battle_config.prevent_logout)
- iMap->quit(sd);
+ DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout)
+ map->quit(sd);
else if (sd->fd) {
//Disassociate session from player (session is deleted after this function was called)
//And set a timer to make him quit later.
session[sd->fd]->session_data = NULL;
sd->fd = 0;
- iTimer->add_timer(iTimer->gettick() + 10000, clif->delayquit, sd->bl.id, 0);
+ timer->add(timer->gettick() + 10000, clif->delayquit, sd->bl.id, 0);
}
}
@@ -1672,7 +1696,7 @@ void clif_changemap(struct map_session_data *sd, short m, int x, int y) {
WFIFOHEAD(fd,packet_len(0x91));
WFIFOW(fd,0) = 0x91;
- mapindex_getmapname_ext(map[m].cName ? map[m].cName : map[m].name, (char*)WFIFOP(fd,2));
+ mapindex->getmapname_ext(map->list[m].custom_name ? map->list[map->list[m].instance_src_map].name : map->list[m].name, (char*)WFIFOP(fd,2));
WFIFOW(fd,18) = x;
WFIFOW(fd,20) = y;
WFIFOSET(fd,packet_len(0x91));
@@ -1688,7 +1712,7 @@ void clif_changemapserver(struct map_session_data* sd, unsigned short map_index,
WFIFOHEAD(fd,packet_len(0x92));
WFIFOW(fd,0) = 0x92;
- mapindex_getmapname_ext(mapindex_id2name(map_index), (char*)WFIFOP(fd,2));
+ mapindex->getmapname_ext(mapindex_id2name(map_index), (char*)WFIFOP(fd,2));
WFIFOW(fd,18) = x;
WFIFOW(fd,20) = y;
WFIFOL(fd,22) = htonl(ip);
@@ -1700,7 +1724,7 @@ void clif_changemapserver(struct map_session_data* sd, unsigned short map_index,
void clif_blown(struct block_list *bl)
{
//Aegis packets says fixpos, but it's unsure whether slide works better or not.
-// clif_fixpos(bl);
+ clif->fixpos(bl);
clif->slide(bl, bl->x, bl->y);
}
@@ -1709,9 +1733,9 @@ void clif_blown(struct block_list *bl)
/// isn't walkable, the char doesn't move at all. If the char is
/// sitting it will stand up (ZC_STOPMOVE).
/// 0088 <id>.L <x>.W <y>.W
-void clif_fixpos(struct block_list *bl)
-{
+void clif_fixpos(struct block_list *bl) {
unsigned char buf[10];
+
nullpo_retv(bl);
WBUFW(buf,0) = 0x88;
@@ -1745,29 +1769,40 @@ void clif_npcbuysell(struct map_session_data* sd, int id)
/// Presents list of items, that can be bought in an NPC shop (ZC_PC_PURCHASE_ITEMLIST).
/// 00c6 <packet len>.W { <price>.L <discount price>.L <item type>.B <name id>.W }*
-void clif_buylist(struct map_session_data *sd, struct npc_data *nd)
-{
+void clif_buylist(struct map_session_data *sd, struct npc_data *nd) {
+ struct npc_item_list *shop = NULL;
+ unsigned short shop_size = 0;
int fd,i,c;
nullpo_retv(sd);
nullpo_retv(nd);
+ if( nd->subtype == SCRIPT ) {
+ shop = nd->u.scr.shop->item;
+ shop_size = nd->u.scr.shop->items;
+ } else {
+ shop = nd->u.shop.shop_item;
+ shop_size = nd->u.shop.count;
+ }
+
fd = sd->fd;
- WFIFOHEAD(fd, 4 + nd->u.shop.count * 11);
+
+ WFIFOHEAD(fd, 4 + shop_size * 11);
WFIFOW(fd,0) = 0xc6;
c = 0;
- for( i = 0; i < nd->u.shop.count; i++ )
- {
- struct item_data* id = itemdb_exists(nd->u.shop.shop_item[i].nameid);
- int val = nd->u.shop.shop_item[i].value;
- if( id == NULL )
- continue;
- WFIFOL(fd, 4+c*11) = val;
- WFIFOL(fd, 8+c*11) = pc->modifybuyvalue(sd,val);
- WFIFOB(fd,12+c*11) = itemtype(id->type);
- WFIFOW(fd,13+c*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid;
- c++;
+ for( i = 0; i < shop_size; i++ ) {
+ if( shop[i].nameid ) {
+ struct item_data* id = itemdb->exists(shop[i].nameid);
+ int val = shop[i].value;
+ if( id == NULL )
+ continue;
+ WFIFOL(fd, 4+c*11) = val;
+ WFIFOL(fd, 8+c*11) = pc->modifybuyvalue(sd,val);
+ WFIFOB(fd,12+c*11) = itemtype(id->type);
+ WFIFOW(fd,13+c*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid;
+ c++;
+ }
}
WFIFOW(fd,2) = 4 + c*11;
@@ -1782,12 +1817,12 @@ void clif_hercules_chsys_create(struct hChSysCh *channel, char *name, char *pass
channel->pass[0] = '\0';
else
safestrncpy(channel->pass, pass, HCHSYS_NAME_LENGTH);
-
+
channel->opt = hChSys_OPT_BASE;
channel->banned = NULL;
-
+
channel->msg_delay = 0;
-
+
if( channel->type != hChSys_MAP && channel->type != hChSys_ALLY )
strdb_put(clif->channel_db, channel->name, channel);
}
@@ -1807,11 +1842,14 @@ void clif_selllist(struct map_session_data *sd)
{
if( sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] )
{
- if( !itemdb_cansell(&sd->status.inventory[i], pc->get_group_level(sd)) )
+ if( !itemdb_cansell(&sd->status.inventory[i], pc_get_group_level(sd)) )
continue;
if( sd->status.inventory[i].expire_time )
continue; // Cannot Sell Rental Items
+
+ if( sd->status.inventory[i].bound && !pc_can_give_bound_items(sd))
+ continue; // Don't allow sale of bound items
val=sd->inventory_data[i]->value_sell;
if( val < 0 )
@@ -1837,10 +1875,10 @@ void clif_selllist(struct map_session_data *sd)
/// - append this text
void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) {
int fd = sd->fd;
- int slen = strlen(mes) + 9;
+ size_t slen = strlen(mes) + 9;
sd->state.dialog = 1;
-
+
WFIFOHEAD(fd, slen);
WFIFOW(fd,0)=0xb4;
WFIFOW(fd,2)=slen;
@@ -1947,16 +1985,15 @@ void clif_sendfakenpc(struct map_session_data *sd, int npcid) {
/// WARNING: the 'cancel' button closes other windows besides the dialog window and the menu window.
/// Which suggests their have intertwined behavior. (probably the mouse targeting)
/// TODO investigate behavior of other windows [FlavioJS]
-void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes)
-{
+void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes) {
int fd = sd->fd;
- int slen = strlen(mes) + 9;
+ size_t slen = strlen(mes) + 9;
struct block_list *bl = NULL;
- if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = iMap->id2bl(npcid)) && (bl->m!=sd->bl.m ||
- bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 ||
- bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1))))
- clif->sendfakenpc(sd, npcid);
+ if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) && (bl->m!=sd->bl.m ||
+ bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 ||
+ bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1))))
+ clif->sendfakenpc(sd, npcid);
WFIFOHEAD(fd, slen);
WFIFOW(fd,0)=0xb7;
@@ -1978,17 +2015,16 @@ void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes)
/// - if npcid exists in the client:
/// - 0143 <npcid of inputnum window>.L <atoi(text)>.L
/// - close inputnum window
-void clif_scriptinput(struct map_session_data *sd, int npcid)
-{
+void clif_scriptinput(struct map_session_data *sd, int npcid) {
int fd;
struct block_list *bl = NULL;
nullpo_retv(sd);
- if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = iMap->id2bl(npcid)) && (bl->m!=sd->bl.m ||
- bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 ||
- bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1))))
- clif->sendfakenpc(sd, npcid);
+ if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) && (bl->m!=sd->bl.m ||
+ bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 ||
+ bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1))))
+ clif->sendfakenpc(sd, npcid);
fd=sd->fd;
WFIFOHEAD(fd, packet_len(0x142));
@@ -2009,17 +2045,16 @@ void clif_scriptinput(struct map_session_data *sd, int npcid)
/// - if npcid is 0 or npcid exists in the client:
/// - 01d5 <packetlen>.W <npcid of inputstr window>.L <text>.?B
/// - close inputstr window
-void clif_scriptinputstr(struct map_session_data *sd, int npcid)
-{
+void clif_scriptinputstr(struct map_session_data *sd, int npcid) {
int fd;
struct block_list *bl = NULL;
nullpo_retv(sd);
- if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = iMap->id2bl(npcid)) && (bl->m!=sd->bl.m ||
- bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 ||
- bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1))))
- clif->sendfakenpc(sd, npcid);
+ if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) && (bl->m!=sd->bl.m ||
+ bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 ||
+ bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1))))
+ clif->sendfakenpc(sd, npcid);
fd=sd->fd;
WFIFOHEAD(fd, packet_len(0x1d4));
@@ -2059,10 +2094,10 @@ void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, in
void clif_hercules_chsys_join(struct hChSysCh *channel, struct map_session_data *sd) {
if( idb_put(channel->users, sd->status.char_id, sd) )
return;
-
+
RECREATE(sd->channels, struct hChSysCh *, ++sd->channel_count);
sd->channels[ sd->channel_count - 1 ] = channel;
-
+
if( sd->stealth ) {
sd->stealth = false;
} else if( channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) {
@@ -2070,12 +2105,12 @@ void clif_hercules_chsys_join(struct hChSysCh *channel, struct map_session_data
sprintf(message, "#%s '%s' joined",channel->name,sd->status.name);
clif->chsys_msg(channel,sd,message);
}
-
+
/* someone is cheating, we kindly disconnect the bastard */
if( sd->channel_count > 200 ) {
set_eof(sd->fd);
}
-
+
}
/// Displays an illustration image.
/// 0145 <image name>.16B <type>.B (ZC_SHOW_IMAGE)
@@ -2179,23 +2214,23 @@ void clif_addcards2(unsigned short *cards, struct item* item) {
//Client only receives four cards.. so randomly send them a set of cards. [Skotlex]
if( MAX_SLOTS > 4 && (j = itemdb_slot(item->nameid)) > 4 )
i = rnd()%(j-3); //eg: 6 slots, possible i values: 0->3, 1->4, 2->5 => i = rnd()%3;
-
+
//Normal items.
if( item->card[i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
cards[0] = j;
else
cards[0] = item->card[i];
-
+
if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
cards[1] = j;
else
cards[1] = item->card[i];
-
+
if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
cards[2] = j;
else
cards[2] = item->card[i];
-
+
if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 )
cards[3] = j;
else
@@ -2220,18 +2255,18 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) {
p.PacketType = additemType;
p.Index = n+2;
p.count = amount;
-
+
if( !fail ) {
if( n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <=0 || sd->inventory_data[n] == NULL )
return;
-
+
if (sd->inventory_data[n]->view_id > 0)
p.nameid = sd->inventory_data[n]->view_id;
else
p.nameid = sd->status.inventory[n].nameid;
-
- p.IsIdentified = sd->status.inventory[n].identify;
- p.IsDamaged = sd->status.inventory[n].attribute;
+
+ p.IsIdentified = sd->status.inventory[n].identify ? 1 : 0;
+ p.IsDamaged = sd->status.inventory[n].attribute ? 1 : 0;
p.refiningLevel =sd->status.inventory[n].refine;
clif->addcards2(&p.slot.card[0], &sd->status.inventory[n]);
p.location = pc->equippoint(sd,n);
@@ -2240,7 +2275,10 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) {
p.HireExpireDate = sd->status.inventory[n].expire_time;
#endif
#if PACKETVER >= 20071002
- p.bindOnEquipType = 0; // unused
+ /* why restrict the flag to non-stackable? because this is the only packet allows stackable to,
+ * show the color, and therefore it'd be inconsistent with the rest (aka it'd show yellow, you relog/refresh and boom its gone)
+ */
+ p.bindOnEquipType = sd->status.inventory[n].bound && !itemdb->isstackable2(sd->inventory_data[n]) ? 2 : sd->inventory_data[n]->flag.bindonequip ? 1 : 0;
#endif
}
p.result = (unsigned char)fail;
@@ -2322,91 +2360,112 @@ void clif_item_sub(unsigned char *buf, int n, struct item *i, struct item_data *
}
}
-//Unified inventory function which sends all of the inventory (requires two packets, one for equipable items and one for stackable ones. [Skotlex]
-void clif_inventorylist(struct map_session_data *sd) {
- int i,n,ne,arrow=-1;
- unsigned char *buf;
- unsigned char *bufe;
+void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct item_data *id, int eqp_pos) {
-#if PACKETVER < 5
- const int s = 10; //Entry size.
-#elif PACKETVER < 20080102
- const int s = 18;
-#else
- const int s = 22;
-#endif
-#if PACKETVER < 20071002
- const int se = 20;
-#elif PACKETVER < 20100629
- const int se = 26;
-#else
- const int se = 28;
+ p->index = idx;
+
+ if (id->view_id > 0)
+ p->ITID = id->view_id;
+ else
+ p->ITID = i->nameid;
+
+ p->type = itemtype(id->type);
+
+#if PACKETVER < 20120925
+ p->IsIdentified = i->identify ? 1 : 0;
#endif
- buf = (unsigned char*)aMalloc(MAX_INVENTORY * s + 4);
- bufe = (unsigned char*)aMalloc(MAX_INVENTORY * se + 4);
+ p->location = eqp_pos;
+ p->WearState = i->equip;
+
+#if PACKETVER < 20120925
+ p->IsDamaged = i->attribute ? 1 : 0;
+#endif
+ p->RefiningLevel = i->refine;
- for( i = 0, n = 0, ne = 0; i < MAX_INVENTORY; i++ )
- {
- if( sd->status.inventory[i].nameid <=0 || sd->inventory_data[i] == NULL )
- continue;
+ clif->addcards2(&p->slot.card[0], i);
- if( !itemdb_isstackable2(sd->inventory_data[i]) )
- { //Non-stackable (Equippable)
- WBUFW(bufe,ne*se+4)=i+2;
- clif->item_sub(bufe, ne*se+6, &sd->status.inventory[i], sd->inventory_data[i], pc->equippoint(sd,i));
- clif->addcards(WBUFP(bufe, ne*se+16), &sd->status.inventory[i]);
#if PACKETVER >= 20071002
- WBUFL(bufe,ne*se+24)=sd->status.inventory[i].expire_time;
- WBUFW(bufe,ne*se+28)=0; //Unknown
+ p->HireExpireDate = i->expire_time;
#endif
+
+#if PACKETVER >= 20080102
+ p->bindOnEquipType = i->bound ? 2 : id->flag.bindonequip ? 1 : 0;
+#endif
+
#if PACKETVER >= 20100629
- if (sd->inventory_data[i]->equip&EQP_VISIBLE)
- WBUFW(bufe,ne*se+30)= sd->inventory_data[i]->look;
- else
- WBUFW(bufe,ne*se+30)=0;
+ p->wItemSpriteNumber = id->equip&EQP_VISIBLE ? id->look : 0;
#endif
- ne++;
- }
- else
- { //Stackable.
- WBUFW(buf,n*s+4)=i+2;
- clif->item_sub(buf, n*s+6, &sd->status.inventory[i], sd->inventory_data[i], -2);
- if( sd->inventory_data[i]->equip == EQP_AMMO && sd->status.inventory[i].equip )
- arrow=i;
+
+#if PACKETVER >= 20120925
+ p->Flag.IsIdentified = i->identify ? 1 : 0;
+ p->Flag.IsDamaged = i->attribute ? 1 : 0;
+ p->Flag.PlaceETCTab = i->favorite ? 1 : 0;
+ p->Flag.SpareBits = 0;
+#endif
+}
+void clif_item_normal(short idx, struct NORMALITEM_INFO *p, struct item *i, struct item_data *id) {
+ p->index = idx;
+
+ if (id->view_id > 0)
+ p->ITID = id->view_id;
+ else
+ p->ITID = i->nameid;
+
+ p->type = itemtype(id->type);
+
+#if PACKETVER < 20120925
+ p->IsIdentified = i->identify ? 1 : 0;
+#endif
+
+ p->count = i->amount;
+ p->WearState = id->equip;
+
#if PACKETVER >= 5
- clif->addcards(WBUFP(buf, n*s+14), &sd->status.inventory[i]);
+ clif->addcards2(&p->slot.card[0], i);
#endif
+
#if PACKETVER >= 20080102
- WBUFL(buf,n*s+22)=sd->status.inventory[i].expire_time;
+ p->HireExpireDate = i->expire_time;
#endif
- n++;
- }
- }
- if( n ) {
-#if PACKETVER < 5
- WBUFW(buf,0)=0xa3;
-#elif PACKETVER < 20080102
- WBUFW(buf,0)=0x1ee;
-#else
- WBUFW(buf,0)=0x2e8;
+
+#if PACKETVER >= 20120925
+ p->Flag.IsIdentified = i->identify ? 1 : 0;
+ p->Flag.PlaceETCTab = i->favorite ? 1 : 0;
+ p->Flag.SpareBits = 0;
#endif
- WBUFW(buf,2)=4+n*s;
- clif->send(buf, WBUFW(buf,2), &sd->bl, SELF);
+}
+void clif_inventorylist(struct map_session_data *sd) {
+ int i, normal = 0, equip = 0;
+
+ for( i = 0; i < MAX_INVENTORY; i++ ) {
+
+ if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL )
+ continue;
+ if( !itemdb->isstackable2(sd->inventory_data[i]) ) //Non-stackable (Equippable)
+ clif_item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.inventory[i],sd->inventory_data[i],pc->equippoint(sd,i));
+ else //Stackable (Normal)
+ clif_item_normal(i+2,&itemlist_normal.list[normal++],&sd->status.inventory[i],sd->inventory_data[i]);
}
- if( arrow >= 0 )
- clif->arrowequip(sd,arrow);
- if( ne ) {
-#if PACKETVER < 20071002
- WBUFW(bufe,0)=0xa4;
-#else
- WBUFW(bufe,0)=0x2d0;
-#endif
- WBUFW(bufe,2)=4+ne*se;
- clif->send(bufe, WBUFW(bufe,2), &sd->bl, SELF);
+ if( normal ) {
+ itemlist_normal.PacketType = inventorylistnormalType;
+ itemlist_normal.PacketLength = 4 + (sizeof(struct NORMALITEM_INFO) * normal);
+
+ clif->send(&itemlist_normal, itemlist_normal.PacketLength, &sd->bl, SELF);
}
-#if PACKETVER >= 20111122
+
+ if( sd->equip_index[EQI_AMMO] >= 0 )
+ clif->arrowequip(sd,sd->equip_index[EQI_AMMO]);
+
+ if( equip ) {
+ itemlist_equip.PacketType = inventorylistequipType;
+ itemlist_equip.PacketLength = 4 + (sizeof(struct EQUIPITEM_INFO) * equip);
+
+ clif->send(&itemlist_equip, itemlist_equip.PacketLength, &sd->bl, SELF);
+ }
+/* on 20120925 onwards this is a field on clif_item_equip/normal */
+#if PACKETVER >= 20111122 && PACKETVER < 20120925
for( i = 0; i < MAX_INVENTORY; i++ ) {
if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL )
continue;
@@ -2415,224 +2474,121 @@ void clif_inventorylist(struct map_session_data *sd) {
clif->favorite_item(sd, i);
}
#endif
-
- if( buf ) aFree(buf);
- if( bufe ) aFree(bufe);
}
//Required when items break/get-repaired. Only sends equippable item list.
-void clif_equiplist(struct map_session_data *sd)
-{
- int i,n,fd = sd->fd;
- unsigned char *buf;
-#if PACKETVER < 20071002
- const int cmd = 20;
-#elif PACKETVER < 20100629
- const int cmd = 26;
-#else
- const int cmd = 28;
-#endif
+void clif_equiplist(struct map_session_data *sd) {
+ int i, equip = 0;
- WFIFOHEAD(fd, MAX_INVENTORY * cmd + 4);
- buf = WFIFOP(fd,0);
+ for( i = 0; i < MAX_INVENTORY; i++ ) {
- for(i=0,n=0;i<MAX_INVENTORY;i++){
- if (sd->status.inventory[i].nameid <=0 || sd->inventory_data[i] == NULL)
+ if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL )
continue;
+ if( !itemdb->isstackable2(sd->inventory_data[i]) ) //Non-stackable (Equippable)
+ clif_item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.inventory[i],sd->inventory_data[i],pc->equippoint(sd,i));
+ }
+
+ if( equip ) {
+ itemlist_equip.PacketType = inventorylistequipType;
+ itemlist_equip.PacketLength = 4 + (sizeof(struct EQUIPITEM_INFO) * equip);
- if(itemdb_isstackable2(sd->inventory_data[i]))
+ clif->send(&itemlist_equip, itemlist_equip.PacketLength, &sd->bl, SELF);
+ }
+
+ /* on 20120925 onwards this is a field on clif_item_equip */
+#if PACKETVER >= 20111122 && PACKETVER < 20120925
+ for( i = 0; i < MAX_INVENTORY; i++ ) {
+ if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL )
continue;
- //Equippable
- WBUFW(buf,n*cmd+4)=i+2;
- clif->item_sub(buf, n*cmd+6, &sd->status.inventory[i], sd->inventory_data[i], pc->equippoint(sd,i));
- clif->addcards(WBUFP(buf, n*cmd+16), &sd->status.inventory[i]);
-#if PACKETVER >= 20071002
- WBUFL(buf,n*cmd+24)=sd->status.inventory[i].expire_time;
- WBUFW(buf,n*cmd+28)=0; //Unknown
-#endif
-#if PACKETVER >= 20100629
- if (sd->inventory_data[i]->equip&EQP_VISIBLE)
- WBUFW(buf,n*cmd+30)= sd->inventory_data[i]->look;
- else
- WBUFW(buf,n*cmd+30)=0;
-#endif
- n++;
+
+ if ( sd->status.inventory[i].favorite )
+ clif->favorite_item(sd, i);
}
- if (n) {
-#if PACKETVER < 20071002
- WBUFW(buf,0)=0xa4;
-#else
- WBUFW(buf,0)=0x2d0;
#endif
- WBUFW(buf,2)=4+n*cmd;
- WFIFOSET(fd,WFIFOW(fd,2));
- }
}
-void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length)
-{
+void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length) {
+ int i = 0;
struct item_data *id;
- int i,n,ne;
- unsigned char *buf;
- unsigned char *bufe;
-#if PACKETVER < 5
- const int s = 10; //Entry size.
-#elif PACKETVER < 20080102
- const int s = 18;
-#else
- const int s = 22;
-#endif
-#if PACKETVER < 20071002
- const int cmd = 20;
-#elif PACKETVER < 20100629
- const int cmd = 26;
-#else
- const int cmd = 28;
-#endif
- buf = (unsigned char*)aMalloc(items_length * s + 4);
- bufe = (unsigned char*)aMalloc(items_length * cmd + 4);
+ do {
+ int normal = 0, equip = 0, k = 0;
- for( i = 0, n = 0, ne = 0; i < items_length; i++ )
- {
- if( items[i].nameid <= 0 )
- continue;
- id = itemdb_search(items[i].nameid);
- if( !itemdb_isstackable2(id) )
- { //Equippable
- WBUFW(bufe,ne*cmd+4)=i+1;
- clif->item_sub(bufe, ne*cmd+6, &items[i], id, id->equip);
- clif->addcards(WBUFP(bufe, ne*cmd+16), &items[i]);
-#if PACKETVER >= 20071002
- WBUFL(bufe,ne*cmd+24)=items[i].expire_time;
- WBUFW(bufe,ne*cmd+28)=0; //Unknown
-#endif
- ne++;
+ for( ; i < items_length && k < 500; i++, k++ ) {
+
+ if( items[i].nameid <= 0 )
+ continue;
+
+ id = itemdb->search(items[i].nameid);
+
+ if( !itemdb->isstackable2(id) ) //Non-stackable (Equippable)
+ clif_item_equip(i+1,&storelist_equip.list[equip++],&items[i],id,id->equip);
+ else //Stackable (Normal)
+ clif_item_normal(i+1,&storelist_normal.list[normal++],&items[i],id);
}
- else
- { //Stackable
- WBUFW(buf,n*s+4)=i+1;
- clif->item_sub(buf, n*s+6, &items[i], id,-1);
-#if PACKETVER >= 5
- clif->addcards(WBUFP(buf,n*s+14), &items[i]);
-#endif
-#if PACKETVER >= 20080102
- WBUFL(buf,n*s+22)=items[i].expire_time;
+
+ if( normal ) {
+ storelist_normal.PacketType = storagelistnormalType;
+ storelist_normal.PacketLength = ( sizeof( storelist_normal ) - sizeof( storelist_normal.list ) ) + (sizeof(struct NORMALITEM_INFO) * normal);
+
+#if PACKETVER >= 20120925
+ safestrncpy(storelist_normal.name, "Storage", NAME_LENGTH);
#endif
- n++;
+
+ clif->send(&storelist_normal, storelist_normal.PacketLength, &sd->bl, SELF);
}
- }
- if( n )
- {
-#if PACKETVER < 5
- WBUFW(buf,0)=0xa5;
-#elif PACKETVER < 20080102
- WBUFW(buf,0)=0x1f0;
-#else
- WBUFW(buf,0)=0x2ea;
-#endif
- WBUFW(buf,2)=4+n*s;
- clif->send(buf, WBUFW(buf,2), &sd->bl, SELF);
- }
- if( ne )
- {
-#if PACKETVER < 20071002
- WBUFW(bufe,0)=0xa6;
-#else
- WBUFW(bufe,0)=0x2d1;
+
+ if( equip ) {
+ storelist_equip.PacketType = storagelistequipType;
+ storelist_equip.PacketLength = ( sizeof( storelist_equip ) - sizeof( storelist_equip.list ) ) + (sizeof(struct EQUIPITEM_INFO) * equip);
+
+#if PACKETVER >= 20120925
+ safestrncpy(storelist_equip.name, "Storage", NAME_LENGTH);
#endif
- WBUFW(bufe,2)=4+ne*cmd;
- clif->send(bufe, WBUFW(bufe,2), &sd->bl, SELF);
- }
- if( buf ) aFree(buf);
- if( bufe ) aFree(bufe);
+ clif->send(&storelist_equip, storelist_equip.PacketLength, &sd->bl, SELF);
+ }
+
+ } while ( i < items_length );
+
}
-void clif_cartlist(struct map_session_data *sd)
-{
+void clif_cartlist(struct map_session_data *sd) {
+ int i, normal = 0, equip = 0;
struct item_data *id;
- int i,n,ne;
- unsigned char *buf;
- unsigned char *bufe;
-#if PACKETVER < 5
- const int s = 10; //Entry size.
-#elif PACKETVER < 20080102
- const int s = 18;
-#else
- const int s = 22;
-#endif
-#if PACKETVER < 20071002
- const int cmd = 20;
-#elif PACKETVER < 20100629
- const int cmd = 26;
-#else
- const int cmd = 28;
-#endif
- buf = (unsigned char*)aMalloc(MAX_CART * s + 4);
- bufe = (unsigned char*)aMalloc(MAX_CART * cmd + 4);
+ for( i = 0; i < MAX_CART; i++ ) {
- for( i = 0, n = 0, ne = 0; i < MAX_CART; i++ )
- {
if( sd->status.cart[i].nameid <= 0 )
continue;
- id = itemdb_search(sd->status.cart[i].nameid);
- if( !itemdb_isstackable2(id) )
- { //Equippable
- WBUFW(bufe,ne*cmd+4)=i+2;
- clif->item_sub(bufe, ne*cmd+6, &sd->status.cart[i], id, id->equip);
- clif->addcards(WBUFP(bufe, ne*cmd+16), &sd->status.cart[i]);
-#if PACKETVER >= 20071002
- WBUFL(bufe,ne*cmd+24)=sd->status.cart[i].expire_time;
- WBUFW(bufe,ne*cmd+28)=0; //Unknown
-#endif
- ne++;
- }
- else
- { //Stackable
- WBUFW(buf,n*s+4)=i+2;
- clif->item_sub(buf, n*s+6, &sd->status.cart[i], id,-1);
-#if PACKETVER >= 5
- clif->addcards(WBUFP(buf,n*s+14), &sd->status.cart[i]);
-#endif
-#if PACKETVER >= 20080102
- WBUFL(buf,n*s+22)=sd->status.cart[i].expire_time;
-#endif
- n++;
- }
- }
- if( n )
- {
-#if PACKETVER < 5
- WBUFW(buf,0)=0x123;
-#elif PACKETVER < 20080102
- WBUFW(buf,0)=0x1ef;
-#else
- WBUFW(buf,0)=0x2e9;
-#endif
- WBUFW(buf,2)=4+n*s;
- clif->send(buf, WBUFW(buf,2), &sd->bl, SELF);
+
+ id = itemdb->search(sd->status.cart[i].nameid);
+
+ if( !itemdb->isstackable2(id) ) //Non-stackable (Equippable)
+ clif_item_equip(i+2,&itemlist_equip.list[equip++],&sd->status.cart[i],id,id->equip);
+ else //Stackable (Normal)
+ clif_item_normal(i+2,&itemlist_normal.list[normal++],&sd->status.cart[i],id);
}
- if( ne )
- {
-#if PACKETVER < 20071002
- WBUFW(bufe,0)=0x122;
-#else
- WBUFW(bufe,0)=0x2d2;
-#endif
- WBUFW(bufe,2)=4+ne*cmd;
- clif->send(bufe, WBUFW(bufe,2), &sd->bl, SELF);
+
+ if( normal ) {
+ itemlist_normal.PacketType = cartlistnormalType;
+ itemlist_normal.PacketLength = 4 + (sizeof(struct NORMALITEM_INFO) * normal);
+
+ clif->send(&itemlist_normal, itemlist_normal.PacketLength, &sd->bl, SELF);
}
- if( buf ) aFree(buf);
- if( bufe ) aFree(bufe);
+ if( equip ) {
+ itemlist_equip.PacketType = cartlistequipType;
+ itemlist_equip.PacketLength = 4 + (sizeof(struct EQUIPITEM_INFO) * equip);
+
+ clif->send(&itemlist_equip, itemlist_equip.PacketLength, &sd->bl, SELF);
+ }
}
/// Removes cart (ZC_CARTOFF).
/// 012b
-/// Client behaviour:
+/// Client behavior:
/// Closes the cart storage and removes all it's items from memory.
/// The Num & Weight values of the cart are left untouched and the cart is NOT removed.
void clif_clearcart(int fd)
@@ -2692,14 +2648,14 @@ void read_channels_config(void) {
config_t channels_conf;
config_setting_t *chsys = NULL;
const char *config_filename = "conf/channels.conf"; // FIXME hardcoded name
-
- if (conf_read_file(&channels_conf, config_filename))
+
+ if (libconfig->read_file(&channels_conf, config_filename))
return;
-
- chsys = config_lookup(&channels_conf, "chsys");
-
+
+ chsys = libconfig->lookup(&channels_conf, "chsys");
+
if (chsys != NULL) {
- config_setting_t *settings = config_setting_get_elem(chsys, 0);
+ config_setting_t *settings = libconfig->setting_get_elem(chsys, 0);
config_setting_t *channels;
config_setting_t *colors;
int i,k;
@@ -2710,45 +2666,46 @@ void read_channels_config(void) {
local_autojoin = 0, ally_autojoin = 0,
allow_user_channel_creation = 0,
irc_enabled = 0;
-
- if( !config_setting_lookup_string(settings, "map_local_channel_name", &local_name) )
+
+ if( !libconfig->setting_lookup_string(settings, "map_local_channel_name", &local_name) )
local_name = "map";
safestrncpy(hChSys.local_name, local_name, HCHSYS_NAME_LENGTH);
-
- if( !config_setting_lookup_string(settings, "ally_channel_name", &ally_name) )
+
+ if( !libconfig->setting_lookup_string(settings, "ally_channel_name", &ally_name) )
ally_name = "ally";
safestrncpy(hChSys.ally_name, ally_name, HCHSYS_NAME_LENGTH);
-
- if( !config_setting_lookup_string(settings, "irc_channel_name", &irc_name) )
+
+ if( !libconfig->setting_lookup_string(settings, "irc_channel_name", &irc_name) )
irc_name = "irc";
safestrncpy(hChSys.irc_name, irc_name, HCHSYS_NAME_LENGTH);
-
- config_setting_lookup_bool(settings, "map_local_channel", &local_enabled);
- config_setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled);
- config_setting_lookup_bool(settings, "irc_channel_enabled", &irc_enabled);
-
+
+ libconfig->setting_lookup_bool(settings, "map_local_channel", &local_enabled);
+ libconfig->setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled);
+ libconfig->setting_lookup_bool(settings, "irc_channel_enabled", &irc_enabled);
+
if( local_enabled )
hChSys.local = true;
if( ally_enabled )
hChSys.ally = true;
if( irc_enabled )
hChSys.irc = true;
-
+
hChSys.irc_server[0] = hChSys.irc_channel[0] = hChSys.irc_nick[0] = hChSys.irc_nick_pw[0] = '\0';
-
+
if( hChSys.irc ) {
const char *irc_server, *irc_channel,
*irc_nick, *irc_nick_pw;
- if( config_setting_lookup_string(settings, "irc_channel_network", &irc_server) ) {
+ int irc_use_ghost = 0;
+ if( libconfig->setting_lookup_string(settings, "irc_channel_network", &irc_server) ) {
if( !strstr(irc_server,":") ) {
hChSys.irc = false;
ShowWarning("channels.conf : network port wasn't found in 'irc_channel_network', disabling irc channel...\n");
} else {
unsigned char d = 0, dlen = strlen(irc_server);
char server[40];
-
+
memset(server, '\0', sizeof(server));
-
+
for(d = 0; d < dlen; d++) {
if(irc_server[d] == ':') {
memcpy(server, irc_server, d);
@@ -2763,13 +2720,13 @@ void read_channels_config(void) {
hChSys.irc = false;
ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n");
}
- if( config_setting_lookup_string(settings, "irc_channel_channel", &irc_channel) )
+ if( libconfig->setting_lookup_string(settings, "irc_channel_channel", &irc_channel) )
safestrncpy(hChSys.irc_channel, irc_channel, 50);
else {
hChSys.irc = false;
ShowWarning("channels.conf : irc channel enabled but irc_channel_channel wasn't found, disabling irc channel...\n");
}
- if( config_setting_lookup_string(settings, "irc_channel_nick", &irc_nick) ) {
+ if( libconfig->setting_lookup_string(settings, "irc_channel_nick", &irc_nick) ) {
if( strcmpi(irc_nick,"Hercules_chSysBot") == 0 ) {
sprintf(hChSys.irc_nick, "Hercules_chSysBot%d",rand()%777);
} else
@@ -2778,103 +2735,106 @@ void read_channels_config(void) {
hChSys.irc = false;
ShowWarning("channels.conf : irc channel enabled but irc_channel_nick wasn't found, disabling irc channel...\n");
}
- if( config_setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw) )
+ if( libconfig->setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw) ) {
safestrncpy(hChSys.irc_nick_pw, irc_nick_pw, 30);
+ config_setting_lookup_bool(settings, "irc_channel_use_ghost", &irc_use_ghost);
+ hChSys.irc_use_ghost = irc_use_ghost;
+ }
}
-
- config_setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin);
- config_setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin);
+
+ libconfig->setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin);
+ libconfig->setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin);
if( local_autojoin )
hChSys.local_autojoin = true;
if( ally_autojoin )
hChSys.ally_autojoin = true;
-
- config_setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation);
+
+ libconfig->setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation);
if( allow_user_channel_creation )
hChSys.allow_user_channel_creation = true;
- if( (colors = config_setting_get_member(settings, "colors")) != NULL ) {
- int color_count = config_setting_length(colors);
- CREATE( hChSys.colors, unsigned long, color_count );
+ if( (colors = libconfig->setting_get_member(settings, "colors")) != NULL ) {
+ int color_count = libconfig->setting_length(colors);
+ CREATE( hChSys.colors, unsigned int, color_count );
CREATE( hChSys.colors_name, char *, color_count );
for(i = 0; i < color_count; i++) {
- config_setting_t *color = config_setting_get_elem(colors, i);
+ config_setting_t *color = libconfig->setting_get_elem(colors, i);
CREATE( hChSys.colors_name[i], char, HCHSYS_NAME_LENGTH );
-
+
safestrncpy(hChSys.colors_name[i], config_setting_name(color), HCHSYS_NAME_LENGTH);
- hChSys.colors[i] = strtoul(config_setting_get_string_elem(colors,i),NULL,0);
+ hChSys.colors[i] = (unsigned int)strtoul(libconfig->setting_get_string_elem(colors,i),NULL,0);
hChSys.colors[i] = (hChSys.colors[i] & 0x0000FF) << 16 | (hChSys.colors[i] & 0x00FF00) | (hChSys.colors[i] & 0xFF0000) >> 16;//RGB to BGR
}
hChSys.colors_count = color_count;
}
-
- config_setting_lookup_string(settings, "map_local_channel_color", &local_color);
-
+
+ libconfig->setting_lookup_string(settings, "map_local_channel_color", &local_color);
+
for (k = 0; k < hChSys.colors_count; k++) {
if( strcmpi(hChSys.colors_name[k],local_color) == 0 )
break;
}
-
+
if( k < hChSys.colors_count ) {
hChSys.local_color = k;
} else {
ShowError("channels.conf: unknown color '%s' for 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name);
hChSys.local = false;
}
-
- config_setting_lookup_string(settings, "ally_channel_color", &ally_color);
-
+
+ libconfig->setting_lookup_string(settings, "ally_channel_color", &ally_color);
+
for (k = 0; k < hChSys.colors_count; k++) {
if( strcmpi(hChSys.colors_name[k],ally_color) == 0 )
break;
}
-
+
if( k < hChSys.colors_count ) {
hChSys.ally_color = k;
} else {
ShowError("channels.conf: unknown color '%s' for 'ally_channel_color', disabling '#%s'...\n",ally_color,ally_name);
hChSys.ally = false;
}
-
- config_setting_lookup_string(settings, "irc_channel_color", &irc_color);
-
+
+ libconfig->setting_lookup_string(settings, "irc_channel_color", &irc_color);
+
for (k = 0; k < hChSys.colors_count; k++) {
if( strcmpi(hChSys.colors_name[k],irc_color) == 0 )
break;
}
-
+
if( k < hChSys.colors_count ) {
hChSys.irc_color = k;
} else {
ShowError("channels.conf: unknown color '%s' for 'irc_channel_color', disabling '#%s'...\n",irc_color,irc_name);
hChSys.irc = false;
}
-
+
if( hChSys.irc ) {
struct hChSysCh *chd;
CREATE( chd, struct hChSysCh, 1 );
-
+
safestrncpy(chd->name, hChSys.irc_name, HCHSYS_NAME_LENGTH);
chd->type = hChSys_IRC;
-
+
clif->chsys_create(chd,NULL,NULL,hChSys.irc_color);
ircbot->channel = chd;
}
-
- if( (channels = config_setting_get_member(settings, "default_channels")) != NULL ) {
- int channel_count = config_setting_length(channels);
-
+
+ if( (channels = libconfig->setting_get_member(settings, "default_channels")) != NULL ) {
+ int channel_count = libconfig->setting_length(channels);
+
for(i = 0; i < channel_count; i++) {
- config_setting_t *channel = config_setting_get_elem(channels, i);
+ config_setting_t *channel = libconfig->setting_get_elem(channels, i);
const char *name = config_setting_name(channel);
- const char *color = config_setting_get_string_elem(channels,i);
+ const char *color = libconfig->setting_get_string_elem(channels,i);
struct hChSysCh *chd;
-
+
for (k = 0; k < hChSys.colors_count; k++) {
if( strcmpi(hChSys.colors_name[k],color) == 0 )
break;
@@ -2889,16 +2849,16 @@ void read_channels_config(void) {
}
CREATE( chd, struct hChSysCh, 1 );
-
+
safestrncpy(chd->name, name, HCHSYS_NAME_LENGTH);
chd->type = hChSys_PUBLIC;
-
+
clif->chsys_create(chd,NULL,NULL,k);
}
}
-
+
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(clif->channel_db), config_filename);
- config_destroy(&channels_conf);
+ libconfig->destroy(&channels_conf);
}
}
@@ -2951,7 +2911,7 @@ int clif_hpmeter_sub(struct block_list *bl, va_list ap) {
*------------------------------------------*/
int clif_hpmeter(struct map_session_data *sd) {
nullpo_ret(sd);
- iMap->foreachinarea(clif->hpmeter_sub, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd);
+ map->foreachinarea(clif->hpmeter_sub, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd);
return 0;
}
@@ -2963,10 +2923,9 @@ int clif_hpmeter(struct map_session_data *sd) {
/// 013a <atk range>.W (ZC_ATTACK_RANGE)
/// 0141 <status id>.L <base status>.L <plus status>.L (ZC_COUPLESTATUS)
/// TODO: Extract individual packets.
-/// FIXME: Packet lengths from packet_len(cmd)
void clif_updatestatus(struct map_session_data *sd,int type)
{
- int fd,len=8;
+ int fd,len;
nullpo_retv(sd);
@@ -2978,6 +2937,7 @@ void clif_updatestatus(struct map_session_data *sd,int type)
WFIFOHEAD(fd, 14);
WFIFOW(fd,0)=0xb0;
WFIFOW(fd,2)=type;
+ len = packet_len(0xb0);
switch(type){
// 00b0
case SP_WEIGHT:
@@ -3029,7 +2989,8 @@ void clif_updatestatus(struct map_session_data *sd,int type)
case SP_HP:
WFIFOL(fd,4)=sd->battle_status.hp;
// TODO: Won't these overwrite the current packet?
- clif->hpmeter(sd);
+ if( map->list[sd->bl.m].hpmeter_visible )
+ clif->hpmeter(sd);
if( !battle_config.party_hp_mode && sd->status.party_id )
clif->party_hp(sd);
if( sd->bg_id )
@@ -3082,22 +3043,27 @@ void clif_updatestatus(struct map_session_data *sd,int type)
case SP_ZENY:
WFIFOW(fd,0)=0xb1;
WFIFOL(fd,4)=sd->status.zeny;
+ len = packet_len(0xb1);
break;
case SP_BASEEXP:
WFIFOW(fd,0)=0xb1;
WFIFOL(fd,4)=sd->status.base_exp;
+ len = packet_len(0xb1);
break;
case SP_JOBEXP:
WFIFOW(fd,0)=0xb1;
WFIFOL(fd,4)=sd->status.job_exp;
+ len = packet_len(0xb1);
break;
case SP_NEXTBASEEXP:
WFIFOW(fd,0)=0xb1;
WFIFOL(fd,4)=pc->nextbaseexp(sd);
+ len = packet_len(0xb1);
break;
case SP_NEXTJOBEXP:
WFIFOW(fd,0)=0xb1;
WFIFOL(fd,4)=pc->nextjobexp(sd);
+ len = packet_len(0xb1);
break;
/**
@@ -3111,7 +3077,7 @@ void clif_updatestatus(struct map_session_data *sd,int type)
case SP_ULUK:
WFIFOW(fd,0)=0xbe;
WFIFOB(fd,4)=pc->need_status_point(sd,type-SP_USTR+SP_STR,1);
- len=5;
+ len = packet_len(0xbe);
break;
/**
@@ -3120,7 +3086,7 @@ void clif_updatestatus(struct map_session_data *sd,int type)
case SP_ATTACKRANGE:
WFIFOW(fd,0)=0x13a;
WFIFOW(fd,2)=sd->battle_status.rhw.range;
- len=4;
+ len = packet_len(0x13a);
break;
case SP_STR:
@@ -3128,42 +3094,42 @@ void clif_updatestatus(struct map_session_data *sd,int type)
WFIFOL(fd,2)=type;
WFIFOL(fd,6)=sd->status.str;
WFIFOL(fd,10)=sd->battle_status.str - sd->status.str;
- len=14;
+ len = packet_len(0x141);
break;
case SP_AGI:
WFIFOW(fd,0)=0x141;
WFIFOL(fd,2)=type;
WFIFOL(fd,6)=sd->status.agi;
WFIFOL(fd,10)=sd->battle_status.agi - sd->status.agi;
- len=14;
+ len = packet_len(0x141);
break;
case SP_VIT:
WFIFOW(fd,0)=0x141;
WFIFOL(fd,2)=type;
WFIFOL(fd,6)=sd->status.vit;
WFIFOL(fd,10)=sd->battle_status.vit - sd->status.vit;
- len=14;
+ len = packet_len(0x141);
break;
case SP_INT:
WFIFOW(fd,0)=0x141;
WFIFOL(fd,2)=type;
WFIFOL(fd,6)=sd->status.int_;
WFIFOL(fd,10)=sd->battle_status.int_ - sd->status.int_;
- len=14;
+ len = packet_len(0x141);
break;
case SP_DEX:
WFIFOW(fd,0)=0x141;
WFIFOL(fd,2)=type;
WFIFOL(fd,6)=sd->status.dex;
WFIFOL(fd,10)=sd->battle_status.dex - sd->status.dex;
- len=14;
+ len = packet_len(0x141);
break;
case SP_LUK:
WFIFOW(fd,0)=0x141;
WFIFOL(fd,2)=type;
WFIFOL(fd,6)=sd->status.luk;
WFIFOL(fd,10)=sd->battle_status.luk - sd->status.luk;
- len=14;
+ len = packet_len(0x141);
break;
case SP_CARTINFO:
@@ -3172,7 +3138,7 @@ void clif_updatestatus(struct map_session_data *sd,int type)
WFIFOW(fd,4)=MAX_CART;
WFIFOL(fd,6)=sd->cart_weight;
WFIFOL(fd,10)=sd->cart_weight_max;
- len=14;
+ len = packet_len(0x121);
break;
default:
@@ -3182,7 +3148,6 @@ void clif_updatestatus(struct map_session_data *sd,int type)
WFIFOSET(fd,len);
}
-
/// Notifies client of a parameter change of an another player (ZC_PAR_CHANGE_USER).
/// 01ab <account id>.L <var id>.W <value>.L
void clif_changestatus(struct map_session_data* sd,int type,int val)
@@ -3222,9 +3187,9 @@ void clif_changelook(struct block_list *bl,int type,int val)
nullpo_retv(bl);
sd = BL_CAST(BL_PC, bl);
- sc = status_get_sc(bl);
- vd = status_get_viewdata(bl);
- //nullpo_ret(vd);
+ sc = status->get_sc(bl);
+ vd = status->get_viewdata(bl);
+
if( vd ) //temp hack to let Warp Portal change appearance
switch(type) {
case LOOK_WEAPON:
@@ -3245,13 +3210,19 @@ void clif_changelook(struct block_list *bl,int type,int val)
break;
case LOOK_BASE:
if( !sd ) break;
-
- if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) )
+ // We shouldn't update LOOK_BASE if the player is disguised
+ // if we do so the client will think that the player class
+ // is really a mob and issues like 7725 will happen in every
+ // SC_ that alters class_ in any way [Panikon]
+ if( sd->disguise != -1 )
+ return;
+
+ if( sd->sc.option&OPTION_COSTUME )
vd->weapon = vd->shield = 0;
-
+
if( !vd->cloth_color )
break;
-
+
if( sd ) {
if( sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette )
vd->cloth_color = 0;
@@ -3261,6 +3232,8 @@ void clif_changelook(struct block_list *bl,int type,int val)
vd->cloth_color = 0;
if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette )
vd->cloth_color = 0;
+ if( sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */ )
+ vd->cloth_color = 0;
}
break;
case LOOK_HAIR:
@@ -3288,6 +3261,8 @@ void clif_changelook(struct block_list *bl,int type,int val)
val = 0;
if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette )
val = 0;
+ if( sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */ )
+ val = 0;
}
vd->cloth_color = val;
break;
@@ -3333,6 +3308,7 @@ void clif_changelook(struct block_list *bl,int type,int val)
WBUFW(buf,0)=0x1d7;
WBUFL(buf,2)=bl->id;
if(type == LOOK_WEAPON || type == LOOK_SHIELD) {
+ nullpo_retv(vd);
WBUFB(buf,6)=LOOK_WEAPON;
WBUFW(buf,7)=vd->weapon;
WBUFW(buf,9)=vd->shield;
@@ -3341,7 +3317,7 @@ void clif_changelook(struct block_list *bl,int type,int val)
WBUFL(buf,7)=val;
}
clif->send(buf,packet_len(0x1d7),bl,target);
- if( disguised(bl) && ((TBL_PC*)sd)->fontcolor ) {
+ if( disguised(bl) && sd && sd->fontcolor ) {
WBUFL(buf,2)=-bl->id;
clif->send(buf,packet_len(0x1d7),bl,SELF);
}
@@ -3510,14 +3486,14 @@ void clif_arrow_create_list(struct map_session_data *sd)
WFIFOW(fd,0) = 0x1ad;
for (i = 0, c = 0; i < MAX_SKILL_ARROW_DB; i++) {
- if (skill_arrow_db[i].nameid > 0 &&
- (j = pc->search_inventory(sd, skill_arrow_db[i].nameid)) >= 0 &&
- !sd->status.inventory[j].equip && sd->status.inventory[j].identify)
- {
- if ((j = itemdb_viewid(skill_arrow_db[i].nameid)) > 0)
+ if (skill->arrow_db[i].nameid > 0
+ && (j = pc->search_inventory(sd, skill->arrow_db[i].nameid)) != INDEX_NOT_FOUND
+ && !sd->status.inventory[j].equip && sd->status.inventory[j].identify
+ ) {
+ if ((j = itemdb_viewid(skill->arrow_db[i].nameid)) > 0)
WFIFOW(fd,c*2+4) = j;
else
- WFIFOW(fd,c*2+4) = skill_arrow_db[i].nameid;
+ WFIFOW(fd,c*2+4) = skill->arrow_db[i].nameid;
c++;
}
}
@@ -3556,52 +3532,39 @@ void clif_statusupack(struct map_session_data *sd,int type,int ok,int val)
/// Notifies the client about the result of a request to equip an item (ZC_REQ_WEAR_EQUIP_ACK).
/// 00aa <index>.W <equip location>.W <result>.B
/// 00aa <index>.W <equip location>.W <view id>.W <result>.B (PACKETVER >= 20100629)
-/// result:
-/// 0 = failure
-/// 1 = success
-/// 2 = failure due to low level
-void clif_equipitemack(struct map_session_data *sd,int n,int pos,int ok)
-{
- int fd;
+void clif_equipitemack(struct map_session_data *sd,int n,int pos,enum e_EQUIP_ITEM_ACK result) {
+ struct packet_equipitem_ack p;
nullpo_retv(sd);
- fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0xaa));
- WFIFOW(fd,0)=0xaa;
- WFIFOW(fd,2)=n+2;
- WFIFOW(fd,4)=pos;
-#if PACKETVER < 20100629
- WFIFOB(fd,6)=ok;
-#else
- if (ok && sd->inventory_data[n]->equip&EQP_VISIBLE)
- WFIFOW(fd,6)=sd->inventory_data[n]->look;
+ p.PacketType = equipitemackType;
+ p.index = n+2;
+ p.wearLocation = pos;
+#if PACKETVER >= 20100629
+ if (result == EIA_SUCCESS && sd->inventory_data[n]->equip&EQP_VISIBLE)
+ p.wItemSpriteNumber = sd->inventory_data[n]->look;
else
- WFIFOW(fd,6)=0;
- WFIFOB(fd,8)=ok;
+ p.wItemSpriteNumber = 0;
#endif
- WFIFOSET(fd,packet_len(0xaa));
+ p.result = (unsigned char)result;
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
}
/// Notifies the client about the result of a request to take off an item (ZC_REQ_TAKEOFF_EQUIP_ACK).
/// 00ac <index>.W <equip location>.W <result>.B
-/// result:
-/// 0 = failure
-/// 1 = success
-void clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok)
-{
- int fd;
+void clif_unequipitemack(struct map_session_data *sd,int n,int pos,enum e_UNEQUIP_ITEM_ACK result) {
+ struct packet_unequipitem_ack p;
nullpo_retv(sd);
- fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0xac));
- WFIFOW(fd,0)=0xac;
- WFIFOW(fd,2)=n+2;
- WFIFOW(fd,4)=pos;
- WFIFOB(fd,6)=ok;
- WFIFOSET(fd,packet_len(0xac));
+ p.PacketType = unequipitemackType;
+ p.index = n+2;
+ p.wearLocation = pos;
+ p.result = (unsigned char)result;
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
}
@@ -3642,9 +3605,9 @@ void clif_changeoption(struct block_list* bl)
struct map_session_data* sd;
nullpo_retv(bl);
-
- if ( !(sc = status_get_sc(bl)) && bl->type != BL_NPC ) return; //How can an option change if there's no sc?
-
+
+ if ( !(sc = status->get_sc(bl)) && bl->type != BL_NPC ) return; //How can an option change if there's no sc?
+
sd = BL_CAST(BL_PC, bl);
#if PACKETVER >= 7
@@ -3689,7 +3652,7 @@ void clif_changeoption2(struct block_list* bl) {
unsigned char buf[20];
struct status_change *sc;
- if ( !(sc = status_get_sc(bl)) && bl->type != BL_NPC ) return; //How can an option change if there's no sc?
+ if ( !(sc = status->get_sc(bl)) && bl->type != BL_NPC ) return; //How can an option change if there's no sc?
WBUFW(buf,0) = 0x28a;
WBUFL(buf,2) = bl->id;
@@ -3750,8 +3713,8 @@ void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok)
}
}
-void clif_hercules_chsys_send(struct hChSysCh *channel, struct map_session_data *sd, char *msg) {
- if( channel->msg_delay != 0 && DIFF_TICK(sd->hchsysch_tick + ( channel->msg_delay * 1000 ), iTimer->gettick()) > 0 && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) {
+void clif_hercules_chsys_send(struct hChSysCh *channel, struct map_session_data *sd, const char *msg) {
+ if( channel->msg_delay != 0 && DIFF_TICK(sd->hchsysch_tick + ( channel->msg_delay * 1000 ), timer->gettick()) > 0 && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) {
clif->colormes(sd->fd,COLOR_RED,msg_txt(1455));
return;
} else {
@@ -3761,7 +3724,7 @@ void clif_hercules_chsys_send(struct hChSysCh *channel, struct map_session_data
if( channel->type == hChSys_IRC )
ircbot->relay(sd->status.name,msg);
if( channel->msg_delay != 0 )
- sd->hchsysch_tick = iTimer->gettick();
+ sd->hchsysch_tick = timer->gettick();
}
}
@@ -4004,8 +3967,7 @@ void clif_leavechat(struct chat_data* cd, struct map_session_data* sd, bool flag
/// Opens a trade request window from char 'name'.
/// 00e5 <nick>.24B (ZC_REQ_EXCHANGE_ITEM)
/// 01f4 <nick>.24B <charid>.L <baselvl>.W (ZC_REQ_EXCHANGE_ITEM2)
-void clif_traderequest(struct map_session_data* sd, const char* name)
-{
+void clif_traderequest(struct map_session_data* sd, const char* name) {
int fd = sd->fd;
#if PACKETVER < 6
@@ -4013,8 +3975,8 @@ void clif_traderequest(struct map_session_data* sd, const char* name)
WFIFOW(fd,0) = 0xe5;
safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH);
WFIFOSET(fd,packet_len(0xe5));
-#else
- struct map_session_data* tsd = iMap->id2sd(sd->trade_partner);
+#else // PACKETVER >= 6
+ struct map_session_data* tsd = map->id2sd(sd->trade_partner);
if( !tsd ) return;
WFIFOHEAD(fd,packet_len(0x1f4));
@@ -4023,7 +3985,7 @@ void clif_traderequest(struct map_session_data* sd, const char* name)
WFIFOL(fd,26) = tsd->status.char_id;
WFIFOW(fd,30) = tsd->status.base_level;
WFIFOSET(fd,packet_len(0x1f4));
-#endif
+#endif // PACKETVER < 6
}
@@ -4037,23 +3999,24 @@ void clif_traderequest(struct map_session_data* sd, const char* name)
/// 3 = Accept
/// 4 = Cancel
/// 5 = Busy
-void clif_tradestart(struct map_session_data* sd, uint8 type)
-{
+void clif_tradestart(struct map_session_data* sd, uint8 type) {
int fd = sd->fd;
- struct map_session_data* tsd = iMap->id2sd(sd->trade_partner);
- if( PACKETVER < 6 || !tsd ) {
- WFIFOHEAD(fd,packet_len(0xe7));
- WFIFOW(fd,0) = 0xe7;
- WFIFOB(fd,2) = type;
- WFIFOSET(fd,packet_len(0xe7));
- } else {
+#if PACKETVER >= 6
+ struct map_session_data* tsd = map->id2sd(sd->trade_partner);
+ if( tsd ) {
WFIFOHEAD(fd,packet_len(0x1f5));
WFIFOW(fd,0) = 0x1f5;
WFIFOB(fd,2) = type;
WFIFOL(fd,3) = tsd->status.char_id;
WFIFOW(fd,7) = tsd->status.base_level;
WFIFOSET(fd,packet_len(0x1f5));
+ return;
}
+#endif // PACKETVER >= 6
+ WFIFOHEAD(fd,packet_len(0xe7));
+ WFIFOW(fd,0) = 0xe7;
+ WFIFOB(fd,2) = type;
+ WFIFOSET(fd,packet_len(0xe7));
}
@@ -4252,7 +4215,7 @@ void clif_storageitemadded(struct map_session_data* sd, struct item* i, int inde
WFIFOW(fd, 2) = index+1; // index
WFIFOL(fd, 4) = amount; // amount
WFIFOW(fd, 8) = ( view > 0 ) ? view : i->nameid; // id
- WFIFOB(fd,10) = itemdb_type(i->nameid); //type
+ WFIFOB(fd,10) = itemtype(itemdb_type(i->nameid)); //type
WFIFOB(fd,11) = i->identify; //identify flag
WFIFOB(fd,12) = i->attribute; // attribute
WFIFOB(fd,13) = i->refine; //refine
@@ -4302,7 +4265,7 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
if( dstsd->chatID ) {
struct chat_data *cd = NULL;
- if( (cd = (struct chat_data*)iMap->id2bl(dstsd->chatID)) && cd->usersd[0]==dstsd)
+ if( (cd = (struct chat_data*)map->id2bl(dstsd->chatID)) && cd->usersd[0]==dstsd)
clif->dispchat(cd,sd->fd);
} else if( dstsd->state.vending )
clif->showvendingboard(&dstsd->bl,dstsd->message,sd->fd);
@@ -4316,7 +4279,7 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
clif->charm_single(sd->fd, dstsd, i);
}
for( i = 0; i < dstsd->sc_display_count; i++ ) {
- clif->sc_load(&sd->bl,dstsd->bl.id,SELF,StatusIconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3);
+ clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3);
}
if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting.
(sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround
@@ -4331,7 +4294,7 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
ARR_FIND( 0, 5, i, dstsd->devotion[i] > 0 );
if( i < 5 ) clif->devotion(&dstsd->bl, sd);
// display link (dstsd - crusader) to sd
- if( dstsd->sc.data[SC_DEVOTION] && (d_bl = iMap->id2bl(dstsd->sc.data[SC_DEVOTION]->val1)) != NULL )
+ if( dstsd->sc.data[SC_DEVOTION] && (d_bl = map->id2bl(dstsd->sc.data[SC_DEVOTION]->val1)) != NULL )
clif->devotion(d_bl, sd);
}
@@ -4339,7 +4302,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
struct unit_data *ud;
struct view_data *vd;
- vd = status_get_viewdata(bl);
+ vd = status->get_viewdata(bl);
if (!vd || vd->class_ == INVISIBLE_CLASS)
return;
@@ -4349,7 +4312,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->option&OPTION_INVISIBLE))
return;
- if ( ( ud = unit_bl2ud(bl) ) && ud->walktimer != INVALID_TIMER )
+ if ( ( ud = unit->bl2ud(bl) ) && ud->walktimer != INVALID_TIMER )
clif->set_unit_walking(bl,sd,ud,SELF);
else
clif->set_unit_idle(bl,sd,SELF);
@@ -4363,9 +4326,9 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
clif->getareachar_pc(sd, tsd);
if(tsd->state.size==SZ_BIG) // tiny/big players [Valaris]
clif->specialeffect_single(bl,423,sd->fd);
- else if(tsd->state.size==SZ_MEDIUM)
+ else if(tsd->state.size==SZ_SMALL)
clif->specialeffect_single(bl,421,sd->fd);
- if( tsd->bg_id && map[tsd->bl.m].flag.battleground )
+ if( tsd->bg_id && map->list[tsd->bl.m].flag.battleground )
clif->sendbgemblem_single(sd->fd,tsd);
if ( tsd->status.robe )
clif->refreshlook(&sd->bl,bl->id,LOOK_ROBE,tsd->status.robe,SELF);
@@ -4379,10 +4342,10 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
{
TBL_NPC* nd = (TBL_NPC*)bl;
if( nd->chat_id )
- clif->dispchat((struct chat_data*)iMap->id2bl(nd->chat_id),sd->fd);
+ clif->dispchat((struct chat_data*)map->id2bl(nd->chat_id),sd->fd);
if( nd->size == SZ_BIG )
clif->specialeffect_single(bl,423,sd->fd);
- else if( nd->size == SZ_MEDIUM )
+ else if( nd->size == SZ_SMALL )
clif->specialeffect_single(bl,421,sd->fd);
}
break;
@@ -4391,7 +4354,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
TBL_MOB* md = (TBL_MOB*)bl;
if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris]
clif->specialeffect_single(bl,423,sd->fd);
- else if(md->special_state.size==SZ_MEDIUM)
+ else if(md->special_state.size==SZ_SMALL)
clif->specialeffect_single(bl,421,sd->fd);
#if PACKETVER >= 20120404
if( !(md->status.mode&MD_BOSS) ){
@@ -4458,79 +4421,74 @@ int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, i
/// 10 = critical hit
/// 11 = lucky dodge
/// 12 = (touch skill?)
-int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int damage, int div, int type, int damage2)
-{
- unsigned char buf[33];
+int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int ddelay, int64 in_damage, short div, unsigned char type, int64 in_damage2) {
+ struct packet_damage p;
struct status_change *sc;
#if PACKETVER < 20071113
- const int cmd = 0x8a;
+ short damage,damage2;
#else
- const int cmd = 0x2e1;
+ int damage,damage2;
#endif
nullpo_ret(src);
nullpo_ret(dst);
- type = clif_calc_delay(type,div,damage+damage2,ddelay);
- sc = status_get_sc(dst);
- if(sc && sc->count) {
- if(sc->data[SC_ILLUSION]) {
- if(damage) damage = damage*(sc->data[SC_ILLUSION]->val2) + rnd()%100;
- if(damage2) damage2 = damage2*(sc->data[SC_ILLUSION]->val2) + rnd()%100;
- }
- }
+ sc = status->get_sc(dst);
- WBUFW(buf,0)=cmd;
- WBUFL(buf,2)=src->id;
- WBUFL(buf,6)=dst->id;
- WBUFL(buf,10)=tick;
- WBUFL(buf,14)=sdelay;
- WBUFL(buf,18)=ddelay;
-#if PACKETVER < 20071113
- if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) {
- WBUFW(buf,22)=damage?div:0;
- WBUFW(buf,27)=damage2?div:0;
- } else {
- WBUFW(buf,22)=min(damage, INT16_MAX);
- WBUFW(buf,27)=damage2;
+ if(sc && sc->count && sc->data[SC_ILLUSION]) {
+ if(in_damage) in_damage = in_damage*(sc->data[SC_ILLUSION]->val2) + rnd()%100;
+ if(in_damage2) in_damage2 = in_damage2*(sc->data[SC_ILLUSION]->val2) + rnd()%100;
}
- WBUFW(buf,24)=div;
- WBUFB(buf,26)=type;
+
+#if PACKETVER < 20071113
+ damage = (short)min(in_damage,INT16_MAX);
+ damage2 = (short)min(in_damage2,INT16_MAX);
#else
- if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) {
- WBUFL(buf,22)=damage?div:0;
- WBUFL(buf,29)=damage2?div:0;
+ damage = (int)min(in_damage,INT_MAX);
+ damage2 = (int)min(in_damage2,INT_MAX);
+#endif
+
+ type = clif_calc_delay(type,div,damage+damage2,ddelay);
+
+ p.PacketType = damageType;
+ p.GID = src->id;
+ p.targetGID = dst->id;
+ p.startTime = (uint32)timer->gettick();
+ p.attackMT = sdelay;
+ p.attackedMT = ddelay;
+ p.count = div;
+ p.action = type;
+
+ if( battle_config.hide_woe_damage && map_flag_gvg2(src->m) ) {
+ p.damage = damage?div:0;
+ p.leftDamage = damage2?div:0;
} else {
- WBUFL(buf,22)=damage;
- WBUFL(buf,29)=damage2;
+ p.damage = damage;
+ p.leftDamage = damage2;
}
- WBUFW(buf,26)=div;
- WBUFB(buf,28)=type;
-#endif
+
if(disguised(dst)) {
- clif->send(buf,packet_len(cmd),dst,AREA_WOS);
- WBUFL(buf,6) = -dst->id;
- clif->send(buf,packet_len(cmd),dst,SELF);
+ clif->send(&p,sizeof(p),dst,AREA_WOS);
+ p.targetGID = -dst->id;
+ clif->send(&p,sizeof(p),dst,SELF);
} else
- clif->send(buf,packet_len(cmd),dst,AREA);
+ clif->send(&p,sizeof(p),dst,AREA);
if(disguised(src)) {
- WBUFL(buf,2) = -src->id;
+ p.GID = -src->id;
if (disguised(dst))
- WBUFL(buf,6) = dst->id;
-#if PACKETVER < 20071113
- if(damage > 0) WBUFW(buf,22) = -1;
- if(damage2 > 0) WBUFW(buf,27) = -1;
-#else
- if(damage > 0) WBUFL(buf,22) = -1;
- if(damage2 > 0) WBUFL(buf,29) = -1;
-#endif
- clif->send(buf,packet_len(cmd),src,SELF);
+ p.targetGID = dst->id;
+
+ if(damage > 0) p.damage = -1;
+ if(damage2 > 0) p.leftDamage = -1;
+
+ clif->send(&p,sizeof(p),src,SELF);
}
if(src == dst) {
- unit_setdir(src,unit_getdir(src));
+ unit->setdir(src,unit->getdir(src));
}
+
//Return adjusted can't walk delay for further processing.
return clif->calc_walkdelay(dst,ddelay,type,damage+damage2,div);
}
@@ -4540,7 +4498,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic
*------------------------------------------*/
void clif_takeitem(struct block_list* src, struct block_list* dst)
{
- //clif_damage(src,dst,0,0,0,0,0,1,0);
+ //clif->damage(src,dst,0,0,0,0,1,0);
unsigned char buf[32];
nullpo_retv(src);
@@ -4595,15 +4553,14 @@ void clif_standing(struct block_list* bl)
/// Inform client(s) about a map-cell change (ZC_UPDATE_MAPINFO).
/// 0192 <x>.W <y>.W <type>.W <map name>.16B
-void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_target target)
-{
+void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_target target) {
unsigned char buf[32];
WBUFW(buf,0) = 0x192;
WBUFW(buf,2) = x;
WBUFW(buf,4) = y;
WBUFW(buf,6) = type;
- mapindex_getmapname_ext(map[m].cName ? map[m].cName : map[m].name,(char*)WBUFP(buf,8));
+ mapindex->getmapname_ext(map->list[m].custom_name ? map->list[map->list[m].instance_src_map].name : map->list[m].name,(char*)WBUFP(buf,8));
if( fd ) {
WFIFOHEAD(fd,packet_len(0x192));
@@ -4642,94 +4599,103 @@ void clif_getareachar_item(struct map_session_data* sd,struct flooritem_data* fi
WFIFOSET(fd,packet_len(0x9d));
}
+void clif_graffiti_entry(struct block_list *bl, struct skill_unit *su, enum send_target target) {
+ struct packet_graffiti_entry p;
+
+ p.PacketType = graffiti_entryType;
+ p.AID = su->bl.id;
+ p.creatorAID = su->group->src_id;
+ p.xPos = su->bl.x;
+ p.yPos = su->bl.y;
+ p.job = su->group->unit_id;
+ p.isContens = 1;
+ p.isVisible = 1;
+ safestrncpy(p.msg, su->group->valstr, 80);
+
+ clif->send(&p,sizeof(p),bl,target);
+}
/// Notifies the client of a skill unit.
/// 011f <id>.L <creator id>.L <x>.W <y>.W <unit id>.B <visible>.B (ZC_SKILL_ENTRY)
/// 01c9 <id>.L <creator id>.L <x>.W <y>.W <unit id>.B <visible>.B <has msg>.B <msg>.80B (ZC_SKILL_ENTRY2)
/// 08c7 <lenght>.W <id> L <creator id>.L <x>.W <y>.W <unit id>.B <range>.W <visible>.B (ZC_SKILL_ENTRY3)
/// 099f <lenght>.W <id> L <creator id>.L <x>.W <y>.W <unit id>.L <range>.W <visible>.B (ZC_SKILL_ENTRY4)
-void clif_getareachar_skillunit(struct map_session_data *sd, struct skill_unit *unit) {
- int fd = sd->fd, header = 0x11f, pos=0;
+void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *su, enum send_target target) {
+ struct packet_skill_entry p;
+ nullpo_retv(bl);
+ nullpo_retv(su);
- if( unit->group->state.guildaura )
+ if( su->group->state.guildaura )
return;
-#if PACKETVER >= 20130320
- if(unit->group->unit_id > UCHAR_MAX){
- header = 0x99f;
- pos = 2;
- }
-#endif
-
#if PACKETVER >= 3
- if(unit->group->unit_id==UNT_GRAFFITI) { // Graffiti [Valaris]
- WFIFOHEAD(fd,packet_len(0x1c9));
- WFIFOW(fd, 0)=0x1c9;
- WFIFOL(fd, 2)=unit->bl.id;
- WFIFOL(fd, 6)=unit->group->src_id;
- WFIFOW(fd,10)=unit->bl.x;
- WFIFOW(fd,12)=unit->bl.y;
- WFIFOB(fd,14)=unit->group->unit_id;
- WFIFOB(fd,15)=1;
- WFIFOB(fd,16)=1;
- safestrncpy((char*)WFIFOP(fd,17),unit->group->valstr,MESSAGE_SIZE);
- WFIFOSET(fd,packet_len(0x1c9));
+ if(su->group->unit_id == UNT_GRAFFITI) {
+ clif->graffiti_entry(bl,su,target);
return;
}
#endif
- WFIFOHEAD(fd,packet_len(header));
- WFIFOW(fd, 0)=header;
- if(pos > 0)
- WFIFOL(fd, pos)=packet_len(header);
- WFIFOL(fd, 2 + pos)=unit->bl.id;
- WFIFOL(fd, 6 + pos)=unit->group->src_id;
- WFIFOW(fd,10 + pos)=unit->bl.x;
- WFIFOW(fd,12 + pos)=unit->bl.y;
- if (battle_config.traps_setting&1 && skill->get_inf2(unit->group->skill_id)&INF2_TRAP)
- WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps.
- else if (skill->get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT))
- WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps.
- else if(pos > 0){
- WFIFOL(fd,16)=unit->group->unit_id;
- WFIFOW(fd,20)=unit->range;
- pos += 5;
- }else
- WFIFOB(fd,14)=unit->group->unit_id;
- WFIFOB(fd,15 + pos)=1; // ignored by client (always gets set to 1)
- WFIFOSET(fd,packet_len(header));
- if(unit->group->skill_id == WZ_ICEWALL)
- clif->changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,5,SELF);
+ p.PacketType = skill_entryType;
+
+#if PACKETVER >= 20110718
+ p.PacketLength = sizeof(p);
+#endif
+
+ p.AID = su->bl.id;
+ p.creatorAID = su->group->src_id;
+ p.xPos = su->bl.x;
+ p.yPos = su->bl.y;
+
+ //Use invisible unit id for traps.
+ if ((battle_config.traps_setting&1 && skill->get_inf2(su->group->skill_id)&INF2_TRAP) ||
+ (skill->get_unit_flag(su->group->skill_id) & UF_RANGEDSINGLEUNIT && !(su->val2 & UF_RANGEDSINGLEUNIT)))
+ p.job = UNT_DUMMYSKILL;
+ else
+ p.job = su->group->unit_id;
+
+#if PACKETVER >= 20110718
+ p.RadiusRange = (unsigned char)su->range;
+#endif
+
+ p.isVisible = 1;
+
+#if PACKETVER >= 20130731
+ p.level = (unsigned char)su->group->skill_lv;
+#endif
+
+ clif->send(&p,sizeof(p),bl,target);
+
+ if(su->group->skill_id == WZ_ICEWALL)
+ clif->changemapcell(bl->type == BL_PC ? ((TBL_PC*)bl)->fd : 0,su->bl.m,su->bl.x,su->bl.y,5,SELF);
}
/*==========================================
* Server tells client to remove unit of id 'unit->bl.id'
*------------------------------------------*/
-void clif_clearchar_skillunit(struct skill_unit *unit, int fd) {
- nullpo_retv(unit);
+void clif_clearchar_skillunit(struct skill_unit *su, int fd) {
+ nullpo_retv(su);
WFIFOHEAD(fd,packet_len(0x120));
WFIFOW(fd, 0)=0x120;
- WFIFOL(fd, 2)=unit->bl.id;
+ WFIFOL(fd, 2)=su->bl.id;
WFIFOSET(fd,packet_len(0x120));
- if(unit->group && unit->group->skill_id == WZ_ICEWALL)
- clif->changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,SELF);
+ if(su->group && su->group->skill_id == WZ_ICEWALL)
+ clif->changemapcell(fd,su->bl.m,su->bl.x,su->bl.y,su->val2,SELF);
}
/// Removes a skill unit (ZC_SKILL_DISAPPEAR).
/// 0120 <id>.L
-void clif_skill_delunit(struct skill_unit *unit)
-{
+void clif_skill_delunit(struct skill_unit *su) {
unsigned char buf[16];
- nullpo_retv(unit);
+ nullpo_retv(su);
WBUFW(buf, 0)=0x120;
- WBUFL(buf, 2)=unit->bl.id;
- clif->send(buf,packet_len(0x120),&unit->bl,AREA);
+ WBUFL(buf, 2)=su->bl.id;
+ clif->send(buf,packet_len(0x120),&su->bl,AREA);
}
@@ -4766,7 +4732,7 @@ int clif_getareachar(struct block_list* bl,va_list ap) {
clif->getareachar_item(sd,(struct flooritem_data*) bl);
break;
case BL_SKILL:
- clif->getareachar_skillunit(sd,(TBL_SKILL*)bl);
+ clif->getareachar_skillunit(&sd->bl,(TBL_SKILL*)bl,SELF);
break;
default:
if(&sd->bl == bl)
@@ -4791,13 +4757,14 @@ int clif_outsight(struct block_list *bl,va_list ap)
tsd = BL_CAST(BL_PC, tbl);
if (tsd && tsd->fd) { //tsd has lost sight of the bl object.
+ nullpo_ret(bl);
switch(bl->type){
case BL_PC:
if (sd->vd.class_ != INVISIBLE_CLASS)
clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd);
if(sd->chatID){
struct chat_data *cd;
- cd=(struct chat_data*)iMap->id2bl(sd->chatID);
+ cd=(struct chat_data*)map->id2bl(sd->chatID);
if(cd->usersd[0]==sd)
clif->dispchat(cd,tsd->fd);
}
@@ -4817,13 +4784,14 @@ int clif_outsight(struct block_list *bl,va_list ap)
clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd);
break;
default:
- if ((vd=status_get_viewdata(bl)) && vd->class_ != INVISIBLE_CLASS)
+ if ((vd=status->get_viewdata(bl)) && vd->class_ != INVISIBLE_CLASS)
clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd);
break;
}
}
if (sd && sd->fd) { //sd is watching tbl go out of view.
- if (((vd=status_get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS) &&
+ nullpo_ret(tbl);
+ if (((vd=status->get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS) &&
!(tbl->type == BL_NPC && (((TBL_NPC*)tbl)->option&OPTION_INVISIBLE)))
clif->clearunit_single(tbl->id,CLR_OUTSIGHT,sd->fd);
}
@@ -4845,12 +4813,13 @@ int clif_insight(struct block_list *bl,va_list ap)
tsd = BL_CAST(BL_PC, tbl);
if (tsd && tsd->fd) { //Tell tsd that bl entered into his view
- switch(bl->type){
+ nullpo_ret(bl);
+ switch(bl->type) {
case BL_ITEM:
clif->getareachar_item(tsd,(struct flooritem_data*)bl);
break;
case BL_SKILL:
- clif->getareachar_skillunit(tsd,(TBL_SKILL*)bl);
+ clif->getareachar_skillunit(&tsd->bl,(TBL_SKILL*)bl,SELF);
break;
default:
clif->getareachar_unit(tsd,bl);
@@ -4961,23 +4930,31 @@ void clif_deleteskill(struct map_session_data *sd, int id)
clif->skillinfoblock(sd);
}
-
/// Updates a skill in the skill tree (ZC_SKILLINFO_UPDATE).
/// 010e <skill id>.W <level>.W <sp cost>.W <attack range>.W <upgradable>.B
-void clif_skillup(struct map_session_data *sd,uint16 skill_id) {
- int fd, idx = skill->get_index(skill_id);
-
+/// Merged clif_skillup and clif_guild_skillup, same packet was used [panikon]
+/// flag:
+/// 0: guild call
+/// 1: player call
+void clif_skillup(struct map_session_data *sd, uint16 skill_id, int skill_lv, int flag)
+{
+ int fd;
nullpo_retv(sd);
- fd=sd->fd;
- WFIFOHEAD(fd,packet_len(0x10e));
- WFIFOW(fd,0) = 0x10e;
- WFIFOW(fd,2) = skill_id;
- WFIFOW(fd,4) = sd->status.skill[idx].lv;
- WFIFOW(fd,6) = skill->get_sp(skill_id,sd->status.skill[idx].lv);
- WFIFOW(fd,8) = skill->get_range2(&sd->bl,skill_id,sd->status.skill[idx].lv);
- WFIFOB(fd,10) = (sd->status.skill[idx].lv < skill->tree_get_max(sd->status.skill[idx].id, sd->status.class_)) ? 1 : 0;
- WFIFOSET(fd,packet_len(0x10e));
+ fd = sd->fd;
+
+ WFIFOHEAD(fd, packet_len(0x10e));
+ WFIFOW(fd, 0) = 0x10e;
+ WFIFOW(fd, 2) = skill_id;
+ WFIFOW(fd, 4) = skill_lv;
+ WFIFOW(fd, 6) = skill->get_sp(skill_id, skill_lv);
+ WFIFOW(fd, 8) = (flag)?skill->get_range2(&sd->bl, skill_id, skill_lv) : skill->get_range(skill_id, skill_lv);
+ if( flag )
+ WFIFOB(fd,10) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class_)) ? 1 : 0;
+ else
+ WFIFOB(fd,10) = 1;
+
+ WFIFOSET(fd, packet_len(0x10e));
}
@@ -5072,7 +5049,7 @@ void clif_skillcastcancel(struct block_list* bl)
/// 4 = "no party" MsgStringTable[163]
/// 5 = "no shout" MsgStringTable[164]
/// 6 = "no PKing" MsgStringTable[165]
-/// 7 = "no alligning" MsgStringTable[383]
+/// 7 = "no aligning" MsgStringTable[383]
/// ? = ignored
/// cause:
/// 0 = "not enough skill level" MsgStringTable[214] (AL_WARP)
@@ -5121,7 +5098,7 @@ void clif_skill_fail(struct map_session_data *sd,uint16 skill_id,enum useskill_f
/// Skill cooldown display icon (ZC_SKILL_POSTDELAY).
/// 043d <skill ID>.W <tick>.L
-void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned int tick)
+void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned int duration)
{
#if PACKETVER>=20081112
int fd;
@@ -5132,7 +5109,7 @@ void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned
WFIFOHEAD(fd,packet_len(0x43d));
WFIFOW(fd,0) = 0x43d;
WFIFOW(fd,2) = skill_id;
- WFIFOL(fd,4) = tick;
+ WFIFOL(fd,4) = duration;
WFIFOSET(fd,packet_len(0x43d));
#endif
}
@@ -5141,16 +5118,17 @@ void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned
/// Skill attack effect and damage.
/// 0114 <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <damage>.W <level>.W <div>.W <type>.B (ZC_NOTIFY_SKILL)
/// 01de <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <damage>.L <level>.W <div>.W <type>.B (ZC_NOTIFY_SKILL2)
-int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,uint16 skill_id,uint16 skill_lv,int type)
-{
+int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int64 in_damage, int div, uint16 skill_id, uint16 skill_lv, int type) {
unsigned char buf[64];
struct status_change *sc;
+ int damage;
nullpo_ret(src);
nullpo_ret(dst);
+ damage = (int)cap_value(in_damage,INT_MIN,INT_MAX);
type = clif_calc_delay(type,div,damage,ddelay);
- sc = status_get_sc(dst);
+ sc = status->get_sc(dst);
if(sc && sc->count) {
if(sc->data[SC_ILLUSION] && damage)
damage = damage*(sc->data[SC_ILLUSION]->val2) + rnd()%100;
@@ -5161,10 +5139,10 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int
WBUFW(buf,2)=skill_id;
WBUFL(buf,4)=src->id;
WBUFL(buf,8)=dst->id;
- WBUFL(buf,12)=tick;
+ WBUFL(buf,12)=(uint32)tick;
WBUFL(buf,16)=sdelay;
WBUFL(buf,20)=ddelay;
- if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) {
+ if (battle_config.hide_woe_damage && map_flag_gvg2(src->m)) {
WBUFW(buf,24)=damage?div:0;
} else {
WBUFW(buf,24)=damage;
@@ -5192,10 +5170,10 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int
WBUFW(buf,2)=skill_id;
WBUFL(buf,4)=src->id;
WBUFL(buf,8)=dst->id;
- WBUFL(buf,12)=tick;
+ WBUFL(buf,12)=(uint32)tick;
WBUFL(buf,16)=sdelay;
WBUFL(buf,20)=ddelay;
- if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) {
+ if (battle_config.hide_woe_damage && map_flag_gvg2(src->m)) {
WBUFL(buf,24)=damage?div:0;
} else {
WBUFL(buf,24)=damage;
@@ -5227,9 +5205,8 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int
/// Ground skill attack effect and damage (ZC_NOTIFY_SKILL_POSITION).
/// 0115 <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <x>.W <y>.W <damage>.W <level>.W <div>.W <type>.B
-/*
-int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,uint16 skill_id,uint16 skill_lv,int type)
-{
+#if 0
+int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int damage, int div, uint16 skill_id, uint16 skill_lv, int type) {
unsigned char buf[64];
struct status_change *sc;
@@ -5238,7 +5215,7 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned in
type = (type>0)?type:skill_get_hit(skill_id);
type = clif_calc_delay(type,div,damage,ddelay);
- sc = status_get_sc(dst);
+ sc = status->get_sc(dst);
if(sc && sc->count) {
if(sc->data[SC_ILLUSION] && damage)
@@ -5249,7 +5226,7 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned in
WBUFW(buf,2)=skill_id;
WBUFL(buf,4)=src->id;
WBUFL(buf,8)=dst->id;
- WBUFL(buf,12)=tick;
+ WBUFL(buf,12)=(uint32)tick;
WBUFL(buf,16)=sdelay;
WBUFL(buf,20)=ddelay;
WBUFW(buf,24)=dst->x;
@@ -5281,7 +5258,7 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned in
//Because the damage delay must be synced with the client, here is where the can-walk tick must be updated. [Skotlex]
return clif_calc_walkdelay(dst,ddelay,type,damage,div);
}
-*/
+#endif // 0
/// Non-damaging skill effect (ZC_USE_SKILL).
@@ -5319,8 +5296,7 @@ int clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 ski
/// Non-damaging ground skill effect (ZC_NOTIFY_GROUNDSKILL).
/// 0117 <skill id>.W <src id>.L <level>.W <x>.W <y>.W <tick>.L
-void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,int y,int tick)
-{
+void clif_skill_poseffect(struct block_list *src, uint16 skill_id, int val, int x, int y, int64 tick) {
unsigned char buf[32];
nullpo_retv(src);
@@ -5331,7 +5307,7 @@ void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,i
WBUFW(buf,8)=val;
WBUFW(buf,10)=x;
WBUFW(buf,12)=y;
- WBUFL(buf,14)=tick;
+ WBUFL(buf,14)=(uint32)tick;
if(disguised(src)) {
clif->send(buf,packet_len(0x117),src,AREA_WOS);
WBUFL(buf,4)=-src->id;
@@ -5340,65 +5316,6 @@ void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,i
clif->send(buf,packet_len(0x117),src,AREA);
}
-
-/*==========================================
- * Tells all client's nearby 'unit' sight range that it spawned
- *------------------------------------------*/
-//FIXME: this is just an AREA version of clif_getareachar_skillunit()
-void clif_skill_setunit(struct skill_unit *unit)
-{
- unsigned char buf[128];
- int header = 0x11f, pos = 0;
-
- nullpo_retv(unit);
-
- if( unit->group->state.guildaura )
- return;
-
-#if PACKETVER >= 20130320
- if(unit->group->unit_id > UCHAR_MAX){
- header = 0x99f;
- pos = 2;
- }
-#endif
-
-#if PACKETVER >= 3
- if(unit->group->unit_id==UNT_GRAFFITI) { // Graffiti [Valaris]
- WBUFW(buf, 0)=0x1c9;
- WBUFL(buf, 2)=unit->bl.id;
- WBUFL(buf, 6)=unit->group->src_id;
- WBUFW(buf,10)=unit->bl.x;
- WBUFW(buf,12)=unit->bl.y;
- WBUFB(buf,14)=unit->group->unit_id;
- WBUFB(buf,15)=1;
- WBUFB(buf,16)=1;
- safestrncpy((char*)WBUFP(buf,17),unit->group->valstr,MESSAGE_SIZE);
- clif->send(buf,packet_len(0x1c9),&unit->bl,AREA);
- return;
- }
-#endif
- WBUFW(buf, 0)=header;
- if(pos > 0)
- WBUFW(buf, pos)=packet_len(header);
- WBUFL(buf, 2 + pos)=unit->bl.id;
- WBUFL(buf, 6 + pos)=unit->group->src_id;
- WBUFW(buf,10 + pos)=unit->bl.x;
- WBUFW(buf,12 + pos)=unit->bl.y;
- if (unit->group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE)
- WBUFB(buf,14)=unit->val2&UF_SONG?UNT_DISSONANCE:UNT_UGLYDANCE;
- else if (skill->get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT))
- WBUFB(buf, 14) = UNT_DUMMYSKILL; // Only display the unit at center.
- else if(pos > 0){
- WBUFL(buf,16)=unit->group->unit_id;
- WBUFW(buf,20)=unit->range;
- pos += 5;
- }else
- WBUFB(buf,14)=unit->group->unit_id;
- WBUFB(buf,15 + pos)=1; // ignored by client (always gets set to 1)
- clif->send(buf,packet_len(header),&unit->bl,AREA);
-}
-
-
/// Presents a list of available warp destinations (ZC_WARPLIST).
/// 011c <skill id>.W { <map name>.16B }*4
void clif_skill_warppoint(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4)
@@ -5413,10 +5330,10 @@ void clif_skill_warppoint(struct map_session_data* sd, uint16 skill_id, uint16 s
memset(WFIFOP(fd,4), 0x00, 4*MAP_NAME_LENGTH_EXT);
if (map1 == (unsigned short)-1) strcpy((char*)WFIFOP(fd,4), "Random");
else // normal map name
- if (map1 > 0) mapindex_getmapname_ext(mapindex_id2name(map1), (char*)WFIFOP(fd,4));
- if (map2 > 0) mapindex_getmapname_ext(mapindex_id2name(map2), (char*)WFIFOP(fd,20));
- if (map3 > 0) mapindex_getmapname_ext(mapindex_id2name(map3), (char*)WFIFOP(fd,36));
- if (map4 > 0) mapindex_getmapname_ext(mapindex_id2name(map4), (char*)WFIFOP(fd,52));
+ if (map1 > 0) mapindex->getmapname_ext(mapindex_id2name(map1), (char*)WFIFOP(fd,4));
+ if (map2 > 0) mapindex->getmapname_ext(mapindex_id2name(map2), (char*)WFIFOP(fd,20));
+ if (map3 > 0) mapindex->getmapname_ext(mapindex_id2name(map3), (char*)WFIFOP(fd,36));
+ if (map4 > 0) mapindex->getmapname_ext(mapindex_id2name(map4), (char*)WFIFOP(fd,52));
WFIFOSET(fd,packet_len(0x11c));
sd->menuskill_id = skill_id;
@@ -5477,9 +5394,8 @@ void clif_skill_mapinfomessage(struct map_session_data *sd, int type)
/// Displays Sense (WZ_ESTIMATION) information window (ZC_MONSTER_INFO).
/// 018c <class>.W <level>.W <size>.W <hp>.L <def>.W <race>.W <mdef>.W <element>.W
/// <water%>.B <earth%>.B <fire%>.B <wind%>.B <poison%>.B <holy%>.B <shadow%>.B <ghost%>.B <undead%>.B
-void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst)
-{
- struct status_data *status;
+void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst) {
+ struct status_data *dstatus;
unsigned char buf[64];
int i;//, fix;
@@ -5489,29 +5405,29 @@ void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst)
if( dst->type != BL_MOB )
return;
- status = status_get_status_data(dst);
+ dstatus = status->get_status_data(dst);
- WBUFW(buf, 0)=0x18c;
- WBUFW(buf, 2)=status_get_class(dst);
- WBUFW(buf, 4)=status_get_lv(dst);
- WBUFW(buf, 6)=status->size;
- WBUFL(buf, 8)=status->hp;
- WBUFW(buf,12)= (battle_config.estimation_type&1?status->def:0)
- +(battle_config.estimation_type&2?status->def2:0);
- WBUFW(buf,14)=status->race;
- WBUFW(buf,16)= (battle_config.estimation_type&1?status->mdef:0)
- +(battle_config.estimation_type&2?status->mdef2:0);
- WBUFW(buf,18)= status->def_ele;
+ WBUFW(buf, 0) = 0x18c;
+ WBUFW(buf, 2) = status->get_class(dst);
+ WBUFW(buf, 4) = status->get_lv(dst);
+ WBUFW(buf, 6) = dstatus->size;
+ WBUFL(buf, 8) = dstatus->hp;
+ WBUFW(buf,12) = (battle_config.estimation_type&1?dstatus->def:0)
+ + (battle_config.estimation_type&2?dstatus->def2:0);
+ WBUFW(buf,14) = dstatus->race;
+ WBUFW(buf,16) = (battle_config.estimation_type&1?dstatus->mdef:0)
+ + (battle_config.estimation_type&2?dstatus->mdef2:0);
+ WBUFW(buf,18) = dstatus->def_ele;
for(i=0;i<9;i++)
- WBUFB(buf,20+i)= (unsigned char)battle->attr_ratio(i+1,status->def_ele, status->ele_lv);
+ WBUFB(buf,20+i)= (unsigned char)battle->attr_ratio(i+1,dstatus->def_ele, dstatus->ele_lv);
// The following caps negative attributes to 0 since the client displays them as 255-fix. [Skotlex]
-// WBUFB(buf,20+i)= (unsigned char)((fix=battle_attr_ratio(i+1,status->def_ele, status->ele_lv))<0?0:fix);
+// WBUFB(buf,20+i)= (unsigned char)((fix=battle_attr_ratio(i+1,dstatus->def_ele, dstatus->ele_lv))<0?0:fix);
clif->send(buf,packet_len(0x18c),&sd->bl,sd->status.party_id>0?PARTY_SAMEMAP:SELF);
}
-/// Presents a textual list of producable items (ZC_MAKABLEITEMLIST).
+/// Presents a textual list of producible items (ZC_MAKABLEITEMLIST).
/// 018d <packet len>.W { <name id>.W { <material id>.W }*3 }*
/// material id:
/// unused by the client
@@ -5530,13 +5446,13 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id , int
WFIFOW(fd, 0)=0x18d;
for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){
- if( skill->can_produce_mix(sd,skill_produce_db[i].nameid, trigger, 1) &&
- ( ( skill_id > 0 && skill_produce_db[i].req_skill == skill_id ) || skill_id < 0 )
+ if( skill->can_produce_mix(sd,skill->produce_db[i].nameid, trigger, 1) &&
+ ( ( skill_id > 0 && skill->produce_db[i].req_skill == skill_id ) || skill_id < 0 )
){
- if((view = itemdb_viewid(skill_produce_db[i].nameid)) > 0)
+ if((view = itemdb_viewid(skill->produce_db[i].nameid)) > 0)
WFIFOW(fd,c*8+ 4)= view;
else
- WFIFOW(fd,c*8+ 4)= skill_produce_db[i].nameid;
+ WFIFOW(fd,c*8+ 4)= skill->produce_db[i].nameid;
WFIFOW(fd,c*8+ 6)= 0;
WFIFOW(fd,c*8+ 8)= 0;
WFIFOW(fd,c*8+10)= 0;
@@ -5553,7 +5469,7 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id , int
}
-/// Present a list of producable items (ZC_MAKINGITEM_LIST).
+/// Present a list of producible items (ZC_MAKINGITEM_LIST).
/// 025a <packet len>.W <mk type>.W { <name id>.W }*
/// mk type:
/// 1 = cooking
@@ -5577,13 +5493,13 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id
c = 0;
for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) {
- if( !skill->can_produce_mix(sd,skill_produce_db[i].nameid,trigger, qty) )
+ if( !skill->can_produce_mix(sd,skill->produce_db[i].nameid,trigger, qty) )
continue;
- if( (view = itemdb_viewid(skill_produce_db[i].nameid)) > 0 )
+ if( (view = itemdb_viewid(skill->produce_db[i].nameid)) > 0 )
WFIFOW(fd, 6 + 2 * c) = view;
else
- WFIFOW(fd, 6 + 2 * c) = skill_produce_db[i].nameid;
+ WFIFOW(fd, 6 + 2 * c) = skill->produce_db[i].nameid;
c++;
}
@@ -5618,22 +5534,22 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id
void clif_status_change_notick(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3) {
struct packet_sc_notick p;
struct map_session_data *sd;
-
+
nullpo_retv(bl);
-
- if (!(status_type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client
- return;
-
+
if (type == SI_BLANK) //It shows nothing on the client...
return;
-
+
+ if (!(status->type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client
+ return;
+
sd = BL_CAST(BL_PC, bl);
-
+
p.PacketType = sc_notickType;
p.index = type;
p.AID = bl->id;
p.state = (unsigned char)flag;
-
+
clif->send(&p,packet_len(p.PacketType), bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA);
}
@@ -5652,7 +5568,7 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val
nullpo_retv(bl);
- if (!(status_type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client
+ if (!(status->type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client
return;
if ( tick < 0 )
@@ -5681,15 +5597,15 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val
void clif_displaymessage(const int fd, const char* mes) {
nullpo_retv(mes);
- if( fd == -2 ) {
+ if( map->cpsd_active && fd == 0 ) {
ShowInfo("HCP: %s\n",mes);
} else if ( fd > 0 ) {
- int len;
-
+ size_t len;
+
if ( ( len = strnlen(mes, 255) ) > 0 ) { // don't send a void message (it's not displaying on the client chat). @help can send void line.
WFIFOHEAD(fd, 5 + len);
WFIFOW(fd,0) = 0x8e;
- WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate
+ WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate
safestrncpy((char *)WFIFOP(fd,4), mes, len + 1);
WFIFOSET(fd, 5 + len);
}
@@ -5698,49 +5614,81 @@ void clif_displaymessage(const int fd, const char* mes) {
void clif_displaymessage2(const int fd, const char* mes) {
// invalid pointer?
nullpo_retv(mes);
-
+
//Scrapped, as these are shared by disconnected players =X [Skotlex]
if (fd == 0)
;
else {
// Limit message to 255+1 characters (otherwise it causes a buffer overflow in the client)
char *message, *line;
-
+
message = aStrdup(mes);
line = strtok(message, "\n");
while(line != NULL) {
// Limit message to 255+1 characters (otherwise it causes a buffer overflow in the client)
- int len = strnlen(line, 255);
-
+ size_t len = strnlen(line, 255);
+
if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line.
- if( fd == -2 ) {
+ if( map->cpsd_active && fd == 0 ) {
ShowInfo("HCP: %s\n",line);
} else {
WFIFOHEAD(fd, 5 + len);
WFIFOW(fd,0) = 0x8e;
- WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate
+ WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate
safestrncpy((char *)WFIFOP(fd,4), line, len + 1);
WFIFOSET(fd, 5 + len);
}
}
line = strtok(NULL, "\n");
}
- aFree(message);
+ aFree(message);
}
}
+/* oh noo! another version of 0x8e! */
+void clif_displaymessage_sprintf(const int fd, const char *mes, ...) __attribute__((format(printf, 2, 3)));
+void clif_displaymessage_sprintf(const int fd, const char *mes, ...) {
+ va_list ap;
+
+ if (map->cpsd_active && fd == 0) {
+ ShowInfo("HCP: ");
+ va_start(ap,mes);
+ vShowMessage_(MSG_NONE,mes,ap);
+ va_end(ap);
+ ShowMessage("\n");
+ } else if (fd > 0) {
+ int len = 1;
+ char *ptr;
+
+ WFIFOHEAD(fd, 5 + 255);/* ensure the maximum */
+
+ /* process */
+ va_start(ap,mes);
+ len += vsnprintf((char *)WFIFOP(fd,4), 255, mes, ap);
+ va_end(ap);
+ /* adjusting */
+ ptr = (char *)WFIFOP(fd,4);
+ ptr[len - 1] = '\0';
+
+ /* */
+ WFIFOW(fd,0) = 0x8e;
+ WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate
+
+ WFIFOSET(fd, 5 + len);
+ }
+}
/// Send broadcast message in yellow or blue without font formatting (ZC_BROADCAST).
/// 009a <packet len>.W <message>.?B
-void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, enum send_target target)
+void clif_broadcast(struct block_list* bl, const char* mes, size_t len, int type, enum send_target target)
{
- int lp = type ? 4 : 0;
+ int lp = (type&BC_COLOR_MASK) ? 4 : 0;
unsigned char *buf = (unsigned char*)aMalloc((4 + lp + len)*sizeof(unsigned char));
WBUFW(buf,0) = 0x9a;
WBUFW(buf,2) = 4 + lp + len;
- if (type == 0x10) // bc_blue
+ if( type&BC_BLUE )
WBUFL(buf,4) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow.
- else if (type == 0x20) // bc_woe
+ else if( type&BC_WOE )
WBUFL(buf,4) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'.
memcpy(WBUFP(buf, 4 + lp), mes, len);
clif->send(buf, WBUFW(buf,2), bl, target);
@@ -5754,8 +5702,8 @@ void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, e
* Used by npc_globalmessage
*------------------------------------------*/
void clif_GlobalMessage(struct block_list* bl, const char* message) {
- char buf[100];
- int len;
+ char buf[256];
+ size_t len;
nullpo_retv(bl);
if(!message)
@@ -5763,8 +5711,8 @@ void clif_GlobalMessage(struct block_list* bl, const char* message) {
len = strlen(message)+1;
- if( len > sizeof(buf)-8 ) {
- ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%d).\n", message, len);
+ if (len > sizeof(buf)-8) {
+ ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%"PRIuS").\n", message, len);
len = sizeof(buf)-8;
}
@@ -5778,7 +5726,7 @@ void clif_GlobalMessage(struct block_list* bl, const char* message) {
/// Send broadcast message with font formatting (ZC_BROADCAST2).
/// 01c3 <packet len>.W <fontColor>.L <fontType>.W <fontSize>.W <fontAlign>.W <fontY>.W <message>.?B
-void clif_broadcast2(struct block_list* bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target)
+void clif_broadcast2(struct block_list* bl, const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target)
{
unsigned char *buf = (unsigned char*)aMalloc((16 + len)*sizeof(unsigned char));
@@ -5822,7 +5770,7 @@ void clif_resurrection(struct block_list *bl,int type)
unsigned char buf[16];
nullpo_retv(bl);
-
+
WBUFW(buf,0)=0x148;
WBUFL(buf,2)=bl->id;
WBUFW(buf,6)=0;
@@ -5845,7 +5793,7 @@ void clif_map_property(struct map_session_data* sd, enum map_property property)
int fd;
nullpo_retv(sd);
-
+
fd=sd->fd;
WFIFOHEAD(fd,packet_len(0x199));
WFIFOW(fd,0)=0x199;
@@ -5903,14 +5851,14 @@ void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type)
/*==========================================
*
*------------------------------------------*/
-void clif_map_property_mapall(int map, enum map_property property)
+void clif_map_property_mapall(int mapid, enum map_property property)
{
struct block_list bl;
unsigned char buf[16];
-
+
bl.id = 0;
bl.type = BL_NUL;
- bl.m = map;
+ bl.m = mapid;
WBUFW(buf,0)=0x199;
WBUFW(buf,2)=property;
clif->send(buf,packet_len(0x199),&bl,ALL_SAMEMAP);
@@ -5954,8 +5902,7 @@ void clif_upgrademessage(int fd, int result, int item_id)
/// Whisper is transmitted to the destination player (ZC_WHISPER).
/// 0097 <packet len>.W <nick>.24B <message>.?B
/// 0097 <packet len>.W <nick>.24B <isAdmin>.L <message>.?B (PACKETVER >= 20091104)
-void clif_wis_message(int fd, const char* nick, const char* mes, int mes_len)
-{
+void clif_wis_message(int fd, const char* nick, const char* mes, size_t mes_len) {
#if PACKETVER < 20091104
WFIFOHEAD(fd, mes_len + NAME_LENGTH + 4);
WFIFOW(fd,0) = 0x97;
@@ -5964,13 +5911,13 @@ void clif_wis_message(int fd, const char* nick, const char* mes, int mes_len)
safestrncpy((char*)WFIFOP(fd,28), mes, mes_len);
WFIFOSET(fd,WFIFOW(fd,2));
#else
- struct map_session_data *ssd = iMap->nick2sd(nick);
+ struct map_session_data *ssd = map->nick2sd(nick);
WFIFOHEAD(fd, mes_len + NAME_LENGTH + 8);
WFIFOW(fd,0) = 0x97;
WFIFOW(fd,2) = mes_len + NAME_LENGTH + 8;
safestrncpy((char*)WFIFOP(fd,4), nick, NAME_LENGTH);
- WFIFOL(fd,28) = (pc->get_group_level(ssd) == 99) ? 1 : 0; // isAdmin; if nonzero, also displays text above char
+ WFIFOL(fd,28) = (ssd && pc_get_group_level(ssd) == 99) ? 1 : 0; // isAdmin; if nonzero, also displays text above char
safestrncpy((char*)WFIFOP(fd,32), mes, mes_len);
WFIFOSET(fd,WFIFOW(fd,2));
#endif
@@ -5980,16 +5927,24 @@ void clif_wis_message(int fd, const char* nick, const char* mes, int mes_len)
/// Inform the player about the result of his whisper action (ZC_ACK_WHISPER).
/// 0098 <result>.B
/// result:
-/// 0 = success to send wisper
-/// 1 = target character is not loged in
+/// 0 = success to send whisper
+/// 1 = target character is not logged in
/// 2 = ignored by target
/// 3 = everyone ignored by target
-void clif_wis_end(int fd, int flag)
-{
- WFIFOHEAD(fd,packet_len(0x98));
- WFIFOW(fd,0) = 0x98;
- WFIFOW(fd,2) = flag;
- WFIFOSET(fd,packet_len(0x98));
+void clif_wis_end(int fd, int flag) {
+ struct map_session_data *sd = session_isValid(fd) ? session[fd]->session_data : NULL;
+ struct packet_wis_end p;
+
+ if( !sd )
+ return;
+
+ p.PacketType = wisendType;
+ p.result = (char)flag;
+#if PACKETVER >= 20131223
+ p.unknown = 0;
+#endif
+
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
}
@@ -6046,9 +6001,15 @@ void clif_use_card(struct map_session_data *sd,int idx)
if( j == sd->inventory_data[i]->slot ) // No room
continue;
+ if( sd->status.inventory[i].equip > 0 ) // Do not check items that are already equipped
+ continue;
+
WFIFOW(fd,4+c*2)=i+2;
c++;
}
+
+ if( !c ) return; // no item is available for card insertion
+
WFIFOW(fd,2)=4+c*2;
WFIFOSET(fd,WFIFOW(fd,2));
}
@@ -6208,11 +6169,11 @@ void clif_item_refine_list(struct map_session_data *sd)
skill_lv = pc->checkskill(sd,WS_WEAPONREFINE);
fd=sd->fd;
-
+
WFIFOHEAD(fd, MAX_INVENTORY * 13 + 4);
WFIFOW(fd,0)=0x221;
for(i=c=0;i<MAX_INVENTORY;i++){
- if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify
+ if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify
&& (wlv=itemdb_wlv(sd->status.inventory[i].nameid)) >=1
&& !sd->inventory_data[i]->flag.no_refine
&& !(sd->status.inventory[i].equip&EQP_ARMS)){
@@ -6233,7 +6194,7 @@ void clif_item_refine_list(struct map_session_data *sd)
/// Notification of an auto-casted skill (ZC_AUTORUN_SKILL).
-/// 0147 <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradable>.B
+/// 0147 <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradeable>.B
void clif_item_skill(struct map_session_data *sd,uint16 skill_id,uint16 skill_lv)
{
int fd;
@@ -6385,8 +6346,7 @@ void clif_closevendingboard(struct block_list* bl, int fd)
/// Sends a list of items in a shop.
/// R 0133 <packet len>.W <owner id>.L { <price>.L <amount>.W <index>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* (ZC_PC_PURCHASE_ITEMLIST_FROMMC)
/// R 0800 <packet len>.W <owner id>.L <unique id>.L { <price>.L <amount>.W <index>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* (ZC_PC_PURCHASE_ITEMLIST_FROMMC2)
-void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_vending* vending)
-{
+void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_vending* vending_items) {
int i,fd;
int count;
struct map_session_data* vsd;
@@ -6399,8 +6359,8 @@ void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_ven
#endif
nullpo_retv(sd);
- nullpo_retv(vending);
- nullpo_retv(vsd=iMap->id2sd(id));
+ nullpo_retv(vending_items);
+ nullpo_retv(vsd=map->id2sd(id));
fd = sd->fd;
count = vsd->vend_num;
@@ -6413,13 +6373,12 @@ void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_ven
WFIFOL(fd,8) = vsd->vender_id;
#endif
- for( i = 0; i < count; i++ )
- {
- int index = vending[i].index;
- struct item_data* data = itemdb_search(vsd->status.cart[index].nameid);
- WFIFOL(fd,offset+ 0+i*22) = vending[i].value;
- WFIFOW(fd,offset+ 4+i*22) = vending[i].amount;
- WFIFOW(fd,offset+ 6+i*22) = vending[i].index + 2;
+ for( i = 0; i < count; i++ ) {
+ int index = vending_items[i].index;
+ struct item_data* data = itemdb->search(vsd->status.cart[index].nameid);
+ WFIFOL(fd,offset+ 0+i*22) = vending_items[i].value;
+ WFIFOW(fd,offset+ 4+i*22) = vending_items[i].amount;
+ WFIFOW(fd,offset+ 6+i*22) = vending_items[i].index + 2;
WFIFOB(fd,offset+ 8+i*22) = itemtype(data->type);
WFIFOW(fd,offset+ 9+i*22) = ( data->view_id > 0 ) ? data->view_id : vsd->status.cart[index].nameid;
WFIFOB(fd,offset+11+i*22) = vsd->status.cart[index].identify;
@@ -6459,8 +6418,7 @@ void clif_buyvending(struct map_session_data* sd, int index, int amount, int fai
/// Shop creation success (ZC_PC_PURCHASE_MYITEMLIST).
/// 0136 <packet len>.W <owner id>.L { <price>.L <index>.W <amount>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }*
-void clif_openvending(struct map_session_data* sd, int id, struct s_vending* vending)
-{
+void clif_openvending(struct map_session_data* sd, int id, struct s_vending* vending_items) {
int i,fd;
int count;
@@ -6474,11 +6432,11 @@ void clif_openvending(struct map_session_data* sd, int id, struct s_vending* ven
WFIFOW(fd,2) = 8+count*22;
WFIFOL(fd,4) = id;
for( i = 0; i < count; i++ ) {
- int index = vending[i].index;
- struct item_data* data = itemdb_search(sd->status.cart[index].nameid);
- WFIFOL(fd, 8+i*22) = vending[i].value;
- WFIFOW(fd,12+i*22) = vending[i].index + 2;
- WFIFOW(fd,14+i*22) = vending[i].amount;
+ int index = vending_items[i].index;
+ struct item_data* data = itemdb->search(sd->status.cart[index].nameid);
+ WFIFOL(fd, 8+i*22) = vending_items[i].value;
+ WFIFOW(fd,12+i*22) = vending_items[i].index + 2;
+ WFIFOW(fd,14+i*22) = vending_items[i].amount;
WFIFOB(fd,16+i*22) = itemtype(data->type);
WFIFOW(fd,17+i*22) = ( data->view_id > 0 ) ? data->view_id : sd->status.cart[index].nameid;
WFIFOB(fd,19+i*22) = sd->status.cart[index].identify;
@@ -6559,7 +6517,7 @@ void clif_party_member_info(struct party_data *p, struct map_session_data *sd)
WBUFB(buf,14) = (p->party.member[i].online)?0:1;
memcpy(WBUFP(buf,15), p->party.name, NAME_LENGTH);
memcpy(WBUFP(buf,39), sd->status.name, NAME_LENGTH);
- mapindex_getmapname_ext(map[sd->bl.m].cName ? map[sd->bl.m].cName : map[sd->bl.m].name, (char*)WBUFP(buf,63));
+ mapindex->getmapname_ext(map->list[sd->bl.m].custom_name ? map->list[map->list[sd->bl.m].instance_src_map].name : map->list[sd->bl.m].name, (char*)WBUFP(buf,63));
WBUFB(buf,79) = (p->party.item&1)?1:0;
WBUFB(buf,80) = (p->party.item&2)?1:0;
clif->send(buf,packet_len(0x1e9),&sd->bl,PARTY);
@@ -6593,7 +6551,7 @@ void clif_party_info(struct party_data* p, struct map_session_data *sd)
WBUFL(buf,28+c*46) = m->account_id;
memcpy(WBUFP(buf,28+c*46+4), m->name, NAME_LENGTH);
- mapindex_getmapname_ext(mapindex_id2name(m->map), (char*)WBUFP(buf,28+c*46+28));
+ mapindex->getmapname_ext(mapindex_id2name(m->map), (char*)WBUFP(buf,28+c*46+28));
WBUFB(buf,28+c*46+44) = (m->leader) ? 0 : 1;
WBUFB(buf,28+c*46+45) = (m->online) ? 0 : 1;
c++;
@@ -6786,9 +6744,9 @@ void clif_party_message(struct party_data* p, int account_id, const char* mes, i
if(i < MAX_PARTY){
unsigned char buf[1024];
- if( len > sizeof(buf)-8 )
- {
- ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%d, party_id=%d).\n", mes, len, sizeof(buf)-8, p->party.party_id);
+ if (len > sizeof(buf)-8) {
+ ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%"PRIuS", party_id=%d).\n",
+ mes, len, sizeof(buf)-8, p->party.party_id);
len = sizeof(buf)-8;
}
@@ -6983,8 +6941,8 @@ void clif_sendegg(struct map_session_data *sd)
nullpo_retv(sd);
fd=sd->fd;
- if (battle_config.pet_no_gvg && map_flag_gvg(sd->bl.m)) { //Disable pet hatching in GvG grounds during Guild Wars [Skotlex]
- clif->message(fd, msg_txt(666));
+ if (battle_config.pet_no_gvg && map_flag_gvg2(sd->bl.m)) { //Disable pet hatching in GvG grounds during Guild Wars [Skotlex]
+ clif->message(fd, msg_txt(866)); // "Pets are not allowed in Guild Wars."
return;
}
WFIFOHEAD(fd, MAX_INVENTORY * 2 + 4);
@@ -7037,23 +6995,23 @@ void clif_send_petdata(struct map_session_data* sd, struct pet_data* pd, int typ
void clif_send_petstatus(struct map_session_data *sd)
{
int fd;
- struct s_pet *pet;
+ struct s_pet *p;
nullpo_retv(sd);
nullpo_retv(sd->pd);
fd=sd->fd;
- pet = &sd->pd->pet;
+ p = &sd->pd->pet;
WFIFOHEAD(fd,packet_len(0x1a2));
WFIFOW(fd,0)=0x1a2;
- memcpy(WFIFOP(fd,2),pet->name,NAME_LENGTH);
- WFIFOB(fd,26)=battle_config.pet_rename?0:pet->rename_flag;
- WFIFOW(fd,27)=pet->level;
- WFIFOW(fd,29)=pet->hungry;
- WFIFOW(fd,31)=pet->intimate;
- WFIFOW(fd,33)=pet->equip;
+ memcpy(WFIFOP(fd,2),p->name,NAME_LENGTH);
+ WFIFOB(fd,26)=battle_config.pet_rename?0:p->rename_flag;
+ WFIFOW(fd,27)=p->level;
+ WFIFOW(fd,29)=p->hungry;
+ WFIFOW(fd,31)=p->intimate;
+ WFIFOW(fd,33)=p->equip;
#if PACKETVER >= 20081126
- WFIFOW(fd,35)=pet->class_;
+ WFIFOW(fd,35)=p->class_;
#endif
WFIFOSET(fd,packet_len(0x1a2));
}
@@ -7172,7 +7130,7 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd)
if( md && md->master && md->devotion_flag )
WBUFL(buf,6) = md->master->bl.id;
- WBUFW(buf,26) = skill->get_range2(src, ML_DEVOTION, mercenary_checkskill(md, ML_DEVOTION));
+ WBUFW(buf,26) = skill->get_range2(src, ML_DEVOTION, mercenary->checkskill(md, ML_DEVOTION));
}
else
{
@@ -7321,7 +7279,7 @@ void clif_mvp_noitem(struct map_session_data* sd)
/// 0 = "Guild has been created."
/// 1 = "You are already in a Guild."
/// 2 = "That Guild Name already exists."
-/// 3 = "You need the neccessary item to create a Guild."
+/// 3 = "You need the necessary item to create a Guild."
void clif_guild_created(struct map_session_data *sd,int flag)
{
int fd;
@@ -7354,7 +7312,7 @@ void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g)
WFIFOL(fd,2)=g->guild_id;
WFIFOL(fd,6)=g->emblem_id;
WFIFOL(fd,10)=g->position[ps].mode;
- WFIFOB(fd,14)=(bool)(sd->state.gmaster_flag==g);
+ WFIFOB(fd,14)=(bool)(sd->state.gmaster_flag == 1);
WFIFOL(fd,15)=0; // InterSID (unknown purpose)
memcpy(WFIFOP(fd,19),g->name,NAME_LENGTH);
WFIFOSET(fd,packet_len(0x16c));
@@ -7707,14 +7665,14 @@ void clif_guild_emblem_area(struct block_list* bl)
// (emblem in the flag npcs and emblem over the head in agit maps) [FlavioJS]
WBUFW(buf,0) = 0x1b4;
WBUFL(buf,2) = bl->id;
- WBUFL(buf,6) = status_get_guild_id(bl);
- WBUFW(buf,10) = status_get_emblem_id(bl);
+ WBUFL(buf,6) = status->get_guild_id(bl);
+ WBUFW(buf,10) = status->get_emblem_id(bl);
clif->send(buf, 12, bl, AREA_WOS);
}
/// Sends guild skills (ZC_GUILD_SKILLINFO).
-/// 0162 <packet len>.W <skill points>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradable>.B }*
+/// 0162 <packet len>.W <skill points>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradeable>.B }*
void clif_guild_skillinfo(struct map_session_data* sd)
{
int fd;
@@ -7901,13 +7859,11 @@ void clif_guild_message(struct guild *g,int account_id,const char *mes,int len)
struct map_session_data *sd;
uint8 buf[256];
- if( len == 0 )
- {
+ if (len == 0)
return;
- }
- else if( len > sizeof(buf)-5 )
- {
- ShowWarning("clif_guild_message: Truncated message '%s' (len=%d, max=%d, guild_id=%d).\n", mes, len, sizeof(buf)-5, g->guild_id);
+
+ if (len > sizeof(buf)-5) {
+ ShowWarning("clif_guild_message: Truncated message '%s' (len=%d, max=%"PRIuS", guild_id=%d).\n", mes, len, sizeof(buf)-5, g->guild_id);
len = sizeof(buf)-5;
}
@@ -7919,29 +7875,6 @@ void clif_guild_message(struct guild *g,int account_id,const char *mes,int len)
clif->send(buf, WBUFW(buf,2), &sd->bl, GUILD_NOBG);
}
-
-/*==========================================
- * Server tells client 'sd' that his guild skill 'skill_id' gone to level 'lv'
- *------------------------------------------*/
-int clif_guild_skillup(struct map_session_data *sd,uint16 skill_id,int lv)
-{// TODO: Merge with clif_skillup (same packet).
- int fd;
-
- nullpo_ret(sd);
-
- fd=sd->fd;
- WFIFOHEAD(fd,11);
- WFIFOW(fd,0) = 0x10e;
- WFIFOW(fd,2) = skill_id;
- WFIFOW(fd,4) = lv;
- WFIFOW(fd,6) = skill->get_sp(skill_id,lv);
- WFIFOW(fd,8) = skill->get_range(skill_id,lv);
- WFIFOB(fd,10) = 1;
- WFIFOSET(fd,11);
- return 0;
-}
-
-
/// Request for guild alliance (ZC_REQ_ALLY_GUILD).
/// 0171 <inviter account id>.L <guild name>.24B
void clif_guild_reqalliance(struct map_session_data *sd,int account_id,const char *name)
@@ -8106,28 +8039,22 @@ void clif_wedding_effect(struct block_list *bl)
/// Notifies the client of the name of the partner character (ZC_COUPLENAME).
/// 01e6 <partner name>.24B
-void clif_callpartner(struct map_session_data *sd)
-{
+void clif_callpartner(struct map_session_data *sd) {
unsigned char buf[26];
nullpo_retv(sd);
WBUFW(buf,0) = 0x1e6;
- if( sd->status.partner_id )
- {
+ if( sd->status.partner_id ) {
const char *p;
- if( ( p = iMap->charid2nick(sd->status.partner_id) ) != NULL )
- {
+ if( ( p = map->charid2nick(sd->status.partner_id) ) != NULL ) {
memcpy(WBUFP(buf,2), p, NAME_LENGTH);
- }
- else
- {
+ } else {
WBUFB(buf,2) = 0;
}
- }
- else
- {// Send zero-length name if no partner, to initialize the client buffer.
+ } else {
+ // Send zero-length name if no partner, to initialize the client buffer.
WBUFB(buf,2) = 0;
}
@@ -8184,25 +8111,18 @@ void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_sess
}
*/
-
-/*==========================================
- *
- *------------------------------------------*/
-void clif_disp_onlyself(struct map_session_data *sd, const char *mes, int len) {
- clif->disp_message(&sd->bl, mes, len, SELF);
-}
-
/*==========================================
* Displays a message using the guild-chat colors to the specified targets. [Skotlex]
*------------------------------------------*/
-void clif_disp_message(struct block_list* src, const char* mes, int len, enum send_target target)
+void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum send_target target)
{
unsigned char buf[256];
- if( len == 0 ) {
+ if (len == 0)
return;
- } else if( len > sizeof(buf)-5 ) {
- ShowWarning("clif_disp_message: Truncated message '%s' (len=%d, max=%d, aid=%d).\n", mes, len, sizeof(buf)-5, src->id);
+
+ if (len > sizeof(buf)-5) {
+ ShowWarning("clif_disp_message: Truncated message '%s' (len=%"PRIuS", max=%"PRIuS", aid=%d).\n", mes, len, sizeof(buf)-5, src->id);
len = sizeof(buf)-5;
}
@@ -8219,7 +8139,7 @@ void clif_disp_message(struct block_list* src, const char* mes, int len, enum se
/// result:
/// 0 = failure
/// 1 = success
-void clif_GM_kickack(struct map_session_data *sd, int id)
+void clif_GM_kickack(struct map_session_data *sd, int result)
{
int fd;
@@ -8228,22 +8148,21 @@ void clif_GM_kickack(struct map_session_data *sd, int id)
fd = sd->fd;
WFIFOHEAD(fd,packet_len(0xcd));
WFIFOW(fd,0) = 0xcd;
- WFIFOB(fd,2) = id; // FIXME: this is not account id
+ WFIFOB(fd,2) = result;
WFIFOSET(fd, packet_len(0xcd));
}
-void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd)
-{
+void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd) {
int fd = tsd->fd;
if( fd > 0 )
clif->authfail_fd(fd, 15);
else
- iMap->quit(tsd);
+ map->quit(tsd);
if( sd )
- clif->GM_kickack(sd,tsd->status.account_id);
+ clif->GM_kickack(sd, 1);
}
@@ -8269,7 +8188,7 @@ void clif_manner_message(struct map_session_data* sd, uint32 type)
}
-/// Followup to 0x14a type 3/5, informs who did the manner adjustment action (ZC_NOTIFY_MANNER_POINT_GIVEN).
+/// Follow-up to 0x14a type 3/5, informs who did the manner adjustment action (ZC_NOTIFY_MANNER_POINT_GIVEN).
/// 014b <type>.B <GM name>.24B
/// type:
/// 0 = positive (unmute)
@@ -8360,7 +8279,7 @@ void clif_playBGM(struct map_session_data* sd, const char* name)
/// term:
/// unknown purpose, only relevant to act = 1
/// npc id:
-/// The accustic direction of the sound is determined by the
+/// The acoustic direction of the sound is determined by the
/// relative position of the NPC to the player (3D sound).
void clif_soundeffect(struct map_session_data* sd, struct block_list* bl, const char* name, int type)
{
@@ -8453,7 +8372,7 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen
// Modification of clif_messagecolor to send colored messages to players to chat log only (doesn't display overhead)
/// 02c1 <packet len>.W <id>.L <color>.L <message>.?B
int clif_colormes(int fd, enum clif_colors color, const char* msg) {
- unsigned short msg_len = strlen(msg) + 1;
+ size_t msg_len = strlen(msg) + 1;
WFIFOHEAD(fd,msg_len + 12);
WFIFOW(fd,0) = 0x2C1;
@@ -8468,15 +8387,15 @@ int clif_colormes(int fd, enum clif_colors color, const char* msg) {
/// Monster/NPC color chat [SnakeDrak] (ZC_NPC_CHAT).
/// 02c1 <packet len>.W <id>.L <color>.L <message>.?B
-void clif_messagecolor(struct block_list* bl, unsigned long color, const char* msg) {
- unsigned short msg_len = strlen(msg) + 1;
+void clif_messagecolor(struct block_list* bl, unsigned int color, const char* msg) {
+ size_t msg_len = strlen(msg) + 1;
uint8 buf[256];
color = (color & 0x0000FF) << 16 | (color & 0x00FF00) | (color & 0xFF0000) >> 16; // RGB to BGR
nullpo_retv(bl);
- if( msg_len > sizeof(buf)-12 ) {
- ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%u).\n", msg, msg_len);
+ if (msg_len > sizeof(buf)-12) {
+ ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%"PRIuS").\n", msg, msg_len);
msg_len = sizeof(buf)-12;
}
@@ -8509,6 +8428,34 @@ void clif_message(struct block_list* bl, const char* msg) {
clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC);
}
+/**
+ * Notifies the client that the storage window is still open
+ *
+ * Should only be used in cases where the client closed the
+ * storage window without server's consent
+ **/
+void clif_refresh_storagewindow( struct map_session_data *sd ) {
+ // Notify the client that the storage is open
+ if( sd->state.storage_flag == 1 ) {
+ storage->sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
+ clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
+ clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE);
+ }
+ // Notify the client that the gstorage is open otherwise it will
+ // remain locked forever and nobody will be able to access it
+ if( sd->state.storage_flag == 2 ) {
+ struct guild_storage *gstor;
+ if( (gstor = gstorage->id2storage2(sd->status.guild_id)) == NULL) {
+ // Shouldn't happen... The information should already be at the map-server
+ intif->request_guild_storage(sd->status.account_id,sd->status.guild_id);
+ } else {
+ storage->sortitem(gstor->items, ARRAYLENGTH(gstor->items));
+ clif->storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items));
+ clif->updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE);
+ }
+ }
+}
+
// refresh the client's screen, getting rid of any effects
void clif_refresh(struct map_session_data *sd)
{
@@ -8545,10 +8492,10 @@ void clif_refresh(struct map_session_data *sd)
}
if( sd->ed )
clif->elemental_info(sd);
- iMap->foreachinrange(clif->getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd);
+ map->foreachinrange(clif->getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd);
clif->weather_check(sd);
if( sd->chatID )
- chat_leavechat(sd,0);
+ chat->leave(sd,0);
if( sd->state.vending )
clif->openvending(sd, sd->bl.id, sd->vending);
if( pc_issit(sd) )
@@ -8562,13 +8509,14 @@ void clif_refresh(struct map_session_data *sd)
buyingstore->close(sd);
mail->clear(sd);
-
+
if( disguised(&sd->bl) ) {/* refresh-da */
short disguise = sd->disguise;
pc->disguise(sd, -1);
pc->disguise(sd, disguise);
}
-
+
+ clif->refresh_storagewindow(sd);
}
@@ -8656,11 +8604,11 @@ void clif_charnameack (int fd, struct block_list *bl)
nullpo_retv(md);
memcpy(WBUFP(buf,6), md->name, NAME_LENGTH);
- if( md->guardian_data && md->guardian_data->guild_id )
+ if( md->guardian_data && md->guardian_data->g )
{
WBUFW(buf, 0) = cmd = 0x195;
WBUFB(buf,30) = 0;
- memcpy(WBUFP(buf,54), md->guardian_data->guild_name, NAME_LENGTH);
+ memcpy(WBUFP(buf,54), md->guardian_data->g->name, NAME_LENGTH);
memcpy(WBUFP(buf,78), md->guardian_data->castle->castle_name, NAME_LENGTH);
}
else if( battle_config.show_mob_info )
@@ -8697,7 +8645,7 @@ void clif_charnameack (int fd, struct block_list *bl)
return;
}
- // if no receipient specified just update nearby clients
+ // if no recipient specified just update nearby clients
if (fd == 0)
clif->send(buf, packet_len(cmd), bl, AREA);
else {
@@ -8792,11 +8740,11 @@ void clif_slide(struct block_list *bl, int x, int y)
/// 008d <packet len>.W <id>.L <message>.?B
void clif_disp_overhead(struct block_list *bl, const char* mes)
{
- unsigned char buf[256]; //This should be more than sufficient, the theorical max is CHAT_SIZE + 8 (pads and extra inserted crap)
- int len_mes = strlen(mes)+1; //Account for \0
+ unsigned char buf[256]; //This should be more than sufficient, the theoretical max is CHAT_SIZE + 8 (pads and extra inserted crap)
+ size_t len_mes = strlen(mes)+1; //Account for \0
if (len_mes > sizeof(buf)-8) {
- ShowError("clif_disp_overhead: Message too long (length %d)\n", len_mes);
+ ShowError("clif_disp_overhead: Message too long (length %"PRIuS")\n", len_mes);
len_mes = sizeof(buf)-8; //Trunk it to avoid problems.
}
// send message to others
@@ -8813,7 +8761,7 @@ void clif_disp_overhead(struct block_list *bl, const char* mes)
safestrncpy((char*)WBUFP(buf,4), mes, len_mes);
clif->send(buf, WBUFW(buf,2), bl, SELF);
}
-
+
}
/*==========================
@@ -8900,27 +8848,27 @@ void clif_starskill(struct map_session_data* sd, const char* mapname, int monste
}
/*==========================================
- * Info about Star Glaldiator save map [Komurka]
+ * Info about Star Gladiator save map [Komurka]
* type: 1: Information, 0: Map registered
*------------------------------------------*/
void clif_feel_info(struct map_session_data* sd, unsigned char feel_level, unsigned char type)
{
char mapname[MAP_NAME_LENGTH_EXT];
- mapindex_getmapname_ext(mapindex_id2name(sd->feel_map[feel_level].index), mapname);
+ mapindex->getmapname_ext(mapindex_id2name(sd->feel_map[feel_level].index), mapname);
clif->starskill(sd, mapname, 0, feel_level, type ? 1 : 0);
}
/*==========================================
- * Info about Star Glaldiator hate mob [Komurka]
+ * Info about Star Gladiator hate mob [Komurka]
* type: 1: Register mob, 0: Information.
*------------------------------------------*/
void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int class_, unsigned char type)
{
if( pcdb_checkid(class_) ) {
clif->starskill(sd, pc->job_name(class_), class_, hate_level, type ? 10 : 11);
- } else if( mobdb_checkid(class_) ) {
- clif->starskill(sd, mob_db(class_)->jname, class_, hate_level, type ? 10 : 11);
+ } else if( mob->db_checkid(class_) ) {
+ clif->starskill(sd, mob->db(class_)->jname, class_, hate_level, type ? 10 : 11);
} else {
ShowWarning("clif_hate_info: Received invalid class %d for this packet (char_id=%d, hate_level=%u, type=%u).\n", class_, sd->status.char_id, (unsigned int)hate_level, (unsigned int)type);
}
@@ -8931,7 +8879,7 @@ void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int cl
*------------------------------------------*/
void clif_mission_info(struct map_session_data *sd, int mob_id, unsigned char progress)
{
- clif->starskill(sd, mob_db(mob_id)->jname, mob_id, progress, 20);
+ clif->starskill(sd, mob->db(mob_id)->jname, mob_id, progress, 20);
}
/*==========================================
@@ -8987,69 +8935,41 @@ void clif_equpcheckbox(struct map_session_data* sd)
/// 02d7 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE, PACKETVER >= 20100629)
/// 0859 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE2, PACKETVER >= 20101124)
/// 0859 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <robe>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE2, PACKETVER >= 20110111)
-void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* tsd)
-{
- uint8* buf;
- int i, n, fd, offset = 0;
-#if PACKETVER < 20100629
- const int s = 26;
-#else
- const int s = 28;
-#endif
+void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* tsd) {
+ int i, k, equip = 0;
+
nullpo_retv(sd);
nullpo_retv(tsd);
- fd = sd->fd;
- WFIFOHEAD(fd, MAX_INVENTORY * s + 43);
- buf = WFIFOP(fd,0);
+ for( i = 0; i < EQI_MAX; i++ ) {
+ if( (k = tsd->equip_index[i]) >= 0 ) {
-#if PACKETVER < 20101124
- WBUFW(buf, 0) = 0x2d7;
-#else
- WBUFW(buf, 0) = 0x859;
-#endif
- safestrncpy((char*)WBUFP(buf, 4), tsd->status.name, NAME_LENGTH);
- WBUFW(buf,28) = tsd->status.class_;
- WBUFW(buf,30) = tsd->vd.hair_style;
- WBUFW(buf,32) = tsd->vd.head_bottom;
- WBUFW(buf,34) = tsd->vd.head_mid;
- WBUFW(buf,36) = tsd->vd.head_top;
-#if PACKETVER >= 20110111
- WBUFW(buf,38) = tsd->vd.robe;
- offset+= 2;
- buf = WBUFP(buf,2);
-#endif
- WBUFW(buf,38) = tsd->vd.hair_color;
- WBUFW(buf,40) = tsd->vd.cloth_color;
- WBUFB(buf,42) = tsd->vd.sex;
+ if (tsd->status.inventory[k].nameid <= 0 || tsd->inventory_data[k] == NULL) // Item doesn't exist
+ continue;
- for(i=0,n=0; i < MAX_INVENTORY; i++)
- {
- if (tsd->status.inventory[i].nameid <= 0 || tsd->inventory_data[i] == NULL) // Item doesn't exist
- continue;
- if (!itemdb_isequip2(tsd->inventory_data[i])) // Is not equippable
- continue;
+ clif_item_equip(k+2,&viewequip_list.list[equip++],&tsd->status.inventory[k],tsd->inventory_data[k],pc->equippoint(tsd,k));
- // Inventory position
- WBUFW(buf, n*s+43) = i + 2;
- // Add refine, identify flag, element, etc.
- clif->item_sub(WBUFP(buf,0), n*s+45, &tsd->status.inventory[i], tsd->inventory_data[i], pc->equippoint(tsd, i));
- // Add cards
- clif->addcards(WBUFP(buf, n*s+55), &tsd->status.inventory[i]);
- // Expiration date stuff, if all of those are set to 0 then the client doesn't show anything related (6 bytes)
- WBUFL(buf, n*s+63) = tsd->status.inventory[i].expire_time;
- WBUFW(buf, n*s+67) = 0;
-#if PACKETVER >= 20100629
- if (tsd->inventory_data[i]->equip&EQP_VISIBLE)
- WBUFW(buf, n*s+69) = tsd->inventory_data[i]->look;
- else
- WBUFW(buf, n*s+69) = 0;
-#endif
- n++;
+ }
}
- WFIFOW(fd, 2) = 43+offset+n*s; // Set length
- WFIFOSET(fd, WFIFOW(fd, 2));
+ viewequip_list.PacketType = viewequipackType;
+ viewequip_list.PacketLength = ( sizeof( viewequip_list ) - sizeof( viewequip_list.list ) ) + ( sizeof(struct EQUIPITEM_INFO) * equip );
+
+ safestrncpy(viewequip_list.characterName, tsd->status.name, NAME_LENGTH);
+
+ viewequip_list.job = tsd->status.class_;
+ viewequip_list.head = tsd->vd.hair_style;
+ viewequip_list.accessory = tsd->vd.head_bottom;
+ viewequip_list.accessory2 = tsd->vd.head_mid;
+ viewequip_list.accessory3 = tsd->vd.head_top;
+#if PACKETVER >= 20110111
+ viewequip_list.robe = tsd->vd.robe;
+#endif
+ viewequip_list.headpalette = tsd->vd.hair_color;
+ viewequip_list.bodypalette = tsd->vd.cloth_color;
+ viewequip_list.sex = tsd->vd.sex;
+
+ clif->send(&viewequip_list, viewequip_list.PacketLength, &sd->bl, SELF);
}
@@ -9098,21 +9018,14 @@ void clif_msg_skill(struct map_session_data* sd, uint16 skill_id, int msg_id)
WFIFOSET(fd, packet_len(0x7e6));
}
-
-/// View player equip request denied
-void clif_viewequip_fail(struct map_session_data* sd)
-{
- clif_msg(sd, 0x54d);
-}
-
-
/// Validates one global/guild/party/whisper message packet and tries to recognize its components.
/// Returns true if the packet was parsed successfully.
/// Formats: 0 - <packet id>.w <packet len>.w (<name> : <message>).?B 00
/// 1 - <packet id>.w <packet len>.w <name>.24B <message>.?B 00
-bool clif_process_message(struct map_session_data* sd, int format, char** name_, int* namelen_, char** message_, int* messagelen_) {
+bool clif_process_message(struct map_session_data *sd, int format, char **name_, size_t *namelen_, char **message_, size_t *messagelen_) {
char *text, *name, *message;
- unsigned int packetlen, textlen, namelen, messagelen;
+ unsigned int packetlen, textlen;
+ size_t namelen, messagelen;
int fd = sd->fd;
*name_ = NULL;
@@ -9141,7 +9054,7 @@ bool clif_process_message(struct map_session_data* sd, int format, char** name_,
if( strncmp(name, sd->status.name, namelen) || // the text must start with the speaker's name
name[namelen] != ' ' || name[namelen+1] != ':' || name[namelen+2] != ' ' ) // followed by ' : '
{
- //Hacked message, or infamous "client desynch" issue where they pick one char while loading another.
+ //Hacked message, or infamous "client desynchronize" issue where they pick one char while loading another.
ShowWarning("clif_process_message: Player '%s' sent a message using an incorrect name! Forcing a relog...\n", sd->status.name);
set_eof(fd); // Just kick them out to correct it.
return false;
@@ -9204,14 +9117,14 @@ void clif_hercules_chsys_msg(struct hChSysCh *channel, struct map_session_data *
DBIterator *iter = db_iterator(channel->users);
struct map_session_data *user;
unsigned short msg_len = strlen(msg) + 1;
-
+
WFIFOHEAD(sd->fd,msg_len + 12);
WFIFOW(sd->fd,0) = 0x2C1;
WFIFOW(sd->fd,2) = msg_len + 12;
WFIFOL(sd->fd,4) = 0;
WFIFOL(sd->fd,8) = hChSys.colors[channel->color];
safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len);
-
+
for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) {
if( user->fd == sd->fd )
continue;
@@ -9219,9 +9132,9 @@ void clif_hercules_chsys_msg(struct hChSysCh *channel, struct map_session_data *
memcpy(WFIFOP(user->fd,0), WFIFOP(sd->fd,0), msg_len + 12);
WFIFOSET(user->fd, msg_len + 12);
}
-
+
WFIFOSET(sd->fd, msg_len + 12);
-
+
dbi_destroy(iter);
}
@@ -9230,19 +9143,19 @@ void clif_hercules_chsys_msg2(struct hChSysCh *channel, char *msg) {
struct map_session_data *user;
unsigned char buf[210];
unsigned short msg_len = strlen(msg) + 1;
-
+
WBUFW(buf,0) = 0x2C1;
WBUFW(buf,2) = msg_len + 12;
WBUFL(buf,4) = 0;
WBUFL(buf,8) = hChSys.colors[channel->color];
safestrncpy((char*)WBUFP(buf,12), msg, msg_len);
-
+
for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) {
WFIFOHEAD(user->fd,msg_len + 12);
memcpy(WFIFOP(user->fd,0), WBUFP(buf,0), msg_len + 12);
WFIFOSET(user->fd, msg_len + 12);
}
-
+
dbi_destroy(iter);
}
@@ -9282,7 +9195,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
}
//Check for double login.
- bl = iMap->id2bl(account_id);
+ bl = map->id2bl(account_id);
if(bl && bl->type != BL_PC) {
ShowError("clif_parse_WantToConnection: a non-player object already has id %d, please increase the starting account number\n", account_id);
WFIFOHEAD(fd,packet_len(0x6a));
@@ -9295,7 +9208,7 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
}
if (bl ||
- ((node=chrif_search(account_id)) && //An already existing node is valid only if it is for this login.
+ ((node=chrif->search(account_id)) && //An already existing node is valid only if it is for this login.
!(node->account_id == account_id && node->char_id == char_id && node->state == ST_LOGIN)))
{
clif->authfail_fd(fd, 8); //Still recognizes last connection
@@ -9304,8 +9217,11 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
CREATE(sd, TBL_PC, 1);
sd->fd = fd;
- sd->cryptKey = (( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF;
-
+
+ sd->cryptKey = (( ((( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF)
+ * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF;
+ sd->parse_cmd_func = clif->parse_cmd;
+
session[fd]->session_data = sd;
pc->setnewpc(sd, account_id, char_id, login_id1, client_tick, sex, fd);
@@ -9321,35 +9237,45 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
WFIFOSET(fd,packet_len(0x283));
#endif
- chrif_authreq(sd);
+ chrif->authreq(sd,false);
}
void clif_hercules_chsys_mjoin(struct map_session_data *sd) {
- if( !map[sd->bl.m].channel ) {
- CREATE(map[sd->bl.m].channel, struct hChSysCh , 1);
- safestrncpy(map[sd->bl.m].channel->name, hChSys.local_name, HCHSYS_NAME_LENGTH);
- map[sd->bl.m].channel->type = hChSys_MAP;
- map[sd->bl.m].channel->m = sd->bl.m;
-
- clif->chsys_create(map[sd->bl.m].channel,NULL,NULL,hChSys.local_color);
+ if( sd->state.autotrade || sd->state.standalone )
+ return;
+ if( !map->list[sd->bl.m].channel ) {
+
+ if (map->list[sd->bl.m].flag.chsysnolocalaj || (map->list[sd->bl.m].instance_id >= 0 && instance->list[map->list[sd->bl.m].instance_id].owner_type != IOT_NONE) )
+ return;
+
+ CREATE(map->list[sd->bl.m].channel, struct hChSysCh , 1);
+ safestrncpy(map->list[sd->bl.m].channel->name, hChSys.local_name, HCHSYS_NAME_LENGTH);
+ map->list[sd->bl.m].channel->type = hChSys_MAP;
+ map->list[sd->bl.m].channel->m = sd->bl.m;
+
+ clif->chsys_create(map->list[sd->bl.m].channel,NULL,NULL,hChSys.local_color);
}
-
- if( map[sd->bl.m].channel->banned && idb_exists(map[sd->bl.m].channel->banned, sd->status.account_id) ) {
+
+ if( map->list[sd->bl.m].channel->banned && idb_exists(map->list[sd->bl.m].channel->banned, sd->status.account_id) ) {
return;
}
-
- clif->chsys_join(map[sd->bl.m].channel,sd);
-
- if( !( map[sd->bl.m].channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) {
+
+ clif->chsys_join(map->list[sd->bl.m].channel,sd);
+
+ if( !( map->list[sd->bl.m].channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) {
char mout[60];
- sprintf(mout, msg_txt(1435),hChSys.local_name,map[sd->bl.m].name); // You're now in the '#%s' channel for '%s'
+ sprintf(mout, msg_txt(1435),hChSys.local_name,map->list[sd->bl.m].name); // You're now in the '#%s' channel for '%s'
clif->colormes(sd->fd, COLOR_DEFAULT, mout);
}
}
/// Notification from the client, that it has finished map loading and is about to display player's character (CZ_NOTIFY_ACTORINIT).
/// 007d
-void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
-{
+void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
+#if PACKETVER >= 20090218
+ int i;
+#endif
+ bool first_time = false;
+
if(sd->bl.prev != NULL)
return;
@@ -9401,21 +9327,29 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
pc->setinvincibletimer(sd,battle_config.pc_invincible_time);
}
- if( map[sd->bl.m].users++ == 0 && battle_config.dynamic_mobs )
- iMap->spawnmobs(sd->bl.m);
- if( !(sd->sc.option&OPTION_INVISIBLE) ) { // increment the number of pvp players on the map
- map[sd->bl.m].users_pvp++;
+ if( map->list[sd->bl.m].users++ == 0 && battle_config.dynamic_mobs )
+ map->spawnmobs(sd->bl.m);
+
+ if( map->list[sd->bl.m].instance_id >= 0 ) {
+ instance->list[map->list[sd->bl.m].instance_id].users++;
+ instance->check_idle(map->list[sd->bl.m].instance_id);
+ }
+
+ if( pc_has_permission(sd,PC_PERM_VIEW_HPMETER) ) {
+ map->list[sd->bl.m].hpmeter_visible++;
+ sd->state.hpmeter_visible = 1;
}
- if( map[sd->bl.m].instance_id >= 0 ) {
- instances[map[sd->bl.m].instance_id].users++;
- instance->check_idle(map[sd->bl.m].instance_id);
+
+ if( !(sd->sc.option&OPTION_INVISIBLE) ) { // increment the number of pvp players on the map
+ map->list[sd->bl.m].users_pvp++;
}
+
sd->state.debug_remove_map = 0; // temporary state to track double remove_map's [FlavioJS]
// reset the callshop flag if the player changes map
sd->state.callshop = 0;
- iMap->addblock(&sd->bl);
+ map->addblock(&sd->bl);
clif->spawn(&sd->bl);
// Party
@@ -9427,10 +9361,10 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if( sd->bg_id ) clif->bg_hp(sd); // BattleGround System
- if(map[sd->bl.m].flag.pvp && !(sd->sc.option&OPTION_INVISIBLE)) {
+ if(map->list[sd->bl.m].flag.pvp && !(sd->sc.option&OPTION_INVISIBLE)) {
if(!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris]
- if (!map[sd->bl.m].flag.pvp_nocalcrank)
- sd->pvp_timer = iTimer->add_timer(iTimer->gettick()+200, pc->calc_pvprank_timer, sd->bl.id, 0);
+ if (!map->list[sd->bl.m].flag.pvp_nocalcrank)
+ sd->pvp_timer = timer->add(timer->gettick()+200, pc->calc_pvprank_timer, sd->bl.id, 0);
sd->pvp_rank = 0;
sd->pvp_lastusers = 0;
sd->pvp_point = 5;
@@ -9443,32 +9377,33 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if(sd->duel_group)
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE);
- if (map[sd->bl.m].flag.gvg_dungeon)
+ if (map->list[sd->bl.m].flag.gvg_dungeon)
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); //TODO: Figure out the real packet to send here.
- if( map_flag_gvg(sd->bl.m) )
+ if( map_flag_gvg2(sd->bl.m) )
clif->map_property(sd, MAPPROPERTY_AGITZONE);
+
// info about nearby objects
// must use foreachinarea (CIRCULAR_AREA interferes with foreachinrange)
- iMap->foreachinarea(clif->getareachar, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_ALL, sd);
+ map->foreachinarea(clif->getareachar, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_ALL, sd);
// pet
if( sd->pd ) {
- if( battle_config.pet_no_gvg && map_flag_gvg(sd->bl.m) ) { //Return the pet to egg. [Skotlex]
- clif->message(sd->fd, msg_txt(666));
- pet_menu(sd, 3); //Option 3 is return to egg.
+ if( battle_config.pet_no_gvg && map_flag_gvg2(sd->bl.m) ) { //Return the pet to egg. [Skotlex]
+ clif->message(sd->fd, msg_txt(866)); // "Pets are not allowed in Guild Wars."
+ pet->menu(sd, 3); //Option 3 is return to egg.
} else {
- iMap->addblock(&sd->pd->bl);
+ map->addblock(&sd->pd->bl);
clif->spawn(&sd->pd->bl);
clif->send_petdata(sd,sd->pd,0,0);
clif->send_petstatus(sd);
-// skill->unit_move(&sd->pd->bl,gettick(),1);
+// skill->unit_move(&sd->pd->bl,timer->gettick(),1);
}
}
//homunculus [blackhole89]
if( homun_alive(sd->hd) ) {
- iMap->addblock(&sd->hd->bl);
+ map->addblock(&sd->hd->bl);
clif->spawn(&sd->hd->bl);
clif->send_homdata(sd,SP_ACK,0);
clif->hominfo(sd,sd->hd,1);
@@ -9477,11 +9412,11 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if( battle_config.hom_setting&0x8 )
status_calc_bl(&sd->hd->bl, SCB_SPEED); //Homunc mimic their master's speed on each map change
if( !(battle_config.hom_setting&0x2) )
- skill->unit_move(&sd->hd->bl,iTimer->gettick(),1); // apply land skills immediately
+ skill->unit_move(&sd->hd->bl,timer->gettick(),1); // apply land skills immediately
}
if( sd->md ) {
- iMap->addblock(&sd->md->bl);
+ map->addblock(&sd->md->bl);
clif->spawn(&sd->md->bl);
clif->mercenary_info(sd);
clif->mercenary_skillblock(sd);
@@ -9489,7 +9424,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
}
if( sd->ed ) {
- iMap->addblock(&sd->ed->bl);
+ map->addblock(&sd->ed->bl);
clif->spawn(&sd->ed->bl);
clif->elemental_info(sd);
clif->elemental_updatestatus(sd,SP_HP);
@@ -9500,6 +9435,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if(sd->state.connect_new) {
int lv;
+ first_time = true;
sd->state.connect_new = 0;
clif->skillinfoblock(sd);
clif->hotkeys(sd);
@@ -9512,38 +9448,38 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if (sd->sc.option&OPTION_FALCON)
clif->status_change(&sd->bl, SI_FALCON, 1, 0, 0, 0, 0);
- if (sd->sc.option&OPTION_RIDING)
+ if (sd->sc.option&(OPTION_RIDING|OPTION_DRAGON))
clif->status_change(&sd->bl, SI_RIDING, 1, 0, 0, 0, 0);
else if (sd->sc.option&OPTION_WUGRIDER)
clif->status_change(&sd->bl, SI_WUGRIDER, 1, 0, 0, 0, 0);
if(sd->status.manner < 0)
- sc_start(&sd->bl,SC_NOCHAT,100,0,0);
+ sc_start(NULL,&sd->bl,SC_NOCHAT,100,0,0);
//Auron reported that This skill only triggers when you logon on the map o.O [Skotlex]
if ((lv = pc->checkskill(sd,SG_KNOWLEDGE)) > 0) {
if(sd->bl.m == sd->feel_map[0].m
|| sd->bl.m == sd->feel_map[1].m
|| sd->bl.m == sd->feel_map[2].m)
- sc_start(&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv));
+ sc_start(NULL,&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv));
}
if(sd->pd && sd->pd->pet.intimate > 900)
- clif->pet_emotion(sd->pd,(sd->pd->pet.class_ - 100)*100 + 50 + pet_hungry_val(sd->pd));
+ clif->pet_emotion(sd->pd,(sd->pd->pet.class_ - 100)*100 + 50 + pet->hungry_val(sd->pd));
if(homun_alive(sd->hd))
homun->init_timers(sd->hd);
- if (iMap->night_flag && map[sd->bl.m].flag.nightenabled) {
+ if (map->night_flag && map->list[sd->bl.m].flag.nightenabled) {
sd->state.night = 1;
clif->status_change(&sd->bl, SI_SKE, 1, 0, 0, 0, 0);
}
// Notify everyone that this char logged in [Skotlex].
- iMap->map_foreachpc(clif->friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 1);
+ map->foreachpc(clif->friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 1);
//Login Event
- npc_script_event(sd, NPCE_LOGIN);
+ npc->script_event(sd, NPCE_LOGIN);
} else {
//For some reason the client "loses" these on warp/map-change.
clif->updatestatus(sd,SP_STR);
@@ -9559,7 +9495,10 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
sd->npc_menu = 0;
if(sd->npc_id)
- npc_event_dequeue(sd);
+ npc->event_dequeue(sd);
+
+ if( sd->guild && ( battle_config.guild_notice_changemap == 2 || ( battle_config.guild_notice_changemap == 1 && sd->state.changemap ) ) )
+ clif->guild_notice(sd,sd->guild);
}
if( sd->state.changemap ) {// restore information that gets lost on map-change
@@ -9567,37 +9506,39 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
clif->partyinvitationstate(sd);
clif->equpcheckbox(sd);
#endif
- if( (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100) &&
- (map_flag_gvg(sd->state.pmap) || map_flag_gvg(sd->bl.m) || map[sd->state.pmap].flag.battleground || map[sd->bl.m].flag.battleground) )
+ if( (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100)
+ && (map_flag_gvg2(sd->state.pmap) || map_flag_gvg2(sd->bl.m)
+ || map->list[sd->state.pmap].flag.battleground || map->list[sd->bl.m].flag.battleground) )
status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty
- if( iMap->night_flag && map[sd->bl.m].flag.nightenabled ) { //Display night.
+ if( map->night_flag && map->list[sd->bl.m].flag.nightenabled ) {
+ //Display night.
if( !sd->state.night ) {
sd->state.night = 1;
- clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_SKE);
+ clif->status_change(&sd->bl, SI_SKE, 1, 0, 0, 0, 0);
}
} else if( sd->state.night ) { //Clear night display.
sd->state.night = 0;
clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_SKE);
}
- if( map[sd->bl.m].flag.battleground ) {
+ if( map->list[sd->bl.m].flag.battleground ) {
clif->map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground Mode
- if( map[sd->bl.m].flag.battleground == 2 )
+ if( map->list[sd->bl.m].flag.battleground == 2 )
clif->bg_updatescore_single(sd);
}
- if( map[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m) ) {
+ if( map->list[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m) ) {
char output[128];
- sprintf(output, "[ Kill Steal Protection Disable. KS is allowed in this map ]");
- clif->broadcast(&sd->bl, output, strlen(output) + 1, 0x10, SELF);
+ sprintf(output, "[ Kill Steal Protection Disabled. KS is allowed in this map ]");
+ clif->broadcast(&sd->bl, output, strlen(output) + 1, BC_BLUE, SELF);
}
- iMap->iwall_get(sd); // Updates Walls Info on this Map to Client
- status_calc_pc(sd, false);/* some conditions are map-dependent so we must recalculate */
+ map->iwall_get(sd); // Updates Walls Info on this Map to Client
+ status_calc_pc(sd, SCO_NONE);/* some conditions are map-dependent so we must recalculate */
sd->state.changemap = false;
-
- if( hChSys.local && hChSys.local_autojoin && !map[sd->bl.m].flag.chsysnolocalaj ) {
+
+ if( hChSys.local && hChSys.local_autojoin ) {
clif->chsys_mjoin(sd);
}
}
@@ -9605,13 +9546,13 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
mail->clear(sd);
clif->maptypeproperty2(&sd->bl,SELF);
-
+
/* Guild Aura Init */
if( sd->state.gmaster_flag ) {
- guild->aura_refresh(sd,GD_LEADERSHIP,guild->checkskill(sd->state.gmaster_flag,GD_LEADERSHIP));
- guild->aura_refresh(sd,GD_GLORYWOUNDS,guild->checkskill(sd->state.gmaster_flag,GD_GLORYWOUNDS));
- guild->aura_refresh(sd,GD_SOULCOLD,guild->checkskill(sd->state.gmaster_flag,GD_SOULCOLD));
- guild->aura_refresh(sd,GD_HAWKEYES,guild->checkskill(sd->state.gmaster_flag,GD_HAWKEYES));
+ guild->aura_refresh(sd,GD_LEADERSHIP,guild->checkskill(sd->guild,GD_LEADERSHIP));
+ guild->aura_refresh(sd,GD_GLORYWOUNDS,guild->checkskill(sd->guild,GD_GLORYWOUNDS));
+ guild->aura_refresh(sd,GD_SOULCOLD,guild->checkskill(sd->guild,GD_SOULCOLD));
+ guild->aura_refresh(sd,GD_HAWKEYES,guild->checkskill(sd->guild,GD_HAWKEYES));
}
if( sd->state.vending ) { /* show we have a vending */
@@ -9619,8 +9560,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
clif->showvendingboard(&sd->bl,sd->message,0);
}
- if(map[sd->bl.m].flag.loadevent) // Lance
- npc_script_event(sd, NPCE_LOADMAP);
+ if(map->list[sd->bl.m].flag.loadevent) // Lance
+ npc->script_event(sd, NPCE_LOADMAP);
if (pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd)) //blindness [Komurka]
clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_DEVIL1);
@@ -9628,16 +9569,25 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if (sd->sc.opt2) //Client loses these on warp.
clif->changeoption(&sd->bl);
+ if( sd->sc.data[SC_MONSTER_TRANSFORM] && battle_config.mon_trans_disable_in_gvg && map_flag_gvg2(sd->bl.m) ){
+ status_change_end(&sd->bl, SC_MONSTER_TRANSFORM, INVALID_TIMER);
+ clif->message(sd->fd, msg_txt(1488)); // Transforming into monster is not allowed in Guild Wars.
+ }
+
clif->weather_check(sd);
+ // This should be displayed last
+ if( sd->guild && first_time )
+ clif->guild_notice(sd, sd->guild);
+
// For automatic triggering of NPCs after map loading (so you don't need to walk 1 step first)
- if (iMap->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNPC))
- npc_touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y);
+ if (map->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNPC))
+ npc->touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y);
else
sd->areanpc_id = 0;
/* it broke at some point (e.g. during a crash), so we make it visibly dead again. */
- if( !sd->status.hp && !pc_isdead(sd) && status_isdead(&sd->bl) )
+ if( !sd->status.hp && !pc_isdead(sd) && status->isdead(&sd->bl) )
pc_setdead(sd);
// If player is dead, and is spawned (such as @refresh) send death packet. [Valaris]
@@ -9645,23 +9595,38 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
clif->clearunit_area(&sd->bl, CLR_DEAD);
else {
skill->usave_trigger(sd);
- clif->changed_dir(&sd->bl, SELF);
+ sd->ud.dir = 0;/* enforce north-facing (not visually, virtually) */
}
-// Trigger skill effects if you appear standing on them
+ // Trigger skill effects if you appear standing on them
if(!battle_config.pc_invincible_time)
- skill->unit_move(&sd->bl,iTimer->gettick(),1);
+ skill->unit_move(&sd->bl,timer->gettick(),1);
+
+ // NPC Quest / Event Icon Check [Kisuka]
+#if PACKETVER >= 20090218
+ for(i = 0; i < map->list[sd->bl.m].qi_count; i++) {
+ struct questinfo *qi = &map->list[sd->bl.m].qi_data[i];
+ if( quest->check(sd, qi->quest_id, HAVEQUEST) == -1 ) {// Check if quest is not started
+ if( qi->hasJob ) { // Check if quest is job-specific, check is user is said job class.
+ if( sd->class_ == qi->job )
+ clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color);
+ } else {
+ clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color);
+ }
+ }
+ }
+#endif
}
/// Server's tick (ZC_NOTIFY_TIME).
/// 007f <time>.L
-void clif_notify_time(struct map_session_data* sd, unsigned long time) {
+void clif_notify_time(struct map_session_data* sd, int64 time) {
int fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x7f));
WFIFOW(fd,0) = 0x7f;
- WFIFOL(fd,2) = time;
+ WFIFOL(fd,2) = (uint32)time;
WFIFOSET(fd,packet_len(0x7f));
}
@@ -9674,7 +9639,7 @@ void clif_parse_TickSend(int fd, struct map_session_data *sd)
{
sd->client_tick = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
- clif->notify_time(sd, iTimer->gettick());
+ clif->notify_time(sd, timer->gettick());
}
@@ -9724,7 +9689,8 @@ void clif_parse_Hotkey(int fd, struct map_session_data *sd) {
/// Displays cast-like progress bar (ZC_PROGRESS).
/// 02f0 <color>.L <time>.L
-void clif_progressbar(struct map_session_data * sd, unsigned long color, unsigned int second)
+/* TODO ZC_PROGRESS_ACTOR <account_id>.L */
+void clif_progressbar(struct map_session_data * sd, unsigned int color, unsigned int second)
{
int fd = sd->fd;
@@ -9754,11 +9720,11 @@ void clif_parse_progressbar(int fd, struct map_session_data * sd)
{
int npc_id = sd->progressbar.npc_id;
- if( iTimer->gettick() < sd->progressbar.timeout && sd->st )
+ if( timer->gettick() < sd->progressbar.timeout && sd->st )
sd->st->state = END;
- sd->state.workinprogress = sd->progressbar.npc_id = sd->progressbar.timeout = 0;
- npc_scriptcont(sd, npc_id, false);
+ sd->progressbar.timeout = sd->state.workinprogress = sd->progressbar.npc_id = 0;
+ npc->scriptcont(sd, npc_id, false);
}
@@ -9790,9 +9756,10 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
RFIFOPOS(fd, packet_db[RFIFOW(fd,0)].pos[0], &x, &y, NULL);
//Set last idle time... [Skotlex]
- sd->idletime = last_tick;
+ if( battle_config.idletime_criteria & BCIDLE_WALK )
+ sd->idletime = sockt->last_tick;
- unit_walktoxy(&sd->bl, x, y, 4);
+ unit->walktoxy(&sd->bl, x, y, 4);
}
@@ -9820,8 +9787,8 @@ void clif_disconnect_ack(struct map_session_data* sd, short result)
void clif_parse_QuitGame(int fd, struct map_session_data *sd)
{
/* Rovert's prevent logout option fixed [Valaris] */
- if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] &&
- (!battle_config.prevent_logout || DIFF_TICK(iTimer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
+ if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] &&
+ (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
{
set_eof(fd);
@@ -9836,8 +9803,7 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd)
/// 0094 <id>.L (CZ_REQNAME)
/// 0368 <id>.L (CZ_REQNAME2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd)
-{
+void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) {
int id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
struct block_list* bl;
//struct status_change *sc;
@@ -9845,7 +9811,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd)
if( id < 0 && -id == sd->bl.id ) // for disguises [Valaris]
id = sd->bl.id;
- bl = iMap->id2bl(id);
+ bl = map->id2bl(id);
if( bl == NULL )
return; // Lagged clients could request names of already gone mobs/players. [Skotlex]
@@ -9853,26 +9819,26 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd)
return; // Block namerequests past view range
// 'see people in GM hide' cheat detection
- /* disabled due to false positives (network lag + request name of char that's about to hide = race condition)
- sc = status_get_sc(bl);
+#if 0 /* disabled due to false positives (network lag + request name of char that's about to hide = race condition) */
+ sc = status->get_sc(bl);
if (sc && sc->option&OPTION_INVISIBLE && !disguised(bl) &&
bl->type != BL_NPC && //Skip hidden NPCs which can be seen using Maya Purple
- pc->get_group_level(sd) < battle_config.hack_info_GM_level
+ pc_get_group_level(sd) < battle_config.hack_info_GM_level
) {
char gm_msg[256];
sprintf(gm_msg, "Hack on NameRequest: character '%s' (account: %d) requested the name of an invisible target (id: %d).\n", sd->status.name, sd->status.account_id, id);
ShowWarning(gm_msg);
// information is sent to all online GMs
- intif_wis_message_to_gm(iMap->wisp_server_name, battle_config.hack_info_GM_level, gm_msg);
+ intif->wis_message_to_gm(map->wisp_server_name, battle_config.hack_info_GM_level, gm_msg);
return;
}
- */
+#endif // 0
clif->charnameack(fd, bl);
}
-int clif_undisguise_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int clif_undisguise_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data * sd;
- if( (sd = iMap->id2sd(id)) ) {
+ if( (sd = map->id2sd(id)) ) {
sd->fontcolor_tid = INVALID_TIMER;
if( sd->fontcolor && sd->disguise == sd->status.class_ )
pc->disguise(sd,-1);
@@ -9886,10 +9852,10 @@ int clif_undisguise_timer(int tid, unsigned int tick, int id, intptr_t data) {
void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
{
const char* text = (char*)RFIFOP(fd,4);
- int textlen = RFIFOW(fd,2) - 4;
+ size_t textlen = RFIFOW(fd,2) - 4;
char *name, *message, *fakename = NULL;
- int namelen, messagelen;
+ size_t namelen, messagelen;
bool is_fake;
@@ -9897,18 +9863,53 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
return;
- if( atcommand->parse(fd, sd, message, 1) )
+ if( atcommand->exec(fd, sd, message, true) )
return;
- if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
+ if( !pc->can_talk(sd) )
return;
if( battle_config.min_chat_delay ) { //[Skotlex]
- if (DIFF_TICK(sd->cantalk_tick, iTimer->gettick()) > 0)
+ if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
return;
- sd->cantalk_tick = iTimer->gettick() + battle_config.min_chat_delay;
+ sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
-
+
+ if( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE ) {
+ unsigned int next = pc->nextbaseexp(sd);
+ if( next == 0 ) next = pc->thisbaseexp(sd);
+ if( next ) { // 0%, 10%, 20%, ...
+ int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. );
+ if( (battle_config.snovice_call_type || percent) && ( percent%100 ) == 0 ) {// 10.0%, 20.0%, ..., 90.0%
+ switch (sd->state.snovice_call_flag) {
+ case 0:
+ if( strstr(message, msg_txt(1479)) ) // "Dear angel, can you hear my voice?"
+ sd->state.snovice_call_flag = 1;
+ break;
+ case 1: {
+ char buf[256];
+ snprintf(buf, 256, msg_txt(1480), sd->status.name);
+ if( strstr(message, buf) ) // "I am %s Super Novice~"
+ sd->state.snovice_call_flag = 2;
+ }
+ break;
+ case 2:
+ if( strstr(message, msg_txt(1481)) ) // "Help me out~ Please~ T_T"
+ sd->state.snovice_call_flag = 3;
+ break;
+ case 3:
+ sc_start(NULL,&sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
+ clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions
+ sd->state.snovice_call_flag = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ if( battle_config.idletime_criteria & BCIDLE_CHAT )
+ sd->idletime = sockt->last_tick;
+
if( sd->gcbind ) {
clif->chsys_send(sd->gcbind,sd,message);
return;
@@ -9917,21 +9918,21 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
unsigned char mylen = 1;
if( sd->disguise == -1 ) {
- sd->fontcolor_tid = iTimer->add_timer(iTimer->gettick()+5000, clif->undisguise_timer, sd->bl.id, 0);
+ sd->fontcolor_tid = timer->add(timer->gettick()+5000, clif->undisguise_timer, sd->bl.id, 0);
pc->disguise(sd,sd->status.class_);
if( pc_isdead(sd) )
clif_clearunit_single(-sd->bl.id, CLR_DEAD, sd->fd);
- if( unit_is_walking(&sd->bl) )
+ if( unit->is_walking(&sd->bl) )
clif->move(&sd->ud);
} else if ( sd->disguise == sd->status.class_ && sd->fontcolor_tid != INVALID_TIMER ) {
- const struct TimerData *timer;
- if( (timer = iTimer->get_timer(sd->fontcolor_tid)) ) {
- iTimer->settick_timer(sd->fontcolor_tid, timer->tick+5000);
+ const struct TimerData *td;
+ if( (td = timer->get(sd->fontcolor_tid)) ) {
+ timer->settick(sd->fontcolor_tid, td->tick+5000);
}
}
-
+
mylen += snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message);
-
+
WFIFOHEAD(fd,mylen + 12);
WFIFOW(fd,0) = 0x2C1;
WFIFOW(fd,2) = mylen + 12;
@@ -9943,7 +9944,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
WFIFOSET(fd, mylen + 12);
return;
}
-
+
/**
* Fake Name Design by FatalEror (bug report #9)
**/
@@ -9974,13 +9975,14 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
WFIFOW(fd,0) = 0x8e;
}
WFIFOSET(fd, WFIFOW(fd,2));
+
+ // Chat logging type 'O' / Global Chat
+ logs->chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message);
+
#ifdef PCRE_SUPPORT
// trigger listening npcs
- iMap->foreachinrange(npc_chat_sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl);
+ map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl);
#endif
-
- // Chat logging type 'O' / Global Chat
- logs->chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message);
}
@@ -9995,7 +9997,7 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd)
map_name = (char*)RFIFOP(fd,2);
map_name[MAP_NAME_LENGTH_EXT-1]='\0';
sprintf(command, "%cmapmove %s %d %d", atcommand->at_symbol, map_name, RFIFOW(fd,18), RFIFOW(fd,20));
- atcommand->parse(fd, sd, command, 1);
+ atcommand->exec(fd, sd, command, true);
}
@@ -10021,7 +10023,7 @@ void clif_changed_dir(struct block_list *bl, enum send_target target)
WBUFW(buf,0) = 0x9c;
WBUFL(buf,2) = bl->id;
WBUFW(buf,6) = bl->type==BL_PC?((TBL_PC*)bl)->head_dir:0;
- WBUFB(buf,8) = unit_getdir(bl);
+ WBUFB(buf,8) = unit->getdir(bl);
clif->send(buf, packet_len(0x9c), bl, target);
@@ -10070,6 +10072,9 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd)
}
sd->emotionlasttime = time(NULL);
+ if( battle_config.idletime_criteria & BCIDLE_EMOTION )
+ sd->idletime = sockt->last_tick;
+
if(battle_config.client_reshuffle_dice && emoticon>=E_DICE1 && emoticon<=E_DICE6) {// re-roll dice
emoticon = rnd()%6+E_DICE1;
}
@@ -10095,26 +10100,27 @@ void clif_user_count(struct map_session_data* sd, int count) {
/// /w /who (CZ_REQ_USER_COUNT).
/// Request to display amount of currently connected players.
/// 00c1
-void clif_parse_HowManyConnections(int fd, struct map_session_data *sd)
-{
- clif->user_count(sd, iMap->getusers());
+void clif_parse_HowManyConnections(int fd, struct map_session_data *sd) {
+ clif->user_count(sd, map->getusers());
}
-void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, unsigned int tick)
-{
+void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, int64 tick) {
+ struct block_list *target = NULL;
+
if (pc_isdead(sd)) {
clif->clearunit_area(&sd->bl, CLR_DEAD);
return;
}
- if (sd->sc.count &&
- (sd->sc.data[SC_TRICKDEAD] ||
- sd->sc.data[SC_AUTOCOUNTER] ||
- sd->sc.data[SC_BLADESTOP] ||
- sd->sc.data[SC__MANHOLE] ||
- sd->sc.data[SC_CURSEDCIRCLE_ATKER] ||
- sd->sc.data[SC_CURSEDCIRCLE_TARGET] ))
+ // Statuses that don't let the player sit / attack / talk with NPCs(targeted)
+ // (not all are included in pc_can_attack)
+ if( sd->sc.count && (
+ sd->sc.data[SC_TRICKDEAD] ||
+ (sd->sc.data[SC_AUTOCOUNTER] && action_type != 0x07) ||
+ sd->sc.data[SC_BLADESTOP] ||
+ sd->sc.data[SC_DEEP_SLEEP] )
+ )
return;
pc_stop_walking(sd, 1);
@@ -10127,13 +10133,15 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
case 0x00: // once attack
case 0x07: // continuous attack
- if( pc_cant_act(sd) || sd->sc.option&OPTION_HIDE )
+ if( (target = map->id2bl(target_id)) && target->type == BL_NPC ) {
+ npc->click(sd,(TBL_NPC*)target);
return;
-
- if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) )
+ }
+
+ if( pc_cant_act(sd) || pc_issit(sd) || sd->sc.option&OPTION_HIDE )
return;
- if( sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM] )
+ if( sd->sc.option&OPTION_COSTUME )
return;
if (!battle_config.sdelay_attack_enable && pc->checkskill(sd, SA_FREECAST) <= 0) {
@@ -10144,8 +10152,9 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
}
pc->delinvincibletimer(sd);
- sd->idletime = last_tick;
- unit_attack(&sd->bl, target_id, action_type != 0);
+ if( battle_config.idletime_criteria & BCIDLE_ATTACK )
+ sd->idletime = sockt->last_tick;
+ unit->attack(&sd->bl, target_id, action_type != 0);
break;
case 0x02: // sitdown
if (battle_config.basic_skill_check && pc->checkskill(sd, NV_BASIC) < 3) {
@@ -10168,6 +10177,9 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
)) //No sitting during these states either.
break;
+ if( battle_config.idletime_criteria & BCIDLE_SIT )
+ sd->idletime = sockt->last_tick;
+
pc_setsit(sd);
skill->sit(sd,1);
clif->sitting(&sd->bl);
@@ -10178,6 +10190,10 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
clif->standing(&sd->bl);
return;
}
+
+ if( battle_config.idletime_criteria & BCIDLE_SIT )
+ sd->idletime = sockt->last_tick;
+
pc->setstand(sd);
skill->sit(sd,0);
clif->standing(&sd->bl);
@@ -10187,13 +10203,13 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
void clif_hercules_chsys_left(struct hChSysCh *channel, struct map_session_data *sd) {
unsigned char i;
-
+
if ( !idb_remove(channel->users,sd->status.char_id) )
return;
-
+
if( channel == sd->gcbind )
sd->gcbind = NULL;
-
+
if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) {
clif->chsys_delete(channel);
} else if( !hChSys.closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) {
@@ -10201,14 +10217,14 @@ void clif_hercules_chsys_left(struct hChSysCh *channel, struct map_session_data
sprintf(message, "#%s '%s' left",channel->name,sd->status.name);
clif->chsys_msg(channel,sd,message);
}
-
+
for( i = 0; i < sd->channel_count; i++ ) {
if( sd->channels[i] == channel ) {
sd->channels[i] = NULL;
break;
}
}
-
+
if( i < sd->channel_count ) {
unsigned char cursor = 0;
for( i = 0; i < sd->channel_count; i++ ) {
@@ -10230,16 +10246,16 @@ void clif_hercules_chsys_left(struct hChSysCh *channel, struct map_session_data
void clif_hercules_chsys_quitg(struct map_session_data *sd) {
unsigned char i;
struct hChSysCh *channel = NULL;
-
+
for( i = 0; i < sd->channel_count; i++ ) {
if( (channel = sd->channels[i] ) != NULL && channel->type == hChSys_ALLY ) {
-
+
if ( !idb_remove(channel->users,sd->status.char_id) )
continue;
-
+
if( channel == sd->gcbind )
sd->gcbind = NULL;
-
+
if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) {
clif->chsys_delete(channel);
} else if( !hChSys.closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) {
@@ -10250,7 +10266,7 @@ void clif_hercules_chsys_quitg(struct map_session_data *sd) {
sd->channels[i] = NULL;
}
}
-
+
if( i < sd->channel_count ) {
unsigned char cursor = 0;
for( i = 0; i < sd->channel_count; i++ ) {
@@ -10266,21 +10282,21 @@ void clif_hercules_chsys_quitg(struct map_session_data *sd) {
sd->channels = NULL;
}
}
-
+
}
void clif_hercules_chsys_quit(struct map_session_data *sd) {
unsigned char i;
struct hChSysCh *channel = NULL;
-
+
for( i = 0; i < sd->channel_count; i++ ) {
if( (channel = sd->channels[i] ) != NULL ) {
idb_remove(channel->users,sd->status.char_id);
-
+
if( channel == sd->gcbind )
sd->gcbind = NULL;
-
+
if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) {
clif->chsys_delete(channel);
} else if( !hChSys.closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) {
@@ -10288,13 +10304,13 @@ void clif_hercules_chsys_quit(struct map_session_data *sd) {
sprintf(message, "#%s '%s' left",channel->name,sd->status.name);
clif->chsys_msg(channel,sd,message);
}
-
+
}
}
sd->channel_count = 0;
aFree(sd->channels);
- sd->channels = NULL;
+ sd->channels = NULL;
}
/// Request for an action.
@@ -10305,7 +10321,7 @@ void clif_hercules_chsys_quit(struct map_session_data *sd) {
/// 1 = pick up item
/// 2 = sit down
/// 3 = stand up
-/// 7 = continous attack
+/// 7 = continuous attack
/// 12 = (touch skill?)
/// There are various variants of this packet, some of them have padding between fields.
void clif_parse_ActionRequest(int fd, struct map_session_data *sd)
@@ -10313,7 +10329,7 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd)
clif->pActionRequest_sub(sd,
RFIFOB(fd,packet_db[RFIFOW(fd,0)].pos[1]),
RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]),
- iTimer->gettick()
+ timer->gettick()
);
}
@@ -10326,14 +10342,14 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd)
void clif_parse_Restart(int fd, struct map_session_data *sd) {
switch(RFIFOB(fd,2)) {
case 0x00:
- pc->respawn(sd,CLR_RESPAWN);
+ pc->respawn(sd,CLR_OUTSIGHT);
break;
case 0x01:
/* Rovert's Prevent logout option - Fixed [Valaris] */
- if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] &&
- (!battle_config.prevent_logout || DIFF_TICK(iTimer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
+ if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] &&
+ (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
{ //Send to char-server for character selection.
- chrif_charselectreq(sd, session[fd]->client_addr);
+ chrif->charselectreq(sd, session[fd]->client_addr);
} else {
clif->disconnect_ack(sd, 1);
}
@@ -10350,25 +10366,29 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
int i;
char *target, *message;
- int namelen, messagelen;
+ size_t namelen, messagelen;
// validate packet and retrieve name and message
if( !clif->process_message(sd, 1, &target, &namelen, &message, &messagelen) )
return;
- if ( atcommand->parse(fd, sd, message, 1) )
+ if ( atcommand->exec(fd, sd, message, true) )
return;
- if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))
+ // Statuses that prevent the player from whispering
+ if( !pc->can_talk(sd) )
return;
if (battle_config.min_chat_delay) { //[Skotlex]
- if (DIFF_TICK(sd->cantalk_tick, iTimer->gettick()) > 0) {
+ if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) {
return;
}
- sd->cantalk_tick = iTimer->gettick() + battle_config.min_chat_delay;
+ sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
+ if( battle_config.idletime_criteria & BCIDLE_CHAT )
+ sd->idletime = sockt->last_tick;
+
// Chat logging type 'W' / Whisper
logs->chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message);
@@ -10377,8 +10397,8 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
//-------------------------------------------------------//
if (target[0] && (strncasecmp(target,"NPC:",4) == 0) && (strlen(target) > 4)) {
char* str = target+4; //Skip the NPC: string part.
- struct npc_data* npc;
- if ((npc = npc_name2id(str))) {
+ struct npc_data *nd;
+ if ((nd = npc->name2id(str))) {
char split_data[NUM_WHISPER_VAR][CHAT_SIZE_MAX];
char *split;
char output[256];
@@ -10402,11 +10422,11 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
for( i = 0; i < NUM_WHISPER_VAR; ++i ) {
sprintf(output, "@whispervar%d$", i);
- set_var(sd,output,(char *) split_data[i]);
+ script->set_var(sd,output,(char *) split_data[i]);
}
- sprintf(output, "%s::OnWhisperGlobal", npc->exname);
- npc_event(sd,output,0); // Calls the NPC label
+ sprintf(output, "%s::OnWhisperGlobal", nd->exname);
+ npc->event(sd,output,0); // Calls the NPC label
return;
}
@@ -10415,19 +10435,19 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
char* chname = target;
chname++;
-
+
if( hChSys.local && strcmpi(chname, hChSys.local_name) == 0 ) {
- if( !map[sd->bl.m].channel ) {
+ if( !map->list[sd->bl.m].channel ) {
clif->chsys_mjoin(sd);
}
- channel = map[sd->bl.m].channel;
+ channel = map->list[sd->bl.m].channel;
} else if( hChSys.ally && sd->status.guild_id && strcmpi(chname, hChSys.ally_name) == 0 ) {
struct guild *g = sd->guild;
if( !g ) return;
- channel = (struct hChSysCh *)g->channel;
+ channel = g->channel;
}
if( channel || (channel = strdb_get(clif->channel_db,chname)) ) {
- unsigned char k;
+ int k;
for( k = 0; k < sd->channel_count; k++ ) {
if( sd->channels[k] == channel )
break;
@@ -10437,11 +10457,10 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
} else if( channel->pass[0] == '\0' && !(channel->banned && idb_exists(channel->banned, sd->status.account_id)) ) {
if( channel->type == hChSys_ALLY ) {
struct guild *g = sd->guild, *sg = NULL;
- int k;
for (k = 0; k < MAX_GUILDALLIANCE; k++) {
if( g->alliance[k].opposition == 0 && g->alliance[k].guild_id && (sg = guild->search(g->alliance[k].guild_id) ) ) {
- if( !(((struct hChSysCh*)sg->channel)->banned && idb_exists(((struct hChSysCh*)sg->channel)->banned, sd->status.account_id)))
- clif->chsys_join((struct hChSysCh *)sg->channel,sd);
+ if( !(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id)))
+ clif->chsys_join(sg->channel,sd);
}
}
}
@@ -10455,7 +10474,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
}
// searching destination character
- dstsd = iMap->nick2sd(target);
+ dstsd = map->nick2sd(target);
if (dstsd == NULL || strcmp(dstsd->status.name, target) != 0) {
// player is not on this map-server
@@ -10463,14 +10482,14 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
// if there are 'Test' player on an other map-server and 'test' player on this map-server,
// and if we ask for 'Test', we must not contact 'test' player
// so, we send information to inter-server, which is the only one which decide (and copy correct name).
- intif_wis_message(sd, target, message, messagelen);
+ intif->wis_message(sd, target, message, messagelen);
return;
}
// if player ignores everyone
- if (dstsd->state.ignoreAll) {
- if (dstsd->sc.option & OPTION_INVISIBLE && pc->get_group_level(sd) < pc->get_group_level(dstsd))
- clif->wis_end(fd, 1); // 1: target character is not loged in
+ if (dstsd->state.ignoreAll && pc_get_group_level(sd) <= pc_get_group_level(dstsd)) {
+ if (dstsd->sc.option & OPTION_INVISIBLE && pc_get_group_level(sd) < pc_get_group_level(dstsd))
+ clif->wis_end(fd, 1); // 1: target character is not logged in
else
clif->wis_end(fd, 3); // 3: everyone ignored by target
return;
@@ -10480,15 +10499,17 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
if( dstsd->state.autotrade == 1 ) {
char output[256];
sprintf(output, "%s is in autotrade mode and cannot receive whispered messages.", dstsd->status.name);
- clif->wis_message(fd, iMap->wisp_server_name, output, strlen(output) + 1);
+ clif->wis_message(fd, map->wisp_server_name, output, strlen(output) + 1);
return;
}
- // if player ignores the source character
- ARR_FIND(0, MAX_IGNORE_LIST, i, dstsd->ignore[i].name[0] == '\0' || strcmp(dstsd->ignore[i].name, sd->status.name) == 0);
- if(i < MAX_IGNORE_LIST && dstsd->ignore[i].name[0] != '\0') { // source char present in ignore list
- clif->wis_end(fd, 2); // 2: ignored by target
- return;
+ if( pc_get_group_level(sd) <= pc_get_group_level(dstsd) ) {
+ // if player ignores the source character
+ ARR_FIND(0, MAX_IGNORE_LIST, i, dstsd->ignore[i].name[0] == '\0' || strcmp(dstsd->ignore[i].name, sd->status.name) == 0);
+ if(i < MAX_IGNORE_LIST && dstsd->ignore[i].name[0] != '\0') { // source char present in ignore list
+ clif->wis_end(fd, 2); // 2: ignored by target
+ return;
+ }
}
// notify sender of success
@@ -10511,7 +10532,7 @@ void clif_parse_Broadcast(int fd, struct map_session_data* sd) {
mes_len_check(msg, len, CHAT_SIZE_MAX);
sprintf(command, "%ckami %s", atcommand->at_symbol, msg);
- atcommand->parse(fd, sd, command, 1);
+ atcommand->exec(fd, sd, command, true);
}
@@ -10519,14 +10540,13 @@ void clif_parse_Broadcast(int fd, struct map_session_data* sd) {
/// 009f <id>.L (CZ_ITEM_PICKUP)
/// 0362 <id>.L (CZ_ITEM_PICKUP2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_TakeItem(int fd, struct map_session_data *sd)
-{
+void clif_parse_TakeItem(int fd, struct map_session_data *sd) {
struct flooritem_data *fitem;
int map_object_id;
map_object_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
- fitem = (struct flooritem_data*)iMap->id2bl(map_object_id);
+ fitem = (struct flooritem_data*)map->id2bl(map_object_id);
do {
if (pc_isdead(sd)) {
@@ -10586,6 +10606,9 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd)
if (!pc->dropitem(sd, item_index, item_amount))
break;
+ if( battle_config.idletime_criteria & BCIDLE_DROPITEM )
+ sd->idletime = sockt->last_tick;
+
return;
}
@@ -10611,7 +10634,8 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd)
return;
//Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex]
- sd->idletime = last_tick;
+ if( battle_config.idletime_criteria & BCIDLE_USEITEM )
+ sd->idletime = sockt->last_tick;
n = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-2;
if(n <0 || n >= MAX_INVENTORY)
@@ -10623,16 +10647,17 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd)
/// Request to equip an item (CZ_REQ_WEAR_EQUIP).
/// 00a9 <index>.W <position>.W
-void clif_parse_EquipItem(int fd,struct map_session_data *sd)
-{
- int index;
+/// 0998 <index>.W <position>.L
+void clif_parse_EquipItem(int fd,struct map_session_data *sd) {
+ struct packet_equip_item *p = P2PTR(fd);
if(pc_isdead(sd)) {
clif->clearunit_area(&sd->bl,CLR_DEAD);
return;
}
- index = RFIFOW(fd,2)-2;
- if (index < 0 || index >= MAX_INVENTORY)
+
+ p->index = p->index - 2;
+ if (p->index >= MAX_INVENTORY)
return; //Out of bounds check.
if( sd->npc_id ) {
@@ -10643,24 +10668,27 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd)
else if ( pc_cant_act2(sd) || sd->state.prerefining )
return;
- if(!sd->status.inventory[index].identify) {
- clif->equipitemack(sd,index,0,0); // fail
+ if(!sd->status.inventory[p->index].identify) {
+ clif->equipitemack(sd,p->index,0,EIA_FAIL);// fail
return;
}
- if(!sd->inventory_data[index])
+ if(!sd->inventory_data[p->index])
return;
- if(sd->inventory_data[index]->type == IT_PETARMOR){
- pet_equipitem(sd,index);
+ if(sd->inventory_data[p->index]->type == IT_PETARMOR){
+ pet->equipitem(sd,p->index);
return;
}
+ if( battle_config.idletime_criteria & BCIDLE_USEITEM )
+ sd->idletime = sockt->last_tick;
+
//Client doesn't send the position for ammo.
- if(sd->inventory_data[index]->type == IT_AMMO)
- pc->equipitem(sd,index,EQP_AMMO);
+ if(sd->inventory_data[p->index]->type == IT_AMMO)
+ pc->equipitem(sd,p->index,EQP_AMMO);
else
- pc->equipitem(sd,index,RFIFOW(fd,4));
+ pc->equipitem(sd,p->index,p->wearLocation);
}
void clif_hercules_chsys_delete(struct hChSysCh *channel) {
@@ -10700,7 +10728,7 @@ void clif_hercules_chsys_delete(struct hChSysCh *channel) {
}
db_destroy(channel->users);
if( channel->m ) {
- map[channel->m].channel = NULL;
+ map->list[channel->m].channel = NULL;
aFree(channel);
} else if ( channel->type == hChSys_ALLY )
aFree(channel);
@@ -10711,20 +10739,20 @@ void clif_hercules_chsys_gjoin(struct guild *g1,struct guild *g2) {
struct map_session_data *sd;
struct hChSysCh *channel;
int j;
-
- if( (channel = (struct hChSysCh*)g1->channel) ) {
+
+ if( (channel = g1->channel) ) {
for(j = 0; j < g2->max_member; j++) {
if( (sd = g2->member[j].sd) != NULL ) {
- if( !(((struct hChSysCh*)g1->channel)->banned && idb_exists(((struct hChSysCh*)g1->channel)->banned, sd->status.account_id)))
+ if( !(g1->channel->banned && idb_exists(g1->channel->banned, sd->status.account_id)))
clif->chsys_join(channel,sd);
}
}
}
-
- if( (channel = (struct hChSysCh*)g2->channel) ) {
+
+ if( (channel = g2->channel) ) {
for(j = 0; j < g1->max_member; j++) {
if( (sd = g1->member[j].sd) != NULL ) {
- if( !(((struct hChSysCh*)g2->channel)->banned && idb_exists(((struct hChSysCh*)g2->channel)->banned, sd->status.account_id)))
+ if( !(g2->channel->banned && idb_exists(g2->channel->banned, sd->status.account_id)))
clif->chsys_join(channel,sd);
}
}
@@ -10734,16 +10762,16 @@ void clif_hercules_chsys_gleave(struct guild *g1,struct guild *g2) {
struct map_session_data *sd;
struct hChSysCh *channel;
int j;
-
- if( (channel = (struct hChSysCh*)g1->channel) ) {
+
+ if( (channel = g1->channel) ) {
for(j = 0; j < g2->max_member; j++) {
if( (sd = g2->member[j].sd) != NULL ) {
clif->chsys_left(channel,sd);
}
}
}
-
- if( (channel = (struct hChSysCh*)g2->channel) ) {
+
+ if( (channel = g2->channel) ) {
for(j = 0; j < g1->max_member; j++) {
if( (sd = g1->member[j].sd) != NULL ) {
clif->chsys_left(channel,sd);
@@ -10773,6 +10801,9 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd)
index = RFIFOW(fd,2)-2;
+ if( battle_config.idletime_criteria & BCIDLE_USEITEM )
+ sd->idletime = sockt->last_tick;
+
pc->unequipitem(sd,index,1);
}
@@ -10795,13 +10826,13 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd)
#endif
return;
}
- if ( pc_cant_act2(sd) || !(bl = iMap->id2bl(RFIFOL(fd,2))) || sd->state.vending )
+ if ( pc_cant_act2(sd) || !(bl = map->id2bl(RFIFOL(fd,2))) || sd->state.vending )
return;
-
+
switch (bl->type) {
case BL_MOB:
case BL_PC:
- clif->pActionRequest_sub(sd, 0x07, bl->id, iTimer->gettick());
+ clif->pActionRequest_sub(sd, 0x07, bl->id, timer->gettick());
break;
case BL_NPC:
if( sd->ud.skill_id < RK_ENCHANTBLADE && sd->ud.skilltimer != INVALID_TIMER ) {// TODO: should only work with none 3rd job skills
@@ -10811,7 +10842,7 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd)
break;
}
if( bl->m != -1 )// the user can't click floating npcs directly (hack attempt)
- npc_click(sd,(TBL_NPC*)bl);
+ npc->click(sd,(TBL_NPC*)bl);
break;
}
}
@@ -10826,7 +10857,7 @@ void clif_parse_NpcBuySellSelected(int fd,struct map_session_data *sd)
{
if (sd->state.trading)
return;
- npc_buysellsel(sd,RFIFOL(fd,2),RFIFOB(fd,6));
+ npc->buysellsel(sd,RFIFOL(fd,2),RFIFOB(fd,6));
}
@@ -10858,7 +10889,7 @@ void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd)
if( sd->state.trading || !sd->npc_shopid )
result = 1;
else
- result = npc_buylist(sd,n,item_list);
+ result = npc->buylist(sd,n,item_list);
sd->npc_shopid = 0; //Clear shop data.
@@ -10894,7 +10925,7 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd)
if (sd->state.trading || !sd->npc_shopid)
fail = 1;
else
- fail = npc_selllist(sd,n,item_list);
+ fail = npc->selllist(sd,n,item_list);
sd->npc_shopid = 0; //Clear shop data.
@@ -10923,10 +10954,10 @@ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd)
clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,3);
return;
}
- if( npc_isnear(&sd->bl) ) {
+ if( npc->isnear(&sd->bl) ) {
// uncomment for more verbose message.
//char output[150];
- //sprintf(output, msg_txt(662), battle_config.min_npc_vendchat_distance);
+ //sprintf(output, msg_txt(862), battle_config.min_npc_vendchat_distance); // "You're too close to a NPC, you must be at least %d cells away from any NPC."
//clif_displaymessage(sd->fd, output);
clif->skill_fail(sd,1,USESKILL_FAIL_THERE_ARE_NPC_AROUND,0);
return;
@@ -10938,7 +10969,7 @@ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd)
safestrncpy(s_password, password, CHATROOM_PASS_SIZE);
safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); //NOTE: assumes that safestrncpy will not access the len+1'th byte
- chat_createpcchat(sd, s_title, s_password, limit, pub);
+ chat->create_pc_chat(sd, s_title, s_password, limit, pub);
}
@@ -10949,7 +10980,7 @@ void clif_parse_ChatAddMember(int fd, struct map_session_data* sd)
int chatid = RFIFOL(fd,2);
const char* password = (char*)RFIFOP(fd,6); // not zero-terminated
- chat_joinchat(sd,chatid,password);
+ chat->join(sd,chatid,password);
}
@@ -10974,7 +11005,7 @@ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd)
safestrncpy(s_password, password, CHATROOM_PASS_SIZE);
safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); //NOTE: assumes that safestrncpy will not access the len+1'th byte
- chat_changechatstatus(sd, s_title, s_password, limit, pub);
+ chat->change_status(sd, s_title, s_password, limit, pub);
}
@@ -10985,7 +11016,7 @@ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd)
/// 1 = normal
void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd)
{
- chat_changechatowner(sd,(char*)RFIFOP(fd,6));
+ chat->change_owner(sd,(char*)RFIFOP(fd,6));
}
@@ -10993,7 +11024,7 @@ void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd)
/// 00e2 <name>.24B
void clif_parse_KickFromChat(int fd,struct map_session_data *sd)
{
- chat_kickchat(sd,(char*)RFIFOP(fd,2));
+ chat->kick(sd,(char*)RFIFOP(fd,2));
}
@@ -11001,11 +11032,11 @@ void clif_parse_KickFromChat(int fd,struct map_session_data *sd)
/// 00e3
void clif_parse_ChatLeave(int fd, struct map_session_data* sd)
{
- chat_leavechat(sd,0);
+ chat->leave(sd,0);
}
-//Handles notifying asker and rejecter of what has just ocurred.
+//Handles notifying asker and rejecter of what has just occurred.
//Type is used to determine the correct msg_txt to use:
//0:
void clif_noask_sub(struct map_session_data *src, struct map_session_data *target, int type) {
@@ -11013,20 +11044,19 @@ void clif_noask_sub(struct map_session_data *src, struct map_session_data *targe
char output[256];
// Your request has been rejected by autoreject option.
msg = msg_txt(392);
- clif->disp_onlyself(src, msg, strlen(msg));
+ clif_disp_onlyself(src, msg, strlen(msg));
//Notice that a request was rejected.
snprintf(output, 256, msg_txt(393+type), src->status.name, 256);
- clif->disp_onlyself(target, output, strlen(output));
+ clif_disp_onlyself(target, output, strlen(output));
}
/// Request to begin a trade (CZ_REQ_EXCHANGE_ITEM).
/// 00e4 <account id>.L
-void clif_parse_TradeRequest(int fd,struct map_session_data *sd)
-{
+void clif_parse_TradeRequest(int fd,struct map_session_data *sd) {
struct map_session_data *t_sd;
- t_sd = iMap->id2sd(RFIFOL(fd,2));
+ t_sd = map->id2sd(RFIFOL(fd,2));
if(!sd->chatID && pc_cant_act(sd))
return; //You can trade while in a chatroom.
@@ -11105,13 +11135,16 @@ void clif_parse_StopAttack(int fd,struct map_session_data *sd)
/// Request to move an item from inventory to cart (CZ_MOVE_ITEM_FROM_BODY_TO_CART).
/// 0126 <index>.W <amount>.L
-void clif_parse_PutItemToCart(int fd,struct map_session_data *sd)
-{
+void clif_parse_PutItemToCart(int fd,struct map_session_data *sd) {
+ int flag = 0;
if (pc_istrading(sd))
return;
if (!pc_iscarton(sd))
return;
- pc->putitemtocart(sd,RFIFOW(fd,2)-2,RFIFOL(fd,4));
+ if ( (flag = pc->putitemtocart(sd,RFIFOW(fd,2)-2,RFIFOL(fd,4))) ) {
+ clif->dropitem(sd, RFIFOW(fd,2)-2,0);
+ clif->cart_additem_ack(sd,flag == 1?0x0:0x1);
+ }
}
@@ -11129,16 +11162,16 @@ void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd)
/// 012a
void clif_parse_RemoveOption(int fd,struct map_session_data *sd)
{
- /**
- * Attempts to remove these options when this function is called (will remove all available)
- **/
+ if( !(sd->sc.option&(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR))
#ifdef NEW_CARTS
- pc->setoption(sd,sd->sc.option&~(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR));
- if( sd->sc.data[SC_PUSH_CART] )
+ && sd->sc.data[SC_PUSH_CART] ){
pc->setcart(sd,0);
#else
- pc->setoption(sd,sd->sc.option&~(OPTION_CART|OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR));
+ ){
+ pc->setoption(sd,sd->sc.option&~OPTION_CART);
#endif
+ }else // priority to remove this option before we can clear cart
+ pc->setoption(sd,sd->sc.option&~(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR));
}
@@ -11148,8 +11181,17 @@ void clif_parse_ChangeCart(int fd,struct map_session_data *sd)
{// TODO: State tracking?
int type;
- if( sd && pc->checkskill(sd, MC_CHANGECART) < 1 )
+ nullpo_retv(sd);
+
+ if( pc->checkskill(sd, MC_CHANGECART) < 1 )
+ return;
+
+#ifdef RENEWAL
+ if( sd->npc_id || sd->state.workinprogress&1 ){
+ clif->msg(sd, 0x783);
return;
+ }
+#endif
type = (int)RFIFOW(fd,2);
#ifdef NEW_CARTS
@@ -11178,11 +11220,18 @@ void clif_parse_ChangeCart(int fd,struct map_session_data *sd)
/// status id:
/// SP_STR ~ SP_LUK
/// amount:
-/// client sends always 1 for this, even when using /str+ and
-/// the like
-void clif_parse_StatusUp(int fd,struct map_session_data *sd)
-{
- pc->statusup(sd,RFIFOW(fd,2));
+/// Old clients send always 1 for this, even when using /str+ and the like.
+/// Newer clients (2013-12-23 and newer) send the correct amount.
+void clif_parse_StatusUp(int fd,struct map_session_data *sd) {
+ int increase_amount;
+
+ increase_amount = RFIFOB(fd,4);
+ if( increase_amount < 0 )
+ {
+ ShowDebug("clif_parse_StatusUp: Negative 'increase' value sent by client! (fd: %d, value: %d)\n",
+ fd, increase_amount);
+ }
+ pc->statusup(sd, RFIFOW(fd,2), increase_amount);
}
@@ -11193,8 +11242,7 @@ void clif_parse_SkillUp(int fd,struct map_session_data *sd)
pc->skillup(sd,RFIFOW(fd,2));
}
-void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id)
-{
+void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id) {
int lv;
if( !hd )
@@ -11212,11 +11260,10 @@ void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_dat
if( skill_lv > lv )
skill_lv = lv;
if( skill_lv )
- unit_skilluse_id(&hd->bl, target_id, skill_id, skill_lv);
+ unit->skilluse_id(&hd->bl, target_id, skill_id, skill_lv);
}
-void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo)
-{
+void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) {
int lv;
if( !hd )
return;
@@ -11233,11 +11280,10 @@ void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_da
if( skill_lv > lv )
skill_lv = lv;
if( skill_lv )
- unit_skilluse_pos(&hd->bl, x, y, skill_id, skill_lv);
+ unit->skilluse_pos(&hd->bl, x, y, skill_id, skill_lv);
}
-void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id)
-{
+void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id) {
int lv;
if( !md )
@@ -11251,15 +11297,14 @@ void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_ses
} else if( DIFF_TICK(tick, md->ud.canact_tick) < 0 )
return;
- lv = mercenary_checkskill(md, skill_id);
+ lv = mercenary->checkskill(md, skill_id);
if( skill_lv > lv )
skill_lv = lv;
if( skill_lv )
- unit_skilluse_id(&md->bl, target_id, skill_id, skill_lv);
+ unit->skilluse_id(&md->bl, target_id, skill_id, skill_lv);
}
-void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo)
-{
+void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) {
int lv;
if( !md )
return;
@@ -11274,11 +11319,11 @@ void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_se
if( md->sc.data[SC_BASILICA] )
return;
- lv = mercenary_checkskill(md, skill_id);
+ lv = mercenary->checkskill(md, skill_id);
if( skill_lv > lv )
skill_lv = lv;
if( skill_lv )
- unit_skilluse_pos(&md->bl, x, y, skill_id, skill_lv);
+ unit->skilluse_pos(&md->bl, x, y, skill_id, skill_lv);
}
@@ -11290,7 +11335,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
{
uint16 skill_id, skill_lv;
int tmp, target_id;
- unsigned int tick = iTimer->gettick();
+ int64 tick = timer->gettick();
skill_lv = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0]);
skill_id = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[1]);
@@ -11313,7 +11358,8 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
}
// Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
- sd->idletime = last_tick;
+ if( battle_config.idletime_criteria & BCIDLE_USESKILLTOID )
+ sd->idletime = sockt->last_tick;
if( sd->npc_id || sd->state.workinprogress&1 ){
#ifdef RENEWAL
@@ -11321,8 +11367,14 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
#endif
return;
}
- if( pc_cant_act(sd) && skill_id != RK_REFRESH && !(skill_id == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN)) )
+
+ if( pc_cant_act(sd)
+ && skill_id != RK_REFRESH
+ && !(skill_id == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN))
+ && ( sd->state.storage_flag && !(tmp&INF_SELF_SKILL) ) // SELF skills can be used with the storage open, issue: 8027
+ )
return;
+
if( pc_issit(sd) )
return;
@@ -11345,7 +11397,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
}
}
- if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) )
+ if( sd->sc.option&OPTION_COSTUME )
return;
if( sd->sc.data[SC_BASILICA] && (skill_id != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) )
@@ -11362,7 +11414,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
skill_lv = sd->skillitemlv;
if( !(tmp&INF_SELF_SKILL) )
pc->delinvincibletimer(sd); // Target skills thru items cancel invincibility. [Inkfish]
- unit_skilluse_id(&sd->bl, target_id, skill_id, skill_lv);
+ unit->skilluse_id(&sd->bl, target_id, skill_id, skill_lv);
return;
}
@@ -11370,7 +11422,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
if( skill_id >= GD_SKILLBASE ) {
if( sd->state.gmaster_flag )
- skill_lv = guild->checkskill(sd->state.gmaster_flag, skill_id);
+ skill_lv = guild->checkskill(sd->guild, skill_id);
else
skill_lv = 0;
} else {
@@ -11382,7 +11434,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
pc->delinvincibletimer(sd);
if( skill_lv )
- unit_skilluse_id(&sd->bl, target_id, skill_id, skill_lv);
+ unit->skilluse_id(&sd->bl, target_id, skill_id, skill_lv);
}
/*==========================================
@@ -11390,7 +11442,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
*------------------------------------------*/
void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 skill_lv, uint16 skill_id, short x, short y, int skillmoreinfo)
{
- unsigned int tick = iTimer->gettick();
+ int64 tick = timer->gettick();
if( !(skill->get_inf(skill_id)&INF_GROUND_SKILL) )
return; //Using a target skill on the ground? WRONG.
@@ -11404,9 +11456,17 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski
clif->pUseSkillToPos_mercenary(sd->md, sd, tick, skill_id, skill_lv, x, y, skillmoreinfo);
return;
}
+
+#ifdef RENEWAL
+ if( sd->state.workinprogress&1 ){
+ clif->msg(sd, 0x783); // TODO look for the client date that has this message.
+ return;
+ }
+#endif
//Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
- sd->idletime = last_tick;
+ if( battle_config.idletime_criteria & BCIDLE_USESKILLTOPOS )
+ sd->idletime = sockt->last_tick;
if( skill->not_ok(skill_id, sd) )
return;
@@ -11429,7 +11489,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski
}
}
- if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) )
+ if( sd->sc.option&OPTION_COSTUME )
return;
if( sd->sc.data[SC_BASILICA] && (skill_id != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) )
@@ -11447,14 +11507,14 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski
if( sd->skillitem == skill_id ) {
if( skill_lv != sd->skillitemlv )
skill_lv = sd->skillitemlv;
- unit_skilluse_pos(&sd->bl, x, y, skill_id, skill_lv);
+ unit->skilluse_pos(&sd->bl, x, y, skill_id, skill_lv);
} else {
int lv;
sd->skillitem = sd->skillitemlv = 0;
if( (lv = pc->checkskill(sd, skill_id)) > 0 ) {
if( skill_lv > lv )
skill_lv = lv;
- unit_skilluse_pos(&sd->bl, x, y, skill_id,skill_lv);
+ unit->skilluse_pos(&sd->bl, x, y, skill_id,skill_lv);
}
}
}
@@ -11508,12 +11568,15 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd)
{
uint16 skill_id = RFIFOW(fd,2);
char map_name[MAP_NAME_LENGTH];
- mapindex_getmapname((char*)RFIFOP(fd,4), map_name);
+
+ mapindex->getmapname((char*)RFIFOP(fd,4), map_name);
+ sd->state.workinprogress = 0;
if(skill_id != sd->menuskill_id)
return;
- if( pc_cant_act(sd) ) {
+ // It is possible to use teleport with the storage window open issue:8027
+ if( pc_cant_act(sd) && (!sd->state.storage_flag && skill_id != AL_TELEPORT) ) {
clif_menuskill_clear(sd);
return;
}
@@ -11640,7 +11703,7 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd)
#ifdef SECURE_NPCTIMEOUT
if( sd->npc_idle_timer != INVALID_TIMER ) {
#endif
- TBL_NPC* nd = iMap->id2nd(npc_id);
+ TBL_NPC* nd = map->id2nd(npc_id);
ShowWarning("Invalid menu selection on npc %d:'%s' - got %d, valid range is [%d..%d] (player AID:%d, CID:%d, name:'%s')!\n", npc_id, (nd)?nd->name:"invalid npc id", select, 1, sd->npc_menu, sd->bl.id, sd->status.char_id, sd->status.name);
clif->GM_kick(NULL,sd);
#ifdef SECURE_NPCTIMEOUT
@@ -11650,7 +11713,7 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd)
}
sd->npc_menu = select;
- npc_scriptcont(sd,npc_id, false);
+ npc->scriptcont(sd,npc_id, false);
}
@@ -11658,7 +11721,7 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd)
/// 00b9 <npc id>.L
void clif_parse_NpcNextClicked(int fd,struct map_session_data *sd)
{
- npc_scriptcont(sd,RFIFOL(fd,2), false);
+ npc->scriptcont(sd,RFIFOL(fd,2), false);
}
@@ -11670,7 +11733,7 @@ void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd)
int amount = (int)RFIFOL(fd,6);
sd->npc_amount = amount;
- npc_scriptcont(sd, npcid, false);
+ npc->scriptcont(sd, npcid, false);
}
@@ -11686,7 +11749,7 @@ void clif_parse_NpcStringInput(int fd, struct map_session_data* sd)
return; // invalid input
safestrncpy(sd->npc_str, message, min(message_len,CHATBOX_SIZE));
- npc_scriptcont(sd, npcid, false);
+ npc->scriptcont(sd, npcid, false);
}
@@ -11696,7 +11759,7 @@ void clif_parse_NpcCloseClicked(int fd,struct map_session_data *sd)
{
if (!sd->npc_id) //Avoid parsing anything when the script was done with. [Skotlex]
return;
- npc_scriptcont(sd, RFIFOL(fd,2), true);
+ npc->scriptcont(sd, RFIFOL(fd,2), true);
}
@@ -11757,9 +11820,17 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd)
/// 01ce <skill id>.L
void clif_parse_AutoSpell(int fd,struct map_session_data *sd)
{
- if (sd->menuskill_id != SA_AUTOSPELL)
+ uint16 skill_id = RFIFOL(fd,2);
+
+ sd->state.workinprogress = 0;
+
+ if( sd->menuskill_id != SA_AUTOSPELL )
+ return;
+
+ if( !skill_id )
return;
- skill->autospell(sd,RFIFOL(fd,2));
+
+ skill->autospell(sd, skill_id);
clif_menuskill_clear(sd);
}
@@ -11788,12 +11859,11 @@ void clif_parse_InsertCard(int fd,struct map_session_data *sd)
/// 0193 <char id>.L (CZ_REQNAME_BYGID)
/// 0369 <char id>.L (CZ_REQNAME_BYGID2)
/// There are various variants of this packet, some of them have padding between fields.
-void clif_parse_SolveCharName(int fd, struct map_session_data *sd)
-{
+void clif_parse_SolveCharName(int fd, struct map_session_data *sd) {
int charid;
charid = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
- iMap->reqnickdb(sd, charid);
+ map->reqnickdb(sd, charid);
}
@@ -11807,11 +11877,11 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) {
char cmd[15];
if( RFIFOW(fd,2) )
- sprintf(cmd,"%cresetskill",atcommand->at_symbol);
+ sprintf(cmd,"%cskreset",atcommand->at_symbol);
else
- sprintf(cmd,"%cresetstat",atcommand->at_symbol);
+ sprintf(cmd,"%cstreset",atcommand->at_symbol);
- atcommand->parse(fd, sd, cmd, 1);
+ atcommand->exec(fd, sd, cmd, true);
}
@@ -11828,7 +11898,7 @@ void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd)
mes_len_check(msg, len, CHAT_SIZE_MAX);
sprintf(command, "%clkami %s", atcommand->at_symbol, msg);
- atcommand->parse(fd, sd, command, 1);
+ atcommand->exec(fd, sd, command, true);
}
@@ -11849,10 +11919,9 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd)
return;
if (sd->state.storage_flag == 1)
- storage_storageadd(sd, item_index, item_amount);
- else
- if (sd->state.storage_flag == 2)
- storage_guild_storageadd(sd, item_index, item_amount);
+ storage->add(sd, item_index, item_amount);
+ else if (sd->state.storage_flag == 2)
+ gstorage->add(sd, item_index, item_amount);
}
@@ -11868,9 +11937,9 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd)
item_amount = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[1]);
if (sd->state.storage_flag == 1)
- storage_storageget(sd, item_index, item_amount);
+ storage->get(sd, item_index, item_amount);
else if(sd->state.storage_flag == 2)
- storage_guild_storageget(sd, item_index, item_amount);
+ gstorage->get(sd, item_index, item_amount);
}
@@ -11884,10 +11953,9 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd)
return;
if (sd->state.storage_flag == 1)
- storage_storageaddfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4));
- else
- if (sd->state.storage_flag == 2)
- storage_guild_storageaddfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4));
+ storage->addfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4));
+ else if (sd->state.storage_flag == 2)
+ gstorage->addfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4));
}
@@ -11901,10 +11969,9 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd)
return;
if (sd->state.storage_flag == 1)
- storage_storagegettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4));
- else
- if (sd->state.storage_flag == 2)
- storage_guild_storagegettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4));
+ storage->gettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4));
+ else if (sd->state.storage_flag == 2)
+ gstorage->gettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4));
}
@@ -11913,9 +11980,9 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd)
void clif_parse_CloseKafra(int fd, struct map_session_data *sd)
{
if( sd->state.storage_flag == 1 )
- storage_storageclose(sd);
+ storage->close(sd);
else if( sd->state.storage_flag == 2 )
- storage_guild_storageclose(sd);
+ gstorage->close(sd);
}
@@ -11975,12 +12042,12 @@ void clif_storagepassword_result(struct map_session_data* sd, short result, shor
/// Party creation request
/// 00f9 <party name>.24B (CZ_MAKE_GROUP)
/// 01e8 <party name>.24B <item pickup rule>.B <item share rule>.B (CZ_MAKE_GROUP2)
-void clif_parse_CreateParty(int fd, struct map_session_data *sd)
-{
+void clif_parse_CreateParty(int fd, struct map_session_data *sd) {
char* name = (char*)RFIFOP(fd,2);
name[NAME_LENGTH-1] = '\0';
- if( map[sd->bl.m].flag.partylock ) { // Party locked.
+ if( map->list[sd->bl.m].flag.partylock ) {
+ // Party locked.
clif->message(fd, msg_txt(227));
return;
}
@@ -11992,14 +12059,14 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd)
party->create(sd,name,0,0);
}
-void clif_parse_CreateParty2(int fd, struct map_session_data *sd)
-{
+void clif_parse_CreateParty2(int fd, struct map_session_data *sd) {
char* name = (char*)RFIFOP(fd,2);
int item1 = RFIFOB(fd,26);
int item2 = RFIFOB(fd,27);
name[NAME_LENGTH-1] = '\0';
- if( map[sd->bl.m].flag.partylock ) {// Party locked.
+ if( map->list[sd->bl.m].flag.partylock ) {
+ // Party locked.
clif->message(fd, msg_txt(227));
return;
}
@@ -12015,16 +12082,16 @@ void clif_parse_CreateParty2(int fd, struct map_session_data *sd)
/// Party invitation request
/// 00fc <account id>.L (CZ_REQ_JOIN_GROUP)
/// 02c4 <char name>.24B (CZ_PARTY_JOIN_REQ)
-void clif_parse_PartyInvite(int fd, struct map_session_data *sd)
-{
+void clif_parse_PartyInvite(int fd, struct map_session_data *sd) {
struct map_session_data *t_sd;
- if(map[sd->bl.m].flag.partylock) {// Party locked.
+ if(map->list[sd->bl.m].flag.partylock) {
+ // Party locked.
clif->message(fd, msg_txt(227));
return;
}
- t_sd = iMap->id2sd(RFIFOL(fd,2));
+ t_sd = map->id2sd(RFIFOL(fd,2));
if(t_sd && t_sd->state.noask) {// @noask [LuzZza]
clif->noask_sub(sd, t_sd, 1);
@@ -12034,18 +12101,18 @@ void clif_parse_PartyInvite(int fd, struct map_session_data *sd)
party->invite(sd, t_sd);
}
-void clif_parse_PartyInvite2(int fd, struct map_session_data *sd)
-{
+void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) {
struct map_session_data *t_sd;
char *name = (char*)RFIFOP(fd,2);
name[NAME_LENGTH-1] = '\0';
- if(map[sd->bl.m].flag.partylock) { // Party locked.
+ if(map->list[sd->bl.m].flag.partylock) {
+ // Party locked.
clif->message(fd, msg_txt(227));
return;
}
- t_sd = iMap->nick2sd(name);
+ t_sd = map->nick2sd(name);
if(t_sd && t_sd->state.noask) { // @noask [LuzZza]
clif->noask_sub(sd, t_sd, 1);
@@ -12075,9 +12142,9 @@ void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd)
/// Request to leave party (CZ_REQ_LEAVE_GROUP).
/// 0100
-void clif_parse_LeaveParty(int fd, struct map_session_data *sd)
-{
- if(map[sd->bl.m].flag.partylock) { //Guild locked.
+void clif_parse_LeaveParty(int fd, struct map_session_data *sd) {
+ if(map->list[sd->bl.m].flag.partylock) {
+ // Party locked.
clif->message(fd, msg_txt(227));
return;
}
@@ -12087,9 +12154,9 @@ void clif_parse_LeaveParty(int fd, struct map_session_data *sd)
/// Request to expel a party member (CZ_REQ_EXPEL_GROUP_MEMBER).
/// 0103 <account id>.L <char name>.24B
-void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd)
-{
- if(map[sd->bl.m].flag.partylock) { //Guild locked.
+void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) {
+ if(map->list[sd->bl.m].flag.partylock) {
+ // Party locked.
clif->message(fd, msg_txt(227));
return;
}
@@ -12136,44 +12203,46 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd)
int textlen = RFIFOW(fd,2) - 4;
char *name, *message;
- int namelen, messagelen;
+ size_t namelen, messagelen;
// validate packet and retrieve name and message
if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
return;
- if( atcommand->parse(fd, sd, message, 1) )
+ if( atcommand->exec(fd, sd, message, true) )
return;
- if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
+ if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
return;
if( battle_config.min_chat_delay )
{ //[Skotlex]
- if (DIFF_TICK(sd->cantalk_tick, iTimer->gettick()) > 0)
+ if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
return;
- sd->cantalk_tick = iTimer->gettick() + battle_config.min_chat_delay;
+ sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
+ if( battle_config.idletime_criteria & BCIDLE_CHAT )
+ sd->idletime = sockt->last_tick;
+
party->send_message(sd, text, textlen);
}
/// Changes Party Leader (CZ_CHANGE_GROUP_MASTER).
/// 07da <account id>.L
-void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd)
-{
- party->changeleader(sd, iMap->id2sd(RFIFOL(fd,2)));
+void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd) {
+ party->changeleader(sd, map->id2sd(RFIFOL(fd,2)));
}
-#ifndef PARTY_RECRUIT
/// Party Booking in KRO [Spiria]
///
-/// Request to register a party booking advertisment (CZ_PARTY_BOOKING_REQ_REGISTER).
+/// Request to register a party booking advertisement (CZ_PARTY_BOOKING_REQ_REGISTER).
/// 0802 <level>.W <map id>.W { <job>.W }*6
void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd)
{
+#ifndef PARTY_RECRUIT
short level = RFIFOW(fd,2);
short mapid = RFIFOW(fd,4);
short job[PARTY_BOOKING_JOBS];
@@ -12183,10 +12252,13 @@ void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd)
job[i] = RFIFOB(fd,6+i*2);
party->booking_register(sd, level, mapid, job);
+#else
+ return;
+#endif
}
-/// Result of request to register a party booking advertisment (ZC_PARTY_BOOKING_ACK_REGISTER).
+/// Result of request to register a party booking advertisement (ZC_PARTY_BOOKING_ACK_REGISTER).
/// 0803 <result>.W
/// result:
/// 0 = success
@@ -12194,19 +12266,24 @@ void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd)
/// 2 = already registered
void clif_PartyBookingRegisterAck(struct map_session_data *sd, int flag)
{
+#ifndef PARTY_RECRUIT
int fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x803));
WFIFOW(fd,0) = 0x803;
WFIFOW(fd,2) = flag;
WFIFOSET(fd,packet_len(0x803));
+#else
+ return;
+#endif
}
-/// Request to search for party booking advertisments (CZ_PARTY_BOOKING_REQ_SEARCH).
+/// Request to search for party booking advertisement (CZ_PARTY_BOOKING_REQ_SEARCH).
/// 0804 <level>.W <map id>.W <job>.W <last index>.L <result count>.W
void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data* sd)
{
+#ifndef PARTY_RECRUIT
short level = RFIFOW(fd,2);
short mapid = RFIFOW(fd,4);
short job = RFIFOW(fd,6);
@@ -12214,6 +12291,9 @@ void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data* sd)
short resultcount = RFIFOW(fd,12);
party->booking_search(sd, level, mapid, job, lastindex, resultcount);
+#else
+ return;
+#endif
}
@@ -12224,6 +12304,7 @@ void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data* sd)
/// 1 = yes
void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results, int count, bool more_result)
{
+#ifndef PARTY_RECRUIT
int i, j;
int size = sizeof(struct party_booking_ad_info); // structure size (48)
struct party_booking_ad_info *pb_ad;
@@ -12243,19 +12324,26 @@ void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results,
WFIFOW(fd,i*size+41+j*2) = pb_ad->p_detail.job[j];
}
WFIFOSET(fd,WFIFOW(fd,2));
+#else
+ return;
+#endif
}
-/// Request to delete own party booking advertisment (CZ_PARTY_BOOKING_REQ_DELETE).
+/// Request to delete own party booking advertisement (CZ_PARTY_BOOKING_REQ_DELETE).
/// 0806
void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd)
{
+#ifndef PARTY_RECRUIT
if(party->booking_delete(sd))
clif->PartyBookingDeleteAck(sd, 0);
+#else
+ return;
+#endif
}
-/// Result of request to delete own party booking advertisment (ZC_PARTY_BOOKING_ACK_DELETE).
+/// Result of request to delete own party booking advertisement (ZC_PARTY_BOOKING_ACK_DELETE).
/// 0807 <result>.W
/// result:
/// 0 = success
@@ -12264,19 +12352,24 @@ void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd)
/// 3 = nothing registered
void clif_PartyBookingDeleteAck(struct map_session_data* sd, int flag)
{
+#ifndef PARTY_RECRUIT
int fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x807));
WFIFOW(fd,0) = 0x807;
WFIFOW(fd,2) = flag;
WFIFOSET(fd,packet_len(0x807));
+#else
+ return;
+#endif
}
-/// Request to update party booking advertisment (CZ_PARTY_BOOKING_REQ_UPDATE).
+/// Request to update party booking advertisement (CZ_PARTY_BOOKING_REQ_UPDATE).
/// 0808 { <job>.W }*6
void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data* sd)
{
+#ifndef PARTY_RECRUIT
short job[PARTY_BOOKING_JOBS];
int i;
@@ -12284,13 +12377,17 @@ void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data* sd)
job[i] = RFIFOW(fd,2+i*2);
party->booking_update(sd, job);
+#else
+ return;
+#endif
}
-/// Notification about new party booking advertisment (ZC_PARTY_BOOKING_NOTIFY_INSERT).
+/// Notification about new party booking advertisement (ZC_PARTY_BOOKING_NOTIFY_INSERT).
/// 0809 <index>.L <char name>.24B <expire time>.L <level>.W <map id>.W { <job>.W }*6
void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_booking_ad_info* pb_ad)
{
+#ifndef PARTY_RECRUIT
int i;
uint8 buf[38+PARTY_BOOKING_JOBS*2];
@@ -12306,13 +12403,17 @@ void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_boo
WBUFW(buf,38+i*2) = pb_ad->p_detail.job[i];
clif->send(buf, packet_len(0x809), &sd->bl, ALL_CLIENT);
+#else
+ return;
+#endif
}
-/// Notification about updated party booking advertisment (ZC_PARTY_BOOKING_NOTIFY_UPDATE).
+/// Notification about updated party booking advertisement (ZC_PARTY_BOOKING_NOTIFY_UPDATE).
/// 080a <index>.L { <job>.W }*6
void clif_PartyBookingUpdateNotify(struct map_session_data* sd, struct party_booking_ad_info* pb_ad)
{
+#ifndef PARTY_RECRUIT
int i;
uint8 buf[6+PARTY_BOOKING_JOBS*2];
@@ -12323,33 +12424,43 @@ void clif_PartyBookingUpdateNotify(struct map_session_data* sd, struct party_boo
for(i=0; i<PARTY_BOOKING_JOBS; i++)
WBUFW(buf,6+i*2) = pb_ad->p_detail.job[i];
clif->send(buf,packet_len(0x80a),&sd->bl,ALL_CLIENT); // Now UPDATE all client.
+#else
+ return;
+#endif
}
-/// Notification about deleted party booking advertisment (ZC_PARTY_BOOKING_NOTIFY_DELETE).
+/// Notification about deleted party booking advertisement (ZC_PARTY_BOOKING_NOTIFY_DELETE).
/// 080b <index>.L
void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index)
{
+#ifndef PARTY_RECRUIT
uint8 buf[6];
WBUFW(buf,0) = 0x80b;
WBUFL(buf,2) = index;
clif->send(buf, packet_len(0x80b), &sd->bl, ALL_CLIENT); // Now UPDATE all client.
+#else
+ return;
+#endif
}
-#else
/// Modified version of Party Booking System for 2012-04-10 or 2012-04-18 (RagexeRE).
/// Code written by mkbu95, Spiria, Yommy and Ind
-/// Request to register a party booking advertisment (CZ_PARTY_RECRUIT_REQ_REGISTER).
+/// Request to register a party booking advertisement (CZ_PARTY_RECRUIT_REQ_REGISTER).
/// 08e5 <level>.W <notice>.37B
-void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd)
+void clif_parse_PartyRecruitRegisterReq(int fd, struct map_session_data* sd)
{
+#ifdef PARTY_RECRUIT
short level = RFIFOW(fd,2);
const char *notice = (const char*)RFIFOP(fd, 4);
- party->booking_register(sd, level, notice);
+ party->recruit_register(sd, level, notice);
+#else
+ return;
+#endif
}
/// Party booking search results (ZC_PARTY_RECRUIT_ACK_SEARCH).
@@ -12357,8 +12468,9 @@ void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd)
/// more results:
/// 0 = no
/// 1 = yes
-void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results, int count, bool more_result)
+void clif_PartyRecruitSearchAck(int fd, struct party_booking_ad_info** results, int count, bool more_result)
{
+#ifdef PARTY_RECRUIT
int i;
int size = sizeof(struct party_booking_ad_info);
struct party_booking_ad_info *pb_ad;
@@ -12379,76 +12491,100 @@ void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results,
}
WFIFOSET(fd,WFIFOW(fd,2));
+#else
+ return;
+#endif
}
-/// Result of request to register a party booking advertisment (ZC_PARTY_RECRUIT_ACK_REGISTER).
+/// Result of request to register a party booking advertisement (ZC_PARTY_RECRUIT_ACK_REGISTER).
/// 08e6 <result>.W
/// result:
/// 0 = success
/// 1 = failure
/// 2 = already registered
-void clif_PartyBookingRegisterAck(struct map_session_data *sd, int flag)
+void clif_PartyRecruitRegisterAck(struct map_session_data *sd, int flag)
{
+#ifdef PARTY_RECRUIT
int fd = sd->fd;
WFIFOHEAD(fd, packet_len(0x8e6));
WFIFOW(fd, 0) = 0x8e6;
WFIFOW(fd, 2) = flag;
WFIFOSET(fd, packet_len(0x8e6));
+#else
+ return;
+#endif
}
-/// Request to search for party booking advertisments (CZ_PARTY_RECRUIT_REQ_SEARCH).
+/// Request to search for party booking advertisement (CZ_PARTY_RECRUIT_REQ_SEARCH).
/// 08e7 <level>.W <map id>.W <last index>.L <result count>.W
-void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data* sd)
+void clif_parse_PartyRecruitSearchReq(int fd, struct map_session_data* sd)
{
+#ifdef PARTY_RECRUIT
short level = RFIFOW(fd, 2);
short mapid = RFIFOW(fd, 4);
unsigned long lastindex = RFIFOL(fd, 6);
short resultcount = RFIFOW(fd, 10);
- party->booking_search(sd, level, mapid, lastindex, resultcount);
+ party->recruit_search(sd, level, mapid, lastindex, resultcount);
+#else
+ return;
+#endif
}
-/// Request to delete own party booking advertisment (CZ_PARTY_RECRUIT_REQ_DELETE).
+/// Request to delete own party booking advertisement (CZ_PARTY_RECRUIT_REQ_DELETE).
/// 08e9
-void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd)
+void clif_parse_PartyRecruitDeleteReq(int fd, struct map_session_data* sd)
{
+#ifdef PARTY_RECRUIT
if(party->booking_delete(sd))
- clif->PartyBookingDeleteAck(sd, 0);
+ clif->PartyRecruitDeleteAck(sd, 0);
+#else
+ return;
+#endif
}
-/// Result of request to delete own party booking advertisment (ZC_PARTY_RECRUIT_ACK_DELETE).
+/// Result of request to delete own party booking advertisement (ZC_PARTY_RECRUIT_ACK_DELETE).
/// 08ea <result>.W
/// result:
/// 0 = success
/// 1 = success (auto-removed expired ad)
/// 2 = failure
/// 3 = nothing registered
-void clif_PartyBookingDeleteAck(struct map_session_data* sd, int flag)
+void clif_PartyRecruitDeleteAck(struct map_session_data* sd, int flag)
{
+#ifdef PARTY_RECRUIT
int fd = sd->fd;
WFIFOHEAD(fd, packet_len(0x8ea));
WFIFOW(fd, 0) = 0x8ea;
WFIFOW(fd, 2) = flag;
WFIFOSET(fd, packet_len(0x8ea));
+#else
+ return;
+#endif
}
-/// Request to update party booking advertisment (CZ_PARTY_RECRUIT_REQ_UPDATE).
+/// Request to update party booking advertisement (CZ_PARTY_RECRUIT_REQ_UPDATE).
/// 08eb <notice>.37B
-void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data *sd)
+void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd)
{
+#ifdef PARTY_RECRUIT
const char *notice;
notice = (const char*)RFIFOP(fd, 2);
-
- party->booking_update(sd, notice);
+
+ party->recruit_update(sd, notice);
+#else
+ return;
+#endif
}
-/// Notification about new party booking advertisment (ZC_PARTY_RECRUIT_NOTIFY_INSERT).
+/// Notification about new party booking advertisement (ZC_PARTY_RECRUIT_NOTIFY_INSERT).
/// 08ec <index>.L <expire time>.L <char name>.24B <level>.W <notice>.37B
-void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_booking_ad_info* pb_ad)
+void clif_PartyRecruitInsertNotify(struct map_session_data* sd, struct party_booking_ad_info* pb_ad)
{
+#ifdef PARTY_RECRUIT
unsigned char buf[2+6+6+24+4+37+1];
if (pb_ad == NULL)
@@ -12461,73 +12597,100 @@ void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_boo
WBUFW(buf,34) = pb_ad->p_detail.level;
memcpy(WBUFP(buf, 36), pb_ad->p_detail.notice, PB_NOTICE_LENGTH);
clif->send(buf, packet_len(0x8ec), &sd->bl, ALL_CLIENT);
+#else
+ return;
+#endif
}
-/// Notification about updated party booking advertisment (ZC_PARTY_RECRUIT_NOTIFY_UPDATE).
+/// Notification about updated party booking advertisement (ZC_PARTY_RECRUIT_NOTIFY_UPDATE).
/// 08ed <index>.L <notice>.37B
-void clif_PartyBookingUpdateNotify(struct map_session_data *sd, struct party_booking_ad_info* pb_ad)
+void clif_PartyRecruitUpdateNotify(struct map_session_data *sd, struct party_booking_ad_info* pb_ad)
{
+#ifdef PARTY_RECRUIT
unsigned char buf[2+6+37+1];
-
+
WBUFW(buf, 0) = 0x8ed;
WBUFL(buf, 2) = pb_ad->index;
memcpy(WBUFP(buf, 6), pb_ad->p_detail.notice, PB_NOTICE_LENGTH);
clif->send(buf, packet_len(0x8ed), &sd->bl, ALL_CLIENT);
+#else
+ return;
+#endif
}
-/// Notification about deleted party booking advertisment (ZC_PARTY_RECRUIT_NOTIFY_DELETE).
+/// Notification about deleted party booking advertisement (ZC_PARTY_RECRUIT_NOTIFY_DELETE).
/// 08ee <index>.L
-void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index)
+void clif_PartyRecruitDeleteNotify(struct map_session_data* sd, int index)
{
+#ifdef PARTY_RECRUIT
unsigned char buf[2+6+1];
WBUFW(buf, 0) = 0x8ee;
WBUFL(buf, 2) = index;
clif->send(buf, packet_len(0x8ee), &sd->bl, ALL_CLIENT);
+#else
+ return;
+#endif
}
/// Request to add to filtering list (PARTY_RECRUIT_ADD_FILTERLINGLIST).
/// 08ef <index>.L
void clif_parse_PartyBookingAddFilteringList(int fd, struct map_session_data *sd)
{
+#ifdef PARTY_RECRUIT
int index = RFIFOL(fd, 2);
clif->PartyBookingAddFilteringList(index, sd);
+#else
+ return;
+#endif
}
/// Request to remove from filtering list (PARTY_RECRUIT_SUB_FILTERLINGLIST).
/// 08f0 <GID>.L
void clif_parse_PartyBookingSubFilteringList(int fd, struct map_session_data *sd)
{
+#ifdef PARTY_RECRUIT
int gid = RFIFOL(fd, 2);
clif->PartyBookingSubFilteringList(gid, sd);
+#else
+ return;
+#endif
}
/// Request to recruit volunteer (PARTY_RECRUIT_REQ_VOLUNTEER).
/// 08f1 <index>.L
void clif_parse_PartyBookingReqVolunteer(int fd, struct map_session_data *sd)
{
+#ifdef PARTY_RECRUIT
int index = RFIFOL(fd, 2);
clif->PartyBookingVolunteerInfo(index, sd);
+#else
+ return;
+#endif
}
/// Request volunteer information (PARTY_RECRUIT_VOLUNTEER_INFO).
/// 08f2 <AID>.L <job>.L <level>.W <char name>.24B
void clif_PartyBookingVolunteerInfo(int index, struct map_session_data *sd)
{
+#ifdef PARTY_RECRUIT
unsigned char buf[2+4+4+2+24+1];
-
+
WBUFW(buf, 0) = 0x8f2;
WBUFL(buf, 2) = sd->status.account_id;
WBUFL(buf, 6) = sd->status.class_;
WBUFW(buf, 10) = sd->status.base_level;
memcpy(WBUFP(buf, 12), sd->status.name, NAME_LENGTH);
-
+
clif->send(buf, packet_len(0x8f2), &sd->bl, ALL_CLIENT);
+#else
+ return;
+#endif
}
#if 0 //Disabled for now. Needs more info.
@@ -12571,63 +12734,87 @@ void clif_PartyBookingFailedRecall(int fd, struct map_session_data *sd)
/// 08f9 <refuse AID>.L
void clif_parse_PartyBookingRefuseVolunteer(int fd, struct map_session_data *sd)
{
- unsigned long aid = RFIFOL(fd, 2);
+#ifdef PARTY_RECRUIT
+ unsigned int aid = RFIFOL(fd, 2);
clif->PartyBookingRefuseVolunteer(aid, sd);
+#else
+ return;
+#endif
}
/// 08fa <index>.L
-void clif_PartyBookingRefuseVolunteer(unsigned long aid, struct map_session_data *sd)
+void clif_PartyBookingRefuseVolunteer(unsigned int aid, struct map_session_data *sd)
{
+#ifdef PARTY_RECRUIT
unsigned char buf[2+6];
-
+
WBUFW(buf, 0) = 0x8fa;
WBUFL(buf, 2) = aid;
-
+
clif->send(buf, packet_len(0x8fa), &sd->bl, ALL_CLIENT);
+#else
+ return;
+#endif
}
/// 08fb <index>.L
void clif_parse_PartyBookingCancelVolunteer(int fd, struct map_session_data *sd)
{
+#ifdef PARTY_RECRUIT
int index = RFIFOL(fd, 2);
clif->PartyBookingCancelVolunteer(index, sd);
+#else
+ return;
+#endif
}
/// 0909 <index>.L
void clif_PartyBookingCancelVolunteer(int index, struct map_session_data *sd)
{
+#ifdef PARTY_RECRUIT
unsigned char buf[2+6+1];
-
+
WBUFW(buf, 0) = 0x909;
WBUFL(buf, 2) = index;
-
+
clif->send(buf, packet_len(0x909), &sd->bl, ALL_CLIENT);
+#else
+ return;
+#endif
}
/// 090b <gid>.L <char name>.24B
void clif_PartyBookingAddFilteringList(int index, struct map_session_data *sd)
{
+#ifdef PARTY_RECRUIT
unsigned char buf[2+6+24+1];
WBUFW(buf, 0) = 0x90b;
WBUFL(buf, 2) = sd->bl.id;
memcpy(WBUFP(buf, 6), sd->status.name, NAME_LENGTH);
-
+
clif->send(buf, packet_len(0x90b), &sd->bl, ALL_CLIENT);
+#else
+ return;
+#endif
}
/// 090c <gid>.L <char name>.24B
void clif_PartyBookingSubFilteringList(int gid, struct map_session_data *sd)
{
+#ifdef PARTY_RECRUIT
unsigned char buf[2+6+24+1];
WBUFW(buf, 0) = 0x90c;
WBUFL(buf, 2) = gid;
memcpy(WBUFP(buf, 6), sd->status.name, NAME_LENGTH);
-
+
clif->send(buf, packet_len(0x90c), &sd->bl, ALL_CLIENT);
+#else
+ return;
+#endif
}
#if 0
@@ -12641,7 +12828,6 @@ void clif_PartyBookingRefuseVolunteerToPM(struct map_session_data *sd)
{
}
#endif //if 0
-#endif
/// Request to close own vending (CZ_REQ_CLOSESTORE).
/// 012e
@@ -12699,23 +12885,22 @@ void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd)
/// result:
/// 0 = canceled
/// 1 = open
-void clif_parse_OpenVending(int fd, struct map_session_data* sd)
-{
+void clif_parse_OpenVending(int fd, struct map_session_data* sd) {
short len = (short)RFIFOW(fd,2) - 85;
const char* message = (char*)RFIFOP(fd,4);
bool flag = (bool)RFIFOB(fd,84);
const uint8* data = (uint8*)RFIFOP(fd,85);
-
+
if( !flag )
sd->state.prevend = sd->state.workinprogress = 0;
if( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM )
return;
- if( map[sd->bl.m].flag.novending ) {
+ if( map->list[sd->bl.m].flag.novending ) {
clif->message (sd->fd, msg_txt(276)); // "You can't open a shop on this map"
return;
}
- if( iMap->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOVENDING) ) {
+ if( map->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOVENDING) ) {
clif->message (sd->fd, msg_txt(204)); // "You can't open a shop on this cell."
return;
}
@@ -12728,12 +12913,12 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd)
/// Guild creation request (CZ_REQ_MAKE_GUILD).
/// 0165 <char id>.L <guild name>.24B
-void clif_parse_CreateGuild(int fd,struct map_session_data *sd)
-{
+void clif_parse_CreateGuild(int fd,struct map_session_data *sd) {
char* name = (char*)RFIFOP(fd,6);
name[NAME_LENGTH-1] = '\0';
- if(map[sd->bl.m].flag.guildlock) { //Guild locked.
+ if(map->list[sd->bl.m].flag.guildlock) {
+ //Guild locked.
clif->message(fd, msg_txt(228));
return;
}
@@ -12833,20 +13018,126 @@ void clif_parse_GuildRequestEmblem(int fd,struct map_session_data *sd)
clif->guild_emblem(sd,g);
}
-
/// Validates data of a guild emblem (compressed bitmap)
-bool clif_validate_emblem(const uint8* emblem, unsigned long emblem_len) {
- bool success;
- uint8 buf[1800]; // no well-formed emblem bitmap is larger than 1782 (24 bit) / 1654 (8 bit) bytes
+bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) {
+ enum e_bitmapconst {
+ RGBTRIPLE_SIZE = 3, // sizeof(RGBTRIPLE)
+ RGBQUAD_SIZE = 4, // sizeof(RGBQUAD)
+ BITMAPFILEHEADER_SIZE = 14, // sizeof(BITMAPFILEHEADER)
+ BITMAPINFOHEADER_SIZE = 40, // sizeof(BITMAPINFOHEADER)
+ BITMAP_WIDTH = 24,
+ BITMAP_HEIGHT = 24,
+ };
+#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
+#pragma pack(push, 1)
+#endif // not NetBSD < 6 / Solaris
+ struct s_bitmaptripple {
+ //uint8 b;
+ //uint8 g;
+ //uint8 r;
+ unsigned int rgb:24;
+ } __attribute__((packed));
+#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
+#pragma pack(pop)
+#endif // not NetBSD < 6 / Solaris
+ uint8 buf[1800]; // no well-formed emblem bitmap is larger than 1782 (24 bit) / 1654 (8 bit) bytes
unsigned long buf_len = sizeof(buf);
+ int header = 0, bitmap = 0, offbits = 0, palettesize = 0, i = 0;
+
+ if( decode_zip(buf, &buf_len, emblem, emblem_len) != 0 || buf_len < BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE
+ || RBUFW(buf,0) != 0x4d42 // BITMAPFILEHEADER.bfType (signature)
+ || RBUFL(buf,2) != buf_len // BITMAPFILEHEADER.bfSize (file size)
+ || RBUFL(buf,14) != BITMAPINFOHEADER_SIZE // BITMAPINFOHEADER.biSize (other headers are not supported)
+ || RBUFL(buf,18) != BITMAP_WIDTH // BITMAPINFOHEADER.biWidth
+ || RBUFL(buf,22) != BITMAP_HEIGHT // BITMAPINFOHEADER.biHeight (top-down bitmaps (-24) are not supported)
+ || RBUFL(buf,30) != 0 // BITMAPINFOHEADER.biCompression == BI_RGB (compression not supported)
+ ) {
+ // Invalid data
+ return false;
+ }
- success = ( decode_zip(buf, &buf_len, emblem, emblem_len) == 0 && buf_len >= 18 ) // sizeof(BITMAPFILEHEADER) + sizeof(biSize) of the following info header struct
- && RBUFW(buf,0) == 0x4d42 // BITMAPFILEHEADER.bfType (signature)
- && RBUFL(buf,2) == buf_len // BITMAPFILEHEADER.bfSize (file size)
- && RBUFL(buf,10) < buf_len // BITMAPFILEHEADER.bfOffBits (offset to bitmap bits)
- ;
+ offbits = RBUFL(buf,10); // BITMAPFILEHEADER.bfOffBits (offset to bitmap bits)
+
+ switch( RBUFW(buf,28) ) { // BITMAPINFOHEADER.biBitCount
+ case 8:
+ palettesize = RBUFL(buf,46); // BITMAPINFOHEADER.biClrUsed (number of colors in the palette)
+ if( palettesize == 0 )
+ palettesize = 256; // Defaults to 2^n if set to zero
+ else if( palettesize > 256 )
+ return false;
+ header = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE + RGBQUAD_SIZE * palettesize; // headers + palette
+ bitmap = BITMAP_WIDTH * BITMAP_HEIGHT;
+ break;
+ case 24:
+ header = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE;
+ bitmap = BITMAP_WIDTH * BITMAP_HEIGHT * RGBTRIPLE_SIZE;
+ break;
+ default:
+ return false;
+ }
+
+ // NOTE: This check gives a little freedom for bitmap-producing implementations,
+ // that align the start of bitmap data, which is harmless but unnecessary.
+ // If you want it paranoidly strict, change the first condition from < to !=.
+ // This also allows files with trailing garbage at the end of the file.
+ // If you want to avoid that, change the last condition to !=.
+ if( offbits < header || buf_len <= bitmap || offbits > buf_len - bitmap ) {
+ return false;
+ }
- return success;
+ if( battle_config.client_emblem_max_blank_percent < 100 ) {
+ int required_pixels = BITMAP_WIDTH * BITMAP_HEIGHT * (100 - battle_config.client_emblem_max_blank_percent) / 100;
+ int found_pixels = 0;
+ /// Checks what percentage of a guild emblem is blank. A blank emblem
+ /// consists solely of magenta pixels. Since the client uses 16-bit
+ /// colors, any magenta shade that reduces to #ff00ff passes off as
+ /// transparent color as well (down to #f807f8).
+ ///
+ /// Unlike real magenta, reduced magenta causes the guild window to
+ /// become see-through in the transparent parts of the emblem
+ /// background (glitch).
+ switch( RBUFW(buf,28) ) {
+ case 8: // palette indexes
+ {
+ const uint8 *indexes = (const uint8 *)RBUFP(buf,offbits);
+ const uint32 *palette = (const uint32 *)RBUFP(buf,BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE);
+
+ for( i = 0; i < BITMAP_WIDTH * BITMAP_HEIGHT; i++ ) {
+ if( indexes[i] >= palettesize ) // Invalid color
+ return false;
+
+ // if( color->r < 0xF8 || color->g > 0x07 || color->b < 0xF8 )
+ if( ( palette[indexes[i]]&0x00F8F8F8 ) != 0x00F800F8 ) {
+ if( ++found_pixels >= required_pixels ) {
+ // Enough valid pixels were found
+ return true;
+ }
+ }
+ }
+ break;
+ }
+ case 24: // full colors
+ {
+ const struct s_bitmaptripple *pixels = (const struct s_bitmaptripple*)RBUFP(buf,offbits);
+
+ for( i = 0; i < BITMAP_WIDTH * BITMAP_HEIGHT; i++ ) {
+ // if( pixels[i].r < 0xF8 || pixels[i].g > 0x07 || pixels[i].b < 0xF8 )
+ if( ( pixels[i].rgb&0xF8F8F8 ) != 0xF800F8 ) {
+ if( ++found_pixels >= required_pixels ) {
+ // Enough valid pixels were found
+ return true;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ // Not enough non-blank pixels found
+ return false;
+ }
+
+ return true;
}
@@ -12854,14 +13145,15 @@ bool clif_validate_emblem(const uint8* emblem, unsigned long emblem_len) {
/// 0153 <packet len>.W <emblem data>.?B
void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd)
{
- unsigned long emblem_len = RFIFOW(fd,2)-4;
+ unsigned int emblem_len = RFIFOW(fd,2)-4;
const uint8* emblem = RFIFOP(fd,4);
if( !emblem_len || !sd->state.gmaster_flag )
return;
- if( !clif->validate_emblem(emblem, emblem_len) ) {
- ShowWarning("clif_parse_GuildChangeEmblem: Rejected malformed guild emblem (size=%lu, accound_id=%d, char_id=%d, guild_id=%d).\n", emblem_len, sd->status.account_id, sd->status.char_id, sd->status.guild_id);
+ if (!clif->validate_emblem(emblem, emblem_len)) {
+ ShowWarning("clif_parse_GuildChangeEmblem: Rejected malformed guild emblem (size=%u, accound_id=%d, char_id=%d, guild_id=%d).\n",
+ emblem_len, sd->status.account_id, sd->status.char_id, sd->status.guild_id);
return;
}
@@ -12880,7 +13172,7 @@ void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd)
if(!sd->state.gmaster_flag)
return;
- // compensate for some client defects when using multilanguage mode
+ // compensate for some client defects when using multilingual mode
if (msg1[0] == '|' && msg1[3] == '|') msg1+= 3; // skip duplicate marker
if (msg2[0] == '|' && msg2[3] == '|') msg2+= 3; // skip duplicate marker
if (msg2[0] == '|') msg2[strnlen(msg2, MAX_GUILDMES2)-1] = '\0'; // delete extra space at the end of string
@@ -12889,43 +13181,40 @@ void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd)
}
// Helper function for guild invite functions
-int
-clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_session_data *t_sd) {
- if (t_sd == NULL) {// not online or does not exist
- return 1;
- }
-
- if (map[sd->bl.m].flag.guildlock) { //Guild locked.
+bool clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_session_data *t_sd) {
+ if ( t_sd == NULL )// not online or does not exist
+ return false;
+
+ if ( map->list[sd->bl.m].flag.guildlock ) {
+ //Guild locked.
clif->message(fd, msg_txt(228));
- return 1;
+ return false;
}
-
- if (t_sd && t_sd->state.noask) {// @noask [LuzZza]
+
+ if ( t_sd && t_sd->state.noask ) {// @noask [LuzZza]
clif->noask_sub(sd, t_sd, 2);
- return 1;
+ return false;
}
guild->invite(sd,t_sd);
- return 0;
+ return true;
}
/// Guild invite request (CZ_REQ_JOIN_GUILD).
/// 0168 <account id>.L <inviter account id>.L <inviter char id>.L
-void clif_parse_GuildInvite(int fd,struct map_session_data *sd)
-{
- struct map_session_data *t_sd = iMap->id2sd(RFIFOL(fd,2));
+void clif_parse_GuildInvite(int fd,struct map_session_data *sd) {
+ struct map_session_data *t_sd = map->id2sd(RFIFOL(fd,2));
- if (clif_sub_guild_invite(fd, sd, t_sd))
+ if (!clif_sub_guild_invite(fd, sd, t_sd))
return;
}
/// Guild invite request (/guildinvite) (CZ_REQ_JOIN_GUILD2).
/// 0916 <char name>.24B
-void clif_parse_GuildInvite2(int fd, struct map_session_data *sd)
-{
- struct map_session_data *t_sd = iMap->nick2sd((char *)RFIFOP(fd, 2));
-
- if (clif_sub_guild_invite(fd, sd, t_sd))
+void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) {
+ struct map_session_data *t_sd = map->nick2sd((char *)RFIFOP(fd, 2));
+
+ if (!clif_sub_guild_invite(fd, sd, t_sd))
return;
}
@@ -12942,14 +13231,14 @@ void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd)
/// Request to leave guild (CZ_REQ_LEAVE_GUILD).
/// 0159 <guild id>.L <account id>.L <char id>.L <reason>.40B
-void clif_parse_GuildLeave(int fd,struct map_session_data *sd)
-{
- if(map[sd->bl.m].flag.guildlock) { //Guild locked.
+void clif_parse_GuildLeave(int fd,struct map_session_data *sd) {
+ if(map->list[sd->bl.m].flag.guildlock) {
+ //Guild locked.
clif->message(fd, msg_txt(228));
return;
}
if( sd->bg_id ) {
- clif->message(fd, msg_txt(670)); //"You can't leave battleground guilds."
+ clif->message(fd, msg_txt(870)); //"You can't leave battleground guilds."
return;
}
@@ -12959,9 +13248,9 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd)
/// Request to expel a member of a guild (CZ_REQ_BAN_GUILD).
/// 015b <guild id>.L <account id>.L <char id>.L <reason>.40B
-void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd)
-{
- if( map[sd->bl.m].flag.guildlock || sd->bg_id ) { // Guild locked.
+void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) {
+ if( map->list[sd->bl.m].flag.guildlock || sd->bg_id ) {
+ // Guild locked.
clif->message(fd, msg_txt(228));
return;
}
@@ -12977,27 +13266,30 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd)
int textlen = RFIFOW(fd,2) - 4;
char *name, *message;
- int namelen, messagelen;
+ size_t namelen, messagelen;
// validate packet and retrieve name and message
if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
return;
- if( atcommand->parse(fd, sd, message, 1) )
+ if( atcommand->exec(fd, sd, message, true) )
return;
- if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
+ if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
return;
if( battle_config.min_chat_delay )
{ //[Skotlex]
- if (DIFF_TICK(sd->cantalk_tick, iTimer->gettick()) > 0)
+ if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
return;
- sd->cantalk_tick = iTimer->gettick() + battle_config.min_chat_delay;
+ sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
+ if( battle_config.idletime_criteria & BCIDLE_CHAT )
+ sd->idletime = sockt->last_tick;
+
if( sd->bg_id )
- bg_send_message(sd, text, textlen);
+ bg->send_message(sd, text, textlen);
else
guild->send_message(sd, text, textlen);
}
@@ -13005,19 +13297,19 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd)
/// Guild alliance request (CZ_REQ_ALLY_GUILD).
/// 0170 <account id>.L <inviter account id>.L <inviter char id>.L
-void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd)
-{
+void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) {
struct map_session_data *t_sd;
if(!sd->state.gmaster_flag)
return;
- if(map[sd->bl.m].flag.guildlock) { //Guild locked.
+ if(map->list[sd->bl.m].flag.guildlock) {
+ //Guild locked.
clif->message(fd, msg_txt(228));
return;
}
- t_sd = iMap->id2sd(RFIFOL(fd,2));
+ t_sd = map->id2sd(RFIFOL(fd,2));
// @noask [LuzZza]
if(t_sd && t_sd->state.noask) {
@@ -13045,12 +13337,12 @@ void clif_parse_GuildReplyAlliance(int fd, struct map_session_data *sd)
/// relation:
/// 0 = Ally
/// 1 = Enemy
-void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd)
-{
+void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd) {
if(!sd->state.gmaster_flag)
return;
- if(map[sd->bl.m].flag.guildlock) { //Guild locked.
+ if(map->list[sd->bl.m].flag.guildlock) {
+ //Guild locked.
clif->message(fd, msg_txt(228));
return;
}
@@ -13060,19 +13352,19 @@ void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd)
/// Request to set a guild as opposition (CZ_REQ_HOSTILE_GUILD).
/// 0180 <account id>.L
-void clif_parse_GuildOpposition(int fd, struct map_session_data *sd)
-{
+void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) {
struct map_session_data *t_sd;
if(!sd->state.gmaster_flag)
return;
- if(map[sd->bl.m].flag.guildlock) { //Guild locked.
+ if(map->list[sd->bl.m].flag.guildlock) {
+ //Guild locked.
clif->message(fd, msg_txt(228));
return;
}
- t_sd = iMap->id2sd(RFIFOL(fd,2));
+ t_sd = map->id2sd(RFIFOL(fd,2));
// @noask [LuzZza]
if(t_sd && t_sd->state.noask) {
@@ -13089,9 +13381,9 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd)
/// key:
/// now guild name; might have been (intended) email, since the
/// field name and size is same as the one in CH_DELETE_CHAR.
-void clif_parse_GuildBreak(int fd, struct map_session_data *sd)
-{
- if( map[sd->bl.m].flag.guildlock ) { //Guild locked.
+void clif_parse_GuildBreak(int fd, struct map_session_data *sd) {
+ if( map->list[sd->bl.m].flag.guildlock ) {
+ //Guild locked.
clif->message(fd, msg_txt(228));
return;
}
@@ -13112,7 +13404,7 @@ void clif_parse_GuildBreak(int fd, struct map_session_data *sd)
/// 4 = unequip accessory
void clif_parse_PetMenu(int fd, struct map_session_data *sd)
{
- pet_menu(sd,RFIFOB(fd,2));
+ pet->menu(sd,RFIFOB(fd,2));
}
@@ -13120,7 +13412,7 @@ void clif_parse_PetMenu(int fd, struct map_session_data *sd)
/// 019f <id>.L
void clif_parse_CatchPet(int fd, struct map_session_data *sd)
{
- pet_catch_process2(sd,RFIFOL(fd,2));
+ pet->catch_process2(sd,RFIFOL(fd,2));
}
@@ -13129,11 +13421,9 @@ void clif_parse_CatchPet(int fd, struct map_session_data *sd)
void clif_parse_SelectEgg(int fd, struct map_session_data *sd)
{
if (sd->menuskill_id != SA_TAMINGMONSTER || sd->menuskill_val != -1) {
- //Forged packet, disconnect them [Kevin]
- clif->authfail_fd(fd, 0);
return;
}
- pet_select_egg(sd,RFIFOW(fd,2)-2);
+ pet->select_egg(sd,RFIFOW(fd,2)-2);
clif_menuskill_clear(sd);
}
@@ -13173,7 +13463,7 @@ void clif_parse_SendEmotion(int fd, struct map_session_data *sd)
/// 01a5 <name>.24B
void clif_parse_ChangePetName(int fd, struct map_session_data *sd)
{
- pet_change_name(sd,(char*)RFIFOP(fd,2));
+ pet->change_name(sd,(char*)RFIFOP(fd,2));
}
@@ -13181,13 +13471,12 @@ void clif_parse_ChangePetName(int fd, struct map_session_data *sd)
/// Request to disconnect a character.
/// 00cc <account id>.L
/// NOTE: Also sent when using GM right click menu "(name) force to quit"
-void clif_parse_GMKick(int fd, struct map_session_data *sd)
-{
+void clif_parse_GMKick(int fd, struct map_session_data *sd) {
struct block_list *target;
int tid;
tid = RFIFOL(fd,2);
- target = iMap->id2bl(tid);
+ target = map->id2bl(tid);
if (!target) {
clif->GM_kickack(sd, 0);
return;
@@ -13197,8 +13486,8 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd)
case BL_PC:
{
char command[NAME_LENGTH+6];
- sprintf(command, "%ckick %s", atcommand->at_symbol, status_get_name(target));
- atcommand->parse(fd, sd, command, 1);
+ sprintf(command, "%ckick %s", atcommand->at_symbol, status->get_name(target));
+ atcommand->exec(fd, sd, command, true);
}
break;
@@ -13212,7 +13501,7 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd)
clif->GM_kickack(sd, 0);
return;
}
- sprintf(command, "/kick %s (%d)", status_get_name(target), status_get_class(target));
+ sprintf(command, "/kick %s (%d)", status->get_name(target), status->get_class(target));
logs->atcommand(sd, command);
status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target'
}
@@ -13220,9 +13509,14 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd)
case BL_NPC:
{
- char command[NAME_LENGTH+11];
- sprintf(command, "%cunloadnpc %s", atcommand->at_symbol, status_get_name(target));
- atcommand->parse(fd, sd, command, 1);
+ struct npc_data* nd = (struct npc_data *)target;
+ if( !pc->can_use_command(sd, "@unloadnpc")) {
+ clif->GM_kickack(sd, 0);
+ return;
+ }
+ npc->unload_duplicates(nd);
+ npc->unload(nd,true);
+ npc->read_event_script();
}
break;
@@ -13238,7 +13532,7 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd)
void clif_parse_GMKickAll(int fd, struct map_session_data* sd) {
char cmd[15];
sprintf(cmd,"%ckickall",atcommand->at_symbol);
- atcommand->parse(fd, sd, cmd, 1);
+ atcommand->exec(fd, sd, cmd, true);
}
@@ -13258,23 +13552,22 @@ void clif_parse_GMShift(int fd, struct map_session_data *sd)
player_name[NAME_LENGTH-1] = '\0';
sprintf(command, "%cjumpto %s", atcommand->at_symbol, player_name);
- atcommand->parse(fd, sd, command, 1);
+ atcommand->exec(fd, sd, command, true);
}
/// /remove (CZ_REMOVE_AID_SSO).
/// Request to warp to a character with given account ID.
/// 0843 <account id>.L
-void clif_parse_GMRemove2(int fd, struct map_session_data* sd)
-{
+void clif_parse_GMRemove2(int fd, struct map_session_data* sd) {
int account_id;
struct map_session_data* pl_sd;
account_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
- if( (pl_sd = iMap->id2sd(account_id)) != NULL ) {
+ if( (pl_sd = map->id2sd(account_id)) != NULL ) {
char command[NAME_LENGTH+8];
sprintf(command, "%cjumpto %s", atcommand->at_symbol, pl_sd->status.name);
- atcommand->parse(fd, sd, command, 1);
+ atcommand->exec(fd, sd, command, true);
}
}
@@ -13295,52 +13588,92 @@ void clif_parse_GMRecall(int fd, struct map_session_data *sd)
player_name[NAME_LENGTH-1] = '\0';
sprintf(command, "%crecall %s", atcommand->at_symbol, player_name);
- atcommand->parse(fd, sd, command, 1);
+ atcommand->exec(fd, sd, command, true);
}
/// /recall (CZ_RECALL_SSO).
/// Request to summon a player with given account ID to own position.
/// 0842 <account id>.L
-void clif_parse_GMRecall2(int fd, struct map_session_data* sd)
-{
+void clif_parse_GMRecall2(int fd, struct map_session_data* sd) {
int account_id;
struct map_session_data* pl_sd;
account_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]);
- if( (pl_sd = iMap->id2sd(account_id)) != NULL ) {
+ if( (pl_sd = map->id2sd(account_id)) != NULL ) {
char command[NAME_LENGTH+8];
sprintf(command, "%crecall %s", atcommand->at_symbol, pl_sd->status.name);
- atcommand->parse(fd, sd, command, 1);
+ atcommand->exec(fd, sd, command, true);
}
}
/// /item /monster (CZ_ITEM_CREATE).
-/// Request to make items or spawn monsters.
+/// Request to execute GM commands.
+/// usage:
+/// /item n - summon n monster or acquire n item/s
+/// /item money - grants 2147483647 Zeny
+/// /item whereisboss - locate boss mob in current map.(not yet implemented)
+/// /item regenboss_n t - regenerate n boss monster by t millisecond.(not yet implemented)
+/// /item onekillmonster - toggle an ability to kill mobs in one hit.(not yet implemented)
+/// /item bossinfo - display the information of a boss monster in current map.(not yet implemented)
+/// /item cap_n - capture n monster as pet.(not yet implemented)
+/// /item agitinvest - reset current global agit investments.(not yet implemented)
/// 013f <item/mob name>.24B
-void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd)
-{
- char *monster_item_name;
- char command[NAME_LENGTH+10];
+/// 09ce <item/mob name>.100B [Ind/Yommy<3]
+void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) {
+ struct packet_gm_monster_item *p = P2PTR(fd);
+ int i, count;
+ char *item_monster_name;
+ struct item_data *item_array[10];
+ struct mob_db *mob_array[10];
+ char command[256];
+
+ item_monster_name = p->str;
+ item_monster_name[(sizeof(struct packet_gm_monster_item)-2)-1] = '\0';
+
+ if ( (count=itemdb->search_name_array(item_array, 10, item_monster_name, 1)) > 0 ) {
+ for(i = 0; i < count; i++) {
+ if( !item_array[i] )
+ continue;
+ // It only accepts aegis name
+ if( battle_config.case_sensitive_aegisnames && strcmp(item_array[i]->name, item_monster_name) == 0 )
+ break;
+ if( !battle_config.case_sensitive_aegisnames && strcasecmp(item_array[i]->name, item_monster_name) == 0 )
+ break;
+ }
- monster_item_name = (char*)RFIFOP(fd,2);
- monster_item_name[NAME_LENGTH-1] = '\0';
+ if( i < count ) {
+ if( item_array[i]->type == IT_WEAPON || item_array[i]->type == IT_ARMOR ) // nonstackable
+ snprintf(command, sizeof(command)-1, "%citem2 %d 1 0 0 0 0 0 0 0", atcommand->at_symbol, item_array[i]->nameid);
+ else
+ snprintf(command, sizeof(command)-1, "%citem %d 20", atcommand->at_symbol, item_array[i]->nameid);
+ atcommand->exec(fd, sd, command, true);
+ return;
+ }
+ }
- // FIXME: Should look for item first, then for monster.
- // FIXME: /monster takes mob_db Sprite_Name as argument
- if( mobdb_searchname(monster_item_name) ) {
- snprintf(command, sizeof(command)-1, "%cmonster %s", atcommand->at_symbol, monster_item_name);
- atcommand->parse(fd, sd, command, 1);
+ if( strcmp("money", item_monster_name) == 0 ){
+ snprintf(command, sizeof(command)-1, "%czeny %d", atcommand->at_symbol, INT_MAX);
+ atcommand->exec(fd, sd, command, true);
return;
}
- // FIXME: Stackables have a quantity of 20.
- // FIXME: Equips are supposed to be unidentified.
- if( itemdb_searchname(monster_item_name) ) {
- snprintf(command, sizeof(command)-1, "%citem %s", atcommand->at_symbol, monster_item_name);
- atcommand->parse(fd, sd, command, 1);
- return;
+ if( (count=mob->db_searchname_array(mob_array, 10, item_monster_name, 1)) > 0) {
+ for(i = 0; i < count; i++) {
+ if( !mob_array[i] )
+ continue;
+ // It only accepts sprite name
+ if( battle_config.case_sensitive_aegisnames && strcmp(mob_array[i]->sprite, item_monster_name) == 0 )
+ break;
+ if( !battle_config.case_sensitive_aegisnames && strcasecmp(mob_array[i]->sprite, item_monster_name) == 0 )
+ break;
+ }
+
+ if( i < count ){
+ snprintf(command, sizeof(command)-1, "%cmonster %s", atcommand->at_symbol, mob_array[i]->sprite);
+ atcommand->exec(fd, sd, command, true);
+ }
}
}
@@ -13354,7 +13687,7 @@ void clif_parse_GMHide(int fd, struct map_session_data *sd) {
sprintf(cmd,"%chide",atcommand->at_symbol);
- atcommand->parse(fd, sd, cmd, 1);
+ atcommand->exec(fd, sd, cmd, true);
}
@@ -13364,8 +13697,7 @@ void clif_parse_GMHide(int fd, struct map_session_data *sd) {
/// 0 = positive points
/// 1 = negative points
/// 2 = self mute (+10 minutes)
-void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd)
-{
+void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) {
int id, type, value;
struct map_session_data *dstsd;
char command[NAME_LENGTH+15];
@@ -13377,17 +13709,39 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd)
if( type == 0 )
value = -value;
- //If type is 2 and the ids don't match, this is a crafted hacked packet!
- //Disabled because clients keep self-muting when you give players public @ commands... [Skotlex]
- if (type == 2 /* && (pc->get_group_level(sd) > 0 || sd->bl.id != id)*/)
- return;
+ if (type == 2) {
+ if (!battle_config.client_accept_chatdori)
+ return;
+ if (pc_get_group_level(sd) > 0 || sd->bl.id != id)
+ return;
- dstsd = iMap->id2sd(id);
- if( dstsd == NULL )
- return;
+ value = battle_config.client_accept_chatdori;
+ dstsd = sd;
+ } else {
+ dstsd = map->id2sd(id);
+ if( dstsd == NULL )
+ return;
+ }
+
+ if (type == 2 || ( (pc_get_group_level(sd)) > pc_get_group_level(dstsd) && !pc->can_use_command(sd, "@mute"))) {
+ clif->manner_message(sd, 0);
+ clif->manner_message(dstsd, 5);
+
+ if (dstsd->status.manner < value) {
+ dstsd->status.manner -= value;
+ sc_start(NULL,&dstsd->bl,SC_NOCHAT,100,0,0);
+
+ } else {
+ dstsd->status.manner = 0;
+ status_change_end(&dstsd->bl, SC_NOCHAT, INVALID_TIMER);
+ }
+
+ if( type != 2 )
+ clif->GM_silence(sd, dstsd, type);
+ }
sprintf(command, "%cmute %d %s", atcommand->at_symbol, value, dstsd->status.name);
- atcommand->parse(fd, sd, command, 1);
+ atcommand->exec(fd, sd, command, true);
}
@@ -13401,7 +13755,7 @@ void clif_parse_GMRc(int fd, struct map_session_data* sd)
name[NAME_LENGTH-1] = '\0';
sprintf(command, "%cmute %d %s", atcommand->at_symbol, 60, name);
- atcommand->parse(fd, sd, command, 1);
+ atcommand->exec(fd, sd, command, true);
}
@@ -13435,18 +13789,17 @@ void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd)
/// type:
/// 0 = not walkable
/// 1 = walkable
-void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd)
-{
+void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) {
int x,y,type;
- if( pc_has_permission(sd, PC_PERM_USE_CHANGEMAPTYPE) )
+ if (!pc_has_permission(sd, PC_PERM_USE_CHANGEMAPTYPE))
return;
x = RFIFOW(fd,2);
y = RFIFOW(fd,4);
type = RFIFOW(fd,6);
- iMap->setgatcell(sd->bl.m,x,y,type);
+ map->setgatcell(sd->bl.m,x,y,type);
clif->changemapcell(0,sd->bl.m,x,y,type,ALL_SAMEMAP);
//FIXME: once players leave the map, the client 'forgets' this information.
}
@@ -13458,8 +13811,7 @@ void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd)
/// type:
/// 0 = (/ex nick) deny speech from nick
/// 1 = (/in nick) allow speech from nick
-void clif_parse_PMIgnore(int fd, struct map_session_data* sd)
-{
+void clif_parse_PMIgnore(int fd, struct map_session_data* sd) {
char* nick;
uint8 type;
int i;
@@ -13469,7 +13821,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data* sd)
type = RFIFOB(fd,26);
if( type == 0 ) { // Add name to ignore list (block)
- if (strcmp(iMap->wisp_server_name, nick) == 0) {
+ if (strcmp(map->wisp_server_name, nick) == 0) {
clif->wisexin(sd, type, 1); // fail
return;
}
@@ -13595,6 +13947,10 @@ void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd)
/// "Help me out~ Please~ T_T"
void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd)
{
+ /* [Ind/Hercules] */
+ /* game client is currently broken on this (not sure the packetver range) */
+ /* it sends the request when the criteria doesn't match (and of course we let it fail) */
+ /* so restoring the old parse_globalmes method. */
if( ( sd->class_&MAPID_UPPERMASK ) == MAPID_SUPER_NOVICE ) {
unsigned int next = pc->nextbaseexp(sd);
if( next == 0 ) next = pc->thisbaseexp(sd);
@@ -13602,7 +13958,7 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd)
int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. );
if( percent && ( percent%100 ) == 0 ) {// 10.0%, 20.0%, ..., 90.0%
- sc_start(&sd->bl, status_skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
+ sc_start(NULL,&sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions
}
}
@@ -13637,7 +13993,7 @@ void clif_friendslist_toggle(struct map_session_data *sd,int account_id, int cha
}
-//Subfunction called from clif_foreachclient to toggle friends on/off [Skotlex]
+//Sub-function called from clif_foreachclient to toggle friends on/off [Skotlex]
int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap)
{
int account_id, char_id, online;
@@ -13670,7 +14026,7 @@ void clif_friendslist_send(struct map_session_data *sd)
}
for (n = 0; n < i; n++) { //Sending the online players
- if (iMap->charid2sd(sd->status.friends[n].char_id))
+ if (map->charid2sd(sd->status.friends[n].char_id))
clif->friendslist_toggle(sd, sd->status.friends[n].account_id, sd->status.friends[n].char_id, 1);
}
}
@@ -13717,12 +14073,11 @@ void clif_friendlist_req(struct map_session_data* sd, int account_id, int char_i
/// Request to add a player as friend (CZ_ADD_FRIENDS).
/// 0202 <name>.24B
-void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd)
-{
+void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) {
struct map_session_data *f_sd;
int i;
- f_sd = iMap->nick2sd((char*)RFIFOP(fd,2));
+ f_sd = map->nick2sd((char*)RFIFOP(fd,2));
// ensure that the request player's friend list is not full
ARR_FIND(0, MAX_FRIENDS, i, sd->status.friends[i].char_id == 0);
@@ -13751,7 +14106,7 @@ void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd)
// Friend already exists
for (i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id != 0; i++) {
if (sd->status.friends[i].char_id == f_sd->status.char_id) {
- clif->message(fd, msg_txt(671)); //"Friend already exists."
+ clif->message(fd, msg_txt(871)); //"Friend already exists."
return;
}
}
@@ -13787,7 +14142,7 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd)
return;
}
- f_sd = iMap->id2sd(account_id); //The account id is the same as the bl.id of players.
+ f_sd = map->id2sd(account_id); //The account id is the same as the bl.id of players.
if (f_sd == NULL)
return;
@@ -13847,12 +14202,12 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd)
(sd->status.friends[i].char_id != char_id || sd->status.friends[i].account_id != account_id); i++);
if (i == MAX_FRIENDS) {
- clif->message(fd, msg_txt(672)); //"Name not found in list."
+ clif->message(fd, msg_txt(872)); //"Name not found in list."
return;
}
//remove from friend's list first
- if( (f_sd = iMap->id2sd(account_id)) && f_sd->status.char_id == char_id) {
+ if( (f_sd = map->id2sd(account_id)) && f_sd->status.char_id == char_id) {
for (i = 0; i < MAX_FRIENDS &&
(f_sd->status.friends[i].char_id != sd->status.char_id || f_sd->status.friends[i].account_id != sd->status.account_id); i++);
@@ -13871,8 +14226,8 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd)
}
} else { //friend not online -- ask char server to delete from his friendlist
- if(chrif_removefriend(char_id,sd->status.char_id)) { // char-server offline, abort
- clif->message(fd, msg_txt(673)); //"This action can't be performed at the moment. Please try again later."
+ if(!chrif->removefriend(char_id,sd->status.char_id)) { // char-server offline, abort
+ clif->message(fd, msg_txt(873)); //"This action can't be performed at the moment. Please try again later."
return;
}
}
@@ -13885,7 +14240,7 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd)
memcpy(&sd->status.friends[j-1], &sd->status.friends[j], sizeof(sd->status.friends[0]));
memset(&sd->status.friends[MAX_FRIENDS-1], 0, sizeof(sd->status.friends[MAX_FRIENDS-1]));
- clif->message(fd, msg_txt(674)); //"Friend removed"
+ clif->message(fd, msg_txt(874)); //"Friend removed"
WFIFOHEAD(fd,packet_len(0x20a));
WFIFOW(fd,0) = 0x20a;
@@ -13919,50 +14274,118 @@ void clif_parse_PVPInfo(int fd,struct map_session_data *sd)
clif->PVPInfo(sd);
}
+/// Ranking list
-/// /blacksmith list (ZC_BLACKSMITH_RANK).
-/// 0219 { <name>.24B }*10 { <point>.L }*10
-void clif_blacksmith(struct map_session_data* sd)
-{
- int i, fd = sd->fd;
+/// ranking pointlist { <name>.24B <point>.L }*10
+void clif_ranklist_sub(unsigned char *buf, enum fame_list_type type) {
const char* name;
+ struct fame_list* list;
+ int i;
- WFIFOHEAD(fd,packet_len(0x219));
- WFIFOW(fd,0) = 0x219;
- //Packet size limits this list to 10 elements. [Skotlex]
- for (i = 0; i < 10 && i < MAX_FAME_LIST; i++) {
- if (smith_fame_list[i].id > 0) {
- if (strcmp(smith_fame_list[i].name, "-") == 0 &&
- (name = iMap->charid2nick(smith_fame_list[i].id)) != NULL)
- {
- strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), name, NAME_LENGTH);
- } else
- strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), smith_fame_list[i].name, NAME_LENGTH);
- } else
- strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), "None", 5);
- WFIFOL(fd, 242 + i * 4) = smith_fame_list[i].fame;
+ switch( type ) {
+ case RANKTYPE_BLACKSMITH: list = pc->smith_fame_list; break;
+ case RANKTYPE_ALCHEMIST: list = pc->chemist_fame_list; break;
+ case RANKTYPE_TAEKWON: list = pc->taekwon_fame_list; break;
+ default: return; // Unsupported
+ }
+
+ // Packet size limits this list to 10 elements. [Skotlex]
+ for( i = 0; i < 10 && i < MAX_FAME_LIST; i++ ) {
+ if( list[i].id > 0 ) {
+ if( strcmp(list[i].name, "-") == 0 && (name = map->charid2nick(list[i].id)) != NULL ) {
+ strncpy((char *)(WBUFP(buf, 24 * i)), name, NAME_LENGTH);
+ } else {
+ strncpy((char *)(WBUFP(buf, 24 * i)), list[i].name, NAME_LENGTH);
+ }
+ } else {
+ strncpy((char *)(WBUFP(buf, 24 * i)), "None", 5);
+ }
+ WBUFL(buf, 24 * 10 + i * 4) = list[i].fame; //points
}
- for(;i < 10; i++) { //In case the MAX is less than 10.
- strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), "Unavailable", 12);
- WFIFOL(fd, 242 + i * 4) = 0;
+ for( ;i < 10; i++ ) { // In case the MAX is less than 10.
+ strncpy((char *)(WBUFP(buf, 24 * i)), "Unavailable", 12);
+ WBUFL(buf, 24 * 10 + i * 4) = 0;
}
+}
- WFIFOSET(fd, packet_len(0x219));
+/// 097d <RankingType>.W {<CharName>.24B <point>L}*10 <mypoint>L (ZC_ACK_RANKING)
+void clif_ranklist(struct map_session_data *sd, enum fame_list_type type) {
+ int fd = sd->fd;
+ int mypoint = 0;
+ int upperMask = sd->class_&MAPID_UPPERMASK;
+
+ WFIFOHEAD(fd, 288);
+ WFIFOW(fd, 0) = 0x97d;
+ WFIFOW(fd, 2) = type;
+ clif_ranklist_sub(WFIFOP(fd,4), type);
+
+ if( (upperMask == MAPID_BLACKSMITH && type == RANKTYPE_BLACKSMITH)
+ || (upperMask == MAPID_ALCHEMIST && type == RANKTYPE_ALCHEMIST)
+ || (upperMask == MAPID_TAEKWON && type == RANKTYPE_TAEKWON)
+ ) {
+ mypoint = sd->status.fame;
+ } else {
+ mypoint = 0;
+ }
+
+ WFIFOL(fd, 284) = mypoint; //mypoint
+ WFIFOSET(fd, 288);
+}
+
+/*
+ * 097c <type> (CZ_REQ_RANKING)
+ * */
+void clif_parse_ranklist(int fd, struct map_session_data *sd) {
+ int16 type = RFIFOW(fd, 2); //type
+
+ switch( type ) {
+ case RANKTYPE_BLACKSMITH:
+ case RANKTYPE_ALCHEMIST:
+ case RANKTYPE_TAEKWON:
+ clif->ranklist(sd, type); // pk_list unsupported atm
+ break;
+ }
+}
+
+// 097e <RankingType>.W <point>.L <TotalPoint>.L (ZC_UPDATE_RANKING_POINT)
+void clif_update_rankingpoint(struct map_session_data *sd, enum fame_list_type type, int points) {
+#if PACKETVER < 20130710
+ switch( type ) {
+ case RANKTYPE_BLACKSMITH: clif->fame_blacksmith(sd,points); break;
+ case RANKTYPE_ALCHEMIST: clif->fame_alchemist(sd,points); break;
+ case RANKTYPE_TAEKWON: clif->fame_taekwon(sd,points); break;
+ }
+#else
+ int fd = sd->fd;
+ WFIFOHEAD(fd, 12);
+ WFIFOW(fd, 0) = 0x97e;
+ WFIFOW(fd, 2) = type;
+ WFIFOL(fd, 4) = points;
+ WFIFOL(fd, 8) = sd->status.fame;
+ WFIFOSET(fd, 12);
+#endif
}
+/// /blacksmith list (ZC_BLACKSMITH_RANK).
+/// 0219 { <name>.24B }*10 { <point>.L }*10
+void clif_blacksmith(struct map_session_data* sd) {
+ int fd = sd->fd;
+
+ WFIFOHEAD(fd,packet_len(0x219));
+ WFIFOW(fd,0) = 0x219;
+ clif_ranklist_sub(WFIFOP(fd, 2), RANKTYPE_BLACKSMITH);
+ WFIFOSET(fd, packet_len(0x219));
+}
/// /blacksmith (CZ_BLACKSMITH_RANK).
/// 0217
-void clif_parse_Blacksmith(int fd,struct map_session_data *sd)
-{
+void clif_parse_Blacksmith(int fd,struct map_session_data *sd) {
clif->blacksmith(sd);
}
-
/// Notification about backsmith points (ZC_BLACKSMITH_POINT).
/// 021b <points>.L <total points>.L
-void clif_fame_blacksmith(struct map_session_data *sd, int points)
-{
+void clif_fame_blacksmith(struct map_session_data *sd, int points) {
int fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x21b));
@@ -13972,49 +14395,26 @@ void clif_fame_blacksmith(struct map_session_data *sd, int points)
WFIFOSET(fd, packet_len(0x21b));
}
-
/// /alchemist list (ZC_ALCHEMIST_RANK).
/// 021a { <name>.24B }*10 { <point>.L }*10
void clif_alchemist(struct map_session_data* sd) {
- int i, fd = sd->fd;
- const char* name;
+ int fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x21a));
WFIFOW(fd,0) = 0x21a;
- //Packet size limits this list to 10 elements. [Skotlex]
- for (i = 0; i < 10 && i < MAX_FAME_LIST; i++) {
- if (chemist_fame_list[i].id > 0) {
- if (strcmp(chemist_fame_list[i].name, "-") == 0 &&
- (name = iMap->charid2nick(chemist_fame_list[i].id)) != NULL)
- {
- memcpy(WFIFOP(fd, 2 + 24 * i), name, NAME_LENGTH);
- } else
- memcpy(WFIFOP(fd, 2 + 24 * i), chemist_fame_list[i].name, NAME_LENGTH);
- } else
- memcpy(WFIFOP(fd, 2 + 24 * i), "None", NAME_LENGTH);
- WFIFOL(fd, 242 + i * 4) = chemist_fame_list[i].fame;
- }
- for(;i < 10; i++) { //In case the MAX is less than 10.
- memcpy(WFIFOP(fd, 2 + 24 * i), "Unavailable", NAME_LENGTH);
- WFIFOL(fd, 242 + i * 4) = 0;
- }
-
+ clif_ranklist_sub(WFIFOP(fd,2), RANKTYPE_ALCHEMIST);
WFIFOSET(fd, packet_len(0x21a));
}
-
/// /alchemist (CZ_ALCHEMIST_RANK).
/// 0218
-void clif_parse_Alchemist(int fd,struct map_session_data *sd)
-{
+void clif_parse_Alchemist(int fd,struct map_session_data *sd) {
clif->alchemist(sd);
}
-
/// Notification about alchemist points (ZC_ALCHEMIST_POINT).
/// 021c <points>.L <total points>.L
-void clif_fame_alchemist(struct map_session_data *sd, int points)
-{
+void clif_fame_alchemist(struct map_session_data *sd, int points) {
int fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x21c));
@@ -14024,48 +14424,26 @@ void clif_fame_alchemist(struct map_session_data *sd, int points)
WFIFOSET(fd, packet_len(0x21c));
}
-
/// /taekwon list (ZC_TAEKWON_RANK).
/// 0226 { <name>.24B }*10 { <point>.L }*10
void clif_taekwon(struct map_session_data* sd) {
- int i, fd = sd->fd;
- const char* name;
+ int fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x226));
WFIFOW(fd,0) = 0x226;
- //Packet size limits this list to 10 elements. [Skotlex]
- for (i = 0; i < 10 && i < MAX_FAME_LIST; i++) {
- if (taekwon_fame_list[i].id > 0) {
- if (strcmp(taekwon_fame_list[i].name, "-") == 0 &&
- (name = iMap->charid2nick(taekwon_fame_list[i].id)) != NULL)
- {
- memcpy(WFIFOP(fd, 2 + 24 * i), name, NAME_LENGTH);
- } else
- memcpy(WFIFOP(fd, 2 + 24 * i), taekwon_fame_list[i].name, NAME_LENGTH);
- } else
- memcpy(WFIFOP(fd, 2 + 24 * i), "None", NAME_LENGTH);
- WFIFOL(fd, 242 + i * 4) = taekwon_fame_list[i].fame;
- }
- for(;i < 10; i++) { //In case the MAX is less than 10.
- memcpy(WFIFOP(fd, 2 + 24 * i), "Unavailable", NAME_LENGTH);
- WFIFOL(fd, 242 + i * 4) = 0;
- }
+ clif_ranklist_sub(WFIFOP(fd,2), RANKTYPE_TAEKWON);
WFIFOSET(fd, packet_len(0x226));
}
-
/// /taekwon (CZ_TAEKWON_RANK).
/// 0225
-void clif_parse_Taekwon(int fd,struct map_session_data *sd)
-{
+void clif_parse_Taekwon(int fd,struct map_session_data *sd) {
clif->taekwon(sd);
}
-
/// Notification about taekwon points (ZC_TAEKWON_POINT).
/// 0224 <points>.L <total points>.L
-void clif_fame_taekwon(struct map_session_data *sd, int points)
-{
+void clif_fame_taekwon(struct map_session_data *sd, int points) {
int fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x224));
@@ -14075,7 +14453,6 @@ void clif_fame_taekwon(struct map_session_data *sd, int points)
WFIFOSET(fd, packet_len(0x224));
}
-
/// /pk list (ZC_KILLER_RANK).
/// 0238 { <name>.24B }*10 { <point>.L }*10
void clif_ranking_pk(struct map_session_data* sd) {
@@ -14093,8 +14470,7 @@ void clif_ranking_pk(struct map_session_data* sd) {
/// /pk (CZ_KILLER_RANK).
/// 0237
-void clif_parse_RankingPk(int fd,struct map_session_data *sd)
-{
+void clif_parse_RankingPk(int fd,struct map_session_data *sd) {
clif->ranking_pk(sd);
}
@@ -14115,7 +14491,7 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd)
sd->feel_map[i].index = map_id2index(sd->bl.m);
sd->feel_map[i].m = sd->bl.m;
- pc_setglobalreg(sd,sg_info[i].feel_var,sd->feel_map[i].index);
+ pc_setglobalreg(sd,script->add_str(pc->sg_info[i].feel_var),sd->feel_map[i].index);
//Are these really needed? Shouldn't they show up automatically from the feel save packet?
// clif_misceffect2(&sd->bl, 0x1b0);
@@ -14164,9 +14540,9 @@ void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd)
else
return;
- unit_calc_pos(bl, sd->bl.x, sd->bl.y, sd->ud.dir);
- ud = unit_bl2ud(bl);
- unit_walktoxy(bl, ud->to_x, ud->to_y, 4);
+ unit->calc_pos(bl, sd->bl.x, sd->bl.y, sd->ud.dir);
+ ud = unit->bl2ud(bl);
+ unit->walktoxy(bl, ud->to_x, ud->to_y, 4);
}
@@ -14187,7 +14563,7 @@ void clif_parse_HomMoveTo(int fd, struct map_session_data *sd)
else
return;
- unit_walktoxy(bl, x, y, 4);
+ unit->walktoxy(bl, x, y, 4);
}
@@ -14208,8 +14584,8 @@ void clif_parse_HomAttack(int fd,struct map_session_data *sd)
bl = &sd->md->bl;
else return;
- unit_stop_attack(bl);
- unit_attack(bl, target_id, action_type != 0);
+ unit->stop_attack(bl);
+ unit->attack(bl, target_id, action_type != 0);
}
@@ -14235,21 +14611,29 @@ void clif_parse_HomMenu(int fd, struct map_session_data *sd) { //[orn]
/// Request to resurrect oneself using Token of Siegfried (CZ_STANDING_RESURRECTION).
/// 0292
-void clif_parse_AutoRevive(int fd, struct map_session_data *sd)
-{
+void clif_parse_AutoRevive(int fd, struct map_session_data *sd) {
int item_position = pc->search_inventory(sd, ITEMID_TOKEN_OF_SIEGFRIED);
+ int hpsp = 100;
- if (item_position < 0)
- return;
+ if (item_position == INDEX_NOT_FOUND) {
+ if (sd->sc.data[SC_LIGHT_OF_REGENE])
+ hpsp = 20 * sd->sc.data[SC_LIGHT_OF_REGENE]->val1;
+ else
+ return;
+ }
if (sd->sc.data[SC_HELLPOWER]) //Cannot res while under the effect of SC_HELLPOWER.
return;
- if (!status_revive(&sd->bl, 100, 100))
+ if (!status->revive(&sd->bl, hpsp, hpsp))
return;
+ if (item_position == INDEX_NOT_FOUND)
+ status_change_end(&sd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER);
+ else
+ pc->delitem(sd, item_position, 1, 0, 1, LOG_TYPE_CONSUME);
+
clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1);
- pc->delitem(sd, item_position, 1, 0, 1, LOG_TYPE_CONSUME);
}
@@ -14288,7 +14672,7 @@ void clif_check(int fd, struct map_session_data* pl_sd) {
WFIFOW(fd,34) = pl_sd->battle_status.flee2/10;
WFIFOW(fd,36) = pl_sd->battle_status.cri/10;
WFIFOW(fd,38) = (2000-pl_sd->battle_status.amotion)/10; // aspd
- WFIFOW(fd,40) = 0; // FIXME: What is 'plusASPD' supposed to be? Maybe adelay?
+ WFIFOW(fd,40) = 0; // FIXME: What is 'plusASPD' supposed to be? Maybe a delay?
WFIFOSET(fd,packet_len(0x214));
}
@@ -14306,7 +14690,7 @@ void clif_parse_Check(int fd, struct map_session_data *sd)
safestrncpy(charname, (const char*)RFIFOP(fd,packet_db[RFIFOW(fd,0)].pos[0]), sizeof(charname));
- if( ( pl_sd = iMap->nick2sd(charname) ) == NULL || pc->get_group_level(sd) < pc->get_group_level(pl_sd) ) {
+ if( ( pl_sd = map->nick2sd(charname) ) == NULL || pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) {
return;
}
@@ -14353,7 +14737,7 @@ void clif_Mail_getattachment(int fd, uint8 flag)
/// 0249 <result>.B
/// result:
/// 0 = success
-/// 1 = recipinent does not exist
+/// 1 = recipient does not exist
void clif_Mail_send(int fd, bool fail)
{
WFIFOHEAD(fd,packet_len(0x249));
@@ -14456,7 +14840,7 @@ void clif_Mail_refreshinbox(struct map_session_data *sd)
if( md->full ) {// TODO: is this official?
char output[100];
sprintf(output, "Inbox is full (Max %d). Delete some mails.", MAIL_MAX_INBOX);
- clif->disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
}
}
@@ -14468,7 +14852,7 @@ void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd)
struct mail_data* md = &sd->mail.inbox;
if( md->amount < MAIL_MAX_INBOX && (md->full || sd->mail.changed) )
- intif_Mail_requestinbox(sd->status.char_id, 1);
+ intif->Mail_requestinbox(sd->status.char_id, 1);
else
clif->mail_refreshinbox(sd);
@@ -14494,7 +14878,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
struct mail_message *msg = &sd->mail.inbox.msg[i];
struct item *item = &msg->item;
struct item_data *data;
- int msg_len = strlen(msg->body), len;
+ size_t msg_len = strlen(msg->body), len;
if( msg_len == 0 ) {
strcpy(msg->body, "(no message)");
@@ -14512,7 +14896,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
WFIFOL(fd,72) = 0;
WFIFOL(fd,76) = msg->zeny;
- if( item->nameid && (data = itemdb_exists(item->nameid)) != NULL ) {
+ if( item->nameid && (data = itemdb->exists(item->nameid)) != NULL ) {
WFIFOL(fd,80) = item->amount;
WFIFOW(fd,84) = (data->view_id)?data->view_id:item->nameid;
WFIFOW(fd,86) = data->type;
@@ -14532,7 +14916,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
if (msg->status == MAIL_UNREAD) {
msg->status = MAIL_READ;
- intif_Mail_read(mail_id);
+ intif->Mail_read(mail_id);
clif->pMail_refreshinbox(fd, sd);
}
}
@@ -14562,7 +14946,7 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
int i;
bool fail = false;
- if( !chrif_isconnected() )
+ if( !chrif->isconnected() )
return;
if( mail_id <= 0 )
return;
@@ -14585,9 +14969,14 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
struct item_data *data;
unsigned int weight;
- if ((data = itemdb_exists(sd->mail.inbox.msg[i].item.nameid)) == NULL)
+ if ((data = itemdb->exists(sd->mail.inbox.msg[i].item.nameid)) == NULL)
return;
+ if( pc_is90overweight(sd) ) {
+ clif->mail_getattachment(fd, 2);
+ return;
+ }
+
switch( pc->checkadditem(sd, data->nameid, sd->mail.inbox.msg[i].item.amount) ) {
case ADDITEM_NEW:
fail = ( pc->inventoryblank(sd) == 0 );
@@ -14612,7 +15001,7 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item));
clif->mail_read(sd, mail_id);
- intif_Mail_getattach(sd->status.char_id, mail_id);
+ intif->Mail_getattach(sd->status.char_id, mail_id);
}
@@ -14623,7 +15012,7 @@ void clif_parse_Mail_delete(int fd, struct map_session_data *sd)
int mail_id = RFIFOL(fd,2);
int i;
- if( !chrif_isconnected() )
+ if( !chrif->isconnected() )
return;
if( mail_id <= 0 )
return;
@@ -14639,7 +15028,7 @@ void clif_parse_Mail_delete(int fd, struct map_session_data *sd)
return;
}
- intif_Mail_delete(sd->status.char_id, mail_id);
+ intif->Mail_delete(sd->status.char_id, mail_id);
}
}
@@ -14658,7 +15047,7 @@ void clif_parse_Mail_return(int fd, struct map_session_data *sd)
ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
if( i < MAIL_MAX_INBOX && sd->mail.inbox.msg[i].send_id != 0 )
- intif_Mail_return(sd->status.char_id, mail_id);
+ intif->Mail_return(sd->status.char_id, mail_id);
else
clif->mail_return(sd->fd, mail_id, 1);
}
@@ -14672,7 +15061,7 @@ void clif_parse_Mail_setattach(int fd, struct map_session_data *sd)
int amount = RFIFOL(fd,4);
unsigned char flag;
- if( !chrif_isconnected() )
+ if( !chrif->isconnected() )
return;
if (idx < 0 || amount < 0)
return;
@@ -14706,7 +15095,7 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd)
struct mail_message msg;
int body_len;
- if( !chrif_isconnected() )
+ if( !chrif->isconnected() )
return;
if( sd->state.trading )
return;
@@ -14716,8 +15105,8 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd)
return;
}
- if( DIFF_TICK(sd->cansendmail_tick, iTimer->gettick()) > 0 ) {
- clif->message(sd->fd,msg_txt(675)); //"Cannot send mails too fast!!."
+ if( DIFF_TICK(sd->cansendmail_tick, timer->gettick()) > 0 ) {
+ clif->message(sd->fd,msg_txt(875)); //"Cannot send mails too fast!!."
clif->mail_send(fd, true); // fail
return;
}
@@ -14751,10 +15140,10 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd)
memset(msg.body, 0x00, MAIL_BODY_LENGTH);
msg.timestamp = time(NULL);
- if( !intif_Mail_send(sd->status.account_id, &msg) )
+ if( !intif->Mail_send(sd->status.account_id, &msg) )
mail->deliveryfail(sd, &msg);
- sd->cansendmail_tick = iTimer->gettick() + 1000; // 1 Second flood Protection
+ sd->cansendmail_tick = timer->gettick() + 1000; // 1 Second flood Protection
}
@@ -14774,6 +15163,9 @@ void clif_Auction_openwindow(struct map_session_data *sd)
if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading )
return;
+ if( !battle_config.feature_auction )
+ return;
+
WFIFOHEAD(fd,packet_len(0x25f));
WFIFOW(fd,0) = 0x25f;
WFIFOL(fd,2) = 0;
@@ -14803,7 +15195,7 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages,
WFIFOL(fd,k) = auction.auction_id;
safestrncpy((char*)WFIFOP(fd,4+k), auction.seller_name, NAME_LENGTH);
- if( (item = itemdb_exists(auction.item.nameid)) != NULL && item->view_id > 0 )
+ if( (item = itemdb->exists(auction.item.nameid)) != NULL && item->view_id > 0 )
WFIFOW(fd,28+k) = item->view_id;
else
WFIFOW(fd,28+k) = auction.item.nameid;
@@ -14863,6 +15255,9 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd)
int amount = RFIFOL(fd,4); // Always 1
struct item_data *item;
+ if( !battle_config.feature_auction )
+ return;
+
if( sd->auction.amount > 0 )
sd->auction.amount = 0;
@@ -14876,16 +15271,17 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd)
return;
}
- if( (item = itemdb_exists(sd->status.inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC) )
+ if( (item = itemdb->exists(sd->status.inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC) )
{ // Consumable or pets are not allowed
clif->auction_setitem(sd->fd, idx, true);
return;
}
- if( !pc->can_give_items(sd) || sd->status.inventory[idx].expire_time ||
+ if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time ||
!sd->status.inventory[idx].identify ||
- !itemdb_canauction(&sd->status.inventory[idx],pc->get_group_level(sd)) ) { // Quest Item or something else
- clif->auction_setitem(sd->fd, idx, true);
+ !itemdb_canauction(&sd->status.inventory[idx],pc_get_group_level(sd)) || // Quest Item or something else
+ (sd->status.inventory[idx].bound && !pc_can_give_bound_items(sd)) ) {
+ clif->auction_setitem(sd->fd, idx, true);
return;
}
@@ -14938,6 +15334,9 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
struct auction_data auction;
struct item_data *item;
+ if( !battle_config.feature_auction )
+ return;
+
auction.price = RFIFOL(fd,2);
auction.buynow = RFIFOL(fd,6);
auction.hours = RFIFOW(fd,10);
@@ -14958,9 +15357,8 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
return;
}
- // Auction checks...
if( sd->status.zeny < (auction.hours * battle_config.auction_feeperhour) ) {
- clif->auction_message(fd, 5); // You do not have enough zeny to pay the Auction Fee.
+ clif_Auction_message(fd, 5); // You do not have enough zeny to pay the Auction Fee.
return;
}
@@ -14983,19 +15381,26 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
return;
}
- if( (item = itemdb_exists(sd->status.inventory[sd->auction.index].nameid)) == NULL )
+ if( (item = itemdb->exists(sd->status.inventory[sd->auction.index].nameid)) == NULL )
{ // Just in case
clif->auction_message(fd, 2); // The auction has been canceled
return;
}
+ // Auction checks...
+ if( sd->status.inventory[sd->auction.index].bound && !pc_can_give_bound_items(sd) ) {
+ clif->message(sd->fd, msg_txt(293));
+ clif->auction_message(fd, 2); // The auction has been canceled
+ return;
+ }
+
safestrncpy(auction.item_name, item->jname, sizeof(auction.item_name));
auction.type = item->type;
memcpy(&auction.item, &sd->status.inventory[sd->auction.index], sizeof(struct item));
auction.item.amount = 1;
auction.timestamp = 0;
- if( !intif_Auction_register(&auction) )
+ if( !intif->Auction_register(&auction) )
clif->auction_message(fd, 4); // No Char Server? lets say something to the client
else
{
@@ -15015,7 +15420,7 @@ void clif_parse_Auction_cancel(int fd, struct map_session_data *sd)
{
unsigned int auction_id = RFIFOL(fd,2);
- intif_Auction_cancel(sd->status.char_id, auction_id);
+ intif->Auction_cancel(sd->status.char_id, auction_id);
}
@@ -15025,7 +15430,7 @@ void clif_parse_Auction_close(int fd, struct map_session_data *sd)
{
unsigned int auction_id = RFIFOL(fd,2);
- intif_Auction_close(sd->status.char_id, auction_id);
+ intif->Auction_close(sd->status.char_id, auction_id);
}
@@ -15036,7 +15441,7 @@ void clif_parse_Auction_bid(int fd, struct map_session_data *sd)
unsigned int auction_id = RFIFOL(fd,2);
int bid = RFIFOL(fd,6);
- if( !pc->can_give_items(sd) ) { //They aren't supposed to give zeny [Inkfish]
+ if( !pc_can_give_items(sd) ) { //They aren't supposed to give zeny [Inkfish]
clif->message(sd->fd, msg_txt(246));
return;
}
@@ -15045,11 +15450,11 @@ void clif_parse_Auction_bid(int fd, struct map_session_data *sd)
clif->auction_message(fd, 0); // You have failed to bid into the auction
else if( bid > sd->status.zeny )
clif->auction_message(fd, 8); // You do not have enough zeny
- else if ( CheckForCharServer() ) // char server is down (bugreport:1138)
+ else if ( intif->CheckForCharServer() ) // char server is down (bugreport:1138)
clif->auction_message(fd, 0); // You have failed to bid into the auction
else {
pc->payzeny(sd, bid, LOG_TYPE_AUCTION, NULL);
- intif_Auction_bid(sd->status.char_id, sd->status.name, auction_id, bid);
+ intif->Auction_bid(sd->status.char_id, sd->status.name, auction_id, bid);
}
}
@@ -15069,10 +15474,13 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd)
short type = RFIFOW(fd,2), page = RFIFOW(fd,32);
int price = RFIFOL(fd,4); // FIXME: bug #5071
+ if( !battle_config.feature_auction )
+ return;
+
clif->pAuction_cancelreg(fd, sd);
safestrncpy(search_text, (char*)RFIFOP(fd,8), sizeof(search_text));
- intif_Auction_requestlist(sd->status.char_id, type, price, search_text, page);
+ intif->Auction_requestlist(sd->status.char_id, type, price, search_text, page);
}
@@ -15084,9 +15492,13 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd)
void clif_parse_Auction_buysell(int fd, struct map_session_data* sd)
{
short type = RFIFOW(fd,2) + 6;
+
+ if( !battle_config.feature_auction )
+ return;
+
clif->pAuction_cancelreg(fd, sd);
- intif_Auction_requestlist(sd->status.char_id, type, 0, "", 1);
+ intif->Auction_requestlist(sd->status.char_id, type, 0, "", 1);
}
@@ -15096,9 +15508,11 @@ void clif_parse_Auction_buysell(int fd, struct map_session_data* sd)
/// List of items offered in a cash shop (ZC_PC_CASH_POINT_ITEMLIST).
/// 0287 <packet len>.W <cash point>.L { <sell price>.L <discount price>.L <item type>.B <name id>.W }*
/// 0287 <packet len>.W <cash point>.L <kafra point>.L { <sell price>.L <discount price>.L <item type>.B <name id>.W }* (PACKETVER >= 20070711)
-void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd)
-{
- int fd,i;
+void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) {
+ struct npc_item_list *shop = NULL;
+ unsigned short shop_size = 0;
+ int fd,i, c = 0;
+ int currency[2] = { 0,0 };
#if PACKETVER < 20070711
const int offset = 8;
#else
@@ -15108,50 +15522,71 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd)
nullpo_retv(sd);
nullpo_retv(nd);
+ if( nd->subtype == SCRIPT ) {
+ shop = nd->u.scr.shop->item;
+ shop_size = nd->u.scr.shop->items;
+
+ npc->trader_count_funds(nd, sd);
+
+ currency[0] = npc->trader_funds[0];
+ currency[1] = npc->trader_funds[1];
+ } else {
+ shop = nd->u.shop.shop_item;
+ shop_size = nd->u.shop.count;
+
+ currency[0] = sd->cashPoints;
+ currency[1] = sd->kafraPoints;
+ }
+
fd = sd->fd;
sd->npc_shopid = nd->bl.id;
- WFIFOHEAD(fd,offset+nd->u.shop.count*11);
+ WFIFOHEAD(fd,offset+shop_size*11);
WFIFOW(fd,0) = 0x287;
- WFIFOW(fd,2) = offset+nd->u.shop.count*11;
- WFIFOL(fd,4) = sd->cashPoints; // Cash Points
+ /* 0x2 = length, set after parsing */
+ WFIFOL(fd,4) = currency[0]; // Cash Points
#if PACKETVER >= 20070711
- WFIFOL(fd,8) = sd->kafraPoints; // Kafra Points
+ WFIFOL(fd,8) = currency[1]; // Kafra Points
#endif
- for( i = 0; i < nd->u.shop.count; i++ ) {
- struct item_data* id = itemdb_search(nd->u.shop.shop_item[i].nameid);
- WFIFOL(fd,offset+0+i*11) = nd->u.shop.shop_item[i].value;
- WFIFOL(fd,offset+4+i*11) = nd->u.shop.shop_item[i].value; // Discount Price
- WFIFOB(fd,offset+8+i*11) = itemtype(id->type);
- WFIFOW(fd,offset+9+i*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid;
+ for( i = 0; i < shop_size; i++ ) {
+ if( shop[i].nameid ) {
+ struct item_data* id = itemdb->search(shop[i].nameid);
+ WFIFOL(fd,offset+0+i*11) = shop[i].value;
+ WFIFOL(fd,offset+4+i*11) = shop[i].value; // Discount Price
+ WFIFOB(fd,offset+8+i*11) = itemtype(id->type);
+ WFIFOW(fd,offset+9+i*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid;
+ c++;
+ }
}
+ WFIFOW(fd,2) = offset+c*11;
WFIFOSET(fd,WFIFOW(fd,2));
}
-
/// Cashshop Buy Ack (ZC_PC_CASH_POINT_UPDATE).
/// 0289 <cash point>.L <error>.W
/// 0289 <cash point>.L <kafra point>.L <error>.W (PACKETVER >= 20070711)
-/// error:
-/// 0 = The deal has successfully completed. (ERROR_TYPE_NONE)
-/// 1 = The Purchase has failed because the NPC does not exist. (ERROR_TYPE_NPC)
-/// 2 = The Purchase has failed because the Kafra Shop System is not working correctly. (ERROR_TYPE_SYSTEM)
-/// 3 = You are over your Weight Limit. (ERROR_TYPE_INVENTORY_WEIGHT)
-/// 4 = You cannot purchase items while you are in a trade. (ERROR_TYPE_EXCHANGE)
-/// 5 = The Purchase has failed because the Item Information was incorrect. (ERROR_TYPE_ITEM_ID)
-/// 6 = You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY)
-/// 7 = You can purchase up to 10 items.
-/// 8 = Some items could not be purchased.
+/// For error return codes see enum cashshop_error@clif.h
void clif_cashshop_ack(struct map_session_data* sd, int error) {
- int fd = sd->fd;
+ struct npc_data *nd;
+ int fd = sd->fd;
+ int currency[2] = { 0,0 };
+
+ if( (nd = map->id2nd(sd->npc_shopid)) && nd->subtype == SCRIPT ) {
+ npc->trader_count_funds(nd,sd);
+ currency[0] = npc->trader_funds[0];
+ currency[1] = npc->trader_funds[1];
+ } else {
+ currency[0] = sd->cashPoints;
+ currency[1] = sd->kafraPoints;
+ }
WFIFOHEAD(fd, packet_len(0x289));
WFIFOW(fd,0) = 0x289;
- WFIFOL(fd,2) = sd->cashPoints;
+ WFIFOL(fd,2) = currency[0];
#if PACKETVER < 20070711
WFIFOW(fd,6) = TOW(error);
#else
- WFIFOL(fd,6) = sd->kafraPoints;
+ WFIFOL(fd,6) = currency[1];
WFIFOW(fd,10) = TOW(error);
#endif
WFIFOSET(fd, packet_len(0x289));
@@ -15175,7 +15610,7 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd)
short amount = RFIFOW(fd,4);
int points = RFIFOL(fd,6);
- fail = npc_cashshop_buy(sd, nameid, amount, points);
+ fail = npc->cashshop_buy(sd, nameid, amount, points);
#else
int len = RFIFOW(fd,2);
int points = RFIFOL(fd,4);
@@ -15187,7 +15622,7 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd)
ShowWarning("Player %u sent incorrect cash shop buy packet (len %u:%u)!\n", sd->status.char_id, len, 10 + count * 4);
return;
}
- fail = npc_cashshop_buylist(sd,points,count,item_list);
+ fail = npc->cashshop_buylist(sd,points,count,item_list);
#endif
}
@@ -15231,9 +15666,8 @@ void clif_Adopt_request(struct map_session_data *sd, struct map_session_data *sr
/// Request to adopt a player (CZ_REQ_JOIN_BABY).
/// 01f9 <account id>.L
-void clif_parse_Adopt_request(int fd, struct map_session_data *sd)
-{
- struct map_session_data *tsd = iMap->id2sd(RFIFOL(fd,2)), *p_sd = iMap->charid2sd(sd->status.partner_id);
+void clif_parse_Adopt_request(int fd, struct map_session_data *sd) {
+ struct map_session_data *tsd = map->id2sd(RFIFOL(fd,2)), *p_sd = map->charid2sd(sd->status.partner_id);
if( pc->can_Adopt(sd, p_sd, tsd) ) {
tsd->adopt_invite = sd->status.account_id;
@@ -15247,13 +15681,12 @@ void clif_parse_Adopt_request(int fd, struct map_session_data *sd)
/// answer:
/// 0 = rejected
/// 1 = accepted
-void clif_parse_Adopt_reply(int fd, struct map_session_data *sd)
-{
+void clif_parse_Adopt_reply(int fd, struct map_session_data *sd) {
int p1_id = RFIFOL(fd,2);
int p2_id = RFIFOL(fd,6);
int result = RFIFOL(fd,10);
- struct map_session_data* p1_sd = iMap->id2sd(p1_id);
- struct map_session_data* p2_sd = iMap->id2sd(p2_id);
+ struct map_session_data* p1_sd = map->id2sd(p1_id);
+ struct map_session_data* p2_sd = map->id2sd(p2_id);
int pid = sd->adopt_invite;
sd->adopt_invite = 0;
@@ -15293,11 +15726,11 @@ void clif_bossmapinfo(int fd, struct mob_data *md, short flag)
} else
WFIFOB(fd,2) = 2; // First Time
} else if (md->spawn_timer != INVALID_TIMER) { // Boss is Dead
- const struct TimerData * timer_data = iTimer->get_timer(md->spawn_timer);
+ const struct TimerData * timer_data = timer->get(md->spawn_timer);
unsigned int seconds;
int hours, minutes;
- seconds = DIFF_TICK(timer_data->tick, iTimer->gettick()) / 1000 + 60;
+ seconds = (unsigned int)(DIFF_TICK(timer_data->tick, timer->gettick()) / 1000 + 60);
hours = seconds / (60 * 60);
seconds = seconds - (60 * 60 * hours);
minutes = seconds / 60;
@@ -15315,10 +15748,9 @@ void clif_bossmapinfo(int fd, struct mob_data *md, short flag)
/// Requesting equip of a player (CZ_EQUIPWIN_MICROSCOPE).
/// 02d6 <account id>.L
-void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd)
-{
+void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) {
int charid = RFIFOL(fd, 2);
- struct map_session_data* tsd = iMap->id2sd(charid);
+ struct map_session_data* tsd = map->id2sd(charid);
if (!tsd)
return;
@@ -15326,7 +15758,7 @@ void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd)
if( tsd->status.show_equip || pc_has_permission(sd, PC_PERM_VIEW_EQUIPMENT) )
clif->viewequip_ack(sd, tsd);
else
- clif->viewequip_fail(sd);
+ clif_viewequip_fail(sd);
}
@@ -15360,8 +15792,7 @@ void clif_parse_PartyTick(int fd, struct map_session_data* sd)
/// Sends list of all quest states (ZC_ALL_QUEST_LIST).
/// 02b1 <packet len>.W <num>.L { <quest id>.L <active>.B }*num
-void clif_quest_send_list(struct map_session_data * sd)
-{
+void clif_quest_send_list(struct map_session_data *sd) {
int fd = sd->fd;
int i;
int len = sd->avail_quests*5+8;
@@ -15382,12 +15813,11 @@ void clif_quest_send_list(struct map_session_data * sd)
/// Sends list of all quest missions (ZC_ALL_QUEST_MISSION).
/// 02b2 <packet len>.W <num>.L { <quest id>.L <start time>.L <expire time>.L <mobs>.W { <mob id>.L <mob count>.W <mob name>.24B }*3 }*num
-void clif_quest_send_mission(struct map_session_data * sd)
-{
+void clif_quest_send_mission(struct map_session_data *sd) {
int fd = sd->fd;
int i, j;
int len = sd->avail_quests*104+8;
- struct mob_db *mob;
+ struct mob_db *monster;
WFIFOHEAD(fd, len);
WFIFOW(fd, 0) = 0x2b2;
@@ -15395,17 +15825,17 @@ void clif_quest_send_mission(struct map_session_data * sd)
WFIFOL(fd, 4) = sd->avail_quests;
for( i = 0; i < sd->avail_quests; i++ ) {
+ struct quest_db *qi = quest->db(sd->quest_log[i].quest_id);
WFIFOL(fd, i*104+8) = sd->quest_log[i].quest_id;
- WFIFOL(fd, i*104+12) = sd->quest_log[i].time - quest_db[sd->quest_index[i]].time;
+ WFIFOL(fd, i*104+12) = sd->quest_log[i].time - qi->time;
WFIFOL(fd, i*104+16) = sd->quest_log[i].time;
- WFIFOW(fd, i*104+20) = quest_db[sd->quest_index[i]].num_objectives;
+ WFIFOW(fd, i*104+20) = qi->num_objectives;
- for( j = 0 ; j < quest_db[sd->quest_index[i]].num_objectives; j++ )
- {
- WFIFOL(fd, i*104+22+j*30) = quest_db[sd->quest_index[i]].mob[j];
+ for( j = 0 ; j < qi->num_objectives; j++ ) {
+ WFIFOL(fd, i*104+22+j*30) = qi->mob[j];
WFIFOW(fd, i*104+26+j*30) = sd->quest_log[i].count[j];
- mob = mob_db(quest_db[sd->quest_index[i]].mob[j]);
- memcpy(WFIFOP(fd, i*104+28+j*30), mob?mob->jname:"NULL", NAME_LENGTH);
+ monster = mob->db(qi->mob[j]);
+ memcpy(WFIFOP(fd, i*104+28+j*30), monster->jname, NAME_LENGTH);
}
}
@@ -15415,25 +15845,25 @@ void clif_quest_send_mission(struct map_session_data * sd)
/// Notification about a new quest (ZC_ADD_QUEST).
/// 02b3 <quest id>.L <active>.B <start time>.L <expire time>.L <mobs>.W { <mob id>.L <mob count>.W <mob name>.24B }*3
-void clif_quest_add(struct map_session_data * sd, struct quest * qd, int index)
-{
+void clif_quest_add(struct map_session_data *sd, struct quest *qd) {
int fd = sd->fd;
int i;
- struct mob_db *mob;
+ struct mob_db *monster;
+ struct quest_db *qi = quest->db(qd->quest_id);
WFIFOHEAD(fd, packet_len(0x2b3));
WFIFOW(fd, 0) = 0x2b3;
WFIFOL(fd, 2) = qd->quest_id;
WFIFOB(fd, 6) = qd->state;
- WFIFOB(fd, 7) = qd->time - quest_db[index].time;
+ WFIFOB(fd, 7) = qd->time - qi->time;
WFIFOL(fd, 11) = qd->time;
- WFIFOW(fd, 15) = quest_db[index].num_objectives;
+ WFIFOW(fd, 15) = qi->num_objectives;
- for( i = 0; i < quest_db[index].num_objectives; i++ ) {
- WFIFOL(fd, i*30+17) = quest_db[index].mob[i];
+ for( i = 0; i < qi->num_objectives; i++ ) {
+ WFIFOL(fd, i*30+17) = qi->mob[i];
WFIFOW(fd, i*30+21) = qd->count[i];
- mob = mob_db(quest_db[index].mob[i]);
- memcpy(WFIFOP(fd, i*30+23), mob?mob->jname:"NULL", NAME_LENGTH);
+ monster = mob->db(qi->mob[i]);
+ memcpy(WFIFOP(fd, i*30+23), monster->jname, NAME_LENGTH);
}
WFIFOSET(fd, packet_len(0x2b3));
@@ -15442,8 +15872,7 @@ void clif_quest_add(struct map_session_data * sd, struct quest * qd, int index)
/// Notification about a quest being removed (ZC_DEL_QUEST).
/// 02b4 <quest id>.L
-void clif_quest_delete(struct map_session_data * sd, int quest_id)
-{
+void clif_quest_delete(struct map_session_data *sd, int quest_id) {
int fd = sd->fd;
WFIFOHEAD(fd, packet_len(0x2b4));
@@ -15455,21 +15884,21 @@ void clif_quest_delete(struct map_session_data * sd, int quest_id)
/// Notification of an update to the hunting mission counter (ZC_UPDATE_MISSION_HUNT).
/// 02b5 <packet len>.W <mobs>.W { <quest id>.L <mob id>.L <total count>.W <current count>.W }*3
-void clif_quest_update_objective(struct map_session_data * sd, struct quest * qd, int index)
-{
+void clif_quest_update_objective(struct map_session_data *sd, struct quest *qd) {
int fd = sd->fd;
int i;
- int len = quest_db[index].num_objectives*12+6;
+ struct quest_db *qi = quest->db(qd->quest_id);
+ int len = qi->num_objectives*12+6;
WFIFOHEAD(fd, len);
WFIFOW(fd, 0) = 0x2b5;
WFIFOW(fd, 2) = len;
- WFIFOW(fd, 4) = quest_db[index].num_objectives;
+ WFIFOW(fd, 4) = qi->num_objectives;
- for( i = 0; i < quest_db[index].num_objectives; i++ ) {
+ for( i = 0; i < qi->num_objectives; i++ ) {
WFIFOL(fd, i*12+6) = qd->quest_id;
- WFIFOL(fd, i*12+10) = quest_db[index].mob[i];
- WFIFOW(fd, i*12+14) = quest_db[index].count[i];
+ WFIFOL(fd, i*12+10) = qi->mob[i];
+ WFIFOW(fd, i*12+14) = qi->count[i];
WFIFOW(fd, i*12+16) = qd->count[i];
}
@@ -15479,16 +15908,14 @@ void clif_quest_update_objective(struct map_session_data * sd, struct quest * qd
/// Request to change the state of a quest (CZ_ACTIVE_QUEST).
/// 02b6 <quest id>.L <active>.B
-void clif_parse_questStateAck(int fd, struct map_session_data * sd)
-{
- quest_update_status(sd, RFIFOL(fd,2), RFIFOB(fd,6)?Q_ACTIVE:Q_INACTIVE);
+void clif_parse_questStateAck(int fd, struct map_session_data *sd) {
+ quest->update_status(sd, RFIFOL(fd,2), RFIFOB(fd,6)?Q_ACTIVE:Q_INACTIVE);
}
/// Notification about the change of a quest state (ZC_ACTIVE_QUEST).
/// 02b7 <quest id>.L <active>.B
-void clif_quest_update_status(struct map_session_data * sd, int quest_id, bool active)
-{
+void clif_quest_update_status(struct map_session_data *sd, int quest_id, bool active) {
int fd = sd->fd;
WFIFOHEAD(fd, packet_len(0x2b7));
@@ -15532,64 +15959,63 @@ void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, s
/// Notification about a mercenary status parameter change (ZC_MER_PAR_CHANGE).
/// 02a2 <var id>.W <value>.L
-void clif_mercenary_updatestatus(struct map_session_data *sd, int type)
-{
+void clif_mercenary_updatestatus(struct map_session_data *sd, int type) {
struct mercenary_data *md;
- struct status_data *status;
+ struct status_data *mstatus;
int fd;
if( sd == NULL || (md = sd->md) == NULL )
return;
fd = sd->fd;
- status = &md->battle_status;
+ mstatus = &md->battle_status;
WFIFOHEAD(fd,packet_len(0x2a2));
WFIFOW(fd,0) = 0x2a2;
WFIFOW(fd,2) = type;
switch( type ) {
case SP_ATK1:
- {
- int atk = rnd()%(status->rhw.atk2 - status->rhw.atk + 1) + status->rhw.atk;
- WFIFOL(fd,4) = cap_value(atk, 0, INT16_MAX);
- }
+ {
+ int atk = rnd()%(mstatus->rhw.atk2 - mstatus->rhw.atk + 1) + mstatus->rhw.atk;
+ WFIFOL(fd,4) = cap_value(atk, 0, INT16_MAX);
+ }
break;
case SP_MATK1:
- WFIFOL(fd,4) = cap_value(status->matk_max, 0, INT16_MAX);
+ WFIFOL(fd,4) = cap_value(mstatus->matk_max, 0, INT16_MAX);
break;
case SP_HIT:
- WFIFOL(fd,4) = status->hit;
+ WFIFOL(fd,4) = mstatus->hit;
break;
case SP_CRITICAL:
- WFIFOL(fd,4) = status->cri/10;
+ WFIFOL(fd,4) = mstatus->cri/10;
break;
case SP_DEF1:
- WFIFOL(fd,4) = status->def;
+ WFIFOL(fd,4) = mstatus->def;
break;
case SP_MDEF1:
- WFIFOL(fd,4) = status->mdef;
+ WFIFOL(fd,4) = mstatus->mdef;
break;
case SP_MERCFLEE:
- WFIFOL(fd,4) = status->flee;
+ WFIFOL(fd,4) = mstatus->flee;
break;
case SP_ASPD:
- WFIFOL(fd,4) = status->amotion;
+ WFIFOL(fd,4) = mstatus->amotion;
break;
case SP_HP:
- WFIFOL(fd,4) = status->hp;
+ WFIFOL(fd,4) = mstatus->hp;
break;
case SP_MAXHP:
- WFIFOL(fd,4) = status->max_hp;
+ WFIFOL(fd,4) = mstatus->max_hp;
break;
case SP_SP:
- WFIFOL(fd,4) = status->sp;
+ WFIFOL(fd,4) = mstatus->sp;
break;
case SP_MAXSP:
- WFIFOL(fd,4) = status->max_sp;
+ WFIFOL(fd,4) = mstatus->max_sp;
break;
case SP_MERCKILLS:
WFIFOL(fd,4) = md->mercenary.kill_count;
break;
case SP_MERCFAITH:
- WFIFOL(fd,4) = mercenary_get_faith(md);
+ WFIFOL(fd,4) = mercenary->get_faith(md);
break;
}
WFIFOSET(fd,packet_len(0x2a2));
@@ -15600,42 +16026,41 @@ void clif_mercenary_updatestatus(struct map_session_data *sd, int type)
/// 029b <id>.L <atk>.W <matk>.W <hit>.W <crit>.W <def>.W <mdef>.W <flee>.W <aspd>.W
/// <name>.24B <level>.W <hp>.L <maxhp>.L <sp>.L <maxsp>.L <expire time>.L <faith>.W
/// <calls>.L <kills>.L <atk range>.W
-void clif_mercenary_info(struct map_session_data *sd)
-{
+void clif_mercenary_info(struct map_session_data *sd) {
int fd;
struct mercenary_data *md;
- struct status_data *status;
+ struct status_data *mstatus;
int atk;
if( sd == NULL || (md = sd->md) == NULL )
return;
fd = sd->fd;
- status = &md->battle_status;
+ mstatus = &md->battle_status;
WFIFOHEAD(fd,packet_len(0x29b));
WFIFOW(fd,0) = 0x29b;
WFIFOL(fd,2) = md->bl.id;
// Mercenary shows ATK as a random value between ATK ~ ATK2
- atk = rnd()%(status->rhw.atk2 - status->rhw.atk + 1) + status->rhw.atk;
+ atk = rnd()%(mstatus->rhw.atk2 - mstatus->rhw.atk + 1) + mstatus->rhw.atk;
WFIFOW(fd,6) = cap_value(atk, 0, INT16_MAX);
- WFIFOW(fd,8) = cap_value(status->matk_max, 0, INT16_MAX);
- WFIFOW(fd,10) = status->hit;
- WFIFOW(fd,12) = status->cri/10;
- WFIFOW(fd,14) = status->def;
- WFIFOW(fd,16) = status->mdef;
- WFIFOW(fd,18) = status->flee;
- WFIFOW(fd,20) = status->amotion;
+ WFIFOW(fd,8) = cap_value(mstatus->matk_max, 0, INT16_MAX);
+ WFIFOW(fd,10) = mstatus->hit;
+ WFIFOW(fd,12) = mstatus->cri/10;
+ WFIFOW(fd,14) = mstatus->def;
+ WFIFOW(fd,16) = mstatus->mdef;
+ WFIFOW(fd,18) = mstatus->flee;
+ WFIFOW(fd,20) = mstatus->amotion;
safestrncpy((char*)WFIFOP(fd,22), md->db->name, NAME_LENGTH);
WFIFOW(fd,46) = md->db->lv;
- WFIFOL(fd,48) = status->hp;
- WFIFOL(fd,52) = status->max_hp;
- WFIFOL(fd,56) = status->sp;
- WFIFOL(fd,60) = status->max_sp;
- WFIFOL(fd,64) = (int)time(NULL) + (mercenary_get_lifetime(md) / 1000);
- WFIFOW(fd,68) = mercenary_get_faith(md);
- WFIFOL(fd,70) = mercenary_get_calls(md);
+ WFIFOL(fd,48) = mstatus->hp;
+ WFIFOL(fd,52) = mstatus->max_hp;
+ WFIFOL(fd,56) = mstatus->sp;
+ WFIFOL(fd,60) = mstatus->max_sp;
+ WFIFOL(fd,64) = (int)time(NULL) + (mercenary->get_lifetime(md) / 1000);
+ WFIFOW(fd,68) = mercenary->get_faith(md);
+ WFIFOL(fd,70) = mercenary->get_calls(md);
WFIFOL(fd,74) = md->mercenary.kill_count;
WFIFOW(fd,78) = md->battle_status.rhw.range;
WFIFOSET(fd,packet_len(0x29b));
@@ -15643,7 +16068,7 @@ void clif_mercenary_info(struct map_session_data *sd)
/// Mercenary skill tree (ZC_MER_SKILLINFO_LIST).
-/// 029d <packet len>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.B }*
+/// 029d <packet len>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradeable>.B }*
void clif_mercenary_skillblock(struct map_session_data *sd)
{
struct mercenary_data *md;
@@ -15685,7 +16110,7 @@ void clif_parse_mercenary_action(int fd, struct map_session_data* sd)
if( sd->md == NULL )
return;
- if( option == 2 ) merc_delete(sd->md, 2);
+ if( option == 2 ) mercenary->delete(sd->md, 2);
}
@@ -15802,11 +16227,11 @@ void clif_bg_xy_remove(struct map_session_data *sd)
/// Notifies clients of a battleground message (ZC_BATTLEFIELD_CHAT).
/// 02dc <packet len>.W <account id>.L <name>.24B <message>.?B
-void clif_bg_message(struct battleground_data *bg, int src_id, const char *name, const char *mes, int len)
+void clif_bg_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes, size_t len)
{
struct map_session_data *sd;
unsigned char *buf;
- if( (sd = bg_getavailablesd(bg)) == NULL )
+ if( !bgd->count || (sd = bg->getavailablesd(bgd)) == NULL )
return;
buf = (unsigned char*)aMalloc((len + NAME_LENGTH + 8)*sizeof(unsigned char));
@@ -15831,31 +16256,33 @@ void clif_parse_BattleChat(int fd, struct map_session_data* sd)
int textlen = RFIFOW(fd,2) - 4;
char *name, *message;
- int namelen, messagelen;
+ size_t namelen, messagelen;
if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
return;
- if( atcommand->parse(fd, sd, message, 1) )
+ if( atcommand->exec(fd, sd, message, true) )
return;
- if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
+ if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
return;
if( battle_config.min_chat_delay ) {
- if( DIFF_TICK(sd->cantalk_tick, iTimer->gettick()) > 0 )
+ if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 )
return;
- sd->cantalk_tick = iTimer->gettick() + battle_config.min_chat_delay;
+ sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
- bg_send_message(sd, text, textlen);
+ if( battle_config.idletime_criteria & BCIDLE_CHAT )
+ sd->idletime = sockt->last_tick;
+
+ bg->send_message(sd, text, textlen);
}
/// Notifies client of a battleground score change (ZC_BATTLEFIELD_NOTIFY_POINT).
/// 02de <camp A points>.W <camp B points>.W
-void clif_bg_updatescore(int16 m)
-{
+void clif_bg_updatescore(int16 m) {
struct block_list bl;
unsigned char buf[6];
@@ -15864,21 +16291,20 @@ void clif_bg_updatescore(int16 m)
bl.m = m;
WBUFW(buf,0) = 0x2de;
- WBUFW(buf,2) = map[m].bgscore_lion;
- WBUFW(buf,4) = map[m].bgscore_eagle;
+ WBUFW(buf,2) = map->list[m].bgscore_lion;
+ WBUFW(buf,4) = map->list[m].bgscore_eagle;
clif->send(buf,packet_len(0x2de),&bl,ALL_SAMEMAP);
}
-void clif_bg_updatescore_single(struct map_session_data *sd)
-{
+void clif_bg_updatescore_single(struct map_session_data *sd) {
int fd;
nullpo_retv(sd);
fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x2de));
WFIFOW(fd,0) = 0x2de;
- WFIFOW(fd,2) = map[sd->bl.m].bgscore_lion;
- WFIFOW(fd,4) = map[sd->bl.m].bgscore_eagle;
+ WFIFOW(fd,2) = map->list[sd->bl.m].bgscore_lion;
+ WFIFOW(fd,4) = map->list[sd->bl.m].bgscore_eagle;
WFIFOSET(fd,packet_len(0x2de));
}
@@ -15918,7 +16344,7 @@ void clif_font(struct map_session_data *sd)
nullpo_retv(sd);
WBUFW(buf,0) = 0x2ef;
WBUFL(buf,2) = sd->bl.id;
- WBUFW(buf,6) = sd->user_font;
+ WBUFW(buf,6) = sd->status.font;
clif->send(buf, packet_len(0x2ef), &sd->bl, AREA);
#endif
}
@@ -15931,34 +16357,34 @@ int clif_instance(int instance_id, int type, int flag) {
struct map_session_data *sd = NULL;
unsigned char buf[255];
enum send_target target = PARTY;
-
- switch( instances[instance_id].owner_type ) {
+
+ switch( instance->list[instance_id].owner_type ) {
case IOT_NONE:
return 0;
case IOT_GUILD:
target = GUILD;
- sd = guild->getavailablesd(guild->search(instances[instance_id].owner_id));
+ sd = guild->getavailablesd(guild->search(instance->list[instance_id].owner_id));
break;
case IOT_PARTY:
/* default is already PARTY */
- sd = party->getavailablesd(party->search(instances[instance_id].owner_id));
+ sd = party->getavailablesd(party->search(instance->list[instance_id].owner_id));
break;
case IOT_CHAR:
target = SELF;
- sd = iMap->id2sd(instances[instance_id].owner_id);
+ sd = map->id2sd(instance->list[instance_id].owner_id);
break;
}
if( !sd )
return 0;
-
+
switch( type ) {
case 1:
// S 0x2cb <Instance name>.61B <Standby Position>.W
// Required to start the instancing information window on Client
// This window re-appear each "refresh" of client automatically until type 4 is send to client.
WBUFW(buf,0) = 0x02CB;
- memcpy(WBUFP(buf,2),instances[instance_id].name,INSTANCE_NAME_LENGTH);
+ memcpy(WBUFP(buf,2),instance->list[instance_id].name,INSTANCE_NAME_LENGTH);
WBUFW(buf,63) = flag;
clif->send(buf,packet_len(0x02CB),&sd->bl,target);
break;
@@ -15973,13 +16399,13 @@ int clif_instance(int instance_id, int type, int flag) {
case 4:
// S 0x2cd <Instance Name>.61B <Instance Remaining Time>.L <Instance Noplayers close time>.L
WBUFW(buf,0) = 0x02CD;
- memcpy(WBUFP(buf,2),instances[instance_id].name,61);
+ memcpy(WBUFP(buf,2),instance->list[instance_id].name,61);
if( type == 3 ) {
- WBUFL(buf,63) = instances[instance_id].progress_timeout;
+ WBUFL(buf,63) = instance->list[instance_id].progress_timeout;
WBUFL(buf,67) = 0;
} else {
WBUFL(buf,63) = 0;
- WBUFL(buf,67) = instances[instance_id].idle_timeout;
+ WBUFL(buf,67) = instance->list[instance_id].idle_timeout;
}
clif->send(buf,packet_len(0x02CD),&sd->bl,target);
break;
@@ -16001,24 +16427,24 @@ int clif_instance(int instance_id, int type, int flag) {
void clif_instance_join(int fd, int instance_id)
{
- if( instances[instance_id].idle_timer != INVALID_TIMER ) {
+ if( instance->list[instance_id].idle_timer != INVALID_TIMER ) {
WFIFOHEAD(fd,packet_len(0x02CD));
WFIFOW(fd,0) = 0x02CD;
- memcpy(WFIFOP(fd,2),instances[instance_id].name,61);
+ memcpy(WFIFOP(fd,2),instance->list[instance_id].name,61);
WFIFOL(fd,63) = 0;
- WFIFOL(fd,67) = instances[instance_id].idle_timeout;
+ WFIFOL(fd,67) = instance->list[instance_id].idle_timeout;
WFIFOSET(fd,packet_len(0x02CD));
- } else if( instances[instance_id].progress_timer != INVALID_TIMER ) {
+ } else if( instance->list[instance_id].progress_timer != INVALID_TIMER ) {
WFIFOHEAD(fd,packet_len(0x02CD));
WFIFOW(fd,0) = 0x02CD;
- memcpy(WFIFOP(fd,2),instances[instance_id].name,61);
- WFIFOL(fd,63) = instances[instance_id].progress_timeout;
+ memcpy(WFIFOP(fd,2),instance->list[instance_id].name,61);
+ WFIFOL(fd,63) = instance->list[instance_id].progress_timeout;
WFIFOL(fd,67) = 0;
WFIFOSET(fd,packet_len(0x02CD));
} else {
WFIFOHEAD(fd,packet_len(0x02CB));
WFIFOW(fd,0) = 0x02CB;
- memcpy(WFIFOP(fd,2),instances[instance_id].name,61);
+ memcpy(WFIFOP(fd,2),instance->list[instance_id].name,61);
WFIFOW(fd,63) = 0;
WFIFOSET(fd,packet_len(0x02CB));
}
@@ -16039,7 +16465,7 @@ void clif_party_show_picker(struct map_session_data * sd, struct item * item_dat
{
#if PACKETVER >= 20071002
unsigned char buf[22];
- struct item_data* id = itemdb_search(item_data->nameid);
+ struct item_data* id = itemdb->search(item_data->nameid);
WBUFW(buf,0) = 0x2b8;
WBUFL(buf,2) = sd->status.account_id;
@@ -16062,8 +16488,7 @@ void clif_party_show_picker(struct map_session_data * sd, struct item * item_dat
/// exp type:
/// 0 = normal exp gain/loss
/// 1 = quest exp gain/loss
-void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool quest)
-{
+void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool is_quest) {
int fd;
nullpo_retv(sd);
@@ -16075,7 +16500,7 @@ void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, b
WFIFOL(fd,2) = sd->bl.id;
WFIFOL(fd,6) = exp;
WFIFOW(fd,10) = type;
- WFIFOW(fd,12) = quest?1:0;// Normal exp is shown in yellow, quest exp is shown in purple.
+ WFIFOW(fd,12) = is_quest?1:0;// Normal exp is shown in yellow, quest exp is shown in purple.
WFIFOSET(fd,packet_len(0x7f6));
}
@@ -16156,29 +16581,29 @@ void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) {
*==========================================*/
void clif_elemental_updatestatus(struct map_session_data *sd, int type) {
struct elemental_data *ed;
- struct status_data *status;
+ struct status_data *estatus;
int fd;
if( sd == NULL || (ed = sd->ed) == NULL )
return;
fd = sd->fd;
- status = &ed->battle_status;
+ estatus = &ed->battle_status;
WFIFOHEAD(fd,8);
WFIFOW(fd,0) = 0x81e;
WFIFOW(fd,2) = type;
switch( type ) {
case SP_HP:
- WFIFOL(fd,4) = status->hp;
+ WFIFOL(fd,4) = estatus->hp;
break;
case SP_MAXHP:
- WFIFOL(fd,4) = status->max_hp;
+ WFIFOL(fd,4) = estatus->max_hp;
break;
case SP_SP:
- WFIFOL(fd,4) = status->sp;
+ WFIFOL(fd,4) = estatus->sp;
break;
case SP_MAXSP:
- WFIFOL(fd,4) = status->max_sp;
+ WFIFOL(fd,4) = estatus->max_sp;
break;
}
WFIFOSET(fd,8);
@@ -16187,21 +16612,21 @@ void clif_elemental_updatestatus(struct map_session_data *sd, int type) {
void clif_elemental_info(struct map_session_data *sd) {
int fd;
struct elemental_data *ed;
- struct status_data *status;
+ struct status_data *estatus;
if( sd == NULL || (ed = sd->ed) == NULL )
return;
fd = sd->fd;
- status = &ed->battle_status;
+ estatus = &ed->battle_status;
WFIFOHEAD(fd,22);
WFIFOW(fd, 0) = 0x81d;
WFIFOL(fd, 2) = ed->bl.id;
- WFIFOL(fd, 6) = status->hp;
- WFIFOL(fd,10) = status->max_hp;
- WFIFOL(fd,14) = status->sp;
- WFIFOL(fd,18) = status->max_sp;
+ WFIFOL(fd, 6) = estatus->hp;
+ WFIFOL(fd,10) = estatus->max_hp;
+ WFIFOL(fd,14) = estatus->sp;
+ WFIFOL(fd,18) = estatus->max_sp;
WFIFOSET(fd,22);
}
@@ -16709,7 +17134,7 @@ void clif_parse_debug(int fd,struct map_session_data *sd) {
}
ShowDebug("Packet debug of 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id);
} else {
- packet_len = RFIFOREST(fd);
+ packet_len = (int)RFIFOREST(fd);
ShowDebug("Packet debug of 0x%04X (length %d), session #%d\n", cmd, packet_len, fd);
}
@@ -16717,7 +17142,7 @@ void clif_parse_debug(int fd,struct map_session_data *sd) {
}
/*==========================================
* Server tells client to display a window similar to Magnifier (item) one
- * Server populates the window with avilable elemental converter options according to player's inventory
+ * Server populates the window with available elemental converter options according to player's inventory
*------------------------------------------*/
int clif_elementalconverter_list(struct map_session_data *sd) {
int i,c,view,fd;
@@ -16731,11 +17156,11 @@ int clif_elementalconverter_list(struct map_session_data *sd) {
WFIFOW(fd, 0)=0x1ad;
for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){
- if( skill->can_produce_mix(sd,skill_produce_db[i].nameid,23, 1) ){
- if((view = itemdb_viewid(skill_produce_db[i].nameid)) > 0)
+ if( skill->can_produce_mix(sd,skill->produce_db[i].nameid,23, 1) ){
+ if((view = itemdb_viewid(skill->produce_db[i].nameid)) > 0)
WFIFOW(fd,c*2+ 4)= view;
else
- WFIFOW(fd,c*2+ 4)= skill_produce_db[i].nameid;
+ WFIFOW(fd,c*2+ 4)= skill->produce_db[i].nameid;
c++;
}
}
@@ -16751,15 +17176,15 @@ int clif_elementalconverter_list(struct map_session_data *sd) {
/**
* Rune Knight
**/
-void clif_millenniumshield(struct map_session_data *sd, short shields ) {
+void clif_millenniumshield(struct block_list *bl, short shields ) {
#if PACKETVER >= 20081217
unsigned char buf[10];
WBUFW(buf,0) = 0x440;
- WBUFL(buf,2) = sd->bl.id;
+ WBUFL(buf,2) = bl->id;
WBUFW(buf,6) = shields;
WBUFW(buf,8) = 0;
- clif->send(buf,packet_len(0x440),&sd->bl,AREA);
+ clif->send(buf,packet_len(0x440),bl,AREA);
#endif
}
/**
@@ -17021,73 +17446,68 @@ void clif_parse_MoveItem(int fd, struct map_session_data *sd) {
/* [Ind/Hercules] */
void clif_cashshop_db(void) {
config_t cashshop_conf;
- config_setting_t *cashshop = NULL;
+ config_setting_t *cashshop = NULL, *cats = NULL;
const char *config_filename = "db/cashshop_db.conf"; // FIXME hardcoded name
- int i;
+ int i, item_count_t = 0;
for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) {
CREATE(clif->cs.data[i], struct hCSData *, 1);
clif->cs.item_count[i] = 0;
}
-
- if (conf_read_file(&cashshop_conf, config_filename)) {
+
+ if (libconfig->read_file(&cashshop_conf, config_filename)) {
ShowError("can't read %s\n", config_filename);
return;
}
-
- cashshop = config_lookup(&cashshop_conf, "cash_shop");
-
- if (cashshop != NULL) {
- config_setting_t *cats = config_setting_get_elem(cashshop, 0);
- config_setting_t *cat;
- int k, item_count_t = 0;
-
+
+ cashshop = libconfig->lookup(&cashshop_conf, "cash_shop");
+
+ if( cashshop != NULL && (cats = libconfig->setting_get_elem(cashshop, 0)) != NULL ) {
for(i = 0; i < CASHSHOP_TAB_MAX; i++) {
+ config_setting_t *cat;
char entry_name[10];
-
+
sprintf(entry_name,"cat_%d",i);
-
- if( (cat = config_setting_get_member(cats, entry_name)) != NULL ) {
- int item_count = config_setting_length(cat);
-
+
+ if( (cat = libconfig->setting_get_member(cats, entry_name)) != NULL ) {
+ int k, item_count = libconfig->setting_length(cat);
+
for(k = 0; k < item_count; k++) {
- config_setting_t *entry = config_setting_get_elem(cat,k);
+ config_setting_t *entry = libconfig->setting_get_elem(cat,k);
const char *name = config_setting_name(entry);
- int price = config_setting_get_int(entry);
+ int price = libconfig->setting_get_int(entry);
struct item_data * data = NULL;
-
+
if( price < 1 ) {
ShowWarning("cashshop_db: unsupported price '%d' for entry named '%s' in category '%s'\n", price, name, entry_name);
continue;
}
-
+
if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) {
- if( !( data = itemdb_exists(atoi(name+2))) ) {
+ if( !( data = itemdb->exists(atoi(name+2))) ) {
ShowWarning("cashshop_db: unknown item id '%s' in category '%s'\n", name+2, entry_name);
continue;
}
} else {
- if( !( data = itemdb_searchname(name) ) ) {
+ if( !( data = itemdb->search_name(name) ) ) {
ShowWarning("cashshop_db: unknown item name '%s' in category '%s'\n", name, entry_name);
continue;
}
}
-
-
+
+
RECREATE(clif->cs.data[i], struct hCSData *, ++clif->cs.item_count[i]);
CREATE(clif->cs.data[i][ clif->cs.item_count[i] - 1 ], struct hCSData , 1);
-
+
clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->id = data->nameid;
clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->price = price;
item_count_t++;
}
- } else {
- ShowError("cashshop_db: category '%s' (%d) not found!!\n",entry_name,i);
}
}
-
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", item_count_t, config_filename);
- config_destroy(&cashshop_conf);
+
+ libconfig->destroy(&cashshop_conf);
}
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", item_count_t, config_filename);
}
/// Items that are in favorite tab of inventory (ZC_ITEM_FAVORITE).
/// 0900 <index>.W <favorite>.B
@@ -17114,25 +17534,30 @@ void clif_snap( struct block_list *bl, short x, short y ) {
void clif_monster_hp_bar( struct mob_data* md, struct map_session_data *sd ) {
struct packet_monster_hp p;
-
+
p.PacketType = monsterhpType;
p.GID = md->bl.id;
p.HP = md->status.hp;
p.MaxHP = md->status.max_hp;
-
+
clif->send(&p,sizeof(p),&sd->bl,SELF);
}
/* [Ind/Hercules] placeholder for unsupported incoming packets (avoids server disconnecting client) */
void __attribute__ ((unused)) clif_parse_dull(int fd,struct map_session_data *sd) {
return;
}
-
void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) {
+
+ if( map->list[sd->bl.m].flag.nocashshop ) {
+ clif->colormes(fd,COLOR_RED,msg_txt(1489)); //Cash Shop is disabled in this map
+ return;
+ }
+
WFIFOHEAD(fd, 10);
WFIFOW(fd, 0) = 0x845;
WFIFOL(fd, 2) = sd->cashPoints; //[Ryuuzaki] - switched positions to reflect proper values
WFIFOL(fd, 6) = sd->kafraPoints;
- WFIFOSET(fd, 10);
+ WFIFOSET(fd, 10);
}
void clif_parse_CashShopClose(int fd, struct map_session_data *sd) {
@@ -17141,35 +17566,43 @@ void clif_parse_CashShopClose(int fd, struct map_session_data *sd) {
void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) {
int i, j = 0;
-
+
for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) {
+ if( clif->cs.item_count[i] == 0 )
+ continue; // Skip empty tabs, the client only expects filled ones
+
WFIFOHEAD(fd, 8 + ( clif->cs.item_count[i] * 6 ) );
WFIFOW(fd, 0) = 0x8ca;
WFIFOW(fd, 2) = 8 + ( clif->cs.item_count[i] * 6 );
WFIFOW(fd, 4) = clif->cs.item_count[i];
WFIFOW(fd, 6) = i;
-
+
for( j = 0; j < clif->cs.item_count[i]; j++ ) {
WFIFOW(fd, 8 + ( 6 * j ) ) = clif->cs.data[i][j]->id;
WFIFOL(fd, 10 + ( 6 * j ) ) = clif->cs.data[i][j]->price;
}
-
+
WFIFOSET(fd, 8 + ( clif->cs.item_count[i] * 6 ));
}
}
void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) {
unsigned short limit = RFIFOW(fd, 4), i, j;
- unsigned int kafra_pay = RFIFOL(fd, 6);// [Ryuuzaki] - These are free cash points (strangely #CASH = main cash curreny for us, confusing)
+ unsigned int kafra_pay = RFIFOL(fd, 6);// [Ryuuzaki] - These are free cash points (strangely #CASH = main cash currently for us, confusing)
+
+ if( map->list[sd->bl.m].flag.nocashshop ) {
+ clif->colormes(fd,COLOR_RED,msg_txt(1489)); //Cash Shop is disabled in this map
+ return;
+ }
for(i = 0; i < limit; i++) {
int qty = RFIFOL(fd, 14 + ( i * 10 ));
int id = RFIFOL(fd, 10 + ( i * 10 ));
short tab = RFIFOW(fd, 18 + ( i * 10 ));
enum CASH_SHOP_BUY_RESULT result = CSBR_UNKNOWN;
-
+
if( tab < 0 || tab > CASHSHOP_TAB_MAX )
continue;
-
+
for( j = 0; j < clif->cs.item_count[tab]; j++ ) {
if( clif->cs.data[tab][j]->id == id )
break;
@@ -17180,24 +17613,24 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) {
result = CSBR_SHORTTAGE_CASH;
} else if( (sd->cashPoints+kafra_pay) < (clif->cs.data[tab][j]->price * qty) ) {
result = CSBR_SHORTTAGE_CASH;
- } else if ( !( data = itemdb_exists(clif->cs.data[tab][j]->id) ) ) {
+ } else if ( !( data = itemdb->exists(clif->cs.data[tab][j]->id) ) ) {
result = CSBR_UNKONWN_ITEM;
} else {
struct item item_tmp;
int k, get_count;
-
+
get_count = qty;
-
- if (!itemdb_isstackable2(data))
+
+ if (!itemdb->isstackable2(data))
get_count = 1;
-
+
pc->paycash(sd, clif->cs.data[tab][j]->price * qty, kafra_pay);// [Ryuuzaki]
for (k = 0; k < qty; k += get_count) {
- if (!pet_create_egg(sd, data->nameid)) {
+ if (!pet->create_egg(sd, data->nameid)) {
memset(&item_tmp, 0, sizeof(item_tmp));
item_tmp.nameid = data->nameid;
item_tmp.identify = 1;
-
+
switch (pc->additem(sd, &item_tmp, get_count, LOG_TYPE_NPC)) {
case 0:
result = CSBR_SUCCESS;
@@ -17218,16 +17651,17 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) {
result = CSBR_RUNE_OVERCOUNT;
break;
}
-
+
if( result != CSBR_SUCCESS )
pc->getcash(sd, clif->cs.data[tab][j]->price * get_count,0);
- }
+ } else /* create_egg succeeded so mark as success */
+ result = CSBR_SUCCESS;
}
}
} else {
result = CSBR_UNKONWN_ITEM;
}
-
+
WFIFOHEAD(fd, 16);
WFIFOW(fd, 0) = 0x849;
WFIFOL(fd, 2) = id;
@@ -17243,7 +17677,7 @@ void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) {
short tab = RFIFOW(fd, 2);
int j;
- if( tab < 0 || tab > CASHSHOP_TAB_MAX )
+ if( tab < 0 || tab > CASHSHOP_TAB_MAX || clif->cs.item_count[tab] == 0 )
return;
WFIFOHEAD(fd, 10 + ( clif->cs.item_count[tab] * 6 ) );
@@ -17251,73 +17685,98 @@ void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) {
WFIFOW(fd, 2) = 10 + ( clif->cs.item_count[tab] * 6 );
WFIFOL(fd, 4) = tab;
WFIFOW(fd, 8) = clif->cs.item_count[tab];
-
+
for( j = 0; j < clif->cs.item_count[tab]; j++ ) {
WFIFOW(fd, 10 + ( 6 * j ) ) = clif->cs.data[tab][j]->id;
WFIFOL(fd, 12 + ( 6 * j ) ) = clif->cs.data[tab][j]->price;
}
-
+
WFIFOSET(fd, 10 + ( clif->cs.item_count[tab] * 6 ));
}
/* [Ind/Hercules] */
void clif_maptypeproperty2(struct block_list *bl,enum send_target t) {
#if PACKETVER >= 20121010
struct packet_maptypeproperty2 p;
-
+
p.PacketType = maptypeproperty2Type;
p.type = 0x28;
- p.flag.usecart = 1;
- p.flag.party = 1;
- p.flag.guild = 1;
+ p.flag.party = map->list[bl->m].flag.pvp ? 1 : 0;
+ p.flag.guild = map_flag_gvg(bl->m) ? 1 : 0;
p.flag.siege = map_flag_gvg2(bl->m) ? 1: 0;
- p.flag.mineffect = 1;
- p.flag.nolockon = 0;
- p.flag.countpk = map[bl->m].flag.pvp ? 1 : 0;
- p.flag.nopartyformation = 0;
- p.flag.noitemconsumption = 0;
- p.flag.summonstarmiracle = 0;
- p.flag.bg = map[bl->m].flag.battleground ? 1 : 0;
-
+ p.flag.mineffect = map_flag_gvg(bl->m); // FIXME/CHECKME Forcing /mineffect in castles during WoE (probably redundant? I'm not sure)
+ p.flag.nolockon = 0; // TODO
+ p.flag.countpk = map->list[bl->m].flag.pvp ? 1 : 0;
+ p.flag.nopartyformation = map->list[bl->m].flag.partylock ? 1 : 0;
+ p.flag.bg = map->list[bl->m].flag.battleground ? 1 : 0;
+ p.flag.noitemconsumption = 0; // TODO
+ p.flag.summonstarmiracle = 0; // TODO
+ p.flag.usecart = 1; // TODO
+ p.flag.SpareBits = 0;
+
clif->send(&p,sizeof(p),bl,t);
#endif
}
void clif_status_change2(struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3) {
struct packet_status_change2 p;
-
+
p.PacketType = status_change2Type;
p.index = type;
p.AID = tid;
p.state = 1;
- p.Left = -1;// officially its 9999 but -1 is a explicit "no-duration" which behaves best [Ind/Hercules]
+ p.Left = 9999;
p.val1 = val1;
p.val2 = val2;
p.val3 = val3;
-
+
clif->send(&p,sizeof(p), bl, target);
}
void clif_partytickack(struct map_session_data* sd, bool flag) {
-
+
WFIFOHEAD(sd->fd, packet_len(0x2c9));
WFIFOW(sd->fd, 0) = 0x2c9;
WFIFOB(sd->fd, 2) = flag;
WFIFOSET(sd->fd, packet_len(0x2c9));
}
+void clif_ShowScript(struct block_list* bl, const char* message) {
+ char buf[256];
+ size_t len;
+ nullpo_retv(bl);
+
+ if(!message)
+ return;
+
+ len = strlen(message)+1;
+
+ if (len > sizeof(buf)-8) {
+ ShowWarning("clif_ShowScript: Truncating too long message '%s' (len=%"PRIuS").\n", message, len);
+ len = sizeof(buf)-8;
+ }
+
+ WBUFW(buf,0)=0x8b3;
+ WBUFW(buf,2)=len+8;
+ WBUFL(buf,4)=bl->id;
+ safestrncpy((char *) WBUFP(buf,8),message,len);
+ clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT);
+}
+
void clif_status_change_end(struct block_list *bl, int tid, enum send_target target, int type) {
struct packet_status_change_end p;
-
+
+ if( bl->type == BL_PC && !((TBL_PC*)bl)->state.active )
+ return;
+
p.PacketType = status_change_endType;
p.index = type;
p.AID = tid;
p.state = 0;
-
+
clif->send(&p,sizeof(p), bl, target);
}
void clif_bgqueue_ack(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK response, unsigned char arena_id) {
-
switch (response) {
case BGQA_FAIL_COOLDOWN:
case BGQA_FAIL_DESERTER:
@@ -17325,39 +17784,38 @@ void clif_bgqueue_ack(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK
break;
default: {
struct packet_bgqueue_ack p;
-
+
p.PacketType = bgqueue_ackType;
p.type = response;
safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name));
-
+
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
break;
- }
+ }
}
-void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, unsigned char arena_id) {
+void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, char *name) {
struct packet_bgqueue_notice_delete p;
-
+
p.PacketType = bgqueue_notice_deleteType;
p.type = response;
- safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name));
-
+ safestrncpy(p.bg_name, name, sizeof(p.bg_name));
+
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) {
- struct packet_bgqueue_register *p = P2PTR(fd, bgqueue_registerType);
+ struct packet_bgqueue_register *p = P2PTR(fd);
struct bg_arena *arena = NULL;
-
if( !bg->queue_on ) return; /* temp, until feature is complete */
-
+
if( !(arena = bg->name2arena(p->bg_name)) ) {
clif->bgqueue_ack(sd,BGQA_FAIL_BGNAME_INVALID,0);
return;
}
-
+
switch( (enum bg_queue_types)p->type ) {
case BGQT_INDIVIDUAL:
case BGQT_PARTY:
@@ -17366,51 +17824,57 @@ void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) {
default:
clif->bgqueue_ack(sd,BGQA_FAIL_TYPE_INVALID, arena->id);
return;
- }
-
+ }
+
bg->queue_add(sd, arena, (enum bg_queue_types)p->type);
}
void clif_bgqueue_update_info(struct map_session_data *sd, unsigned char arena_id, int position) {
struct packet_bgqueue_update_info p;
-
+
p.PacketType = bgqueue_updateinfoType;
safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name));
p.position = position;
-
+
sd->bg_queue.client_has_bg_data = true; // Client creates bg data when this packet arrives
-
+
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) {
- //struct packet_bgqueue_checkstate *p = P2PTR(fd, bgqueue_checkstateType); /* TODO: bgqueue_notice_delete should use this p->bg_name */
- if( !bg->queue_on ) return; /* temp, until feature is complete */
+ struct packet_bgqueue_checkstate *p = P2PTR(fd);
+
if ( sd->bg_queue.arena && sd->bg_queue.type ) {
- sd->bg_queue.client_has_bg_data = true;
clif->bgqueue_update_info(sd,sd->bg_queue.arena->id,bg->id2pos(sd->bg_queue.arena->queue_id,sd->status.account_id));
} else
- clif->bgqueue_notice_delete(sd, BGQND_FAIL_NOT_QUEUING,0);/* TODO: wrong response, should respond with p->bg_name not id 0 */
+ clif->bgqueue_notice_delete(sd, BGQND_FAIL_NOT_QUEUING,p->bg_name);
}
void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) {
- //struct packet_bgqueue_revoke_req *p = P2PTR(fd, bgqueue_revokereqType);
- return;
- //bg->queue_leave(sd, p->bg_name);
+ struct packet_bgqueue_revoke_req *p = P2PTR(fd);
+
+ if( sd->bg_queue.arena )
+ bg->queue_pc_cleanup(sd);
+ else
+ clif->bgqueue_notice_delete(sd, BGQND_FAIL_NOT_QUEUING,p->bg_name);
}
void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) {
- //struct packet_bgqueue_battlebegin_ack *p = P2PTR(fd, bgqueue_checkstateType);
- return;
- //if ( p->result == 1 )
- // bg->queue_pc_ready(sd);
- //else
- // bg->queue_leave(sd, p->bg_name);
+ struct packet_bgqueue_battlebegin_ack *p = P2PTR(fd);
+ struct bg_arena *arena;
+
+ if( !bg->queue_on ) return; /* temp, until feature is complete */
+
+ if( ( arena = bg->name2arena(p->bg_name) ) ) {
+ bg->queue_ready_ack(arena,sd, ( p->result == 1 ) ? true : false);
+ } else {
+ clif->bgqueue_ack(sd,BGQA_FAIL_BGNAME_INVALID, 0);
+ }
}
void clif_bgqueue_joined(struct map_session_data *sd, int pos) {
struct packet_bgqueue_notify_entry p;
-
+
p.PacketType = bgqueue_notify_entryType;
safestrncpy(p.name,sd->status.name,sizeof(p.name));
p.position = pos;
@@ -17426,60 +17890,400 @@ void clif_bgqueue_pcleft(struct map_session_data *sd) {
// Sends BG ready req to all with same bg arena/type as sd
void clif_bgqueue_battlebegins(struct map_session_data *sd, unsigned char arena_id, enum send_target target) {
struct packet_bgqueue_battlebegins p;
-
- p.PacketType = bgqueue_battlebegins;
+
+ p.PacketType = bgqueue_battlebeginsType;
safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name));
safestrncpy(p.game_name, bg->arena[arena_id]->name, sizeof(p.game_name));
-
+
clif->send(&p,sizeof(p), &sd->bl, target);
}
void clif_scriptclear(struct map_session_data *sd, int npcid) {
struct packet_script_clear p;
-
+
p.PacketType = script_clearType;
p.NpcID = npcid;
-
+
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
+/* Made Possible Thanks to Yommy! */
+void clif_package_item_announce(struct map_session_data *sd, unsigned short nameid, unsigned short containerid) {
+ struct packet_package_item_announce p;
+
+ p.PacketType = package_item_announceType;
+ p.PacketLength = 11+NAME_LENGTH;
+ p.type = 0x0;
+ p.ItemID = nameid;
+ p.len = NAME_LENGTH;
+ safestrncpy(p.Name, sd->status.name, sizeof(p.Name));
+ p.unknown = 0x2; // some strange byte, IDA shows.. BYTE3(BoxItemIDLength) = 2;
+ p.BoxItemID = containerid;
+
+ clif->send(&p,sizeof(p), &sd->bl, ALL_CLIENT);
+}
+/* Made Possible Thanks to Yommy! */
+void clif_item_drop_announce(struct map_session_data *sd, unsigned short nameid, char *monsterName) {
+ struct packet_item_drop_announce p;
+
+ p.PacketType = item_drop_announceType;
+ p.PacketLength = sizeof(p);
+ p.type = 0x1;
+ p.ItemID = nameid;
+ p.len = NAME_LENGTH;
+ safestrncpy(p.Name, sd->status.name, sizeof(p.Name));
+ p.monsterNameLen = NAME_LENGTH;
+ safestrncpy(p.monsterName, monsterName, sizeof(p.monsterName));
+
+ clif->send(&p,sizeof(p), &sd->bl, ALL_CLIENT);
+}
+/* [Ind/Hercules] special thanks to Yommy~! */
+void clif_skill_cooldown_list(int fd, struct skill_cd* cd) {
+#if PACKETVER >= 20120604
+ const int offset = 10;
+#else
+ const int offset = 6;
+#endif
+ int i, count = 0;
+
+ WFIFOHEAD(fd,4+(offset*cd->cursor));
+
+#if PACKETVER >= 20120604
+ WFIFOW(fd,0) = 0x985;
+#else
+ WFIFOW(fd,0) = 0x43e;
+#endif
+
+ for( i = 0; i < cd->cursor; i++ ) {
+ if( cd->entry[i]->duration < 1 ) continue;
+
+ WFIFOW(fd, 4 + (count*offset)) = cd->entry[i]->skill_id;
+#if PACKETVER >= 20120604
+ WFIFOL(fd, 6 + (count*offset)) = cd->entry[i]->total;
+ WFIFOL(fd, 10 + (count*offset)) = cd->entry[i]->duration;
+#else
+ WFIFOL(fd, 6 + (count*offset)) = cd->entry[i]->duration;
+#endif
+ count++;
+ }
+
+ WFIFOW(fd,2) = 4+(offset*count);
+
+ WFIFOSET(fd,4+(offset*count));
+}
+/* [Ind/Hercules] - Data Thanks to Yommy
+ * - ADDITEM_TO_CART_FAIL_WEIGHT = 0x0
+ * - ADDITEM_TO_CART_FAIL_COUNT = 0x1
+ */
+void clif_cart_additem_ack(struct map_session_data *sd, int flag) {
+ struct packet_cart_additem_ack p;
+
+ p.PacketType = cart_additem_ackType;
+ p.result = (char)flag;
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+}
+/* Bank System [Yommy/Hercules] */
+void clif_parse_BankDeposit(int fd, struct map_session_data* sd) {
+ struct packet_banking_deposit_req *p = P2PTR(fd);
+ int money;
+
+ if( !battle_config.feature_banking ) {
+ clif->colormes(fd,COLOR_RED,msg_txt(1483));
+ return;
+ }
+
+ money = (int)cap_value(p->Money,0,INT_MAX);
+
+ pc->bank_deposit(sd,money);
+}
+
+void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) {
+ struct packet_banking_withdraw_req *p = P2PTR(fd);
+ int money;
+
+ if( !battle_config.feature_banking ) {
+ clif->colormes(fd,COLOR_RED,msg_txt(1483));
+ return;
+ }
+
+ money = (int)cap_value(p->Money,0,INT_MAX);
+
+ pc->bank_withdraw(sd,money);
+}
+
+void clif_parse_BankCheck(int fd, struct map_session_data* sd) {
+ struct packet_banking_check p;
+
+ if( !battle_config.feature_banking ) {
+ clif->colormes(fd,COLOR_RED,msg_txt(1483));
+ return;
+ }
+
+ p.PacketType = banking_checkType;
+ p.Money = (int)sd->status.bank_vault;
+ p.Reason = (short)0;
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+}
+
+void clif_parse_BankOpen(int fd, struct map_session_data* sd) {
+ return;
+}
+
+void clif_parse_BankClose(int fd, struct map_session_data* sd) {
+ return;
+}
+
+void clif_bank_deposit(struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason) {
+ struct packet_banking_deposit_ack p;
+
+ p.PacketType = banking_deposit_ackType;
+ p.Balance = sd->status.zeny;/* how much zeny char has after operation */
+ p.Money = (int64)sd->status.bank_vault;/* money in the bank */
+ p.Reason = (short)reason;
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+}
+void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason) {
+ struct packet_banking_withdraw_ack p;
+
+ p.PacketType = banking_withdraw_ackType;
+ p.Balance = sd->status.zeny;/* how much zeny char has after operation */
+ p.Money = (int64)sd->status.bank_vault;/* money in the bank */
+ p.Reason = (short)reason;
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+}
+/* TODO: official response packet (tried 0x8cb/0x97b but the display was quite screwed up.) */
+/* currently mimicing */
+void clif_show_modifiers (struct map_session_data *sd) {
+
+ if( sd->status.mod_exp != 100 || sd->status.mod_drop != 100 || sd->status.mod_death != 100 ) {
+ char output[128];
+
+ snprintf(output,128,"Base EXP : %d%% | Base Drop: %d%% | Base Death Penalty: %d%%",
+ sd->status.mod_exp,sd->status.mod_drop,sd->status.mod_death);
+ clif->broadcast2(&sd->bl,output, strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF);
+ }
+
+}
+
+void clif_notify_bounditem(struct map_session_data *sd, unsigned short index) {
+ struct packet_notify_bounditem p;
+
+ p.PacketType = notify_bounditemType;
+ p.index = index+2;
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+}
+
+/**
+ * Parses the (GM) right click option 'remove all equipment'
+ **/
+void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) {
+ struct map_session_data *tsd = map->id2sd(RFIFOL(fd,2));
+ int i;
+
+ /* TODO maybe this could be a new permission? using gm level in the meantime */
+ if( !tsd || pc_get_group_level(tsd) >= pc_get_group_level(sd) )
+ return;
+
+ for( i = 0; i < EQI_MAX; i++ ) {
+ if( tsd->equip_index[ i ] >= 0 )
+ pc->unequipitem( tsd , tsd->equip_index[ i ] , 2 );
+ }
+}
+/**
+ * clif_delay_damage timer, sends the stored data and clears the memory afterwards
+ **/
+int clif_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
+ struct cdelayed_damage *dd = (struct cdelayed_damage *)data;
+
+ clif->send(&dd->p,sizeof(struct packet_damage),&dd->bl,AREA_WOS);
+
+ ers_free(clif->delayed_damage_ers,dd);
+
+ return 0;
+}
+/**
+ * Delays sending a damage packet in order to avoid the visual display to overlap
+ *
+ * @param tick when to trigger the timer (e.g. timer->gettick() + 500)
+ * @param src block_list pointer of the src
+ * @param dst block_list pointer of the damage source
+ * @param sdelay attack motion usually status_get_amotion()
+ * @param ddelay damage motion usually status_get_dmotion()
+ * @param in_damage total damage to be sent
+ * @param div amount of hits
+ * @param type action type
+ *
+ * @return clif->calc_walkdelay used in further processing
+ **/
+int clif_delay_damage(int64 tick, struct block_list *src, struct block_list *dst, int sdelay, int ddelay, int64 in_damage, short div, unsigned char type) {
+ struct cdelayed_damage *dd;
+ struct status_change *sc;
+#if PACKETVER < 20071113
+ short damage;
+#else
+ int damage;
+#endif
+
+ nullpo_ret(src);
+ nullpo_ret(dst);
+
+ sc = status->get_sc(dst);
+
+ if(sc && sc->count && sc->data[SC_ILLUSION]) {
+ if(in_damage) in_damage = in_damage*(sc->data[SC_ILLUSION]->val2) + rnd()%100;
+ }
+
+#if PACKETVER < 20071113
+ damage = (short)min(in_damage,INT16_MAX);
+#else
+ damage = (int)min(in_damage,INT_MAX);
+#endif
+
+ type = clif_calc_delay(type,div,damage,ddelay);
+
+ dd = ers_alloc(clif->delayed_damage_ers, struct cdelayed_damage);
+
+ dd->p.PacketType = damageType;
+ dd->p.GID = src->id;
+ dd->p.targetGID = dst->id;
+ dd->p.startTime = (uint32)timer->gettick();
+ dd->p.attackMT = sdelay;
+ dd->p.attackedMT = ddelay;
+ dd->p.count = div;
+ dd->p.action = type;
+ dd->p.leftDamage = 0;
+
+ if( battle_config.hide_woe_damage && map_flag_gvg2(src->m) )
+ dd->p.damage = damage?div:0;
+ else
+ dd->p.damage = damage;
+
+ dd->bl.m = dst->m;
+ dd->bl.x = dst->x;
+ dd->bl.y = dst->y;
+ dd->bl.type = BL_NUL;
+
+ if( tick > timer->gettick() )
+ timer->add(tick,clif->delay_damage_sub,0,(intptr_t)dd);
+ else {
+ clif->send(&dd->p,sizeof(struct packet_damage),&dd->bl,AREA_WOS);
+
+ ers_free(clif->delayed_damage_ers,dd);
+ }
+
+ return clif->calc_walkdelay(dst,ddelay,type,damage,div);
+}
+/* Thanks to Yommy */
+void clif_parse_NPCShopClosed(int fd, struct map_session_data *sd) {
+ /* TODO track the state <3~ */
+ sd->npc_shopid = 0;
+}
+/* NPC Market (by Ind after an extensive debugging of the packet, only possible thanks to Yommy <3) */
+void clif_npc_market_open(struct map_session_data *sd, struct npc_data *nd) {
+#if PACKETVER >= 20131223
+ struct npc_item_list *shop = nd->u.scr.shop->item;
+ unsigned short shop_size = nd->u.scr.shop->items, i, c;
+ struct item_data *id = NULL;
+
+ npcmarket_open.PacketType = npcmarketopenType;
+
+ for(i = 0, c = 0; i < shop_size; i++) {
+ if( shop[i].nameid && (id = itemdb->exists(shop[i].nameid)) ) {
+ npcmarket_open.list[c].nameid = shop[i].nameid;
+ npcmarket_open.list[c].price = shop[i].value;
+ npcmarket_open.list[c].qty = shop[i].qty;
+ npcmarket_open.list[c].type = itemtype(id->type);
+ npcmarket_open.list[c].view = ( id->view_id > 0 ) ? id->view_id : id->nameid;
+ c++;
+ }
+ }
+
+ npcmarket_open.PacketLength = 4 + ( sizeof(npcmarket_open.list[0]) * c );
+
+ clif->send(&npcmarket_open,npcmarket_open.PacketLength,&sd->bl,SELF);
+#endif
+}
+void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) {
+ /* TODO track the state <3~ */
+ sd->npc_shopid = 0;
+}
+void clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_npc_market_purchase *req, unsigned char response) {
+#if PACKETVER >= 20131223
+ unsigned short c = 0;
+
+ npcmarket_result.PacketType = npcmarketresultackType;
+ npcmarket_result.result = response == 0 ? 1 : 0;/* find other values */
+
+ if( npcmarket_result.result ) {
+ unsigned short i, list_size = (req->PacketLength - 4) / sizeof(req->list[0]), j;
+ struct npc_data* nd;
+ struct npc_item_list *shop = NULL;
+ unsigned short shop_size = 0;
+
+ nd = map->id2nd(sd->npc_shopid);
+
+ shop = nd->u.scr.shop->item;
+ shop_size = nd->u.scr.shop->items;
+
+ for(i = 0; i < list_size; i++) {
+
+ npcmarket_result.list[i].ITID = req->list[i].ITID;
+ npcmarket_result.list[i].qty = req->list[i].qty;
+
+ ARR_FIND( 0, shop_size, j, req->list[i].ITID == shop[j].nameid );
+
+ npcmarket_result.list[i].price = (j != shop_size) ? shop[j].value : 0;
+
+ c++;
+ }
+ }
+
+ npcmarket_result.PacketLength = 5 + ( sizeof(npcmarket_result.list[0]) * c );;
+
+ clif->send(&npcmarket_result,npcmarket_result.PacketLength,&sd->bl,SELF);
+#endif
+}
+void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) {
+#if PACKETVER >= 20131223
+ struct packet_npc_market_purchase *p = P2PTR(fd);
+
+ clif->npc_market_purchase_ack(sd,p,npc->market_buylist(sd,(p->PacketLength - 4) / sizeof(p->list[0]),p));
+#endif
+}
+/* */
unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
if( sd ) {
- sd->cryptKey = (( sd->cryptKey * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF;
return (cmd ^ ((sd->cryptKey >> 16) & 0x7FFF));
}
return (cmd ^ (((( clif->cryptKey[0] * clif->cryptKey[1] ) + clif->cryptKey[2]) >> 16) & 0x7FFF));
}
-unsigned short clif_parse_cmd_normal ( int fd, struct map_session_data *sd ) {
+unsigned short clif_parse_cmd_normal( int fd, struct map_session_data *sd ) {
unsigned short cmd = RFIFOW(fd,0);
- // filter out invalid / unsupported packets
- if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0)
- return 0;
return cmd;
}
-unsigned short clif_parse_cmd_optional ( int fd, struct map_session_data *sd ) {
+unsigned short clif_parse_cmd_decrypt( int fd, struct map_session_data *sd ) {
unsigned short cmd = RFIFOW(fd,0);
- // filter out invalid / unsupported packets
- if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0) {
- cmd = clif->decrypt_cmd( cmd, sd );
- if( cmd > MAX_PACKET_DB || packet_db[cmd].len == 0 )
- return 0;
- RFIFOW(fd, 0) = cmd;
- }
+ cmd = clif->decrypt_cmd(cmd, sd);
return cmd;
}
-unsigned short clif_parse_cmd_decrypt ( int fd, struct map_session_data *sd ) {
+unsigned short clif_parse_cmd_optional( int fd, struct map_session_data *sd ) {
unsigned short cmd = RFIFOW(fd,0);
- cmd = clif->decrypt_cmd( cmd, sd );
-
// filter out invalid / unsupported packets
- if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0 )
- return 0;
-
- RFIFOW(fd, 0) = cmd;
+ if( cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0 ) {
+ if( sd )
+ sd->parse_cmd_func = clif_parse_cmd_decrypt;
+ return clif_parse_cmd_decrypt(fd, sd);
+ } else if( sd ) {
+ sd->parse_cmd_func = clif_parse_cmd_normal;
+ }
return cmd;
}
@@ -17491,14 +18295,16 @@ int clif_parse(int fd) {
int cmd, packet_len;
TBL_PC* sd;
int pnum;
-
+
//TODO apply delays or disconnect based on packet throughput [FlavioJS]
// Note: "click masters" can do 80+ clicks in 10 seconds
-
+
for( pnum = 0; pnum < 3; ++pnum ) { // Limit max packets per cycle to 3 (delay packet spammers) [FlavioJS] -- This actually aids packet spammers, but stuff like /str+ gets slow without it [Ai4rei]
+ unsigned short (*parse_cmd_func)(int fd, struct map_session_data *sd);
// begin main client packet processing loop
-
+
sd = (TBL_PC *)session[fd]->session_data;
+
if (session[fd]->flag.eof) {
if (sd) {
if (sd->state.autotrade) {
@@ -17514,7 +18320,7 @@ int clif_parse(int fd) {
} else {
//Unusual logout (during log on/off/map-changer procedure)
ShowInfo("Player AID:%d/CID:%d logged off.\n", sd->status.account_id, sd->status.char_id);
- iMap->quit(sd);
+ map->quit(sd);
}
} else {
ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", ip2str(session[fd]->client_addr, NULL));
@@ -17522,25 +18328,42 @@ int clif_parse(int fd) {
do_close(fd);
return 0;
}
-
+
if (RFIFOREST(fd) < 2)
return 0;
-
- if( !( cmd = clif->parse_cmd(fd,sd) ) ) {
- ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x, %d bytes received), disconnecting session #%d.\n", RFIFOW(fd,0), RFIFOREST(fd), fd);
+
+ if( HPM->packetsc[hpClif_Parse] ) {
+ int r;
+ if( (r = HPM->parse_packets(fd,hpClif_Parse)) ) {
+ if( r == 1 ) continue;
+ if( r == 2 ) return 0;
+ }
+ }
+
+ if( sd )
+ parse_cmd_func = sd->parse_cmd_func;
+ else
+ parse_cmd_func = clif->parse_cmd;
+
+ cmd = parse_cmd_func(fd,sd);
+
+ // filter out invalid / unsupported packets
+ if (cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0) {
+ ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x (0x%04x), %"PRIuS" bytes received), disconnecting session #%d.\n",
+ cmd, RFIFOW(fd,0), RFIFOREST(fd), fd);
#ifdef DUMP_INVALID_PACKET
ShowDump(RFIFOP(fd,0), RFIFOREST(fd));
#endif
set_eof(fd);
return 0;
}
-
+
// determine real packet length
if ( ( packet_len = packet_db[cmd].len ) == -1) { // variable-length packet
if (RFIFOREST(fd) < 4)
return 0;
-
+
packet_len = RFIFOW(fd,2);
if (packet_len < 4 || packet_len > 32768) {
ShowWarning("clif_parse: Received packet 0x%04x specifies invalid packet_len (%d), disconnecting session #%d.\n", cmd, packet_len, fd);
@@ -17556,6 +18379,13 @@ int clif_parse(int fd) {
if ((int)RFIFOREST(fd) < packet_len)
return 0; // not enough data received to form the packet
+ if( battle_config.packet_obfuscation == 2 || cmd != RFIFOW(fd, 0) || (sd && sd->parse_cmd_func == clif_parse_cmd_decrypt) ) {
+ RFIFOW(fd, 0) = cmd;
+ if( sd ) {
+ sd->cryptKey = (( sd->cryptKey * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF; // Update key for the next packet
+ }
+ }
+
if( packet_db[cmd].func == clif->pDebug )
packet_db[cmd].func(fd, sd);
else if( packet_db[cmd].func != NULL ) {
@@ -17571,36 +18401,36 @@ int clif_parse(int fd) {
else {
const char* packet_txt = "save/packet.txt";
FILE* fp;
-
+
if( ( fp = fopen( packet_txt , "a" ) ) != NULL ) {
if( sd ) {
fprintf(fp, "Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id);
} else {
fprintf(fp, "Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd);
}
-
+
WriteDump(fp, RFIFOP(fd,0), packet_len);
fprintf(fp, "\n");
fclose(fp);
} else {
ShowError("Failed to write '%s'.\n", packet_txt);
-
+
// Dump on console instead
if( sd ) {
ShowDebug("Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id);
} else {
ShowDebug("Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd);
}
-
+
ShowDump(RFIFOP(fd,0), packet_len);
}
}
#endif
-
+
RFIFOSKIP(fd, packet_len);
-
+
}; // main loop end
-
+
return 0;
}
@@ -17609,43 +18439,44 @@ static void __attribute__ ((unused)) packetdb_addpacket(short cmd, int len, ...)
int i;
int pos;
pFunc func;
-
+
if (cmd > MAX_PACKET_DB) {
ShowError("Packet Error: packet 0x%x is greater than the maximum allowed (0x%x), skipping...\n", cmd, MAX_PACKET_DB);
return;
}
-
+
packet_db[cmd].len = len;
-
+
va_start(va,len);
-
+
pos = va_arg(va, int);
-
+
if( pos == 0xFFFF ) /* nothing more to do */
return;
-
+
va_end(va);
va_start(va,len);
-
+
func = va_arg(va,pFunc);
-
+
packet_db[cmd].func = func;
-
+
for (i = 0; i < MAX_PACKET_POS; i++) {
pos = va_arg(va, int);
-
+
if (pos == 0xFFFF)
break;
-
+
packet_db[cmd].pos[i] = pos;
}
+ va_end(va);
}
void packetdb_loaddb(void) {
-
+
memset(packet_db,0,sizeof(packet_db));
- #define packet(id, size, ...) packetdb_addpacket(id, size, ##__VA_ARGS__, 0xFFFF)
- #define packetKeys(a,b,c) { clif->cryptKey[0] = a; clif->cryptKey[1] = b; clif->cryptKey[2] = c; }
+ #define packet(id, size, ...) packetdb_addpacket((id), (size), ##__VA_ARGS__, 0xFFFF)
+ #define packetKeys(a,b,c) do { clif->cryptKey[0] = (a); clif->cryptKey[1] = (b); clif->cryptKey[2] = (c); } while(0)
#include "packets.h" /* load structure data */
#undef packet
#undef packetKeys
@@ -17655,7 +18486,7 @@ void clif_bc_ready(void) {
clif->status_change = clif_status_change;
else
clif->status_change = clif_status_change_notick;
-
+
switch( battle_config.packet_obfuscation ) {
case 0:
clif->parse_cmd = clif_parse_cmd_normal;
@@ -17672,35 +18503,39 @@ void clif_bc_ready(void) {
/*==========================================
*
*------------------------------------------*/
-int do_init_clif(void) {
+int do_init_clif(bool minimal) {
const char* colors[COLOR_MAX] = { "0xFF0000", "0x00ff00", "0xffffff" };
int i;
-
+
+ if (minimal)
+ return 0;
+
/**
* Setup Color Table (saves unnecessary load of strtoul on every call)
**/
for(i = 0; i < COLOR_MAX; i++) {
- color_table[i] = strtoul(colors[i],NULL,0);
+ color_table[i] = (unsigned int)strtoul(colors[i],NULL,0);
color_table[i] = (color_table[i] & 0x0000FF) << 16 | (color_table[i] & 0x00FF00) | (color_table[i] & 0xFF0000) >> 16;//RGB to BGR
}
-
+
packetdb_loaddb();
-
+
set_defaultparse(clif->parse);
if( make_listen_bind(clif->bind_ip,clif->map_port) == -1 ) {
ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",clif->map_port);
exit(EXIT_FAILURE);
}
- iTimer->add_timer_func_list(clif->clearunit_delayed_sub, "clif_clearunit_delayed_sub");
- iTimer->add_timer_func_list(clif->delayquit, "clif_delayquit");
+ timer->add_func_list(clif->clearunit_delayed_sub, "clif_clearunit_delayed_sub");
+ timer->add_func_list(clif->delayquit, "clif_delayquit");
clif->delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR);
+ clif->delayed_damage_ers = ers_new(sizeof(struct cdelayed_damage),"clif.c::delayed_damage_ers",ERS_OPT_CLEAR);
clif->channel_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, HCHSYS_NAME_LENGTH);
hChSys.ally = hChSys.local = hChSys.irc = hChSys.ally_autojoin = hChSys.local_autojoin = false;
clif->chann_config_read();
-
+
return 0;
}
@@ -17708,17 +18543,17 @@ void do_final_clif(void) {
DBIterator *iter = db_iterator(clif->channel_db);
struct hChSysCh *channel;
unsigned char i;
-
+
for( channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter) ) {
clif->chsys_delete(channel);
}
-
+
dbi_destroy(iter);
-
+
for(i = 0; i < hChSys.colors_count; i++) {
aFree(hChSys.colors_name[i]);
}
-
+
if( hChSys.colors_count ) {
aFree(hChSys.colors_name);
aFree(hChSys.colors);
@@ -17726,7 +18561,8 @@ void do_final_clif(void) {
db_destroy(clif->channel_db);
ers_destroy(clif->delay_clearunit_ers);
-
+ ers_destroy(clif->delayed_damage_ers);
+
for(i = 0; i < CASHSHOP_TAB_MAX; i++) {
int k;
for( k = 0; k < clif->cs.item_count[i]; k++ ) {
@@ -17741,6 +18577,8 @@ void clif_defaults(void) {
/* vars */
clif->bind_ip = INADDR_ANY;
clif->map_port = 5121;
+ clif->ally_only = false;
+ clif->delayed_damage_ers = NULL;
/* core */
clif->init = do_init_clif;
clif->final = do_final_clif;
@@ -17777,6 +18615,10 @@ void clif_defaults(void) {
clif->addcards2 = clif_addcards2;
clif->item_sub = clif_item_sub;
clif->getareachar_item = clif_getareachar_item;
+ clif->cart_additem_ack = clif_cart_additem_ack;
+ clif->cashshop_load = clif_cashshop_db;
+ clif->package_announce = clif_package_item_announce;
+ clif->item_drop_announce = clif_item_drop_announce;
/* unit-related */
clif->clearunit_single = clif_clearunit_single;
clif->clearunit_area = clif_clearunit_area;
@@ -17791,18 +18633,20 @@ void clif_defaults(void) {
clif->changetraplook = clif_changetraplook;
clif->refreshlook = clif_refreshlook;
clif->class_change = clif_class_change;
- clif->skill_setunit = clif_skill_setunit;
clif->skill_delunit = clif_skill_delunit;
clif->skillunit_update = clif_skillunit_update;
clif->clearunit_delayed_sub = clif_clearunit_delayed_sub;
clif->set_unit_idle = clif_set_unit_idle;
clif->spawn_unit = clif_spawn_unit;
+ clif->spawn_unit2 = clif_spawn_unit2;
+ clif->set_unit_idle2 = clif_set_unit_idle2;
clif->set_unit_walking = clif_set_unit_walking;
clif->calc_walkdelay = clif_calc_walkdelay;
clif->getareachar_skillunit = clif_getareachar_skillunit;
clif->getareachar_unit = clif_getareachar_unit;
clif->clearchar_skillunit = clif_clearchar_skillunit;
clif->getareachar = clif_getareachar;
+ clif->graffiti_entry = clif_graffiti_entry;
/* main unit spawn */
clif->spawn = clif_spawn;
/* map-related */
@@ -17840,10 +18684,14 @@ void clif_defaults(void) {
clif->sitting = clif_sitting;
clif->standing = clif_standing;
clif->arrow_create_list = clif_arrow_create_list;
+ clif->refresh_storagewindow = clif_refresh_storagewindow;
clif->refresh = clif_refresh;
clif->fame_blacksmith = clif_fame_blacksmith;
clif->fame_alchemist = clif_fame_alchemist;
clif->fame_taekwon = clif_fame_taekwon;
+ clif->ranklist = clif_ranklist;
+ clif->pRanklist = clif_parse_ranklist;
+ clif->update_rankingpoint = clif_update_rankingpoint;
clif->hotkeys = clif_hotkeys_send;
clif->insight = clif_insight;
clif->outsight = clif_outsight;
@@ -17891,7 +18739,6 @@ void clif_defaults(void) {
clif->partytickack = clif_partytickack;
clif->equiptickack = clif_equiptickack;
clif->viewequip_ack = clif_viewequip_ack;
- clif->viewequip_fail = clif_viewequip_fail;
clif->equpcheckbox = clif_equpcheckbox;
clif->displayexp = clif_displayexp;
clif->font = clif_font;
@@ -17907,6 +18754,7 @@ void clif_defaults(void) {
clif->sc_load = clif_status_change2;
clif->sc_end = clif_status_change_end;
clif->initialstatus = clif_initialstatus;
+ clif->cooldown_list = clif_skill_cooldown_list;
/* player-unit-specific-related */
clif->updatestatus = clif_updatestatus;
clif->changestatus = clif_changestatus;
@@ -17973,7 +18821,6 @@ void clif_defaults(void) {
clif->changechatstatus = clif_changechatstatus;
clif->wis_message = clif_wis_message;
clif->wis_end = clif_wis_end;
- clif->disp_onlyself = clif_disp_onlyself;
clif->disp_message = clif_disp_message;
clif->broadcast = clif_broadcast;
clif->broadcast2 = clif_broadcast2;
@@ -17986,11 +18833,13 @@ void clif_defaults(void) {
clif->msgtable_num = clif_msgtable_num;
clif->message = clif_displaymessage;
clif->messageln = clif_displaymessage2;
+ clif->messages = clif_displaymessage_sprintf;
clif->colormes = clif_colormes;
clif->process_message = clif_process_message;
clif->wisexin = clif_wisexin;
clif->wisall = clif_wisall;
clif->PMIgnoreList = clif_PMIgnoreList;
+ clif->ShowScript = clif_ShowScript;
/* trade handling */
clif->traderequest = clif_traderequest;
clif->tradestart = clif_tradestart;
@@ -18055,7 +18904,6 @@ void clif_defaults(void) {
clif->guild_emblem_area = clif_guild_emblem_area;
clif->guild_notice = clif_guild_notice;
clif->guild_message = clif_guild_message;
- clif->guild_skillup = clif_guild_skillup;
clif->guild_reqalliance = clif_guild_reqalliance;
clif->guild_allianceack = clif_guild_allianceack;
clif->guild_delalliance = clif_guild_delalliance;
@@ -18147,14 +18995,18 @@ void clif_defaults(void) {
clif->PartyBookingUpdateNotify = clif_PartyBookingUpdateNotify;
clif->PartyBookingDeleteNotify = clif_PartyBookingDeleteNotify;
clif->PartyBookingInsertNotify = clif_PartyBookingInsertNotify;
+ clif->PartyRecruitRegisterAck = clif_PartyRecruitRegisterAck;
+ clif->PartyRecruitDeleteAck = clif_PartyRecruitDeleteAck;
+ clif->PartyRecruitSearchAck = clif_PartyRecruitSearchAck;
+ clif->PartyRecruitUpdateNotify = clif_PartyRecruitUpdateNotify;
+ clif->PartyRecruitDeleteNotify = clif_PartyRecruitDeleteNotify;
+ clif->PartyRecruitInsertNotify = clif_PartyRecruitInsertNotify;
/* Group Search System Update */
-#ifdef PARTY_RECRUIT
clif->PartyBookingVolunteerInfo = clif_PartyBookingVolunteerInfo;
clif->PartyBookingRefuseVolunteer = clif_PartyBookingRefuseVolunteer;
clif->PartyBookingCancelVolunteer = clif_PartyBookingCancelVolunteer;
clif->PartyBookingAddFilteringList = clif_PartyBookingAddFilteringList;
clif->PartyBookingSubFilteringList = clif_PartyBookingSubFilteringList;
-#endif
/* buying store-related */
clif->buyingstore_open = clif_buyingstore_open;
clif->buyingstore_open_failed = clif_buyingstore_open_failed;
@@ -18173,22 +19025,9 @@ void clif_defaults(void) {
clif->search_store_info_failed = clif_search_store_info_failed;
clif->open_search_store_info = clif_open_search_store_info;
clif->search_store_info_click_ack = clif_search_store_info_click_ack;
- /* elemental-related */
+ /* elemental-related */
clif->elemental_info = clif_elemental_info;
clif->elemental_updatestatus = clif_elemental_updatestatus;
- /* Hercules Channel System */
- clif->chsys_create = clif_hercules_chsys_create;
- clif->chsys_msg = clif_hercules_chsys_msg;
- clif->chsys_msg2 = clif_hercules_chsys_msg2;
- clif->chsys_send = clif_hercules_chsys_send;
- clif->chsys_join = clif_hercules_chsys_join;
- clif->chsys_left = clif_hercules_chsys_left;
- clif->chsys_delete = clif_hercules_chsys_delete;
- clif->chsys_mjoin = clif_hercules_chsys_mjoin;
- clif->chsys_quit = clif_hercules_chsys_quit;
- clif->chsys_quitg = clif_hercules_chsys_quitg;
- clif->chsys_gjoin = clif_hercules_chsys_gjoin;
- clif->chsys_gleave = clif_hercules_chsys_gleave;
/* bgqueue */
clif->bgqueue_ack = clif_bgqueue_ack;
clif->bgqueue_notice_delete = clif_bgqueue_notice_delete;
@@ -18196,19 +19035,44 @@ void clif_defaults(void) {
clif->bgqueue_joined = clif_bgqueue_joined;
clif->bgqueue_pcleft = clif_bgqueue_pcleft;
clif->bgqueue_battlebegins = clif_bgqueue_battlebegins;
- /* misc-handling */
+ /* misc-handling */
clif->adopt_reply = clif_Adopt_reply;
clif->adopt_request = clif_Adopt_request;
clif->readbook = clif_readbook;
clif->notify_time = clif_notify_time;
clif->user_count = clif_user_count;
clif->noask_sub = clif_noask_sub;
- clif->cashshop_load = clif_cashshop_db;
clif->bc_ready = clif_bc_ready;
clif->undisguise_timer = clif_undisguise_timer;
+ /* Hercules Channel System */
+ clif->chsys_create = clif_hercules_chsys_create;
+ clif->chsys_msg = clif_hercules_chsys_msg;
+ clif->chsys_msg2 = clif_hercules_chsys_msg2;
+ clif->chsys_send = clif_hercules_chsys_send;
+ clif->chsys_join = clif_hercules_chsys_join;
+ clif->chsys_left = clif_hercules_chsys_left;
+ clif->chsys_delete = clif_hercules_chsys_delete;
+ clif->chsys_mjoin = clif_hercules_chsys_mjoin;
+ clif->chsys_quit = clif_hercules_chsys_quit;
+ clif->chsys_quitg = clif_hercules_chsys_quitg;
+ clif->chsys_gjoin = clif_hercules_chsys_gjoin;
+ clif->chsys_gleave = clif_hercules_chsys_gleave;
+ /* Bank System [Yommy/Hercules] */
+ clif->bank_deposit = clif_bank_deposit;
+ clif->bank_withdraw = clif_bank_withdraw;
+ /* */
+ clif->show_modifiers = clif_show_modifiers;
+ /* */
+ clif->notify_bounditem = clif_notify_bounditem;
+ /* */
+ clif->delay_damage = clif_delay_damage;
+ clif->delay_damage_sub = clif_delay_damage_sub;
+ /* NPC Market */
+ clif->npc_market_open = clif_npc_market_open;
+ clif->npc_market_purchase_ack = clif_npc_market_purchase_ack;
/*------------------------
*- Parse Incoming Packet
- *------------------------*/
+ *------------------------*/
clif->pWantToConnection = clif_parse_WantToConnection;
clif->pLoadEndAck = clif_parse_LoadEndAck;
clif->pTickSend = clif_parse_TickSend;
@@ -18243,6 +19107,7 @@ void clif_defaults(void) {
clif->pKickFromChat = clif_parse_KickFromChat;
clif->pChatLeave = clif_parse_ChatLeave;
clif->pTradeRequest = clif_parse_TradeRequest;
+ clif->chann_config_read = read_channels_config;
clif->pTradeAck = clif_parse_TradeAck;
clif->pTradeAddItem = clif_parse_TradeAddItem;
clif->pTradeOk = clif_parse_TradeOk;
@@ -18261,7 +19126,7 @@ void clif_defaults(void) {
clif->pUseSkillToPos = clif_parse_UseSkillToPos;
clif->pUseSkillToPosSub = clif_parse_UseSkillToPosSub;
clif->pUseSkillToPos_homun = clif_parse_UseSkillToPos_homun;
- clif->pUseSkillToPos_mercenary = clif_parse_UseSkillToPos_mercenary;
+ clif->pUseSkillToPos_mercenary = clif_parse_UseSkillToPos_mercenary;
clif->pUseSkillToPosMoreInfo = clif_parse_UseSkillToPosMoreInfo;
clif->pUseSkillMap = clif_parse_UseSkillMap;
clif->pRequestMemo = clif_parse_RequestMemo;
@@ -18297,13 +19162,16 @@ void clif_defaults(void) {
clif->pLeaveParty = clif_parse_LeaveParty;
clif->pRemovePartyMember = clif_parse_RemovePartyMember;
clif->pPartyChangeOption = clif_parse_PartyChangeOption;
- clif->chann_config_read = read_channels_config;
clif->pPartyMessage = clif_parse_PartyMessage;
clif->pPartyChangeLeader = clif_parse_PartyChangeLeader;
clif->pPartyBookingRegisterReq = clif_parse_PartyBookingRegisterReq;
clif->pPartyBookingSearchReq = clif_parse_PartyBookingSearchReq;
clif->pPartyBookingDeleteReq = clif_parse_PartyBookingDeleteReq;
clif->pPartyBookingUpdateReq = clif_parse_PartyBookingUpdateReq;
+ clif->pPartyRecruitRegisterReq = clif_parse_PartyRecruitRegisterReq;
+ clif->pPartyRecruitSearchReq = clif_parse_PartyRecruitSearchReq;
+ clif->pPartyRecruitDeleteReq = clif_parse_PartyRecruitDeleteReq;
+ clif->pPartyRecruitUpdateReq = clif_parse_PartyRecruitUpdateReq;
clif->pCloseVending = clif_parse_CloseVending;
clif->pVendingListReq = clif_parse_VendingListReq;
clif->pPurchaseReq = clif_parse_PurchaseReq;
@@ -18344,6 +19212,7 @@ void clif_defaults(void) {
clif->pGMRc = clif_parse_GMRc;
clif->pGMReqAccountName = clif_parse_GMReqAccountName;
clif->pGMChangeMapType = clif_parse_GMChangeMapType;
+ clif->pGMFullStrip = clif_parse_GMFullStrip;
clif->pPMIgnore = clif_parse_PMIgnore;
clif->pPMIgnoreAll = clif_parse_PMIgnoreAll;
clif->pPMIgnoreList = clif_parse_PMIgnoreList;
@@ -18402,28 +19271,37 @@ void clif_defaults(void) {
clif->pDebug = clif_parse_debug;
clif->pSkillSelectMenu = clif_parse_SkillSelectMenu;
clif->pMoveItem = clif_parse_MoveItem;
+ /* dull */
+ clif->pDull = clif_parse_dull;
+ /* BGQueue */
+ clif->pBGQueueRegister = clif_parse_bgqueue_register;
+ clif->pBGQueueCheckState = clif_parse_bgqueue_checkstate;
+ clif->pBGQueueRevokeReq = clif_parse_bgqueue_revoke_req;
+ clif->pBGQueueBattleBeginAck = clif_parse_bgqueue_battlebegin_ack;
/* RagExe Cash Shop [Ind/Hercules] */
clif->pCashShopOpen = clif_parse_CashShopOpen;
clif->pCashShopClose = clif_parse_CashShopClose;
clif->pCashShopReqTab = clif_parse_CashShopReqTab;
clif->pCashShopSchedule = clif_parse_CashShopSchedule;
clif->pCashShopBuy = clif_parse_CashShopBuy;
- /* BGQueue */
- clif->pBGQueueRegister = clif_parse_bgqueue_register;
- clif->pBGQueueCheckState = clif_parse_bgqueue_checkstate;
- clif->pBGQueueRevokeReq = clif_parse_bgqueue_revoke_req;
- clif->pBGQueueBattleBeginAck = clif_parse_bgqueue_battlebegin_ack;
/* */
clif->pPartyTick = clif_parse_PartyTick;
clif->pGuildInvite2 = clif_parse_GuildInvite2;
/* Group Search System Update */
-#ifdef PARTY_RECRUIT
clif->pPartyBookingAddFilter = clif_parse_PartyBookingAddFilteringList;
clif->pPartyBookingSubFilter = clif_parse_PartyBookingSubFilteringList;
clif->pPartyBookingReqVolunteer = clif_parse_PartyBookingReqVolunteer;
clif->pPartyBookingRefuseVolunteer = clif_parse_PartyBookingRefuseVolunteer;
clif->pPartyBookingCancelVolunteer = clif_parse_PartyBookingCancelVolunteer;
-#endif
- /* dull */
- clif->pDull = clif_parse_dull;
+ /* Bank System [Yommy/Hercules] */
+ clif->pBankDeposit = clif_parse_BankDeposit;
+ clif->pBankWithdraw = clif_parse_BankWithdraw;
+ clif->pBankCheck = clif_parse_BankCheck;
+ clif->pBankOpen = clif_parse_BankOpen;
+ clif->pBankClose = clif_parse_BankClose;
+ /* */
+ clif->pNPCShopClosed = clif_parse_NPCShopClosed;
+ /* NPC Market */
+ clif->pNPCMarketClosed = clif_parse_NPCMarketClosed;
+ clif->pNPCMarketPurchase = clif_parse_NPCMarketPurchase;
}
diff --git a/src/map/clif.h b/src/map/clif.h
index 6e1fa81d3..e4de51a83 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -2,14 +2,16 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _CLIF_H_
-#define _CLIF_H_
+#ifndef MAP_CLIF_H
+#define MAP_CLIF_H
+#include <stdarg.h>
+
+#include "map.h"
+#include "packets_struct.h"
#include "../common/cbasetypes.h"
#include "../common/db.h"
#include "../common/mmo.h"
-#include "../common/socket.h"
-#include <stdarg.h>
/**
* Declarations
@@ -18,7 +20,6 @@ struct item;
struct item_data;
struct storage_data;
struct guild_storage;
-struct block_list;
struct unit_data;
struct map_session_data;
struct homun_data;
@@ -38,33 +39,37 @@ struct quest;
struct party_booking_ad_info;
struct view_data;
struct eri;
+struct skill_cd;
/**
* Defines
**/
#define packet_len(cmd) packet_db[cmd].len
-#define P2PTR(fd,cmd) RFIFO2PTR(fd,packet_db[cmd].len)
-#define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0;
+#define P2PTR(fd) RFIFO2PTR(fd)
+#define clif_menuskill_clear(sd) ((sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0)
+#define clif_disp_onlyself(sd,mes,len) clif->disp_message( &(sd)->bl, (mes), (len), SELF )
+#define clif_viewequip_fail( sd ) clif_msg( (sd), 0x54d );
#define HCHSYS_NAME_LENGTH 20
/**
* Enumerations
**/
enum {// packet DB
- MAX_PACKET_DB = 0xF00,
+ MIN_PACKET_DB = 0x0064,
+ MAX_PACKET_DB = 0x0F00,
MAX_PACKET_POS = 20,
};
typedef enum send_target {
ALL_CLIENT,
ALL_SAMEMAP,
- AREA, // area
- AREA_WOS, // area, without self
- AREA_WOC, // area, without chatrooms
- AREA_WOSC, // area, without own chatroom
- AREA_CHAT_WOC, // hearable area, without chatrooms
- CHAT, // current chatroom
- CHAT_WOS, // current chatroom, without self
+ AREA, // area
+ AREA_WOS, // area, without self
+ AREA_WOC, // area, without chatrooms
+ AREA_WOSC, // area, without own chatrooms
+ AREA_CHAT_WOC, // hearable area, without chatrooms
+ CHAT, // current chatroom
+ CHAT_WOS, // current chatroom, without self
PARTY,
PARTY_WOS,
PARTY_SAMEMAP,
@@ -82,7 +87,7 @@ typedef enum send_target {
DUEL_WOS,
SELF,
- BG, // BattleGround System
+ BG, // BattleGround System
BG_WOS,
BG_SAMEMAP,
BG_SAMEMAP_WOS,
@@ -92,6 +97,25 @@ typedef enum send_target {
BG_QUEUE,
} send_target;
+typedef enum broadcast_flags {
+ BC_ALL = 0,
+ BC_MAP = 1,
+ BC_AREA = 2,
+ BC_SELF = 3,
+ BC_TARGET_MASK = 0x07,
+
+ BC_PC = 0x00,
+ BC_NPC = 0x08,
+ BC_SOURCE_MASK = 0x08, // BC_PC|BC_NPC
+
+ BC_YELLOW = 0x00,
+ BC_BLUE = 0x10,
+ BC_WOE = 0x20,
+ BC_COLOR_MASK = 0x30, // BC_YELLOW|BC_BLUE|BC_WOE
+
+ BC_DEFAULT = BC_ALL|BC_PC|BC_YELLOW
+} broadcast_flags;
+
typedef enum emotion_type {
E_GASP = 0, // /!
E_WHAT, // /?
@@ -319,7 +343,25 @@ typedef enum useskill_fail_cause { // clif_skill_fail
}useskill_fail_cause;
enum clif_messages {
+ ITEM_CANT_OBTAIN_WEIGHT = 0x34, /* you cannot carry more items because you are overweight. */
SKILL_CANT_USE_AREA = 0x536,
+ ITEM_CANT_USE_AREA = 0x537,
+};
+
+/**
+ * Used to answer CZ_PC_BUY_CASH_POINT_ITEM (clif_parse_cashshop_buy)
+ **/
+enum cashshop_error {
+ ERROR_TYPE_NONE = 0, // The deal has successfully completed. (ERROR_TYPE_NONE)
+ ERROR_TYPE_NPC, // The Purchase has failed because the NPC does not exist. (ERROR_TYPE_NPC)
+ ERROR_TYPE_SYSTEM, // The Purchase has failed because the Kafra Shop System is not working correctly. (ERROR_TYPE_SYSTEM)
+ ERROR_TYPE_INVENTORY_WEIGHT, // You are over your Weight Limit. (ERROR_TYPE_INVENTORY_WEIGHT)
+ ERROR_TYPE_EXCHANGE, // You cannot purchase items while you are in a trade. (ERROR_TYPE_EXCHANGE)
+ ERROR_TYPE_ITEM_ID, // The Purchase has failed because the Item Information was incorrect. (ERROR_TYPE_ITEM_ID)
+ ERROR_TYPE_MONEY, // You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY)
+ // Unofficial type names
+ ERROR_TYPE_QUANTITY, // You can purchase up to 10 items. (ERROR_TYPE_QUANTITY)
+ ERROR_TYPE_NOT_ALL, // Some items could not be purchased. (ERROR_TYPE_NOT_ALL)
};
/**
@@ -392,6 +434,50 @@ enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED {
BGQND_FAIL_NOT_QUEUING = 11,
};
+enum e_BANKING_DEPOSIT_ACK {
+ BDA_SUCCESS = 0x0,
+ BDA_ERROR = 0x1,
+ BDA_NO_MONEY = 0x2,
+ BDA_OVERFLOW = 0x3,
+};
+enum e_BANKING_WITHDRAW_ACK {
+ BWA_SUCCESS = 0x0,
+ BWA_NO_MONEY = 0x1,
+ BWA_UNKNOWN_ERROR = 0x2,
+};
+
+/* because the client devs were replaced by monkeys. */
+enum e_EQUIP_ITEM_ACK {
+#if PACKETVER >= 20120925
+ EIA_SUCCESS = 0x0,
+ EIA_FAIL_LV = 0x1,
+ EIA_FAIL = 0x2,
+#else
+ EIA_SUCCESS = 0x1,
+ EIA_FAIL_LV = 0x2,
+ EIA_FAIL = 0x0,
+#endif
+};
+
+/* and again. because the client devs were replaced by monkeys. */
+enum e_UNEQUIP_ITEM_ACK {
+#if PACKETVER >= 20120925
+ UIA_SUCCESS = 0x0,
+ UIA_FAIL = 0x1,
+#else
+ UIA_SUCCESS = 0x1,
+ UIA_FAIL = 0x0,
+#endif
+};
+
+enum e_trade_item_ok {
+ TIO_SUCCESS = 0x0,
+ TIO_OVERWEIGHT = 0x1,
+ TIO_CANCEL = 0x2,
+ /* feedback-friendly code that causes the client not to display a error message */
+ TIO_INDROCKS = 0x9,
+};
+
/**
* Structures
**/
@@ -403,7 +489,7 @@ struct s_packet_db {
};
struct {
- unsigned long *colors;
+ unsigned int *colors;
char **colors_name;
unsigned char colors_count;
bool local, ally, irc;
@@ -414,6 +500,7 @@ struct {
bool allow_user_channel_creation;
char irc_server[40], irc_channel[50], irc_nick[40], irc_nick_pw[30];
unsigned short irc_server_port;
+ bool irc_use_ghost;
} hChSys;
struct hChSysBanEntry {
@@ -438,11 +525,16 @@ struct hCSData {
unsigned int price;
};
+struct cdelayed_damage {
+ struct packet_damage p;
+ struct block_list bl;
+};
+
/**
* Vars
**/
struct s_packet_db packet_db[MAX_PACKET_DB + 1];
-unsigned long color_table[COLOR_MAX];
+unsigned int color_table[COLOR_MAX];
/**
* Clif.c Interface
@@ -464,14 +556,18 @@ struct clif_interface {
} cs;
/* */
unsigned int cryptKey[3];
+ /* */
+ bool ally_only;
+ /* */
+ struct eri *delayed_damage_ers;
/* core */
- int (*init) (void);
+ int (*init) (bool minimal);
void (*final) (void);
- int (*setip) (const char* ip);
- void (*setbindip) (const char* ip);
+ bool (*setip) (const char* ip);
+ bool (*setbindip) (const char* ip);
void (*setport) (uint16 port);
uint32 (*refresh_ip) (void);
- int (*send) (const void* buf, int len, struct block_list* bl, enum send_target type);
+ bool (*send) (const void* buf, int len, struct block_list* bl, enum send_target type);
int (*send_sub) (struct block_list *bl, va_list ap);
int (*parse) (int fd);
unsigned short (*parse_cmd) ( int fd, struct map_session_data *sd );
@@ -493,18 +589,21 @@ struct clif_interface {
void (*use_card) (struct map_session_data *sd,int idx);
void (*cart_additem) (struct map_session_data *sd,int n,int amount,int fail);
void (*cart_delitem) (struct map_session_data *sd,int n,int amount);
- void (*equipitemack) (struct map_session_data *sd,int n,int pos,int ok);
- void (*unequipitemack) (struct map_session_data *sd,int n,int pos,int ok);
+ void (*equipitemack) (struct map_session_data *sd,int n,int pos,enum e_EQUIP_ITEM_ACK result);
+ void (*unequipitemack) (struct map_session_data *sd,int n,int pos,enum e_UNEQUIP_ITEM_ACK result);
void (*useitemack) (struct map_session_data *sd,int index,int amount,bool ok);
void (*addcards) (unsigned char* buf, struct item* item);
void (*addcards2) (unsigned short *cards, struct item* item);
void (*item_sub) (unsigned char *buf, int n, struct item *i, struct item_data *id, int equip);
void (*getareachar_item) (struct map_session_data* sd,struct flooritem_data* fitem);
+ void (*cart_additem_ack) (struct map_session_data *sd, int flag);
void (*cashshop_load) (void);
+ void (*package_announce) (struct map_session_data *sd, unsigned short nameid, unsigned short containerid);
+ void (*item_drop_announce) (struct map_session_data *sd, unsigned short nameid, char *monsterName);
/* unit-related */
void (*clearunit_single) (int id, clr_type type, int fd);
void (*clearunit_area) (struct block_list* bl, clr_type type);
- void (*clearunit_delayed) (struct block_list* bl, clr_type type, unsigned int tick);
+ void (*clearunit_delayed) (struct block_list* bl, clr_type type, int64 tick);
void (*walkok) (struct map_session_data *sd);
void (*move) (struct unit_data *ud);
void (*move2) (struct block_list *bl, struct view_data *vd, struct unit_data *ud);
@@ -515,26 +614,28 @@ struct clif_interface {
void (*changetraplook) (struct block_list *bl,int val);
void (*refreshlook) (struct block_list *bl,int id,int type,int val,enum send_target target);
void (*class_change) (struct block_list *bl,int class_,int type);
- void (*skill_setunit) (struct skill_unit *unit);
- void (*skill_delunit) (struct skill_unit *unit);
+ void (*skill_delunit) (struct skill_unit *su);
void (*skillunit_update) (struct block_list* bl);
- int (*clearunit_delayed_sub) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*clearunit_delayed_sub) (int tid, int64 tick, int id, intptr_t data);
void (*set_unit_idle) (struct block_list* bl, struct map_session_data *tsd,enum send_target target);
- void (*spawn_unit) (struct block_list* bl,enum send_target target);
+ void (*spawn_unit) (struct block_list* bl, enum send_target target);
+ void (*spawn_unit2) (struct block_list* bl, enum send_target target);
+ void (*set_unit_idle2) (struct block_list* bl, struct map_session_data *tsd, enum send_target target);
void (*set_unit_walking) (struct block_list* bl, struct map_session_data *tsd,struct unit_data* ud, enum send_target target);
int (*calc_walkdelay) (struct block_list *bl,int delay, int type, int damage, int div_);
- void (*getareachar_skillunit) (struct map_session_data *sd, struct skill_unit *unit);
+ void (*getareachar_skillunit) (struct block_list *bl, struct skill_unit *su, enum send_target target);
void (*getareachar_unit) (struct map_session_data* sd,struct block_list *bl);
- void (*clearchar_skillunit) (struct skill_unit *unit, int fd);
+ void (*clearchar_skillunit) (struct skill_unit *su, int fd);
int (*getareachar) (struct block_list* bl,va_list ap);
+ void (*graffiti_entry) (struct block_list *bl, struct skill_unit *su, enum send_target target);
/* main unit spawn */
- int (*spawn) (struct block_list *bl);
+ bool (*spawn) (struct block_list *bl);
/* map-related */
void (*changemap) (struct map_session_data *sd, short m, int x, int y);
void (*changemapcell) (int fd, int16 m, int x, int y, int type, enum send_target target);
void (*map_property) (struct map_session_data* sd, enum map_property property);
void (*pvpset) (struct map_session_data *sd, int pvprank, int pvpnum,int type);
- void (*map_property_mapall) (int map, enum map_property property);
+ void (*map_property_mapall) (int mapid, enum map_property property);
void (*bossmapinfo) (int fd, struct mob_data *md, short flag);
void (*map_type) (struct map_session_data* sd, enum map_type type);
void (*maptypeproperty2) (struct block_list *bl,enum send_target t);
@@ -560,20 +661,24 @@ struct clif_interface {
void (*scriptclear) (struct map_session_data *sd, int npcid);
/* client-user-interface-related */
void (*viewpoint) (struct map_session_data *sd, int npc_id, int type, int x, int y, int id, int color);
- int (*damage) (struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int damage, int div, int type, int damage2);
+ int (*damage) (struct block_list* src, struct block_list* dst, int sdelay, int ddelay, int64 damage, short div, unsigned char type, int64 damage2);
void (*sitting) (struct block_list* bl);
void (*standing) (struct block_list* bl);
void (*arrow_create_list) (struct map_session_data *sd);
+ void (*refresh_storagewindow) (struct map_session_data *sd);
void (*refresh) (struct map_session_data *sd);
void (*fame_blacksmith) (struct map_session_data *sd, int points);
void (*fame_alchemist) (struct map_session_data *sd, int points);
void (*fame_taekwon) (struct map_session_data *sd, int points);
+ void (*ranklist) (struct map_session_data *sd, enum fame_list_type type);
+ void (*update_rankingpoint) (struct map_session_data *sd, enum fame_list_type type, int points);
+ void (*pRanklist) (int fd, struct map_session_data *sd);
void (*hotkeys) (struct map_session_data *sd);
int (*insight) (struct block_list *bl,va_list ap);
int (*outsight) (struct block_list *bl,va_list ap);
void (*skillcastcancel) (struct block_list* bl);
void (*skill_fail) (struct map_session_data *sd,uint16 skill_id,enum useskill_fail_cause cause,int btype);
- void (*skill_cooldown) (struct map_session_data *sd, uint16 skill_id, unsigned int tick);
+ void (*skill_cooldown) (struct map_session_data *sd, uint16 skill_id, unsigned int duration);
void (*skill_memomessage) (struct map_session_data* sd, int type);
void (*skill_mapinfomessage) (struct map_session_data *sd, int type);
void (*skill_produce_mix_list) (struct map_session_data *sd, int skill_id, int trigger);
@@ -615,11 +720,10 @@ struct clif_interface {
void (*partytickack) (struct map_session_data* sd, bool flag);
void (*equiptickack) (struct map_session_data* sd, int flag);
void (*viewequip_ack) (struct map_session_data* sd, struct map_session_data* tsd);
- void (*viewequip_fail) (struct map_session_data* sd);
void (*equpcheckbox) (struct map_session_data* sd);
- void (*displayexp) (struct map_session_data *sd, unsigned int exp, char type, bool quest);
+ void (*displayexp) (struct map_session_data *sd, unsigned int exp, char type, bool is_quest);
void (*font) (struct map_session_data *sd);
- void (*progressbar) (struct map_session_data * sd, unsigned long color, unsigned int second);
+ void (*progressbar) (struct map_session_data * sd, unsigned int color, unsigned int second);
void (*progressbar_abort) (struct map_session_data * sd);
void (*showdigit) (struct map_session_data* sd, unsigned char type, int value);
int (*elementalconverter_list) (struct map_session_data *sd);
@@ -631,6 +735,7 @@ struct clif_interface {
void (*sc_load) (struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3);
void (*sc_end) (struct block_list *bl, int tid, enum send_target target, int type);
void (*initialstatus) (struct map_session_data *sd);
+ void (*cooldown_list) (int fd, struct skill_cd* cd);
/* player-unit-specific-related */
void (*updatestatus) (struct map_session_data *sd,int type);
void (*changestatus) (struct map_session_data* sd,int type,int val);
@@ -638,7 +743,7 @@ struct clif_interface {
void (*movetoattack) (struct map_session_data *sd,struct block_list *bl);
void (*solved_charname) (int fd, int charid, const char* name);
void (*charnameupdate) (struct map_session_data *ssd);
- int (*delayquit) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*delayquit) (int tid, int64 tick, int id, intptr_t data);
void (*getareachar_pc) (struct map_session_data* sd,struct map_session_data* dstsd);
void (*disconnect_ack) (struct map_session_data* sd, short result);
void (*PVPInfo) (struct map_session_data* sd);
@@ -656,9 +761,9 @@ struct clif_interface {
void (*wedding_effect) (struct block_list *bl);
void (*divorced) (struct map_session_data* sd, const char* name);
void (*callpartner) (struct map_session_data *sd);
- int (*skill_damage) (struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,uint16 skill_id,uint16 skill_lv,int type);
+ int (*skill_damage) (struct block_list *src, struct block_list *dst, int64 tick, int sdelay, int ddelay, int64 damage, int div, uint16 skill_id, uint16 skill_lv, int type);
int (*skill_nodamage) (struct block_list *src,struct block_list *dst,uint16 skill_id,int heal,int fail);
- void (*skill_poseffect) (struct block_list *src,uint16 skill_id,int val,int x,int y,int tick);
+ void (*skill_poseffect) (struct block_list *src, uint16 skill_id, int val, int x, int y, int64 tick);
void (*skill_estimation) (struct map_session_data *sd,struct block_list *dst);
void (*skill_warppoint) (struct map_session_data* sd, uint16 skill_id, uint16 skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4);
void (*skillcasting) (struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, int property, int casttime);
@@ -675,7 +780,7 @@ struct clif_interface {
void (*specialeffect) (struct block_list* bl, int type, enum send_target target);
void (*specialeffect_single) (struct block_list* bl, int type, int fd);
void (*specialeffect_value) (struct block_list* bl, int effect_id, int num, send_target target);
- void (*millenniumshield) (struct map_session_data *sd, short shields );
+ void (*millenniumshield) (struct block_list *bl, short shields );
void (*charm) (struct map_session_data *sd, short type);
void (*charm_single) (int fd, struct map_session_data *sd, short type);
void (*snap) ( struct block_list *bl, short x, short y );
@@ -695,13 +800,12 @@ struct clif_interface {
void (*clearchat) (struct chat_data *cd,int fd);
void (*leavechat) (struct chat_data* cd, struct map_session_data* sd, bool flag);
void (*changechatstatus) (struct chat_data* cd);
- void (*wis_message) (int fd, const char* nick, const char* mes, int mes_len);
+ void (*wis_message) (int fd, const char* nick, const char* mes, size_t mes_len);
void (*wis_end) (int fd, int flag);
- void (*disp_onlyself) (struct map_session_data *sd, const char *mes, int len);
- void (*disp_message) (struct block_list* src, const char* mes, int len, enum send_target target);
- void (*broadcast) (struct block_list* bl, const char* mes, int len, int type, enum send_target target);
- void (*broadcast2) (struct block_list* bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
- void (*messagecolor) (struct block_list* bl, unsigned long color, const char* msg);
+ void (*disp_message) (struct block_list* src, const char* mes, size_t len, enum send_target target);
+ void (*broadcast) (struct block_list* bl, const char* mes, size_t len, int type, enum send_target target);
+ void (*broadcast2) (struct block_list* bl, const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
+ void (*messagecolor) (struct block_list* bl, unsigned int color, const char* msg);
void (*disp_overhead) (struct block_list *bl, const char* mes);
void (*msg) (struct map_session_data* sd, unsigned short id);
void (*msg_value) (struct map_session_data* sd, unsigned short id, int value);
@@ -710,11 +814,14 @@ struct clif_interface {
void (*msgtable_num) (int fd, int line, int num);
void (*message) (const int fd, const char* mes);
void (*messageln) (const int fd, const char* mes);
+ /* message+s(printf) */
+ void (*messages) (const int fd, const char *mes, ...) __attribute__((format(printf, 2, 3)));
int (*colormes) (int fd, enum clif_colors color, const char* msg);
- bool (*process_message) (struct map_session_data* sd, int format, char** name_, int* namelen_, char** message_, int* messagelen_);
+ bool (*process_message) (struct map_session_data *sd, int format, char **name_, size_t *namelen_, char **message_, size_t *messagelen_);
void (*wisexin) (struct map_session_data *sd,int type,int flag);
void (*wisall) (struct map_session_data *sd,int type,int flag);
void (*PMIgnoreList) (struct map_session_data* sd);
+ void (*ShowScript) (struct block_list* bl, const char* message);
/* trade handling */
void (*traderequest) (struct map_session_data* sd, const char* name);
void (*tradestart) (struct map_session_data* sd, uint8 type);
@@ -728,9 +835,9 @@ struct clif_interface {
void (*openvendingreq) (struct map_session_data* sd, int num);
void (*showvendingboard) (struct block_list* bl, const char* message, int fd);
void (*closevendingboard) (struct block_list* bl, int fd);
- void (*vendinglist) (struct map_session_data* sd, unsigned int id, struct s_vending* vending);
+ void (*vendinglist) (struct map_session_data* sd, unsigned int id, struct s_vending* vending_list);
void (*buyvending) (struct map_session_data* sd, int index, int amount, int fail);
- void (*openvending) (struct map_session_data* sd, int id, struct s_vending* vending);
+ void (*openvending) (struct map_session_data* sd, int id, struct s_vending* vending_list);
void (*vendingreport) (struct map_session_data* sd, int index, int amount);
/* storage handling */
void (*storagelist) (struct map_session_data* sd, struct item* items, int items_length);
@@ -740,8 +847,8 @@ struct clif_interface {
void (*storageclose) (struct map_session_data* sd);
/* skill-list handling */
void (*skillinfoblock) (struct map_session_data *sd);
- void (*skillup) (struct map_session_data *sd,uint16 skill_id);
- void (*skillinfo) (struct map_session_data *sd,int skill, int inf);
+ void (*skillup) (struct map_session_data *sd, uint16 skill_id, int skill_lv, int flag);
+ void (*skillinfo) (struct map_session_data *sd,int skill_id, int inf);
void (*addskill) (struct map_session_data *sd, int id);
void (*deleteskill) (struct map_session_data *sd, int id);
/* party-specific */
@@ -779,7 +886,6 @@ struct clif_interface {
void (*guild_emblem_area) (struct block_list* bl);
void (*guild_notice) (struct map_session_data* sd, struct guild* g);
void (*guild_message) (struct guild *g,int account_id,const char *mes,int len);
- int (*guild_skillup) (struct map_session_data *sd,uint16 skill_id,int lv);
void (*guild_reqalliance) (struct map_session_data *sd,int account_id,const char *name);
void (*guild_allianceack) (struct map_session_data *sd,int flag);
void (*guild_delalliance) (struct map_session_data *sd,int guild_id,int flag);
@@ -796,7 +902,7 @@ struct clif_interface {
void (*bg_hp) (struct map_session_data *sd);
void (*bg_xy) (struct map_session_data *sd);
void (*bg_xy_remove) (struct map_session_data *sd);
- void (*bg_message) (struct battleground_data *bg, int src_id, const char *name, const char *mes, int len);
+ void (*bg_message) (struct battleground_data *bgd, int src_id, const char *name, const char *mes, size_t len);
void (*bg_updatescore) (int16 m);
void (*bg_updatescore_single) (struct map_session_data *sd);
void (*sendbgemblem_area) (struct map_session_data *sd);
@@ -820,7 +926,7 @@ struct clif_interface {
void (*friendslist_toggle) (struct map_session_data *sd,int account_id, int char_id, int online);
void (*friendlist_req) (struct map_session_data* sd, int account_id, int char_id, const char* name);
/* gm-related */
- void (*GM_kickack) (struct map_session_data *sd, int id);
+ void (*GM_kickack) (struct map_session_data *sd, int result);
void (*GM_kick) (struct map_session_data *sd,struct map_session_data *tsd);
void (*manner_message) (struct map_session_data* sd, uint32 type);
void (*GM_silence) (struct map_session_data* sd, struct map_session_data* tsd, uint8 type);
@@ -828,17 +934,17 @@ struct clif_interface {
void (*check) (int fd, struct map_session_data* pl_sd);
/* hom-related */
void (*hominfo) (struct map_session_data *sd, struct homun_data *hd, int flag);
- int (*homskillinfoblock) (struct map_session_data *sd);
+ void (*homskillinfoblock) (struct map_session_data *sd);
void (*homskillup) (struct map_session_data *sd, uint16 skill_id);
- int (*hom_food) (struct map_session_data *sd,int foodid,int fail);
+ void (*hom_food) (struct map_session_data *sd,int foodid,int fail);
void (*send_homdata) (struct map_session_data *sd, int state, int param);
/* questlog-related */
- void (*quest_send_list) (struct map_session_data * sd);
- void (*quest_send_mission) (struct map_session_data * sd);
- void (*quest_add) (struct map_session_data * sd, struct quest * qd, int index);
- void (*quest_delete) (struct map_session_data * sd, int quest_id);
- void (*quest_update_status) (struct map_session_data * sd, int quest_id, bool active);
- void (*quest_update_objective) (struct map_session_data * sd, struct quest * qd, int index);
+ void (*quest_send_list) (struct map_session_data *sd);
+ void (*quest_send_mission) (struct map_session_data *sd);
+ void (*quest_add) (struct map_session_data *sd, struct quest *qd);
+ void (*quest_delete) (struct map_session_data *sd, int quest_id);
+ void (*quest_update_status) (struct map_session_data *sd, int quest_id, bool active);
+ void (*quest_update_objective) (struct map_session_data *sd, struct quest *qd);
void (*quest_show_event) (struct map_session_data *sd, struct block_list *bl, short state, short color);
/* mail-related */
void (*mail_window) (int fd, int flag);
@@ -871,14 +977,18 @@ struct clif_interface {
void (*PartyBookingUpdateNotify) (struct map_session_data* sd, struct party_booking_ad_info* pb_ad);
void (*PartyBookingDeleteNotify) (struct map_session_data* sd, int index);
void (*PartyBookingInsertNotify) (struct map_session_data* sd, struct party_booking_ad_info* pb_ad);
+ void (*PartyRecruitRegisterAck) (struct map_session_data *sd, int flag);
+ void (*PartyRecruitDeleteAck) (struct map_session_data* sd, int flag);
+ void (*PartyRecruitSearchAck) (int fd, struct party_booking_ad_info** results, int count, bool more_result);
+ void (*PartyRecruitUpdateNotify) (struct map_session_data* sd, struct party_booking_ad_info* pb_ad);
+ void (*PartyRecruitDeleteNotify) (struct map_session_data* sd, int index);
+ void (*PartyRecruitInsertNotify) (struct map_session_data* sd, struct party_booking_ad_info* pb_ad);
/* Group Search System Update */
-#ifdef PARTY_RECRUIT
void (*PartyBookingVolunteerInfo) (int index, struct map_session_data *sd);
- void (*PartyBookingRefuseVolunteer) (unsigned long aid, struct map_session_data *sd);
+ void (*PartyBookingRefuseVolunteer) (unsigned int aid, struct map_session_data *sd);
void (*PartyBookingCancelVolunteer) (int index, struct map_session_data *sd);
void (*PartyBookingAddFilteringList) (int index, struct map_session_data *sd);
void (*PartyBookingSubFilteringList) (int gid, struct map_session_data *sd);
-#endif
/* buying store-related */
void (*buyingstore_open) (struct map_session_data* sd);
void (*buyingstore_open_failed) (struct map_session_data* sd, unsigned short result, unsigned int weight);
@@ -902,7 +1012,7 @@ struct clif_interface {
void (*elemental_updatestatus) (struct map_session_data *sd, int type);
/* bgqueue */
void (*bgqueue_ack) (struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK response, unsigned char arena_id);
- void (*bgqueue_notice_delete) (struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, unsigned char arena_id);
+ void (*bgqueue_notice_delete) (struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, char *name);
void (*bgqueue_update_info) (struct map_session_data *sd, unsigned char arena_id, int position);
void (*bgqueue_joined) (struct map_session_data *sd, int pos);
void (*bgqueue_pcleft) (struct map_session_data *sd);
@@ -911,13 +1021,16 @@ struct clif_interface {
void (*adopt_reply) (struct map_session_data *sd, int type);
void (*adopt_request) (struct map_session_data *sd, struct map_session_data *src, int p_id);
void (*readbook) (int fd, int book_id, int page);
- void (*notify_time) (struct map_session_data* sd, unsigned long time);
+ void (*notify_time) (struct map_session_data* sd, int64 time);
void (*user_count) (struct map_session_data* sd, int count);
void (*noask_sub) (struct map_session_data *src, struct map_session_data *target, int type);
+ void (*bc_ready) (void);
+ int (*undisguise_timer) (int tid, int64 tick, int id, intptr_t data);
+ /* Hercules Channel System */
void (*chsys_create) (struct hChSysCh *channel, char *name, char *pass, unsigned char color);
void (*chsys_msg) (struct hChSysCh *channel, struct map_session_data *sd, char *msg);
void (*chsys_msg2) (struct hChSysCh *channel, char *msg);
- void (*chsys_send) (struct hChSysCh *channel, struct map_session_data *sd, char *msg);
+ void (*chsys_send) (struct hChSysCh *channel, struct map_session_data *sd, const char *msg);
void (*chsys_join) (struct hChSysCh *channel, struct map_session_data *sd);
void (*chsys_left) (struct hChSysCh *channel, struct map_session_data *sd);
void (*chsys_delete) (struct hChSysCh *channel);
@@ -926,8 +1039,19 @@ struct clif_interface {
void (*chsys_quitg) (struct map_session_data *sd);
void (*chsys_gjoin) (struct guild *g1,struct guild *g2);
void (*chsys_gleave) (struct guild *g1,struct guild *g2);
- void (*bc_ready) (void);
- int (*undisguise_timer) (int tid, unsigned int tick, int id, intptr_t data);
+ /* Bank System [Yommy/Hercules] */
+ void (*bank_deposit) (struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason);
+ void (*bank_withdraw) (struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason);
+ /* */
+ void (*show_modifiers) (struct map_session_data *sd);
+ /* */
+ void (*notify_bounditem) (struct map_session_data *sd, unsigned short index);
+ /* */
+ int (*delay_damage) (int64 tick, struct block_list *src, struct block_list *dst, int sdelay, int ddelay, int64 in_damage, short div, unsigned char type);
+ int (*delay_damage_sub) (int tid, int64 tick, int id, intptr_t data);
+ /* NPC Market */
+ void (*npc_market_open) (struct map_session_data *sd, struct npc_data *nd);
+ void (*npc_market_purchase_ack) (struct map_session_data *sd, struct packet_npc_market_purchase *req, unsigned char response);
/*------------------------
*- Parse Incoming Packet
*------------------------*/
@@ -945,7 +1069,7 @@ struct clif_interface {
void (*pEmotion) (int fd, struct map_session_data *sd);
void (*pHowManyConnections) (int fd, struct map_session_data *sd);
void (*pActionRequest) (int fd, struct map_session_data *sd);
- void (*pActionRequest_sub) (struct map_session_data *sd, int action_type, int target_id, unsigned int tick);
+ void (*pActionRequest_sub) (struct map_session_data *sd, int action_type, int target_id, int64 tick);
void (*pRestart) (int fd, struct map_session_data *sd);
void (*pWisMessage) (int fd, struct map_session_data* sd);
void (*pBroadcast) (int fd, struct map_session_data* sd);
@@ -979,12 +1103,12 @@ struct clif_interface {
void (*pStatusUp) (int fd,struct map_session_data *sd);
void (*pSkillUp) (int fd,struct map_session_data *sd);
void (*pUseSkillToId) (int fd, struct map_session_data *sd);
- void (*pUseSkillToId_homun) (struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id);
- void (*pUseSkillToId_mercenary) (struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id);
+ void (*pUseSkillToId_homun) (struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id);
+ void (*pUseSkillToId_mercenary) (struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, int target_id);
void (*pUseSkillToPos) (int fd, struct map_session_data *sd);
void (*pUseSkillToPosSub) (int fd, struct map_session_data *sd, uint16 skill_lv, uint16 skill_id, short x, short y, int skillmoreinfo);
- void (*pUseSkillToPos_homun) (struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo);
- void (*pUseSkillToPos_mercenary) (struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo);
+ void (*pUseSkillToPos_homun) (struct homun_data *hd, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo);
+ void (*pUseSkillToPos_mercenary) (struct mercenary_data *md, struct map_session_data *sd, int64 tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo);
void (*pUseSkillToPosMoreInfo) (int fd, struct map_session_data *sd);
void (*pUseSkillMap) (int fd, struct map_session_data* sd);
void (*pRequestMemo) (int fd,struct map_session_data *sd);
@@ -1026,6 +1150,10 @@ struct clif_interface {
void (*pPartyBookingSearchReq) (int fd, struct map_session_data* sd);
void (*pPartyBookingDeleteReq) (int fd, struct map_session_data* sd);
void (*pPartyBookingUpdateReq) (int fd, struct map_session_data* sd);
+ void (*pPartyRecruitRegisterReq) (int fd, struct map_session_data* sd);
+ void (*pPartyRecruitSearchReq) (int fd, struct map_session_data* sd);
+ void (*pPartyRecruitDeleteReq) (int fd, struct map_session_data* sd);
+ void (*pPartyRecruitUpdateReq) (int fd, struct map_session_data* sd);
void (*pCloseVending) (int fd, struct map_session_data* sd);
void (*pVendingListReq) (int fd, struct map_session_data* sd);
void (*pPurchaseReq) (int fd, struct map_session_data* sd);
@@ -1066,6 +1194,7 @@ struct clif_interface {
void (*pGMRc) (int fd, struct map_session_data* sd);
void (*pGMReqAccountName) (int fd, struct map_session_data *sd);
void (*pGMChangeMapType) (int fd, struct map_session_data *sd);
+ void (*pGMFullStrip) (int fd, struct map_session_data *sd);
void (*pPMIgnore) (int fd, struct map_session_data* sd);
void (*pPMIgnoreAll) (int fd, struct map_session_data *sd);
void (*pPMIgnoreList) (int fd,struct map_session_data *sd);
@@ -1139,17 +1268,26 @@ struct clif_interface {
void (*pPartyTick) (int fd, struct map_session_data *sd);
void (*pGuildInvite2) (int fd, struct map_session_data *sd);
/* Group Search System Update */
-#ifdef PARTY_RECRUIT
void (*pPartyBookingAddFilter) (int fd, struct map_session_data *sd);
void (*pPartyBookingSubFilter) (int fd, struct map_session_data *sd);
void (*pPartyBookingReqVolunteer) (int fd, struct map_session_data *sd);
void (*pPartyBookingRefuseVolunteer) (int fd, struct map_session_data *sd);
void (*pPartyBookingCancelVolunteer) (int fd, struct map_session_data *sd);
-#endif
-} clif_s;
+ /* Bank System [Yommy/Hercules] */
+ void (*pBankDeposit) (int fd, struct map_session_data *sd);
+ void (*pBankWithdraw) (int fd, struct map_session_data *sd);
+ void (*pBankCheck) (int fd, struct map_session_data *sd);
+ void (*pBankOpen) (int fd, struct map_session_data *sd);
+ void (*pBankClose) (int fd, struct map_session_data *sd);
+ /* */
+ void (*pNPCShopClosed) (int fd, struct map_session_data *sd);
+ /* NPC Market (by Ind after an extensive debugging of the packet, only possible thanks to Yommy <3) */
+ void (*pNPCMarketClosed) (int fd, struct map_session_data *sd);
+ void (*pNPCMarketPurchase) (int fd, struct map_session_data *sd);
+};
struct clif_interface *clif;
void clif_defaults(void);
-#endif /* _CLIF_H_ */
+#endif /* MAP_CLIF_H */
diff --git a/src/map/date.c b/src/map/date.c
index 9f2bc4bee..975a00c50 100644
--- a/src/map/date.c
+++ b/src/map/date.c
@@ -1,9 +1,14 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
+#define HERCULES_CORE
+
#include "date.h"
+
#include <time.h>
+#include "../common/cbasetypes.h"
+
int date_get_year(void)
{
time_t t;
@@ -55,17 +60,21 @@ int date_get_sec(void)
return lt->tm_sec;
}
-int is_day_of_sun(void)
+/*==========================================
+ * Star gladiator related checks
+ *------------------------------------------*/
+
+bool is_day_of_sun(void)
{
return date_get_day()%2 == 0;
}
-int is_day_of_moon(void)
+bool is_day_of_moon(void)
{
return date_get_day()%2 == 1;
}
-int is_day_of_star(void)
+bool is_day_of_star(void)
{
return date_get_day()%5 == 0;
}
diff --git a/src/map/date.h b/src/map/date.h
index cc19d88d1..c3f353f64 100644
--- a/src/map/date.h
+++ b/src/map/date.h
@@ -1,8 +1,10 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
-#ifndef _DATE_H_
-#define _DATE_H_
+#ifndef MAP_DATE_H
+#define MAP_DATE_H
+
+#include "../common/cbasetypes.h"
int date_get_year(void);
int date_get_month(void);
@@ -11,8 +13,8 @@ int date_get_hour(void);
int date_get_min(void);
int date_get_sec(void);
-int is_day_of_sun(void);
-int is_day_of_moon(void);
-int is_day_of_star(void);
+bool is_day_of_sun(void);
+bool is_day_of_moon(void);
+bool is_day_of_star(void);
-#endif /* _DATE_H_ */
+#endif /* MAP_DATE_H */
diff --git a/src/map/duel.c b/src/map/duel.c
index 9a8b6d12b..4e4eeef1f 100644
--- a/src/map/duel.c
+++ b/src/map/duel.c
@@ -2,45 +2,42 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
+#define HERCULES_CORE
-#include "atcommand.h" // msg_txt
-#include "clif.h"
#include "duel.h"
-#include "pc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
-struct duel duel_list[MAX_DUEL];
-int duel_count = 0;
+#include "atcommand.h" // msg_txt
+#include "clif.h"
+#include "pc.h"
+#include "../common/cbasetypes.h"
/*==========================================
* Duel organizing functions [LuzZza]
*------------------------------------------*/
-void duel_savetime(struct map_session_data* sd)
-{
- time_t timer;
+void duel_savetime(struct map_session_data* sd) {
+ time_t clock;
struct tm *t;
- time(&timer);
- t = localtime(&timer);
+ time(&clock);
+ t = localtime(&clock);
- pc_setglobalreg(sd, "PC_LAST_DUEL_TIME", t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min);
+ pc_setglobalreg(sd, script->add_str("PC_LAST_DUEL_TIME"), t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min);
}
-int duel_checktime(struct map_session_data* sd)
-{
+int duel_checktime(struct map_session_data* sd) {
int diff;
- time_t timer;
+ time_t clock;
struct tm *t;
- time(&timer);
- t = localtime(&timer);
+ time(&clock);
+ t = localtime(&clock);
- diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min - pc_readglobalreg(sd, "PC_LAST_DUEL_TIME");
+ diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min - pc_readglobalreg(sd, script->add_str("PC_LAST_DUEL_TIME") );
return !(diff >= 0 && diff < battle_config.duel_time_interval);
}
@@ -53,55 +50,52 @@ static int duel_showinfo_sub(struct map_session_data* sd, va_list va)
if (sd->duel_group != ssd->duel_group) return 0;
sprintf(output, " %d. %s", ++(*p), sd->status.name);
- clif->disp_onlyself(ssd, output, strlen(output));
+ clif_disp_onlyself(ssd, output, strlen(output));
return 1;
}
-void duel_showinfo(const unsigned int did, struct map_session_data* sd)
-{
+void duel_showinfo(const unsigned int did, struct map_session_data* sd) {
int p=0;
char output[256];
- if(duel_list[did].max_players_limit > 0)
+ if(duel->list[did].max_players_limit > 0)
sprintf(output, msg_txt(370), //" -- Duels: %d/%d, Members: %d/%d, Max players: %d --"
- did, duel_count,
- duel_list[did].members_count,
- duel_list[did].members_count + duel_list[did].invites_count,
- duel_list[did].max_players_limit);
+ did, duel->count,
+ duel->list[did].members_count,
+ duel->list[did].members_count + duel->list[did].invites_count,
+ duel->list[did].max_players_limit);
else
sprintf(output, msg_txt(371), //" -- Duels: %d/%d, Members: %d/%d --"
- did, duel_count,
- duel_list[did].members_count,
- duel_list[did].members_count + duel_list[did].invites_count);
+ did, duel->count,
+ duel->list[did].members_count,
+ duel->list[did].members_count + duel->list[did].invites_count);
- clif->disp_onlyself(sd, output, strlen(output));
- iMap->map_foreachpc(duel_showinfo_sub, sd, &p);
+ clif_disp_onlyself(sd, output, strlen(output));
+ map->foreachpc(duel_showinfo_sub, sd, &p);
}
-int duel_create(struct map_session_data* sd, const unsigned int maxpl)
-{
+int duel_create(struct map_session_data* sd, const unsigned int maxpl) {
int i=1;
char output[256];
- while(duel_list[i].members_count > 0 && i < MAX_DUEL) i++;
+ while(duel->list[i].members_count > 0 && i < MAX_DUEL) i++;
if(i == MAX_DUEL) return 0;
- duel_count++;
+ duel->count++;
sd->duel_group = i;
- duel_list[i].members_count++;
- duel_list[i].invites_count = 0;
- duel_list[i].max_players_limit = maxpl;
+ duel->list[i].members_count++;
+ duel->list[i].invites_count = 0;
+ duel->list[i].max_players_limit = maxpl;
strcpy(output, msg_txt(372)); // " -- Duel has been created (@invite/@leave) --"
- clif->disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE);
clif->maptypeproperty2(&sd->bl,SELF);
return i;
}
-void duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd)
-{
+void duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd) {
char output[256];
// " -- Player %s invites %s to duel --"
@@ -109,11 +103,11 @@ void duel_invite(const unsigned int did, struct map_session_data* sd, struct map
clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
target_sd->duel_invite = did;
- duel_list[did].invites_count++;
+ duel->list[did].invites_count++;
// "Blue -- Player %s invites you to PVP duel (@accept/@reject) --"
sprintf(output, msg_txt(374), sd->status.name);
- clif->broadcast((struct block_list *)target_sd, output, strlen(output)+1, 0x10, SELF);
+ clif->broadcast((struct block_list *)target_sd, output, strlen(output)+1, BC_BLUE, SELF);
}
static int duel_leave_sub(struct map_session_data* sd, va_list va)
@@ -124,19 +118,18 @@ static int duel_leave_sub(struct map_session_data* sd, va_list va)
return 0;
}
-void duel_leave(const unsigned int did, struct map_session_data* sd)
-{
+void duel_leave(const unsigned int did, struct map_session_data* sd) {
char output[256];
// " <- Player %s has left duel --"
sprintf(output, msg_txt(375), sd->status.name);
clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
- duel_list[did].members_count--;
+ duel->list[did].members_count--;
- if(duel_list[did].members_count == 0) {
- iMap->map_foreachpc(duel_leave_sub, did);
- duel_count--;
+ if(duel->list[did].members_count == 0) {
+ map->foreachpc(duel_leave_sub, did);
+ duel->count--;
}
sd->duel_group = 0;
@@ -145,13 +138,12 @@ void duel_leave(const unsigned int did, struct map_session_data* sd)
clif->maptypeproperty2(&sd->bl,SELF);
}
-void duel_accept(const unsigned int did, struct map_session_data* sd)
-{
+void duel_accept(const unsigned int did, struct map_session_data* sd) {
char output[256];
- duel_list[did].members_count++;
+ duel->list[did].members_count++;
sd->duel_group = sd->duel_invite;
- duel_list[did].invites_count--;
+ duel->list[did].invites_count--;
sd->duel_invite = 0;
// " -> Player %s has accepted duel --"
@@ -162,23 +154,46 @@ void duel_accept(const unsigned int did, struct map_session_data* sd)
clif->maptypeproperty2(&sd->bl,SELF);
}
-void duel_reject(const unsigned int did, struct map_session_data* sd)
-{
+void duel_reject(const unsigned int did, struct map_session_data* sd) {
char output[256];
// " -- Player %s has rejected duel --"
sprintf(output, msg_txt(377), sd->status.name);
clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
- duel_list[did].invites_count--;
+ duel->list[did].invites_count--;
sd->duel_invite = 0;
}
-void do_final_duel(void)
-{
+void do_final_duel(void) {
}
-void do_init_duel(void)
-{
- memset(&duel_list[0], 0, sizeof(duel_list));
+void do_init_duel(bool minimal) {
+ if (minimal)
+ return;
+
+ memset(&duel->list[0], 0, sizeof(duel->list));
+}
+
+/*=====================================
+* Default Functions : duel.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+void duel_defaults(void) {
+ duel = &duel_s;
+ /* vars */
+ duel->count = 0;
+ /* funcs */
+ //Duel functions // [LuzZza]
+ duel->create = duel_create;
+ duel->invite = duel_invite;
+ duel->accept = duel_accept;
+ duel->reject = duel_reject;
+ duel->leave = duel_leave;
+ duel->showinfo = duel_showinfo;
+ duel->checktime = duel_checktime;
+
+ duel->init = do_init_duel;
+ duel->final = do_final_duel;
}
diff --git a/src/map/duel.h b/src/map/duel.h
index 04d8e4e84..de2bd1bf6 100644
--- a/src/map/duel.h
+++ b/src/map/duel.h
@@ -1,8 +1,13 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _DUEL_H_
-#define _DUEL_H_
+#ifndef MAP_DUEL_H
+#define MAP_DUEL_H
+
+#include "../common/cbasetypes.h"
+
+struct map_session_data;
struct duel {
int members_count;
@@ -11,19 +16,34 @@ struct duel {
};
#define MAX_DUEL 1024
-extern struct duel duel_list[MAX_DUEL];
-extern int duel_count;
-
-//Duel functions // [LuzZza]
-int duel_create(struct map_session_data* sd, const unsigned int maxpl);
-void duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd);
-void duel_accept(const unsigned int did, struct map_session_data* sd);
-void duel_reject(const unsigned int did, struct map_session_data* sd);
-void duel_leave(const unsigned int did, struct map_session_data* sd);
-void duel_showinfo(const unsigned int did, struct map_session_data* sd);
-int duel_checktime(struct map_session_data* sd);
-
-void do_init_duel(void);
-void do_final_duel(void);
-
-#endif /* _DUEL_H_ */
+
+/*=====================================
+* Interface : duel.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+struct duel_interface {
+
+ /* vars */
+ struct duel list[MAX_DUEL];
+ int count;
+
+ /* funcs */
+ //Duel functions // [LuzZza]
+ int (*create) (struct map_session_data* sd, const unsigned int maxpl);
+ void (*invite) (const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd);
+ void (*accept) (const unsigned int did, struct map_session_data* sd);
+ void (*reject) (const unsigned int did, struct map_session_data* sd);
+ void (*leave) (const unsigned int did, struct map_session_data* sd);
+ void (*showinfo) (const unsigned int did, struct map_session_data* sd);
+ int (*checktime) (struct map_session_data* sd);
+
+ void (*init) (bool minimal);
+ void (*final) (void);
+} duel_s;
+
+struct duel_interface *duel;
+
+void duel_defaults(void);
+
+#endif /* MAP_DUEL_H */
diff --git a/src/map/elemental.c b/src/map/elemental.c
index 53c85577b..caba02692 100644
--- a/src/map/elemental.c
+++ b/src/map/elemental.c
@@ -2,142 +2,148 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/malloc.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/mmo.h"
-#include "../common/showmsg.h"
-#include "../common/utils.h"
-#include "../common/random.h"
-#include "../common/strlib.h"
+#define HERCULES_CORE
-#include "log.h"
-#include "clif.h"
+#include "elemental.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "atcommand.h"
+#include "battle.h"
#include "chrif.h"
+#include "clif.h"
+#include "guild.h"
#include "intif.h"
#include "itemdb.h"
+#include "log.h"
#include "map.h"
-#include "pc.h"
-#include "status.h"
-#include "skill.h"
#include "mob.h"
-#include "pet.h"
-#include "battle.h"
+#include "npc.h"
#include "party.h"
-#include "guild.h"
-#include "atcommand.h"
+#include "pc.h"
+#include "pet.h"
#include "script.h"
-#include "npc.h"
+#include "skill.h"
+#include "status.h"
#include "trade.h"
#include "unit.h"
-#include "elemental.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
+#include "../common/cbasetypes.h"
+#include "../common/malloc.h"
+#include "../common/mmo.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-struct s_elemental_db elemental_db[MAX_ELEMENTAL_CLASS]; // Elemental Database
+struct elemental_interface elemental_s;
int elemental_search_index(int class_) {
int i;
- ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, elemental_db[i].class_ == class_);
+ ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, elemental->db[i].class_ == class_);
return (i == MAX_ELEMENTAL_CLASS)?-1:i;
}
bool elemental_class(int class_) {
- return (bool)(elemental_search_index(class_) > -1);
+ return (bool)(elemental->search_index(class_) > -1);
}
struct view_data * elemental_get_viewdata(int class_) {
- int i = elemental_search_index(class_);
+ int i = elemental->search_index(class_);
if( i < 0 )
return 0;
- return &elemental_db[i].vd;
+ return &elemental->db[i].vd;
}
int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime) {
struct s_elemental ele;
struct s_elemental_db *db;
- int i;
+ int i, summon_level, skill_level;
nullpo_retr(1,sd);
- if( (i = elemental_search_index(class_)) < 0 )
+ if( (i = elemental->search_index(class_)) < 0 )
return 0;
- db = &elemental_db[i];
+ db = &elemental->db[i];
memset(&ele,0,sizeof(struct s_elemental));
ele.char_id = sd->status.char_id;
ele.class_ = class_;
ele.mode = EL_MODE_PASSIVE; // Initial mode
- i = db->status.size+1; // summon level
+ summon_level = db->status.size+1; // summon level
- //[(Casterソスs Max HP/ 3 ) + (Casterソスs INT x 10 )+ (Casterソスs Job Level x 20 )] x [(Elemental Summon Level + 2) / 3]
- ele.hp = ele.max_hp = (sd->battle_status.max_hp/3 + sd->battle_status.int_*10 + sd->status.job_level) * ((i + 2) / 3);
- //Casterソスs Max SP /4
+ //[(Caster's Max HP/ 3 ) + (Caster's INT x 10 )+ (Caster's Job Level x 20 )] x [(Elemental Summon Level + 2) / 3]
+ ele.hp = ele.max_hp = (sd->battle_status.max_hp/3 + sd->battle_status.int_*10 + sd->status.job_level) * ((summon_level + 2) / 3);
+ //Caster's Max SP /4
ele.sp = ele.max_sp = sd->battle_status.max_sp/4;
- //Casterソスs [ Max SP / (18 / Elemental Summon Skill Level) 1- 100 ]
- ele.atk = (sd->battle_status.max_sp / (18 / i) * 1 - 100);
- //Casterソスs [ Max SP / (18 / Elemental Summon Skill Level) ]
+ //Caster's [ Max SP / (18 / Elemental Summon Skill Level) 1- 100 ]
+ ele.atk = (sd->battle_status.max_sp / (18 / summon_level) * 1 - 100);
+ //Caster's [ Max SP / (18 / Elemental Summon Skill Level) ]
ele.atk2 = sd->battle_status.max_sp / 18;
- //Casterソスs HIT + (Casterソスs Base Level )
+ //Caster's HIT + (Caster's Base Level)
ele.hit = sd->battle_status.hit + sd->status.base_level;
- //[Elemental Summon Skill Level x (Casterソスs INT / 2 + Casterソスs DEX / 4)]
- ele.matk = i * (sd->battle_status.int_ / 2 + sd->battle_status.dex / 4);
- //150 + [Casterソスs DEX / 10] + [Elemental Summon Skill Level x 3 ]
- ele.amotion = 150 + sd->battle_status.dex / 10 + i * 3;
- //Casterソスs DEF + (Casterソスs Base Level / (5 ソス Elemental Summon Skill Level)
- ele.def = sd->battle_status.def + sd->status.base_level / (5-i);
- //Casterソスs MDEF + (Casterソスs INT / (5 - Elemental Summon Skill Level)
- ele.mdef = sd->battle_status.mdef + sd->battle_status.int_ / (5-i);
- //Casterソスs FLEE + (Casterソスs Base Level / (5 ソス Elemental Summon Skill Level)
- ele.flee = sd->status.base_level / (5-i);
- //Casterソスs HIT + (Casterソスs Base Level )
+ //[Elemental Summon Skill Level x (Caster's INT / 2 + Caster's DEX / 4)]
+ ele.matk = summon_level * (sd->battle_status.int_ / 2 + sd->battle_status.dex / 4);
+ //150 + [Caster's DEX / 10] + [Elemental Summon Skill Level x 3 ]
+ ele.amotion = 150 + sd->battle_status.dex / 10 + summon_level * 3;
+ //Caster's DEF + (Caster's Base Level / (5 - Elemental Summon Skill Level)
+ ele.def = sd->battle_status.def + sd->status.base_level / (5-summon_level);
+ //Caster's MDEF + (Caster's INT / (5 - Elemental Summon Skill Level)
+ ele.mdef = sd->battle_status.mdef + sd->battle_status.int_ / (5-summon_level);
+ //Caster's FLEE + (Caster's Base Level / (5 - Elemental Summon Skill Level)
+ ele.flee = sd->status.base_level / (5-summon_level);
+ //Caster's HIT + (Caster's Base Level)
ele.hit = sd->battle_status.hit + sd->status.base_level;
//per individual bonuses
switch(db->class_){
- case 2114: case 2115:
+ case 2114:
+ case 2115:
case 2116: //ATK + (Summon Agni Skill Level x 20) / HIT + (Summon Agni Skill Level x 10)
- ele.atk += i * 20;
- ele.atk2 += i * 20;
- ele.hit += i * 10;
+ ele.atk += summon_level * 20;
+ ele.atk2 += summon_level * 20;
+ ele.hit += summon_level * 10;
break;
- case 2117: case 2118:
+ case 2117:
+ case 2118:
case 2119: //MDEF + (Summon Aqua Skill Level x 10) / MATK + (Summon Aqua Skill Level x 20)
- ele.mdef += i * 10;
- ele.matk += i * 20;
+ ele.mdef += summon_level * 10;
+ ele.matk += summon_level * 20;
break;
- case 2120: case 2121:
+ case 2120:
+ case 2121:
case 2122: //FLEE + (Summon Ventus Skill Level x 20) / MATK + (Summon Ventus Skill Level x 10)
- ele.flee += i * 20;
- ele.matk += i * 10;
+ ele.flee += summon_level * 20;
+ ele.matk += summon_level * 10;
break;
- case 2123: case 2124:
+ case 2123:
+ case 2124:
case 2125: //DEF + (Summon Tera Skill Level x 25) / ATK + (Summon Tera Skill Level x 5)
- ele.def += i * 25;
- ele.atk += i * 5;
- ele.atk2 += i * 5;
+ ele.def += summon_level * 25;
+ ele.atk += summon_level * 5;
+ ele.atk2 += summon_level * 5;
break;
}
- if( (i=pc->checkskill(sd,SO_EL_SYMPATHY)) > 0 ){
- ele.hp = ele.max_hp = ele.max_hp * 5 * i / 100;
- ele.sp = ele.max_sp = ele.max_sp * 5 * i / 100;
- ele.atk += 25 * i;
- ele.atk2 += 25 * i;
- ele.matk += 25 * i;
+ if ((skill_level=pc->checkskill(sd,SO_EL_SYMPATHY)) > 0) {
+ ele.hp = ele.max_hp += ele.max_hp * 5 * skill_level / 100;
+ ele.sp = ele.max_sp += ele.max_sp * 5 * skill_level / 100;
+ ele.atk += 25 * skill_level;
+ ele.atk2 += 25 * skill_level;
+ ele.matk += 25 * skill_level;
}
ele.life_time = lifetime;
// Request Char Server to create this elemental
- intif_elemental_create(&ele);
+ intif->elemental_create(&ele);
return 1;
}
@@ -147,8 +153,8 @@ int elemental_get_lifetime(struct elemental_data *ed) {
if( ed == NULL || ed->summon_timer == INVALID_TIMER )
return 0;
- td = iTimer->get_timer(ed->summon_timer);
- return (td != NULL) ? DIFF_TICK(td->tick, iTimer->gettick()) : 0;
+ td = timer->get(ed->summon_timer);
+ return (td != NULL) ? DIFF_TICK32(td->tick, timer->gettick()) : 0;
}
int elemental_save(struct elemental_data *ed) {
@@ -164,27 +170,27 @@ int elemental_save(struct elemental_data *ed) {
ed->elemental.mdef = ed->battle_status.mdef;
ed->elemental.flee = ed->battle_status.flee;
ed->elemental.hit = ed->battle_status.hit;
- ed->elemental.life_time = elemental_get_lifetime(ed);
- intif_elemental_save(&ed->elemental);
+ ed->elemental.life_time = elemental->get_lifetime(ed);
+ intif->elemental_save(&ed->elemental);
return 1;
}
-static int elemental_summon_end(int tid, unsigned int tick, int id, intptr_t data) {
+int elemental_summon_end_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
struct elemental_data *ed;
- if( (sd = iMap->id2sd(id)) == NULL )
+ if( (sd = map->id2sd(id)) == NULL )
return 1;
if( (ed = sd->ed) == NULL )
return 1;
if( ed->summon_timer != tid ) {
- ShowError("elemental_summon_end %d != %d.\n", ed->summon_timer, tid);
+ ShowError("elemental_summon_end_timer %d != %d.\n", ed->summon_timer, tid);
return 0;
}
ed->summon_timer = INVALID_TIMER;
- elemental_delete(ed, 0); // Elemental's summon time is over.
+ elemental->delete(ed, 0); // Elemental's summon time is over.
return 0;
}
@@ -192,7 +198,7 @@ static int elemental_summon_end(int tid, unsigned int tick, int id, intptr_t dat
void elemental_summon_stop(struct elemental_data *ed) {
nullpo_retv(ed);
if( ed->summon_timer != INVALID_TIMER )
- iTimer->delete_timer(ed->summon_timer, elemental_summon_end);
+ timer->delete(ed->summon_timer, elemental->summon_end_timer);
ed->summon_timer = INVALID_TIMER;
}
@@ -203,21 +209,21 @@ int elemental_delete(struct elemental_data *ed, int reply) {
sd = ed->master;
ed->elemental.life_time = 0;
- elemental_clean_effect(ed);
- elemental_summon_stop(ed);
+ elemental->clean_effect(ed);
+ elemental->summon_stop(ed);
if( !sd )
- return unit_free(&ed->bl, 0);
+ return unit->free(&ed->bl, 0);
sd->ed = NULL;
sd->status.ele_id = 0;
- return unit_remove_map(&ed->bl, 0);
+ return unit->remove_map(&ed->bl, 0, ALC_MARK);
}
void elemental_summon_init(struct elemental_data *ed) {
if( ed->summon_timer == INVALID_TIMER )
- ed->summon_timer = iTimer->add_timer(iTimer->gettick() + ed->elemental.life_time, elemental_summon_end, ed->master->bl.id, 0);
+ ed->summon_timer = timer->add(timer->gettick() + ed->elemental.life_time, elemental->summon_end_timer, ed->master->bl.id, 0);
ed->regen.state.block = 0;
}
@@ -226,9 +232,9 @@ int elemental_data_received(struct s_elemental *ele, bool flag) {
struct map_session_data *sd;
struct elemental_data *ed;
struct s_elemental_db *db;
- int i = elemental_search_index(ele->class_);
+ int i = elemental->search_index(ele->class_);
- if( (sd = iMap->charid2sd(ele->char_id)) == NULL )
+ if( (sd = map->charid2sd(ele->char_id)) == NULL )
return 0;
if( !flag || i < 0 ) { // Not created - loaded - DB info
@@ -236,32 +242,32 @@ int elemental_data_received(struct s_elemental *ele, bool flag) {
return 0;
}
- db = &elemental_db[i];
+ db = &elemental->db[i];
if( !sd->ed ) { // Initialize it after first summon.
sd->ed = ed = (struct elemental_data*)aCalloc(1,sizeof(struct elemental_data));
ed->bl.type = BL_ELEM;
- ed->bl.id = npc_get_new_npc_id();
+ ed->bl.id = npc->get_new_npc_id();
ed->master = sd;
ed->db = db;
memcpy(&ed->elemental, ele, sizeof(struct s_elemental));
- status_set_viewdata(&ed->bl, ed->elemental.class_);
+ status->set_viewdata(&ed->bl, ed->elemental.class_);
ed->vd->head_mid = 10; // Why?
- status_change_init(&ed->bl);
- unit_dataset(&ed->bl);
+ status->change_init(&ed->bl);
+ unit->dataset(&ed->bl);
ed->ud.dir = sd->ud.dir;
ed->bl.m = sd->bl.m;
ed->bl.x = sd->bl.x;
ed->bl.y = sd->bl.y;
- unit_calc_pos(&ed->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
+ unit->calc_pos(&ed->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
ed->bl.x = ed->ud.to_x;
ed->bl.y = ed->ud.to_y;
- iMap->addiddb(&ed->bl);
- status_calc_elemental(ed,1);
- ed->last_spdrain_time = ed->last_thinktime = iTimer->gettick();
+ map->addiddb(&ed->bl);
+ status_calc_elemental(ed,SCO_FIRST);
+ ed->last_spdrain_time = ed->last_thinktime = timer->gettick();
ed->summon_timer = INVALID_TIMER;
- elemental_summon_init(ed);
+ elemental->summon_init(ed);
} else {
memcpy(&sd->ed->elemental, ele, sizeof(struct s_elemental));
ed = sd->ed;
@@ -270,7 +276,7 @@ int elemental_data_received(struct s_elemental *ele, bool flag) {
sd->status.ele_id = ele->elemental_id;
if( ed->bl.prev == NULL && sd->bl.prev != NULL ) {
- iMap->addblock(&ed->bl);
+ map->addblock(&ed->bl);
clif->spawn(&ed->bl);
clif->elemental_info(sd);
clif->elemental_updatestatus(sd,SP_HP);
@@ -283,7 +289,7 @@ int elemental_data_received(struct s_elemental *ele, bool flag) {
int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id) {
struct block_list *bl;
- sc_type type = status_skill2sc(skill_id);
+ sc_type type = status->skill2sc(skill_id);
nullpo_ret(ed);
@@ -388,7 +394,7 @@ int elemental_clean_effect(struct elemental_data *ed) {
return 1;
}
-int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick) {
+int elemental_action(struct elemental_data *ed, struct block_list *bl, int64 tick) {
struct skill_condition req;
uint16 skill_id, skill_lv;
int i;
@@ -400,7 +406,7 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned
return 0;
if( ed->target_id )
- elemental_unlocktarget(ed); // Remove previous target.
+ elemental->unlocktarget(ed); // Remove previous target.
ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&EL_SKILLMODE_AGGRESSIVE));
if( i == MAX_ELESKILLTREE )
@@ -409,7 +415,7 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned
skill_id = ed->db->skill[i].id;
skill_lv = ed->db->skill[i].lv;
- if( elemental_skillnotok(skill_id, ed) )
+ if( elemental->skillnotok(skill_id, ed) )
return 0;
if( ed->ud.skilltimer != INVALID_TIMER )
@@ -423,8 +429,8 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned
// Not in skill range.
if( !battle->check_range(&ed->bl,bl,skill->get_range(skill_id,skill_lv)) ) {
// Try to walk to the target.
- if( !unit_walktobl(&ed->bl, bl, skill->get_range(skill_id,skill_lv), 2) )
- elemental_unlocktarget(ed);
+ if( !unit->walktobl(&ed->bl, bl, skill->get_range(skill_id,skill_lv), 2) )
+ elemental->unlocktarget(ed);
else {
// Walking, waiting to be in range. Client don't handle it, then we must handle it here.
int walk_dist = distance_bl(&ed->bl,bl) - skill->get_range(skill_id,skill_lv);
@@ -432,15 +438,15 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned
ed->ud.skill_lv = skill_lv;
if( skill->get_inf(skill_id) & INF_GROUND_SKILL )
- ed->ud.skilltimer = iTimer->add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill->castend_pos, ed->bl.id, 0 );
+ ed->ud.skilltimer = timer->add( tick+status->get_speed(&ed->bl)*walk_dist, skill->castend_pos, ed->bl.id, 0 );
else
- ed->ud.skilltimer = iTimer->add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill->castend_id, ed->bl.id, 0 );
+ ed->ud.skilltimer = timer->add( tick+status->get_speed(&ed->bl)*walk_dist, skill->castend_id, ed->bl.id, 0 );
}
return 1;
}
- req = elemental_skill_get_requirements(skill_id, skill_lv);
+ req = elemental->skill_get_requirements(skill_id, skill_lv);
if(req.hp || req.sp){
struct map_session_data *sd = BL_CAST(BL_PC, battle->get_master(&ed->bl));
@@ -455,9 +461,9 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned
//Otherwise, just cast the skill.
if( skill->get_inf(skill_id) & INF_GROUND_SKILL )
- unit_skilluse_pos(&ed->bl, bl->x, bl->y, skill_id, skill_lv);
+ unit->skilluse_pos(&ed->bl, bl->x, bl->y, skill_id, skill_lv);
else
- unit_skilluse_id(&ed->bl, bl->id, skill_id, skill_lv);
+ unit->skilluse_id(&ed->bl, bl->id, skill_id, skill_lv);
// Reset target.
ed->target_id = 0;
@@ -487,23 +493,23 @@ int elemental_change_mode_ack(struct elemental_data *ed, int mode) {
skill_id = ed->db->skill[i].id;
skill_lv = ed->db->skill[i].lv;
- if( elemental_skillnotok(skill_id, ed) )
+ if( elemental->skillnotok(skill_id, ed) )
return 0;
if( ed->ud.skilltimer != INVALID_TIMER )
return 0;
- else if( DIFF_TICK(iTimer->gettick(), ed->ud.canact_tick) < 0 )
+ else if( DIFF_TICK(timer->gettick(), ed->ud.canact_tick) < 0 )
return 0;
ed->target_id = bl->id; // Set new target
- ed->last_thinktime = iTimer->gettick();
+ ed->last_thinktime = timer->gettick();
if( skill->get_inf(skill_id) & INF_GROUND_SKILL )
- unit_skilluse_pos(&ed->bl, bl->x, bl->y, skill_id, skill_lv);
+ unit->skilluse_pos(&ed->bl, bl->x, bl->y, skill_id, skill_lv);
else
- unit_skilluse_id(&ed->bl,bl->id,skill_id,skill_lv);
+ unit->skilluse_id(&ed->bl,bl->id,skill_id,skill_lv);
- ed->target_id = 0; // Reset target after casting the skill to avoid continious attack.
+ ed->target_id = 0; // Reset target after casting the skill to avoid continuous attack.
return 1;
}
@@ -515,10 +521,10 @@ int elemental_change_mode(struct elemental_data *ed, int mode) {
nullpo_ret(ed);
// Remove target
- elemental_unlocktarget(ed);
+ elemental->unlocktarget(ed);
// Removes the effects of the previous mode.
- if(ed->elemental.mode != mode ) elemental_clean_effect(ed);
+ if(ed->elemental.mode != mode ) elemental->clean_effect(ed);
ed->battle_status.mode = ed->elemental.mode = mode;
@@ -527,9 +533,9 @@ int elemental_change_mode(struct elemental_data *ed, int mode) {
else if( mode == EL_MODE_ASSIST ) mode = EL_SKILLMODE_ASSIST; // Assist spirit mode -> Assist spirit skill.
else mode = EL_SKILLMODE_PASIVE; // Passive spirit mode -> Passive spirit skill.
- // Use a skill inmediately after every change mode.
+ // Use a skill immediately after every change mode.
if( mode != EL_SKILLMODE_AGGRESSIVE )
- elemental_change_mode_ack(ed,mode);
+ elemental->change_mode_ack(ed,mode);
return 1;
}
@@ -541,7 +547,7 @@ void elemental_heal(struct elemental_data *ed, int hp, int sp) {
}
int elemental_dead(struct elemental_data *ed) {
- elemental_delete(ed, 1);
+ elemental->delete(ed, 1);
return 0;
}
@@ -576,8 +582,8 @@ struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16
if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL )
return req;
- req.hp = skill_db[idx].hp[skill_lv-1];
- req.sp = skill_db[idx].sp[skill_lv-1];
+ req.hp = skill->db[idx].hp[skill_lv-1];
+ req.sp = skill->db[idx].sp[skill_lv-1];
return req;
}
@@ -591,7 +597,7 @@ int elemental_set_target( struct map_session_data *sd, struct block_list *bl ) {
if( ed->bl.m != bl->m || !check_distance_bl(&ed->bl, bl, ed->db->range2) )
return 0;
- if( !status_check_skilluse(&ed->bl, bl, 0, 0) )
+ if( !status->check_skilluse(&ed->bl, bl, 0, 0) )
return 0;
if( ed->target_id == 0 )
@@ -600,7 +606,7 @@ int elemental_set_target( struct map_session_data *sd, struct block_list *bl ) {
return 1;
}
-static int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap) {
+int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap) {
struct elemental_data *ed;
struct block_list **target;
int dist;
@@ -611,7 +617,7 @@ static int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap
target = va_arg(ap,struct block_list**);
//If can't seek yet, not an enemy, or you can't attack it, skip.
- if( (*target) == bl || !status_check_skilluse(&ed->bl, bl, 0, 0) )
+ if( (*target) == bl || !status->check_skilluse(&ed->bl, bl, 0, 0) )
return 0;
if( battle->check_target(&ed->bl,bl,BCT_ENEMY) <= 0 )
@@ -636,7 +642,7 @@ static int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap
return 0;
}
-static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, unsigned int tick) {
+int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, int64 tick) {
struct block_list *target = NULL;
int master_dist, view_range, mode;
@@ -662,7 +668,7 @@ static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_
}
if( status_get_sp(&sd->bl) < sp ){ // Can't sustain delete it.
- elemental_delete(sd->ed,0);
+ elemental->delete(sd->ed,0);
return 0;
}
@@ -693,37 +699,37 @@ static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_
master_dist = distance_bl(&sd->bl, &ed->bl);
if( master_dist > AREA_SIZE ) { // Master out of vision range.
- elemental_unlocktarget(ed);
- unit_warp(&ed->bl,sd->bl.m,sd->bl.x,sd->bl.y,CLR_TELEPORT);
+ elemental->unlocktarget(ed);
+ unit->warp(&ed->bl,sd->bl.m,sd->bl.x,sd->bl.y,CLR_TELEPORT);
clif->elemental_updatestatus(sd,SP_HP);
clif->elemental_updatestatus(sd,SP_SP);
return 0;
} else if( master_dist > MAX_ELEDISTANCE ) { // Master too far, chase.
short x = sd->bl.x, y = sd->bl.y;
if( ed->target_id )
- elemental_unlocktarget(ed);
+ elemental->unlocktarget(ed);
if( ed->ud.walktimer != INVALID_TIMER && ed->ud.target == sd->bl.id )
return 0; //Already walking to him
if( DIFF_TICK(tick, ed->ud.canmove_tick) < 0 )
return 0; //Can't move yet.
- if( iMap->search_freecell(&ed->bl, sd->bl.m, &x, &y, MIN_ELEDISTANCE, MIN_ELEDISTANCE, 1)
- && unit_walktoxy(&ed->bl, x, y, 0) )
+ if( map->search_freecell(&ed->bl, sd->bl.m, &x, &y, MIN_ELEDISTANCE, MIN_ELEDISTANCE, 1)
+ && unit->walktoxy(&ed->bl, x, y, 0) )
return 0;
}
if( mode == EL_MODE_AGGRESSIVE ) {
- target = iMap->id2bl(ed->ud.target);
+ target = map->id2bl(ed->ud.target);
if( !target )
- iMap->foreachinrange(elemental_ai_sub_timer_activesearch, &ed->bl, view_range, BL_CHAR, ed, &target, status_get_mode(&ed->bl));
+ map->foreachinrange(elemental->ai_sub_timer_activesearch, &ed->bl, view_range, BL_CHAR, ed, &target, status_get_mode(&ed->bl));
if( !target ) { //No targets available.
- elemental_unlocktarget(ed);
+ elemental->unlocktarget(ed);
return 1;
}
if( battle->check_range(&ed->bl,target,view_range) && rnd()%100 < 2 ) { // 2% chance to cast attack skill.
- if( elemental_action(ed,target,tick) )
+ if( elemental->action(ed,target,tick) )
return 1;
}
@@ -733,28 +739,28 @@ static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_
return 1;
if( battle->check_range(&ed->bl, target, ed->base_status.rhw.range) ) {//Target within range, engage
- unit_attack(&ed->bl,target->id,1);
+ unit->attack(&ed->bl,target->id,1);
return 1;
}
//Follow up if possible.
- if( !unit_walktobl(&ed->bl, target, ed->base_status.rhw.range, 2) )
- elemental_unlocktarget(ed);
+ if( !unit->walktobl(&ed->bl, target, ed->base_status.rhw.range, 2) )
+ elemental->unlocktarget(ed);
}
return 0;
}
-static int elemental_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) {
- unsigned int tick = va_arg(ap,unsigned int);
+int elemental_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) {
+ int64 tick = va_arg(ap,int64);
if(sd->status.ele_id && sd->ed)
- elemental_ai_sub_timer(sd->ed,sd,tick);
+ elemental->ai_sub_timer(sd->ed,sd,tick);
return 0;
}
-static int elemental_ai_timer(int tid, unsigned int tick, int id, intptr_t data) {
- iMap->map_foreachpc(elemental_ai_sub_foreachclient,tick);
+int elemental_ai_timer(int tid, int64 tick, int id, intptr_t data) {
+ map->foreachpc(elemental->ai_sub_foreachclient,tick);
return 0;
}
@@ -764,10 +770,12 @@ int read_elementaldb(void) {
char *str[26];
int i, j = 0, k = 0, ele;
struct s_elemental_db *db;
- struct status_data *status;
+ struct status_data *estatus;
- sprintf(line, "%s/%s", iMap->db_path, "elemental_db.txt");
- memset(elemental_db,0,sizeof(elemental_db));
+ sprintf(line, "%s/%s", map->db_path, "elemental_db.txt");
+
+ if( runflag == MAPSERVER_ST_RUNNING ) //only necessary after we're up
+ memset(elemental->db,0,sizeof(elemental->db));
fp = fopen(line, "r");
if( !fp ) {
@@ -794,50 +802,50 @@ int read_elementaldb(void) {
continue;
}
- db = &elemental_db[j];
+ db = &elemental->db[j];
db->class_ = atoi(str[0]);
safestrncpy(db->sprite, str[1], NAME_LENGTH);
safestrncpy(db->name, str[2], NAME_LENGTH);
db->lv = atoi(str[3]);
- status = &db->status;
+ estatus = &db->status;
db->vd.class_ = db->class_;
- status->max_hp = atoi(str[4]);
- status->max_sp = atoi(str[5]);
- status->rhw.range = atoi(str[6]);
- status->rhw.atk = atoi(str[7]);
- status->rhw.atk2 = atoi(str[8]);
- status->def = atoi(str[9]);
- status->mdef = atoi(str[10]);
- status->str = atoi(str[11]);
- status->agi = atoi(str[12]);
- status->vit = atoi(str[13]);
- status->int_ = atoi(str[14]);
- status->dex = atoi(str[15]);
- status->luk = atoi(str[16]);
+ estatus->max_hp = atoi(str[4]);
+ estatus->max_sp = atoi(str[5]);
+ estatus->rhw.range = atoi(str[6]);
+ estatus->rhw.atk = atoi(str[7]);
+ estatus->rhw.atk2 = atoi(str[8]);
+ estatus->def = atoi(str[9]);
+ estatus->mdef = atoi(str[10]);
+ estatus->str = atoi(str[11]);
+ estatus->agi = atoi(str[12]);
+ estatus->vit = atoi(str[13]);
+ estatus->int_ = atoi(str[14]);
+ estatus->dex = atoi(str[15]);
+ estatus->luk = atoi(str[16]);
db->range2 = atoi(str[17]);
db->range3 = atoi(str[18]);
- status->size = atoi(str[19]);
- status->race = atoi(str[20]);
+ estatus->size = atoi(str[19]);
+ estatus->race = atoi(str[20]);
ele = atoi(str[21]);
- status->def_ele = ele%10;
- status->ele_lv = ele/20;
- if( status->def_ele >= ELE_MAX ) {
- ShowWarning("Elemental %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1);
- status->def_ele = ELE_NEUTRAL;
+ estatus->def_ele = ele%10;
+ estatus->ele_lv = ele/20;
+ if( estatus->def_ele >= ELE_MAX ) {
+ ShowWarning("Elemental %d has invalid element type %d (max element is %d)\n", db->class_, estatus->def_ele, ELE_MAX - 1);
+ estatus->def_ele = ELE_NEUTRAL;
}
- if( status->ele_lv < 1 || status->ele_lv > 4 ) {
- ShowWarning("Elemental %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv);
- status->ele_lv = 1;
+ if( estatus->ele_lv < 1 || estatus->ele_lv > 4 ) {
+ ShowWarning("Elemental %d has invalid element level %d (max is 4)\n", db->class_, estatus->ele_lv);
+ estatus->ele_lv = 1;
}
- status->aspd_rate = 1000;
- status->speed = atoi(str[22]);
- status->adelay = atoi(str[23]);
- status->amotion = atoi(str[24]);
- status->dmotion = atoi(str[25]);
+ estatus->aspd_rate = 1000;
+ estatus->speed = atoi(str[22]);
+ estatus->adelay = atoi(str[23]);
+ estatus->amotion = atoi(str[24]);
+ estatus->dmotion = atoi(str[25]);
j++;
}
@@ -857,7 +865,7 @@ int read_elemental_skilldb(void) {
uint16 skill_id, skill_lv;
int skillmode;
- sprintf(line, "%s/%s", iMap->db_path, "elemental_skill_db.txt");
+ sprintf(line, "%s/%s", map->db_path, "elemental_skill_db.txt");
fp = fopen(line, "r");
if( !fp ) {
ShowError("read_elemental_skilldb : can't read elemental_skill_db.txt\n");
@@ -884,7 +892,7 @@ int read_elemental_skilldb(void) {
}
class_ = atoi(str[0]);
- ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, class_ == elemental_db[i].class_);
+ ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, class_ == elemental->db[i].class_);
if( i == MAX_ELEMENTAL_CLASS ) {
ShowError("read_elemental_skilldb : Class not found in elemental_db for skill entry, line %d.\n", k);
continue;
@@ -896,7 +904,7 @@ int read_elemental_skilldb(void) {
continue;
}
- db = &elemental_db[i];
+ db = &elemental->db[i];
skill_lv = atoi(str[2]);
skillmode = atoi(str[3]);
@@ -921,20 +929,23 @@ int read_elemental_skilldb(void) {
}
void reload_elementaldb(void) {
- read_elementaldb();
- reload_elemental_skilldb();
+ elemental->read_db();
+ elemental->reload_skilldb();
}
void reload_elemental_skilldb(void) {
- read_elemental_skilldb();
+ elemental->read_skilldb();
}
-int do_init_elemental(void) {
- read_elementaldb();
- read_elemental_skilldb();
+int do_init_elemental(bool minimal) {
+ if (minimal)
+ return 0;
- iTimer->add_timer_func_list(elemental_ai_timer,"elemental_ai_timer");
- iTimer->add_timer_interval(iTimer->gettick()+MIN_ELETHINKTIME,elemental_ai_timer,0,0,MIN_ELETHINKTIME);
+ elemental->read_db();
+ elemental->read_skilldb();
+
+ timer->add_func_list(elemental->ai_timer,"elemental_ai_timer");
+ timer->add_interval(timer->gettick()+MIN_ELETHINKTIME,elemental->ai_timer,0,0,MIN_ELETHINKTIME);
return 0;
}
@@ -942,3 +953,60 @@ int do_init_elemental(void) {
void do_final_elemental(void) {
return;
}
+
+/*=====================================
+* Default Functions : elemental.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+void elemental_defaults(void) {
+ elemental = &elemental_s;
+
+ /* */
+ elemental->init = do_init_elemental;
+ elemental->final = do_final_elemental;
+
+ /* */
+ memset(elemental->db,0,sizeof(elemental->db));
+
+ /* funcs */
+
+ elemental->class = elemental_class;
+ elemental->get_viewdata = elemental_get_viewdata;
+
+ elemental->create = elemental_create;
+ elemental->data_received = elemental_data_received;
+ elemental->save = elemental_save;
+
+ elemental->change_mode_ack = elemental_change_mode_ack;
+ elemental->change_mode = elemental_change_mode;
+
+ elemental->heal = elemental_heal;
+ elemental->dead = elemental_dead;
+
+ elemental->delete = elemental_delete;
+ elemental->summon_stop = elemental_summon_stop;
+
+ elemental->get_lifetime = elemental_get_lifetime;
+
+ elemental->unlocktarget = elemental_unlocktarget;
+ elemental->skillnotok = elemental_skillnotok;
+ elemental->set_target = elemental_set_target;
+ elemental->clean_single_effect = elemental_clean_single_effect;
+ elemental->clean_effect = elemental_clean_effect;
+ elemental->action = elemental_action;
+ elemental->skill_get_requirements = elemental_skill_get_requirements;
+
+ elemental->read_skilldb = read_elemental_skilldb;
+ elemental->reload_db = reload_elementaldb;
+ elemental->reload_skilldb = reload_elemental_skilldb;
+
+ elemental->search_index = elemental_search_index;
+ elemental->summon_init = elemental_summon_init;
+ elemental->summon_end_timer = elemental_summon_end_timer;
+ elemental->ai_sub_timer_activesearch = elemental_ai_sub_timer_activesearch;
+ elemental->ai_sub_timer = elemental_ai_sub_timer;
+ elemental->ai_sub_foreachclient = elemental_ai_sub_foreachclient;
+ elemental->ai_timer = elemental_ai_timer;
+ elemental->read_db = read_elementaldb;
+}
diff --git a/src/map/elemental.h b/src/map/elemental.h
index f941f3dfd..0c8fff8b3 100644
--- a/src/map/elemental.h
+++ b/src/map/elemental.h
@@ -1,24 +1,33 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _ELEMENTAL_H_
-#define _ELEMENTAL_H_
+#ifndef MAP_ELEMENTAL_H
+#define MAP_ELEMENTAL_H
#include "status.h" // struct status_data, struct status_change
#include "unit.h" // struct unit_data
+#include "../common/mmo.h" // NAME_LENGTH
+/**
+ * Defines
+ **/
#define MIN_ELETHINKTIME 100
#define MIN_ELEDISTANCE 2
#define MAX_ELEDISTANCE 5
-
#define EL_MODE_AGGRESSIVE (MD_CANMOVE|MD_AGGRESSIVE|MD_CANATTACK)
#define EL_MODE_ASSIST (MD_CANMOVE|MD_ASSIST)
#define EL_MODE_PASSIVE MD_CANMOVE
-
#define EL_SKILLMODE_PASIVE 0x1
#define EL_SKILLMODE_ASSIST 0x2
#define EL_SKILLMODE_AGGRESSIVE 0x4
+#define elemental_stop_walking(ed, type) (unit->stop_walking(&(ed)->bl, (type)))
+#define elemental_stop_attack(ed) (unit->stop_attack(&(ed)->bl))
+
+/**
+ * Structures
+ **/
struct elemental_skill {
unsigned short id, lv;
short mode;
@@ -34,8 +43,6 @@ struct s_elemental_db {
struct elemental_skill skill[MAX_ELESKILLTREE];
};
-extern struct s_elemental_db elemental_db[MAX_ELEMENTAL_CLASS];
-
struct elemental_data {
struct block_list bl;
struct unit_data ud;
@@ -51,44 +58,67 @@ struct elemental_data {
int summon_timer;
int skill_timer;
- unsigned last_thinktime, last_linktime, last_spdrain_time;
+ int64 last_thinktime, last_linktime, last_spdrain_time;
short min_chase;
int target_id, attacked_id;
};
-bool elemental_class(int class_);
-struct view_data * elemental_get_viewdata(int class_);
-
-int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime);
-int elemental_data_received(struct s_elemental *ele, bool flag);
-int elemental_save(struct elemental_data *ed);
-
-int elemental_change_mode_ack(struct elemental_data *ed, int mode);
-int elemental_change_mode(struct elemental_data *ed, int mode);
-
-void elemental_heal(struct elemental_data *ed, int hp, int sp);
-int elemental_dead(struct elemental_data *ed);
-
-int elemental_delete(struct elemental_data *ed, int reply);
-void elemental_summon_stop(struct elemental_data *ed);
-
-int elemental_get_lifetime(struct elemental_data *ed);
-
-int elemental_unlocktarget(struct elemental_data *ed);
-int elemental_skillnotok(uint16 skill_id, struct elemental_data *ed);
-int elemental_set_target( struct map_session_data *sd, struct block_list *bl );
-int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id);
-int elemental_clean_effect(struct elemental_data *ed);
-int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick);
-struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv);
+/*=====================================
+* Interface : elemental.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+struct elemental_interface {
+
+ /* vars */
+ struct s_elemental_db db[MAX_ELEMENTAL_CLASS]; // Elemental Database
+
+ /* */
+ int (*init) (bool minimal);
+ void (*final) (void);
+ /* funcs */
+ bool (*class) (int class_);
+ struct view_data * (*get_viewdata) (int class_);
+
+ int (*create) (struct map_session_data *sd, int class_, unsigned int lifetime);
+ int (*data_received) (struct s_elemental *ele, bool flag);
+ int (*save) (struct elemental_data *ed);
+
+ int (*change_mode_ack) (struct elemental_data *ed, int mode);
+ int (*change_mode) (struct elemental_data *ed, int mode);
+
+ void (*heal) (struct elemental_data *ed, int hp, int sp);
+ int (*dead) (struct elemental_data *ed);
+
+ int (*delete) (struct elemental_data *ed, int reply);
+ void (*summon_stop) (struct elemental_data *ed);
+
+ int (*get_lifetime) (struct elemental_data *ed);
+
+ int (*unlocktarget) (struct elemental_data *ed);
+ int (*skillnotok) (uint16 skill_id, struct elemental_data *ed);
+ int (*set_target) (struct map_session_data *sd, struct block_list *bl);
+ int (*clean_single_effect) (struct elemental_data *ed, uint16 skill_id);
+ int (*clean_effect) (struct elemental_data *ed);
+ int (*action) (struct elemental_data *ed, struct block_list *bl, int64 tick);
+ struct skill_condition (*skill_get_requirements) (uint16 skill_id, uint16 skill_lv);
+
+ int (*read_skilldb) (void);
+ void (*reload_db) (void);
+ void (*reload_skilldb) (void);
+
+ int (*search_index) (int class_);
+ void (*summon_init) (struct elemental_data *ed);
+ int (*summon_end_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*ai_sub_timer_activesearch) (struct block_list *bl, va_list ap);
+ int (*ai_sub_timer) (struct elemental_data *ed, struct map_session_data *sd, int64 tick);
+ int (*ai_sub_foreachclient) (struct map_session_data *sd, va_list ap);
+ int (*ai_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*read_db) (void);
+};
-#define elemental_stop_walking(ed, type) unit_stop_walking(&(ed)->bl, type)
-#define elemental_stop_attack(ed) unit_stop_attack(&(ed)->bl)
+struct elemental_interface *elemental;
-int read_elemental_skilldb(void);
-void reload_elementaldb(void);
-void reload_elemental_skilldb(void);
-int do_init_elemental(void);
-void do_final_elemental(void);
+void elemental_defaults(void);
-#endif /* _ELEMENTAL_H_ */
+#endif /* MAP_ELEMENTAL_H */
diff --git a/src/map/guild.c b/src/map/guild.c
index b28c14db7..ac24edeab 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -2,103 +2,66 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/malloc.h"
-#include "../common/mapindex.h"
-#include "../common/showmsg.h"
-#include "../common/ers.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
+#define HERCULES_CORE
-#include "map.h"
+#include "../config/core.h" // GP_BOUND_ITEMS
#include "guild.h"
-#include "storage.h"
-#include "battle.h"
-#include "npc.h"
-#include "pc.h"
-#include "status.h"
-#include "mob.h"
-#include "intif.h"
-#include "clif.h"
-#include "skill.h"
-#include "log.h"
-#include "instance.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "battle.h"
+#include "clif.h"
+#include "instance.h"
+#include "intif.h"
+#include "log.h"
+#include "map.h"
+#include "mob.h"
+#include "npc.h"
+#include "pc.h"
+#include "skill.h"
+#include "status.h"
+#include "storage.h"
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/mapindex.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-static DBMap* guild_db; // int guild_id -> struct guild*
-static DBMap* castle_db; // int castle_id -> struct guild_castle*
-static DBMap* guild_expcache_db; // int char_id -> struct guild_expcache*
-static DBMap* guild_infoevent_db; // int guild_id -> struct eventlist*
-
-struct eventlist {
- char name[EVENT_NAME_LENGTH];
- struct eventlist *next;
-};
-
-//Constant related to the flash of the Guild EXP cache
-#define GUILD_SEND_XY_INVERVAL 5000 // Interval of sending coordinates and HP
-#define GUILD_PAYEXP_INVERVAL 10000 //Interval (maximum survival time of the cache, in milliseconds)
-#define GUILD_PAYEXP_LIST 8192 //The maximum number of cache
-
-//Guild EXP cache
-
-struct guild_expcache {
- int guild_id, account_id, char_id;
- uint64 exp;
-};
-static struct eri *expcache_ers; //For handling of guild exp payment.
-
-#define MAX_GUILD_SKILL_REQUIRE 5
-struct{
- int id;
- int max;
- struct{
- short id;
- short lv;
- }need[MAX_GUILD_SKILL_REQUIRE];
-} guild_skill_tree[MAX_GUILDSKILL];
-
-int guild_payexp_timer(int tid, unsigned int tick, int id, intptr_t data);
-static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data);
-
-/* guild flags cache */
-struct npc_data **guild_flags;
-unsigned short guild_flags_count;
+struct guild_interface guild_s;
/*==========================================
* Retrieves and validates the sd pointer for this guild member [Skotlex]
*------------------------------------------*/
-static TBL_PC* guild_sd_check(int guild_id, int account_id, int char_id)
-{
- TBL_PC* sd = iMap->id2sd(account_id);
+TBL_PC* guild_sd_check(int guild_id, int account_id, int char_id) {
+ TBL_PC* sd = map->id2sd(account_id);
if (!(sd && sd->status.char_id == char_id))
return NULL;
- if (sd->status.guild_id != guild_id)
- { //If player belongs to a different guild, kick him out.
- intif_guild_leave(guild_id,account_id,char_id,0,"** Guild Mismatch **");
+ if (sd->status.guild_id != guild_id) {
+ //If player belongs to a different guild, kick him out.
+ intif->guild_leave(guild_id,account_id,char_id,0,"** Guild Mismatch **");
return NULL;
}
return sd;
}
- // Modified [Komurka]
+// Modified [Komurka]
int guild_skill_get_max (int id) {
if (id < GD_SKILLBASE || id >= GD_SKILLBASE+MAX_GUILDSKILL)
return 0;
- return guild_skill_tree[id-GD_SKILLBASE].max;
+ return guild->skill_tree[id-GD_SKILLBASE].max;
}
-// Retrive skill_lv learned by guild
-
+// Retrieve skill_lv learned by guild
int guild_checkskill(struct guild *g, int id) {
int idx = id - GD_SKILLBASE;
if (idx < 0 || idx >= MAX_GUILDSKILL)
@@ -109,7 +72,7 @@ int guild_checkskill(struct guild *g, int id) {
/*==========================================
* guild_skill_tree.txt reading - from jA [Komurka]
*------------------------------------------*/
-static bool guild_read_guildskill_tree_db(char* split[], int columns, int current)
+bool guild_read_guildskill_tree_db(char* split[], int columns, int current)
{// <skill id>,<max lv>,<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>
int k, id, skill_id;
@@ -122,18 +85,18 @@ static bool guild_read_guildskill_tree_db(char* split[], int columns, int curren
return false;
}
- guild_skill_tree[id].id = skill_id;
- guild_skill_tree[id].max = atoi(split[1]);
+ guild->skill_tree[id].id = skill_id;
+ guild->skill_tree[id].max = atoi(split[1]);
- if( guild_skill_tree[id].id == GD_GLORYGUILD && battle_config.require_glory_guild && guild_skill_tree[id].max == 0 )
+ if( guild->skill_tree[id].id == GD_GLORYGUILD && battle_config.require_glory_guild && guild->skill_tree[id].max == 0 )
{// enable guild's glory when required for emblems
- guild_skill_tree[id].max = 1;
+ guild->skill_tree[id].max = 1;
}
for( k = 0; k < MAX_GUILD_SKILL_REQUIRE; k++ )
{
- guild_skill_tree[id].need[k].id = atoi(split[k*2+2]);
- guild_skill_tree[id].need[k].lv = atoi(split[k*2+3]);
+ guild->skill_tree[id].need[k].id = atoi(split[k*2+2]);
+ guild->skill_tree[id].need[k].lv = atoi(split[k*2+3]);
}
return true;
@@ -155,30 +118,30 @@ int guild_check_skill_require(struct guild *g,int id)
for(i=0;i<MAX_GUILD_SKILL_REQUIRE;i++)
{
- if(guild_skill_tree[idx].need[i].id == 0) break;
- if(guild_skill_tree[idx].need[i].lv > guild->checkskill(g,guild_skill_tree[idx].need[i].id))
+ if(guild->skill_tree[idx].need[i].id == 0) break;
+ if(guild->skill_tree[idx].need[i].lv > guild->checkskill(g,guild->skill_tree[idx].need[i].id))
return 0;
}
return 1;
}
-static bool guild_read_castledb(char* str[], int columns, int current)
+bool guild_read_castledb(char* str[], int columns, int current)
{// <castle id>,<map name>,<castle name>,<castle event>[,<reserved/unused switch flag>]
struct guild_castle *gc;
- int mapindex = mapindex_name2id(str[1]);
+ int index = mapindex->name2id(str[1]);
- if (iMap->mapindex2mapid(mapindex) < 0) // Map not found or on another map-server
+ if (map->mapindex2mapid(index) < 0) // Map not found or on another map-server
return false;
CREATE(gc, struct guild_castle, 1);
gc->castle_id = atoi(str[0]);
- gc->mapindex = mapindex;
+ gc->mapindex = index;
safestrncpy(gc->castle_name, str[2], sizeof(gc->castle_name));
safestrncpy(gc->castle_event, str[3], sizeof(gc->castle_event));
- idb_put(castle_db,gc->castle_id,gc);
+ idb_put(guild->castle_db,gc->castle_id,gc);
- //intif_guild_castle_info(gc->castle_id);
+ //intif->guild_castle_info(gc->castle_id);
return true;
}
@@ -186,14 +149,14 @@ static bool guild_read_castledb(char* str[], int columns, int current)
/// lookup: guild id -> guild*
struct guild* guild_search(int guild_id)
{
- return (struct guild*)idb_get(guild_db,guild_id);
+ return (struct guild*)idb_get(guild->db,guild_id);
}
/// lookup: guild name -> guild*
struct guild* guild_searchname(char* str)
{
struct guild* g;
- DBIterator *iter = db_iterator(guild_db);
+ DBIterator *iter = db_iterator(guild->db);
for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) )
{
@@ -208,18 +171,18 @@ struct guild* guild_searchname(char* str)
/// lookup: castle id -> castle*
struct guild_castle* guild_castle_search(int gcid)
{
- return (struct guild_castle*)idb_get(castle_db,gcid);
+ return (struct guild_castle*)idb_get(guild->castle_db,gcid);
}
/// lookup: map index -> castle*
-struct guild_castle* guild_mapindex2gc(short mapindex)
+struct guild_castle* guild_mapindex2gc(short map_index)
{
struct guild_castle* gc;
- DBIterator *iter = db_iterator(castle_db);
+ DBIterator *iter = db_iterator(guild->castle_db);
for( gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter) )
{
- if( gc->mapindex == mapindex )
+ if( gc->mapindex == map_index )
break;
}
dbi_destroy(iter);
@@ -230,7 +193,7 @@ struct guild_castle* guild_mapindex2gc(short mapindex)
/// lookup: map name -> castle*
struct guild_castle* guild_mapname2gc(const char* mapname)
{
- return guild->mapindex2gc(mapindex_name2id(mapname));
+ return guild->mapindex2gc(mapindex->name2id(mapname));
}
struct map_session_data* guild_getavailablesd(struct guild* g)
@@ -303,7 +266,7 @@ int guild_payexp_timer_sub(DBKey key, DBData *data, va_list ap) {
(g = guild->search(c->guild_id)) == NULL ||
(i = guild->getindex(g, c->account_id, c->char_id)) < 0
) {
- ers_free(expcache_ers, c);
+ ers_free(guild->expcache_ers, c);
return 0;
}
@@ -312,17 +275,16 @@ int guild_payexp_timer_sub(DBKey key, DBData *data, va_list ap) {
else
g->member[i].exp+= c->exp;
- intif_guild_change_memberinfo(g->guild_id,c->account_id,c->char_id,
+ intif->guild_change_memberinfo(g->guild_id,c->account_id,c->char_id,
GMI_EXP,&g->member[i].exp,sizeof(g->member[i].exp));
c->exp=0;
- ers_free(expcache_ers, c);
+ ers_free(guild->expcache_ers, c);
return 0;
}
-int guild_payexp_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
- guild_expcache_db->clear(guild_expcache_db,guild_payexp_timer_sub);
+int guild_payexp_timer(int tid, int64 tick, int id, intptr_t data) {
+ guild->expcache_db->clear(guild->expcache_db,guild->payexp_timer_sub);
return 0;
}
@@ -355,9 +317,8 @@ int guild_send_xy_timer_sub(DBKey key, DBData *data, va_list ap)
}
//Code from party_send_xy_timer [Skotlex]
-static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
- guild_db->foreach(guild_db,guild_send_xy_timer_sub,tick);
+int guild_send_xy_timer(int tid, int64 tick, int id, intptr_t data) {
+ guild->db->foreach(guild->db,guild->send_xy_timer_sub,tick);
return 0;
}
@@ -386,21 +347,21 @@ int guild_create(struct map_session_data *sd, const char *name)
clif->guild_created(sd,1);
return 0;
}
- if( battle_config.guild_emperium_check && pc->search_inventory(sd,714) == -1 )
- {// item required
+ if (battle_config.guild_emperium_check && pc->search_inventory(sd, ITEMID_EMPERIUM) == INDEX_NOT_FOUND) {
+ // item required
clif->guild_created(sd,3);
return 0;
}
- guild_makemember(&m,sd);
+ guild->makemember(&m,sd);
m.position=0;
- intif_guild_create(name,&m);
+ intif->guild_create(name,&m);
return 1;
}
//Whether or not to create guild
int guild_created(int account_id,int guild_id) {
- struct map_session_data *sd=iMap->id2sd(account_id);
+ struct map_session_data *sd=map->id2sd(account_id);
if(sd==NULL)
return 0;
@@ -419,7 +380,7 @@ int guild_created(int account_id,int guild_id) {
//Information request
int guild_request_info(int guild_id)
{
- return intif_guild_request_info(guild_id);
+ return intif->guild_request_info(guild_id);
}
//Information request with event
@@ -428,7 +389,7 @@ int guild_npc_request_info(int guild_id,const char *event)
if( guild->search(guild_id) )
{
if( event && *event )
- npc_event_do(event);
+ npc->event_do(event);
return 0;
}
@@ -440,7 +401,7 @@ int guild_npc_request_info(int guild_id,const char *event)
ev=(struct eventlist *)aCalloc(sizeof(struct eventlist),1);
memcpy(ev->name,event,strlen(event));
//The one in the db (if present) becomes the next event from this.
- if (guild_infoevent_db->put(guild_infoevent_db, DB->i2key(guild_id), DB->ptr2data(ev), &prev))
+ if (guild->infoevent_db->put(guild->infoevent_db, DB->i2key(guild_id), DB->ptr2data(ev), &prev))
ev->next = DB->data2ptr(&prev);
}
@@ -497,16 +458,16 @@ int guild_recv_info(struct guild *sg) {
DBData data;
struct map_session_data *sd;
bool guild_new = false;
- void *aChSysSave = NULL;
+ struct hChSysCh *aChSysSave = NULL;
nullpo_ret(sg);
- if((g = (struct guild*)idb_get(guild_db,sg->guild_id))==NULL) {
+ if((g = (struct guild*)idb_get(guild->db,sg->guild_id))==NULL) {
guild_new = true;
g=(struct guild *)aCalloc(1,sizeof(struct guild));
g->instance = NULL;
g->instances = 0;
- idb_put(guild_db,sg->guild_id,g);
+ idb_put(guild->db,sg->guild_id,g);
if( hChSys.ally ) {
struct hChSysCh *channel;
@@ -526,21 +487,27 @@ int guild_recv_info(struct guild *sg) {
}
for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) {
- if( sd->status.guild_id ) {
- if( sd->status.guild_id == sg->guild_id ) {
- clif->chsys_join(channel,sd);
- sd->guild = g;
- }
-
+ if (!sd->status.guild_id)
+ continue; // Not interested in guildless users
+
+ if (sd->status.guild_id == sg->guild_id) {
+ // Guild member
+ clif->chsys_join(channel,sd);
+ sd->guild = g;
+
for (i = 0; i < MAX_GUILDALLIANCE; i++) {
- if( sg->alliance[i].opposition == 0 && sg->alliance[i].guild_id ) {
- if( sg->alliance[i].guild_id == sd->status.guild_id ) {
- clif->chsys_join(channel,sd);
- } else if( tg[i] != NULL ) {
- if( !(((struct hChSysCh*)tg[i]->channel)->banned && idb_exists(((struct hChSysCh*)tg[i]->channel)->banned, sd->status.account_id)))
- clif->chsys_join((struct hChSysCh*)tg[i]->channel,sd);
- }
- }
+ // Join channels from allied guilds
+ if (tg[i] && !(tg[i]->channel->banned && idb_exists(tg[i]->channel->banned, sd->status.account_id)))
+ clif->chsys_join(tg[i]->channel, sd);
+ }
+ continue;
+ }
+
+ for (i = 0; i < MAX_GUILDALLIANCE; i++) {
+ if (tg[i] && sd->status.guild_id == tg[i]->guild_id) { // Shortcut to skip the alliance checks again
+ // Alliance member
+ if( !(channel->banned && idb_exists(channel->banned, sd->status.account_id)))
+ clif->chsys_join(channel, sd);
}
}
}
@@ -549,13 +516,13 @@ int guild_recv_info(struct guild *sg) {
}
- aChSysSave = (void*)channel;
+ aChSysSave = channel;
}
before=*sg;
- //Perform the check on the user because the first load
- guild_check_member(sg);
- if ((sd = iMap->nick2sd(sg->master)) != NULL) {
+ //Perform the check on the user because the first load
+ guild->check_member(sg);
+ if ((sd = map->nick2sd(sg->master)) != NULL) {
//If the guild master is online the first time the guild_info is received,
//that means he was the first to join, so apply guild skill blocking here.
if( battle_config.guild_skill_relog_delay )
@@ -563,7 +530,7 @@ int guild_recv_info(struct guild *sg) {
//Also set the guild master flag.
sd->guild = g;
- sd->state.gmaster_flag = g;
+ sd->state.gmaster_flag = 1;
clif->charnameupdate(sd); // [LuzZza]
clif->guild_masterormember(sd);
}
@@ -583,7 +550,7 @@ int guild_recv_info(struct guild *sg) {
for(i=bm=m=0;i<g->max_member;i++){
if(g->member[i].account_id>0){
- sd = g->member[i].sd = guild_sd_check(g->guild_id, g->member[i].account_id, g->member[i].char_id);
+ sd = g->member[i].sd = guild->sd_check(g->guild_id, g->member[i].account_id, g->member[i].char_id);
if (sd) clif->charnameupdate(sd); // [LuzZza]
m++;
}else
@@ -610,18 +577,18 @@ int guild_recv_info(struct guild *sg) {
if (before.skill_point != g->skill_point)
clif->guild_skillinfo(sd); //Submit information skills
- if (guild_new) { // Send information and affiliation if unsent
+ if (guild_new) { // Send information and affiliation if unsent
clif->guild_belonginfo(sd, g);
- clif->guild_notice(sd, g);
+ //clif->guild_notice(sd, g); Is already sent in clif_parse_LoadEndAck
sd->guild_emblem_id = g->emblem_id;
}
}
//Occurrence of an event
- if (guild_infoevent_db->remove(guild_infoevent_db, DB->i2key(sg->guild_id), &data)) {
+ if (guild->infoevent_db->remove(guild->infoevent_db, DB->i2key(sg->guild_id), &data)) {
struct eventlist *ev = DB->data2ptr(&data), *ev2;
while(ev) {
- npc_event_do(ev->name);
+ npc->event_do(ev->name);
ev2=ev->next;
aFree(ev);
ev=ev2;
@@ -660,15 +627,19 @@ int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) {
return 0;
}
- if(tsd->status.guild_id>0 ||
- tsd->guild_invite>0 ||
- ((iMap->agit_flag || iMap->agit2_flag) && map[tsd->bl.m].flag.gvg_castle))
- { //Can't invite people inside castles. [Skotlex]
+ if( tsd->status.guild_id > 0
+ || tsd->guild_invite > 0
+ || ( (map->agit_flag || map->agit2_flag)
+ && map->list[tsd->bl.m].flag.gvg_castle
+ && !battle_config.guild_castle_invite
+ )
+ ) {
+ //Can't invite people inside castles. [Skotlex]
clif->guild_inviteack(sd,0);
return 0;
}
- //search an empty spot in guild
+ //search an empty spot in guild
ARR_FIND( 0, g->max_member, i, g->member[i].account_id == 0 );
if(i==g->max_member){
clif->guild_inviteack(sd,3);
@@ -684,8 +655,7 @@ int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) {
/// Guild invitation reply.
/// flag: 0:rejected, 1:accepted
-int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag)
-{
+int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag) {
struct map_session_data* tsd;
nullpo_ret(sd);
@@ -696,10 +666,10 @@ int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag)
// look up the person who sent the invite
//NOTE: this can be NULL because the person might have logged off in the meantime
- tsd = iMap->id2sd(sd->guild_invite_account);
+ tsd = map->id2sd(sd->guild_invite_account);
- if ( sd->status.guild_id > 0 ) // [Paradox924X]
- { // Already in another guild.
+ if ( sd->status.guild_id > 0 ) {
+ // Already in another guild. [Paradox924X]
if ( tsd ) clif->guild_inviteack(tsd,0);
return 0;
}
@@ -731,8 +701,8 @@ int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag)
return 0;
}
- guild_makemember(&m,sd);
- intif_guild_addmember(guild_id, &m);
+ guild->makemember(&m,sd);
+ intif->guild_addmember(guild_id, &m);
//TODO: send a minimap update to this player
}
@@ -753,7 +723,7 @@ void guild_member_joined(struct map_session_data *sd)
return;
}
if (strcmp(sd->status.name,g->master) == 0) { // set the Guild Master flag
- sd->state.gmaster_flag = g;
+ sd->state.gmaster_flag = 1;
// prevent Guild Skills from being used directly after relog
if( battle_config.guild_skill_relog_delay )
guild->block_skill(sd, 300000);
@@ -768,14 +738,14 @@ void guild_member_joined(struct map_session_data *sd)
if( hChSys.ally && hChSys.ally_autojoin ) {
struct guild* sg = NULL;
- struct hChSysCh *channel = (struct hChSysCh*)g->channel;
+ struct hChSysCh *channel = g->channel;
if( !(channel->banned && idb_exists(channel->banned, sd->status.account_id) ) )
clif->chsys_join(channel,sd);
for (i = 0; i < MAX_GUILDALLIANCE; i++) {
if( g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id) ) ) {
- if( !(((struct hChSysCh*)sg->channel)->banned && idb_exists(((struct hChSysCh*)sg->channel)->banned, sd->status.account_id)))
- clif->chsys_join((struct hChSysCh*)sg->channel,sd);
+ if( !(sg->channel->banned && idb_exists(sg->channel->banned, sd->status.account_id)))
+ clif->chsys_join(sg->channel,sd);
}
}
}
@@ -786,33 +756,32 @@ void guild_member_joined(struct map_session_data *sd)
/*==========================================
* Add a player to a given guild_id
*----------------------------------------*/
-int guild_member_added(int guild_id,int account_id,int char_id,int flag)
-{
- struct map_session_data *sd= iMap->id2sd(account_id),*sd2;
+int guild_member_added(int guild_id,int account_id,int char_id,int flag) {
+ struct map_session_data *sd = map->id2sd(account_id),*sd2;
struct guild *g;
if( (g=guild->search(guild_id))==NULL )
return 0;
if(sd==NULL || sd->guild_invite==0){
- // cancel if player not present or invalide guild_id invitation
+ // cancel if player not present or invalid guild_id invitation
if (flag == 0) {
ShowError("guild: member added error %d is not online\n",account_id);
- intif_guild_leave(guild_id,account_id,char_id,0,"** Data Error **");
+ intif->guild_leave(guild_id,account_id,char_id,0,"** Data Error **");
}
return 0;
}
- sd2 = iMap->id2sd(sd->guild_invite_account);
+ sd2 = map->id2sd(sd->guild_invite_account);
sd->guild_invite = 0;
sd->guild_invite_account = 0;
- if (flag == 1) { //failure
+ if (flag == 1) { //failure
if( sd2!=NULL )
clif->guild_inviteack(sd2,3);
return 0;
}
- //if all ok add player to guild
+ //if all ok add player to guild
sd->status.guild_id = g->guild_id;
sd->guild_emblem_id = g->emblem_id;
sd->guild = g;
@@ -845,20 +814,24 @@ int guild_leave(struct map_session_data* sd, int guild_id, int account_id, int c
if(g==NULL)
return 0;
- if(sd->status.account_id!=account_id ||
- sd->status.char_id!=char_id || sd->status.guild_id!=guild_id ||
- ((iMap->agit_flag || iMap->agit2_flag) && map[sd->bl.m].flag.gvg_castle))
+ if( sd->status.account_id != account_id
+ || sd->status.char_id != char_id
+ || sd->status.guild_id != guild_id
+ // Can't leave inside castles
+ || ((map->agit_flag || map->agit2_flag)
+ && map->list[sd->bl.m].flag.gvg_castle
+ && !battle_config.guild_castle_expulsion)
+ )
return 0;
- intif_guild_leave(sd->status.guild_id, sd->status.account_id, sd->status.char_id,0,mes);
+ intif->guild_leave(sd->status.guild_id, sd->status.account_id, sd->status.char_id,0,mes);
return 0;
}
/*==========================================
* Request remove a player to a given guild_id
*----------------------------------------*/
-int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, int char_id, const char* mes)
-{
+int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, int char_id, const char* mes) {
struct map_session_data *tsd;
struct guild *g;
int i,ps;
@@ -876,16 +849,19 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i
if( (ps=guild->getposition(g,sd))<0 || !(g->position[ps].mode&0x0010) )
return 0; //Expulsion permission
- //Can't leave inside guild castles.
- if ((tsd = iMap->id2sd(account_id)) &&
- tsd->status.char_id == char_id &&
- ((iMap->agit_flag || iMap->agit2_flag) && map[tsd->bl.m].flag.gvg_castle))
+ //Can't leave inside guild castles.
+ if ((tsd = map->id2sd(account_id))
+ && tsd->status.char_id == char_id
+ && ((map->agit_flag || map->agit2_flag)
+ && map->list[sd->bl.m].flag.gvg_castle
+ && !battle_config.guild_castle_expulsion)
+ )
return 0;
// find the member and perform expulsion
i = guild->getindex(g, account_id, char_id);
if( i != -1 && strcmp(g->member[i].name,g->master) != 0 ) //Can't expel the GL!
- intif_guild_leave(g->guild_id,account_id,char_id,1,mes);
+ intif->guild_leave(g->guild_id,account_id,char_id,1,mes);
return 0;
}
@@ -894,7 +870,7 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
{
int i;
struct guild* g = guild->search(guild_id);
- struct map_session_data* sd = iMap->charid2sd(char_id);
+ struct map_session_data* sd = map->charid2sd(char_id);
struct map_session_data* online_member_sd;
if(g == NULL)
@@ -906,7 +882,12 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
online_member_sd = guild->getavailablesd(g);
if(online_member_sd == NULL)
- return 0; // noone online to inform
+ return 0; // no one online to inform
+
+#ifdef GP_BOUND_ITEMS
+ //Guild bound item check
+ guild->retrieveitembound(char_id,account_id,guild_id);
+#endif
if(!flag)
clif->guild_leave(online_member_sd, name, mes);
@@ -921,7 +902,7 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
if(sd != NULL && sd->status.guild_id == guild_id) {
// do stuff that needs the guild_id first, BEFORE we wipe it
if (sd->state.storage_flag == 2) //Close the guild storage.
- storage_guild_storageclose(sd);
+ gstorage->close(sd);
guild->send_dot_remove(sd);
if( hChSys.ally ) {
clif->chsys_quitg(sd);
@@ -932,11 +913,37 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
if( g->instances )
instance->check_kick(sd);
clif->charnameupdate(sd); //Update display name [Skotlex]
+ status_change_end(&sd->bl, SC_LEADERSHIP, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_GLORYWOUNDS, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_SOULCOLD, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_HAWKEYES, INVALID_TIMER);
//TODO: send emblem update to self and people around
}
return 0;
}
+void guild_retrieveitembound(int char_id,int aid,int guild_id) {
+#ifdef GP_BOUND_ITEMS
+ TBL_PC *sd = map->charid2sd(char_id);
+ if(sd){ //Character is online
+ pc->bound_clear(sd,IBT_GUILD);
+ } else { //Character is offline, ask char server to do the job
+ struct guild_storage *gstor = gstorage->id2storage2(guild_id);
+ if(gstor && gstor->storage_status == 1) { //Someone is in guild storage, close them
+ struct s_mapiterator* iter = mapit_getallusers();
+ for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) {
+ if(sd->status.guild_id == guild_id && sd->state.storage_flag == 2) {
+ gstorage->close(sd);
+ break;
+ }
+ }
+ mapit->free(iter);
+ }
+ intif->itembound_req(char_id,aid,guild_id);
+ }
+#endif
+}
+
int guild_send_memberinfoshort(struct map_session_data *sd,int online)
{ // cleaned up [LuzZza]
struct guild *g;
@@ -949,7 +956,7 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online)
if(!(g = sd->guild))
return 0;
- intif_guild_memberinfoshort(g->guild_id,
+ intif->guild_memberinfoshort(g->guild_id,
sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class_);
if(!online){
@@ -964,7 +971,6 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online)
if(sd->state.connect_new)
{ //Note that this works because it is invoked in parse_LoadEndAck before connect_new is cleared.
clif->guild_belonginfo(sd,g);
- clif->guild_notice(sd,g);
sd->guild_emblem_id = g->emblem_id;
}
return 0;
@@ -996,13 +1002,13 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin
}
if(idx == -1 || c == 0) {
- //Treat char_id who doesn't match guild_id (not found as member)
- struct map_session_data *sd = iMap->id2sd(account_id);
+ //Treat char_id who doesn't match guild_id (not found as member)
+ struct map_session_data *sd = map->id2sd(account_id);
if(sd && sd->status.char_id == char_id) {
sd->status.guild_id=0;
sd->guild_emblem_id=0;
}
- ShowWarning("guild: not found member %d,%d on %d[%s]\n", account_id,char_id,guild_id,g->name);
+ ShowWarning("guild: not found member %d,%d on %d[%s]\n", account_id,char_id,guild_id,g->name);
return 0;
}
@@ -1010,9 +1016,9 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin
g->connect_member=om;
//Ensure validity of pointer (ie: player logs in/out, changes map-server)
- g->member[idx].sd = guild_sd_check(guild_id, account_id, char_id);
+ g->member[idx].sd = guild->sd_check(guild_id, account_id, char_id);
- if(oldonline!=online)
+ if(oldonline!=online)
clif->guild_memberlogin_notice(g, idx, online);
if(!g->member[idx].sd)
@@ -1042,7 +1048,7 @@ int guild_send_message(struct map_session_data *sd,const char *mes,int len)
if(sd->status.guild_id==0)
return 0;
- intif_guild_message(sd->status.guild_id,sd->status.account_id,mes,len);
+ intif->guild_message(sd->status.guild_id,sd->status.account_id,mes,len);
guild->recv_message(sd->status.guild_id,sd->status.account_id,mes,len);
// Chat logging type 'G' / Guild Chat
@@ -1068,7 +1074,7 @@ int guild_recv_message(int guild_id,int account_id,const char *mes,int len)
*---------------------------------------------------*/
int guild_change_memberposition(int guild_id,int account_id,int char_id,short idx)
{
- return intif_guild_change_memberinfo(guild_id,account_id,char_id,GMI_POSITION,&idx,sizeof(idx));
+ return intif->guild_change_memberinfo(guild_id,account_id,char_id,GMI_POSITION,&idx,sizeof(idx));
}
/*====================================================
@@ -1090,8 +1096,7 @@ int guild_memberposition_changed(struct guild *g,int idx,int pos)
/*====================================================
* Change guild title or member
*---------------------------------------------------*/
-int guild_change_position(int guild_id,int idx,
- int mode,int exp_mode,const char *name)
+int guild_change_position(int guild_id,int idx,int mode,int exp_mode,const char *name)
{
struct guild_position p;
@@ -1101,7 +1106,7 @@ int guild_change_position(int guild_id,int idx,
p.mode=mode&0x11;
p.exp_mode=exp_mode;
safestrncpy(p.name,name,NAME_LENGTH);
- return intif_guild_position(guild_id,idx,&p);
+ return intif->guild_position(guild_id,idx,&p);
}
/*====================================================
@@ -1132,7 +1137,7 @@ int guild_change_notice(struct map_session_data *sd,int guild_id,const char *mes
if(guild_id!=sd->status.guild_id)
return 0;
- return intif_guild_notice(guild_id,mes1,mes2);
+ return intif->guild_notice(guild_id,mes1,mes2);
}
/*====================================================
@@ -1170,7 +1175,7 @@ int guild_change_emblem(struct map_session_data *sd,int len,const char *data)
return 0;
}
- return intif_guild_emblem(sd->status.guild_id,len,data);
+ return intif->guild_emblem(sd->status.guild_id,len,data);
}
/*====================================================
@@ -1197,37 +1202,35 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data)
}
}
{// update guardians (mobs)
- DBIterator* iter = db_iterator(castle_db);
+ DBIterator* iter = db_iterator(guild->castle_db);
struct guild_castle* gc;
for( gc = (struct guild_castle*)dbi_first(iter) ; dbi_exists(iter); gc = (struct guild_castle*)dbi_next(iter) )
{
if( gc->guild_id != guild_id )
continue;
// update permanent guardians
- for( i = 0; i < ARRAYLENGTH(gc->guardian); ++i )
- {
- TBL_MOB* md = (gc->guardian[i].id ? iMap->id2md(gc->guardian[i].id) : NULL);
+ for( i = 0; i < ARRAYLENGTH(gc->guardian); ++i ) {
+ TBL_MOB* md = (gc->guardian[i].id ? map->id2md(gc->guardian[i].id) : NULL);
if( md == NULL || md->guardian_data == NULL )
continue;
- md->guardian_data->emblem_id = emblem_id;
+
clif->guild_emblem_area(&md->bl);
}
// update temporary guardians
- for( i = 0; i < gc->temp_guardians_max; ++i )
- {
- TBL_MOB* md = (gc->temp_guardians[i] ? iMap->id2md(gc->temp_guardians[i]) : NULL);
+ for( i = 0; i < gc->temp_guardians_max; ++i ) {
+ TBL_MOB* md = (gc->temp_guardians[i] ? map->id2md(gc->temp_guardians[i]) : NULL);
if( md == NULL || md->guardian_data == NULL )
continue;
- md->guardian_data->emblem_id = emblem_id;
+
clif->guild_emblem_area(&md->bl);
}
}
dbi_destroy(iter);
}
{// update npcs (flags or other npcs that used flagemblem to attach to this guild)
- for( i = 0; i < guild_flags_count; i++ ) {
- if( guild_flags[i] && guild_flags[i]->u.scr.guild_id == guild_id ) {
- clif->guild_emblem_area(&guild_flags[i]->bl);
+ for( i = 0; i < guild->flags_count; i++ ) {
+ if( guild->flags[i] && guild->flags[i]->u.scr.guild_id == guild_id ) {
+ clif->guild_emblem_area(&guild->flags[i]->bl);
}
}
}
@@ -1237,12 +1240,12 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data)
/**
* @see DBCreateData
*/
-static DBData create_expcache(DBKey key, va_list args)
+DBData create_expcache(DBKey key, va_list args)
{
struct guild_expcache *c;
struct map_session_data *sd = va_arg(args, struct map_session_data*);
- c = ers_alloc(expcache_ers, struct guild_expcache);
+ c = ers_alloc(guild->expcache_ers, struct guild_expcache);
c->guild_id = sd->status.guild_id;
c->account_id = sd->status.account_id;
c->char_id = sd->status.char_id;
@@ -1273,7 +1276,7 @@ unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) {
exp = exp * per / 100;
//Otherwise tax everything.
- c = DB->data2ptr(guild_expcache_db->ensure(guild_expcache_db, DB->i2key(sd->status.char_id), create_expcache, sd));
+ c = DB->data2ptr(guild->expcache_db->ensure(guild->expcache_db, DB->i2key(sd->status.char_id), guild->create_expcache, sd));
if (c->exp > UINT64_MAX - exp)
c->exp = UINT64_MAX;
@@ -1296,7 +1299,7 @@ int guild_getexp(struct map_session_data *sd,int exp)
if (sd->status.guild_id == 0 || sd->guild == NULL)
return 0;
- c = DB->data2ptr(guild_expcache_db->ensure(guild_expcache_db, DB->i2key(sd->status.char_id), create_expcache, sd));
+ c = DB->data2ptr(guild->expcache_db->ensure(guild->expcache_db, DB->i2key(sd->status.char_id), guild->create_expcache, sd));
if (c->exp > UINT64_MAX - exp)
c->exp = UINT64_MAX;
else
@@ -1323,7 +1326,7 @@ int guild_skillup(TBL_PC* sd, uint16 skill_id)
if( g->skill_point > 0 &&
g->skill[idx].id != 0 &&
g->skill[idx].lv < max )
- intif_guild_skillup(g->guild_id, skill_id, sd->status.account_id, max);
+ intif->guild_skillup(g->guild_id, skill_id, sd->status.account_id, max);
return 0;
}
@@ -1331,15 +1334,14 @@ int guild_skillup(TBL_PC* sd, uint16 skill_id)
/*====================================================
* Notification of guildskill skill_id increase request
*---------------------------------------------------*/
-int guild_skillupack(int guild_id,uint16 skill_id,int account_id)
-{
- struct map_session_data *sd=iMap->id2sd(account_id);
+int guild_skillupack(int guild_id,uint16 skill_id,int account_id) {
+ struct map_session_data *sd=map->id2sd(account_id);
struct guild *g=guild->search(guild_id);
int i;
if(g==NULL)
return 0;
if( sd != NULL ) {
- clif->guild_skillup(sd,skill_id,g->skill[skill_id-GD_SKILLBASE].lv);
+ clif->skillup(sd,skill_id,g->skill[skill_id-GD_SKILLBASE].lv, 0);
/* Guild Aura handling */
switch( skill_id ) {
@@ -1347,7 +1349,7 @@ int guild_skillupack(int guild_id,uint16 skill_id,int account_id)
case GD_GLORYWOUNDS:
case GD_SOULCOLD:
case GD_HAWKEYES:
- guild->aura_refresh(sd,skill_id,g->skill[skill_id-GD_SKILLBASE].lv);
+ guild->aura_refresh(sd,skill_id,g->skill[skill_id-GD_SKILLBASE].lv);
break;
}
}
@@ -1362,9 +1364,9 @@ int guild_skillupack(int guild_id,uint16 skill_id,int account_id)
void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv) {
struct skill_unit_group* group = NULL;
- int type = status_skill2sc(skill_id);
- if( !(battle_config.guild_aura&((iMap->agit_flag || iMap->agit2_flag)?2:1)) &&
- !(battle_config.guild_aura&(map_flag_gvg2(sd->bl.m)?8:4)) )
+ int type = status->skill2sc(skill_id);
+ if( !(battle_config.guild_aura&((map->agit_flag || map->agit2_flag)?2:1))
+ && !(battle_config.guild_aura&(map_flag_gvg2(sd->bl.m)?8:4)) )
return;
if( !skill_lv )
return;
@@ -1374,7 +1376,7 @@ void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint1
}
group = skill->unitsetting(&sd->bl,skill_id,skill_lv,sd->bl.x,sd->bl.y,0);
if( group ) {
- sc_start4(&sd->bl,type,100,(battle_config.guild_aura&16)?0:skill_lv,0,0,group->group_id,600000);//duration doesn't matter these status never end with val4
+ sc_start4(NULL,&sd->bl,type,100,(battle_config.guild_aura&16)?0:skill_lv,0,0,group->group_id,600000);//duration doesn't matter these status never end with val4
}
return;
}
@@ -1405,7 +1407,7 @@ void guild_block_skill(struct map_session_data *sd, int time)
uint16 skill_id[] = { GD_BATTLEORDER, GD_REGENERATION, GD_RESTORE, GD_EMERGENCYCALL };
int i;
for (i = 0; i < 4; i++)
- skill->blockpc_start(sd, skill_id[i], time , true);
+ skill->blockpc_start(sd, skill_id[i], time);
}
/*====================================================
@@ -1431,15 +1433,15 @@ int guild_check_alliance(int guild_id1, int guild_id2, int flag)
/*====================================================
* Player sd, asking player tsd an alliance between their 2 guilds
*---------------------------------------------------*/
-int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd)
-{
+int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd) {
struct guild *g[2];
int i;
- if(iMap->agit_flag || iMap->agit2_flag) { // Disable alliance creation during woe [Valaris]
- clif->message(sd->fd,msg_txt(676)); //"Alliances cannot be made during Guild Wars!"
+ if(map->agit_flag || map->agit2_flag) {
+ // Disable alliance creation during woe [Valaris]
+ clif->message(sd->fd,msg_txt(876)); //"Alliances cannot be made during Guild Wars!"
return 0;
- } // end addition [Valaris]
+ }
nullpo_ret(sd);
@@ -1457,11 +1459,11 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd)
if(sd->status.guild_id == tsd->status.guild_id)
return 0;
- if( guild_get_alliance_count(g[0],0) >= battle_config.max_guild_alliance ) {
+ if( guild->get_alliance_count(g[0],0) >= battle_config.max_guild_alliance ) {
clif->guild_allianceack(sd,4);
return 0;
}
- if( guild_get_alliance_count(g[1],0) >= battle_config.max_guild_alliance ) {
+ if( guild->get_alliance_count(g[1],0) >= battle_config.max_guild_alliance ) {
clif->guild_allianceack(sd,3);
return 0;
}
@@ -1489,12 +1491,11 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd)
/*====================================================
* Player sd, answer to player tsd (account_id) for an alliance request
*---------------------------------------------------*/
-int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag)
-{
+int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag) {
struct map_session_data *tsd;
nullpo_ret(sd);
- tsd= iMap->id2sd( account_id );
+ tsd = map->id2sd( account_id );
if (!tsd) { //Character left? Cancel alliance.
clif->guild_allianceack(sd,3);
return 0;
@@ -1510,12 +1511,12 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag)
g=sd->guild;
tg=tsd->guild;
- if(g==NULL || guild_get_alliance_count(g,0) >= battle_config.max_guild_alliance){
+ if(g==NULL || guild->get_alliance_count(g,0) >= battle_config.max_guild_alliance){
clif->guild_allianceack(sd,4);
clif->guild_allianceack(tsd,3);
return 0;
}
- if(tg==NULL || guild_get_alliance_count(tg,0) >= battle_config.max_guild_alliance){
+ if(tg==NULL || guild->get_alliance_count(tg,0) >= battle_config.max_guild_alliance){
clif->guild_allianceack(sd,3);
clif->guild_allianceack(tsd,4);
return 0;
@@ -1524,18 +1525,18 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag)
for(i=0;i<MAX_GUILDALLIANCE;i++){
if(g->alliance[i].guild_id==tsd->status.guild_id &&
g->alliance[i].opposition==1)
- intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id,
+ intif->guild_alliance( sd->status.guild_id,tsd->status.guild_id,
sd->status.account_id,tsd->status.account_id,9 );
}
for(i=0;i<MAX_GUILDALLIANCE;i++){
if(tg->alliance[i].guild_id==sd->status.guild_id &&
tg->alliance[i].opposition==1)
- intif_guild_alliance( tsd->status.guild_id,sd->status.guild_id,
+ intif->guild_alliance( tsd->status.guild_id,sd->status.guild_id,
tsd->status.account_id,sd->status.account_id,9 );
}
// inform other servers
- intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id,
+ intif->guild_alliance( sd->status.guild_id,tsd->status.guild_id,
sd->status.account_id,tsd->status.account_id,0 );
return 0;
} else { // deny
@@ -1550,16 +1551,16 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag)
/*====================================================
* Player sd asking to break alliance with guild guild_id
*---------------------------------------------------*/
-int guild_delalliance(struct map_session_data *sd,int guild_id,int flag)
-{
+int guild_delalliance(struct map_session_data *sd,int guild_id,int flag) {
nullpo_ret(sd);
- if(iMap->agit_flag || iMap->agit2_flag) { // Disable alliance breaking during woe [Valaris]
- clif->message(sd->fd,msg_txt(677)); //"Alliances cannot be broken during Guild Wars!"
+ if(map->agit_flag || map->agit2_flag) {
+ // Disable alliance breaking during woe [Valaris]
+ clif->message(sd->fd,msg_txt(877)); //"Alliances cannot be broken during Guild Wars!"
return 0;
- } // end addition [Valaris]
+ }
- intif_guild_alliance( sd->status.guild_id,guild_id,sd->status.account_id,0,flag|8 );
+ intif->guild_alliance( sd->status.guild_id,guild_id,sd->status.account_id,0,flag|8 );
return 0;
}
@@ -1581,48 +1582,47 @@ int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd)
if(sd->status.guild_id == tsd->status.guild_id)
return 0;
- if( guild_get_alliance_count(g,1) >= battle_config.max_guild_alliance ) {
+ if( guild->get_alliance_count(g,1) >= battle_config.max_guild_alliance ) {
clif->guild_oppositionack(sd,1);
return 0;
}
- for (i = 0; i < MAX_GUILDALLIANCE; i++) { // checking relations
+ for (i = 0; i < MAX_GUILDALLIANCE; i++) { // checking relations
if(g->alliance[i].guild_id==tsd->status.guild_id){
- if (g->alliance[i].opposition == 1) { // check if not already hostile
+ if (g->alliance[i].opposition == 1) { // check if not already hostile
clif->guild_oppositionack(sd,2);
return 0;
}
- if(iMap->agit_flag || iMap->agit2_flag) // Prevent the changing of alliances to oppositions during WoE.
+ if(map->agit_flag || map->agit2_flag) // Prevent the changing of alliances to oppositions during WoE.
return 0;
//Change alliance to opposition.
- intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id,
- sd->status.account_id,tsd->status.account_id,8 );
+ intif->guild_alliance(sd->status.guild_id,tsd->status.guild_id,
+ sd->status.account_id,tsd->status.account_id,8);
}
}
- // inform other serv
- intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id,
- sd->status.account_id,tsd->status.account_id,1 );
+ // inform other serv
+ intif->guild_alliance(sd->status.guild_id,tsd->status.guild_id,
+ sd->status.account_id,tsd->status.account_id,1);
return 0;
}
/*====================================================
* Notification of a relationship between 2 guilds
*---------------------------------------------------*/
-int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag,const char *name1,const char *name2)
-{
- struct guild *g[2];
- int guild_id[2];
- const char *guild_name[2];
- struct map_session_data *sd[2];
+int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag,const char *name1,const char *name2) {
+ struct guild *g[2] = { NULL };
+ int guild_id[2] = { 0 };
+ const char *guild_name[2] = { NULL };
+ struct map_session_data *sd[2] = { NULL };
int j,i;
guild_id[0] = guild_id1;
guild_id[1] = guild_id2;
guild_name[0] = name1;
guild_name[1] = name2;
- sd[0] = iMap->id2sd(account_id1);
- sd[1] = iMap->id2sd(account_id2);
+ sd[0] = map->id2sd(account_id1);
+ sd[1] = map->id2sd(account_id2);
g[0]=guild->search(guild_id1);
g[1]=guild->search(guild_id2);
@@ -1632,7 +1632,7 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id
sd[0]->guild_alliance_account=0;
}
- if (flag & 0x70) { // failure
+ if (flag & 0x70) { // failure
for(i=0;i<2-(flag&1);i++)
if( sd[i]!=NULL )
clif->guild_allianceack(sd[i],((flag>>4)==i+1)?3:4);
@@ -1648,7 +1648,7 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id
}
}
- if (!(flag & 0x08)) { // new relationship
+ if (!(flag & 0x08)) { // new relationship
for(i=0;i<2-(flag&1);i++) {
if(g[i]!=NULL) {
ARR_FIND( 0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == 0 );
@@ -1659,33 +1659,33 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id
}
}
}
- } else { // remove relationship
+ } else { // remove relationship
for(i=0;i<2-(flag&1);i++) {
if( g[i] != NULL ) {
ARR_FIND( 0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == guild_id[1-i] && g[i]->alliance[j].opposition == (flag&1) );
if( j < MAX_GUILDALLIANCE )
g[i]->alliance[j].guild_id = 0;
}
- if (sd[i] != NULL) // notify players
+ if (sd[i] != NULL) // notify players
clif->guild_delalliance(sd[i],guild_id[1-i],(flag&1));
}
}
- if ((flag & 0x0f) == 0) { // alliance notification
+ if ((flag & 0x0f) == 0) { // alliance notification
if( sd[1]!=NULL )
clif->guild_allianceack(sd[1],2);
- } else if ((flag & 0x0f) == 1) { // enemy notification
+ } else if ((flag & 0x0f) == 1) { // enemy notification
if( sd[0]!=NULL )
clif->guild_oppositionack(sd[0],0);
}
- for (i = 0; i < 2 - (flag & 1); i++) { // Retransmission of the relationship list to all members
- struct map_session_data *sd;
+ for (i = 0; i < 2 - (flag & 1); i++) { // Retransmission of the relationship list to all members
+ struct map_session_data *msd;
if(g[i]!=NULL)
for(j=0;j<g[i]->max_member;j++)
- if((sd=g[i]->member[j].sd)!=NULL)
- clif->guild_allianceinfo(sd);
+ if((msd=g[i]->member[j].sd)!=NULL)
+ clif->guild_allianceinfo(msd);
}
return 0;
}
@@ -1708,7 +1708,7 @@ int guild_broken_sub(DBKey key, DBData *data, va_list ap)
for(j=0;j<g->max_member;j++)
if( (sd=g->member[j].sd)!=NULL )
clif->guild_delalliance(sd,guild_id,g->alliance[i].opposition);
- intif_guild_alliance(g->guild_id, guild_id,0,0,g->alliance[i].opposition|8);
+ intif->guild_alliance(g->guild_id, guild_id,0,0,g->alliance[i].opposition|8);
g->alliance[i].guild_id=0;
}
}
@@ -1731,7 +1731,7 @@ int castle_guild_broken_sub(DBKey key, DBData *data, va_list ap)
// We call castle_event::OnGuildBreak of all castles of the guild
// You can set all castle_events in the 'db/castle_db.txt'
safestrncpy(name, gc->castle_event, sizeof(name));
- npc_event_do(strcat(name, "::OnGuildBreak"));
+ npc->event_do(strcat(name, "::OnGuildBreak"));
//Save the new 'owner', this should invoke guardian clean up and other such things.
guild->castledatasave(gc->castle_id, 1, 0);
@@ -1752,23 +1752,40 @@ int guild_broken(int guild_id,int flag)
for(i=0;i<g->max_member;i++){ // Destroy all relationships
if((sd=g->member[i].sd)!=NULL){
if(sd->state.storage_flag == 2)
- storage_guild_storage_quit(sd,1);
+ gstorage->pc_quit(sd,1);
sd->status.guild_id=0;
sd->guild = NULL;
+ sd->state.gmaster_flag = 0;
clif->guild_broken(g->member[i].sd,0);
clif->charnameupdate(sd); // [LuzZza]
+ status_change_end(&sd->bl, SC_LEADERSHIP, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_GLORYWOUNDS, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_SOULCOLD, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_HAWKEYES, INVALID_TIMER);
}
}
- guild_db->foreach(guild_db,guild_broken_sub,guild_id);
- castle_db->foreach(castle_db,castle_guild_broken_sub,guild_id);
- guild_storage_delete(guild_id);
+ guild->db->foreach(guild->db,guild->broken_sub,guild_id);
+ guild->castle_db->foreach(guild->castle_db,guild->castle_broken_sub,guild_id);
+ gstorage->delete(guild_id);
if( hChSys.ally ) {
if( g->channel != NULL ) {
- clif->chsys_delete(( struct hChSysCh * )g->channel);
+ clif->chsys_delete(g->channel);
}
}
- idb_remove(guild_db,guild_id);
+ if( g->instance )
+ aFree(g->instance);
+
+ for( i = 0; i < g->hdatac; i++ ) {
+ if( g->hdata[i]->flag.free ) {
+ aFree(g->hdata[i]->data);
+ }
+ aFree(g->hdata[i]);
+ }
+ if( g->hdata )
+ aFree(g->hdata);
+
+ idb_remove(guild->db,guild_id);
return 0;
}
@@ -1789,7 +1806,7 @@ int guild_gm_change(int guild_id, struct map_session_data *sd)
return 0;
//Notify servers that master has changed.
- intif_guild_change_gm(guild_id, sd->status.name, strlen(sd->status.name)+1);
+ intif->guild_change_gm(guild_id, sd->status.name, strlen(sd->status.name)+1);
return 1;
}
@@ -1821,13 +1838,13 @@ int guild_gm_changed(int guild_id, int account_id, int char_id)
strcpy(g->master, g->member[0].name);
if (g->member[pos].sd && g->member[pos].sd->fd) {
- clif->message(g->member[pos].sd->fd, msg_txt(678)); //"You no longer are the Guild Master."
+ clif->message(g->member[pos].sd->fd, msg_txt(878)); //"You no longer are the Guild Master."
g->member[pos].sd->state.gmaster_flag = 0;
}
if (g->member[0].sd && g->member[0].sd->fd) {
- clif->message(g->member[0].sd->fd, msg_txt(679)); //"You have become the Guild Master!"
- g->member[0].sd->state.gmaster_flag = g;
+ clif->message(g->member[0].sd->fd, msg_txt(879)); //"You have become the Guild Master!"
+ g->member[0].sd->state.gmaster_flag = 1;
//Block his skills for 5 minutes to prevent abuse.
guild->block_skill(g->member[0].sd, 300000);
}
@@ -1848,11 +1865,11 @@ int guild_gm_changed(int guild_id, int account_id, int char_id)
/*====================================================
* Guild disbanded
*---------------------------------------------------*/
-int guild_break(struct map_session_data *sd,char *name)
-{
+int guild_break(struct map_session_data *sd,char *name) {
struct guild *g;
+ struct unit_data *ud;
int i;
-
+
nullpo_ret(sd);
if( (g=sd->guild)==NULL )
@@ -1871,8 +1888,35 @@ int guild_break(struct map_session_data *sd,char *name)
clif->guild_broken(sd,2);
return 0;
}
+
+ /* regardless of char server allowing it, we clear the guild master's auras */
+ if( (ud = unit->bl2ud(&sd->bl)) ) {
+ int count = 0;
+ struct skill_unit_group *groups[4];
+ for (i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++) {
+ switch (ud->skillunit[i]->skill_id) {
+ case GD_LEADERSHIP:
+ case GD_GLORYWOUNDS:
+ case GD_SOULCOLD:
+ case GD_HAWKEYES:
+ if( count == 4 )
+ ShowWarning("guild_break:'%s' got more than 4 guild aura instances! (%d)\n",sd->status.name,ud->skillunit[i]->skill_id);
+ else
+ groups[count++] = ud->skillunit[i];
+ break;
+ }
+
+ }
+ for(i = 0; i < count; i++) {
+ skill->del_unitgroup(groups[i],ALC_MARK);
+ }
+ }
- intif_guild_break(g->guild_id);
+#ifdef GP_BOUND_ITEMS
+ pc->bound_clear(sd,IBT_GUILD);
+#endif
+
+ intif->guild_break(g->guild_id);
return 1;
}
@@ -1883,7 +1927,7 @@ int guild_break(struct map_session_data *sd,char *name)
void guild_castle_map_init(void)
{
DBIterator* iter = NULL;
- int num = db_size(castle_db);
+ int num = db_size(guild->castle_db);
if (num > 0) {
struct guild_castle* gc = NULL;
@@ -1891,12 +1935,12 @@ void guild_castle_map_init(void)
CREATE(castle_ids, int, num);
cursor = castle_ids;
- iter = db_iterator(castle_db);
+ iter = db_iterator(guild->castle_db);
for (gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter)) {
*(cursor++) = gc->castle_id;
}
dbi_destroy(iter);
- if (intif_guild_castle_dataload(num, castle_ids))
+ if (intif->guild_castle_dataload(num, castle_ids))
ShowStatus("Requested '"CL_WHITE"%d"CL_RESET"' guild castles from char-server...\n", num);
aFree(castle_ids);
}
@@ -1926,8 +1970,8 @@ int guild_castledatasave(int castle_id, int index, int value)
struct mob_data *gd;
gc->guild_id = value;
for (i = 0; i < MAX_GUARDIANS; i++)
- if (gc->guardian[i].visible && (gd = iMap->id2md(gc->guardian[i].id)) != NULL)
- mob_guardian_guildchange(gd);
+ if (gc->guardian[i].visible && (gd = map->id2md(gc->guardian[i].id)) != NULL)
+ mob->guardian_guildchange(gd);
break;
}
case 2:
@@ -1938,8 +1982,8 @@ int guild_castledatasave(int castle_id, int index, int value)
struct mob_data *gd;
gc->defense = value;
for (i = 0; i < MAX_GUARDIANS; i++)
- if (gc->guardian[i].visible && (gd = iMap->id2md(gc->guardian[i].id)) != NULL)
- status_calc_mob(gd, 0);
+ if (gc->guardian[i].visible && (gd = map->id2md(gc->guardian[i].id)) != NULL)
+ status_calc_mob(gd, SCO_NONE);
break;
}
case 4:
@@ -1963,7 +2007,7 @@ int guild_castledatasave(int castle_id, int index, int value)
return 0;
}
- if (!intif_guild_castle_datasave(castle_id, index, value)) {
+ if (!intif->guild_castle_datasave(castle_id, index, value)) {
guild->castle_reconnect(castle_id, index, value);
}
return 0;
@@ -1971,14 +2015,14 @@ int guild_castledatasave(int castle_id, int index, int value)
void guild_castle_reconnect_sub(void *key, void *data, va_list ap)
{
- int castle_id = GetWord((int)__64BPTRSIZE(key), 0);
- int index = GetWord((int)__64BPTRSIZE(key), 1);
- intif_guild_castle_datasave(castle_id, index, *(int *)data);
+ int castle_id = GetWord((int)h64BPTRSIZE(key), 0);
+ int index = GetWord((int)h64BPTRSIZE(key), 1);
+ intif->guild_castle_datasave(castle_id, index, *(int *)data);
aFree(data);
}
/**
- * Saves pending guild castle data changes when char-server is
+ * Saves pending guild castle data changes when char-server is
* disconnected.
* On reconnect pushes all changes to char-server for saving.
*/
@@ -1987,13 +2031,13 @@ void guild_castle_reconnect(int castle_id, int index, int value)
static struct linkdb_node *gc_save_pending = NULL;
if (castle_id < 0) { // char-server reconnected
- linkdb_foreach(&gc_save_pending, guild_castle_reconnect_sub);
+ linkdb_foreach(&gc_save_pending, guild->castle_reconnect_sub);
linkdb_final(&gc_save_pending);
} else {
int *data;
CREATE(data, int, 1);
*data = value;
- linkdb_replace(&gc_save_pending, (void*)__64BPTRSIZE((MakeDWord(castle_id, index))), data);
+ linkdb_replace(&gc_save_pending, (void*)h64BPTRSIZE((MakeDWord(castle_id, index))), data);
}
}
@@ -2011,8 +2055,8 @@ int guild_castledataloadack(int len, struct guild_castle *gc)
ev = i; // offset of castle or -1
if( ev < 0 ) { //No castles owned, invoke OnAgitInit as it is.
- npc_event_doall("OnAgitInit");
- npc_event_doall("OnAgitInit2");
+ npc->event_doall("OnAgitInit");
+ npc->event_doall("OnAgitInit2");
} else { // load received castles into memory, one by one
for( i = 0; i < n; i++, gc++ ) {
struct guild_castle *c = guild->castle_search(gc->castle_id);
@@ -2043,7 +2087,7 @@ int guild_castledataloadack(int len, struct guild_castle *gc)
*---------------------------------------------------*/
void guild_agit_start(void)
{ // Run All NPC_Event[OnAgitStart]
- int c = npc_event_doall("OnAgitStart");
+ int c = npc->event_doall("OnAgitStart");
ShowStatus("NPC_Event:[OnAgitStart] Run (%d) Events by @AgitStart.\n",c);
}
@@ -2052,7 +2096,7 @@ void guild_agit_start(void)
*---------------------------------------------------*/
void guild_agit_end(void)
{ // Run All NPC_Event[OnAgitEnd]
- int c = npc_event_doall("OnAgitEnd");
+ int c = npc->event_doall("OnAgitEnd");
ShowStatus("NPC_Event:[OnAgitEnd] Run (%d) Events by @AgitEnd.\n",c);
}
@@ -2061,7 +2105,7 @@ void guild_agit_end(void)
*---------------------------------------------------*/
void guild_agit2_start(void)
{ // Run All NPC_Event[OnAgitStart2]
- int c = npc_event_doall("OnAgitStart2");
+ int c = npc->event_doall("OnAgitStart2");
ShowStatus("NPC_Event:[OnAgitStart2] Run (%d) Events by @AgitStart2.\n",c);
}
@@ -2070,7 +2114,7 @@ void guild_agit2_start(void)
*---------------------------------------------------*/
void guild_agit2_end(void)
{ // Run All NPC_Event[OnAgitEnd2]
- int c = npc_event_doall("OnAgitEnd2");
+ int c = npc->event_doall("OnAgitEnd2");
ShowStatus("NPC_Event:[OnAgitEnd2] Run (%d) Events by @AgitEnd2.\n",c);
}
@@ -2079,7 +2123,7 @@ int guild_checkcastles(struct guild *g)
{
int nb_cas = 0;
struct guild_castle* gc = NULL;
- DBIterator *iter = db_iterator(castle_db);
+ DBIterator *iter = db_iterator(guild->castle_db);
for (gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter)) {
if (gc->guild_id == g->guild_id) {
@@ -2105,38 +2149,38 @@ void guild_flag_add(struct npc_data *nd) {
int i;
/* check */
- for( i = 0; i < guild_flags_count; i++ ) {
- if( guild_flags[i] && guild_flags[i]->bl.id == nd->bl.id ) {
+ for( i = 0; i < guild->flags_count; i++ ) {
+ if( guild->flags[i] && guild->flags[i]->bl.id == nd->bl.id ) {
return;/* exists, most likely updated the id. */
}
}
- i = guild_flags_count;/* save the current slot */
+ i = guild->flags_count;/* save the current slot */
/* add */
- RECREATE(guild_flags,struct npc_data*,++guild_flags_count);
+ RECREATE(guild->flags,struct npc_data*,++guild->flags_count);
/* save */
- guild_flags[i] = nd;
+ guild->flags[i] = nd;
}
void guild_flag_remove(struct npc_data *nd) {
int i, cursor;
- if( guild_flags_count == 0 )
+ if( guild->flags_count == 0 )
return;
/* find it */
- for( i = 0; i < guild_flags_count; i++ ) {
- if( guild_flags[i] && guild_flags[i]->bl.id == nd->bl.id ) {/* found */
- guild_flags[i] = NULL;
+ for( i = 0; i < guild->flags_count; i++ ) {
+ if( guild->flags[i] && guild->flags[i]->bl.id == nd->bl.id ) {/* found */
+ guild->flags[i] = NULL;
break;
}
}
/* compact list */
- for( i = 0, cursor = 0; i < guild_flags_count; i++ ) {
- if( guild_flags[i] == NULL )
+ for( i = 0, cursor = 0; i < guild->flags_count; i++ ) {
+ if( guild->flags[i] == NULL )
continue;
if( cursor != i ) {
- memmove(&guild_flags[cursor], &guild_flags[i], sizeof(struct npc_data*));
+ memmove(&guild->flags[cursor], &guild->flags[i], sizeof(struct npc_data*));
}
cursor++;
@@ -2147,7 +2191,7 @@ void guild_flag_remove(struct npc_data *nd) {
/**
* @see DBApply
*/
-static int eventlist_db_final(DBKey key, DBData *data, va_list ap) {
+int eventlist_db_final(DBKey key, DBData *data, va_list ap) {
struct eventlist *next = NULL;
struct eventlist *current = DB->data2ptr(data);
while (current != NULL) {
@@ -2161,15 +2205,15 @@ static int eventlist_db_final(DBKey key, DBData *data, va_list ap) {
/**
* @see DBApply
*/
-static int guild_expcache_db_final(DBKey key, DBData *data, va_list ap) {
- ers_free(expcache_ers, DB->data2ptr(data));
+int guild_expcache_db_final(DBKey key, DBData *data, va_list ap) {
+ ers_free(guild->expcache_ers, DB->data2ptr(data));
return 0;
}
/**
* @see DBApply
*/
-static int guild_castle_db_final(DBKey key, DBData *data, va_list ap) {
+int guild_castle_db_final(DBKey key, DBData *data, va_list ap) {
struct guild_castle* gc = DB->data2ptr(data);
if( gc->temp_guardians )
aFree(gc->temp_guardians);
@@ -2180,56 +2224,66 @@ static int guild_castle_db_final(DBKey key, DBData *data, va_list ap) {
/* called when scripts are reloaded/unloaded */
void guild_flags_clear(void) {
int i;
- for( i = 0; i < guild_flags_count; i++ ) {
- if( guild_flags[i] )
- guild_flags[i] = NULL;
+ for( i = 0; i < guild->flags_count; i++ ) {
+ if( guild->flags[i] )
+ guild->flags[i] = NULL;
}
- guild_flags_count = 0;
+ guild->flags_count = 0;
}
-void do_init_guild(void) {
- guild_db = idb_alloc(DB_OPT_RELEASE_DATA);
- castle_db = idb_alloc(DB_OPT_BASE);
- guild_expcache_db = idb_alloc(DB_OPT_BASE);
- guild_infoevent_db = idb_alloc(DB_OPT_BASE);
- expcache_ers = ers_new(sizeof(struct guild_expcache),"guild.c::expcache_ers",ERS_OPT_NONE);
-
- guild_flags_count = 0;
-
- sv->readdb(iMap->db_path, "castle_db.txt", ',', 4, 5, -1, &guild_read_castledb);
+void do_init_guild(bool minimal) {
+ if (minimal)
+ return;
+
+ guild->db = idb_alloc(DB_OPT_RELEASE_DATA);
+ guild->castle_db = idb_alloc(DB_OPT_BASE);
+ guild->expcache_db = idb_alloc(DB_OPT_BASE);
+ guild->infoevent_db = idb_alloc(DB_OPT_BASE);
+ guild->expcache_ers = ers_new(sizeof(struct guild_expcache),"guild.c::expcache_ers",ERS_OPT_NONE);
+
+ sv->readdb(map->db_path, "castle_db.txt", ',', 4, 5, -1, guild->read_castledb);
- memset(guild_skill_tree,0,sizeof(guild_skill_tree));
- sv->readdb(iMap->db_path, "guild_skill_tree.txt", ',', 2+MAX_GUILD_SKILL_REQUIRE*2, 2+MAX_GUILD_SKILL_REQUIRE*2, -1, &guild_read_guildskill_tree_db); //guild skill tree [Komurka]
+ sv->readdb(map->db_path, "guild_skill_tree.txt", ',', 2+MAX_GUILD_SKILL_REQUIRE*2, 2+MAX_GUILD_SKILL_REQUIRE*2, -1, guild->read_guildskill_tree_db); //guild skill tree [Komurka]
- iTimer->add_timer_func_list(guild_payexp_timer,"guild_payexp_timer");
- iTimer->add_timer_func_list(guild_send_xy_timer, "guild_send_xy_timer");
- iTimer->add_timer_interval(iTimer->gettick()+GUILD_PAYEXP_INVERVAL,guild_payexp_timer,0,0,GUILD_PAYEXP_INVERVAL);
- iTimer->add_timer_interval(iTimer->gettick()+GUILD_SEND_XY_INVERVAL,guild_send_xy_timer,0,0,GUILD_SEND_XY_INVERVAL);
+ timer->add_func_list(guild->payexp_timer,"guild_payexp_timer");
+ timer->add_func_list(guild->send_xy_timer, "guild_send_xy_timer");
+ timer->add_interval(timer->gettick()+GUILD_PAYEXP_INVERVAL,guild->payexp_timer,0,0,GUILD_PAYEXP_INVERVAL);
+ timer->add_interval(timer->gettick()+GUILD_SEND_XY_INVERVAL,guild->send_xy_timer,0,0,GUILD_SEND_XY_INVERVAL);
}
void do_final_guild(void) {
- DBIterator *iter = db_iterator(guild_db);
+ DBIterator *iter = db_iterator(guild->db);
struct guild *g;
+ int i;
for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) {
if( g->channel != NULL )
- clif->chsys_delete((struct hChSysCh *)g->channel);
+ clif->chsys_delete(g->channel);
if( g->instance != NULL ) {
aFree(g->instance);
g->instance = NULL;
}
+ for( i = 0; i < g->hdatac; i++ ) {
+ if( g->hdata[i]->flag.free ) {
+ aFree(g->hdata[i]->data);
+ }
+ aFree(g->hdata[i]);
+ }
+ if( g->hdata )
+ aFree(g->hdata);
}
dbi_destroy(iter);
- db_destroy(guild_db);
- castle_db->destroy(castle_db,guild_castle_db_final);
- guild_expcache_db->destroy(guild_expcache_db,guild_expcache_db_final);
- guild_infoevent_db->destroy(guild_infoevent_db,eventlist_db_final);
- ers_destroy(expcache_ers);
-
- aFree(guild_flags);/* never empty; created on boot */
+ db_destroy(guild->db);
+ guild->castle_db->destroy(guild->castle_db,guild->castle_db_final);
+ guild->expcache_db->destroy(guild->expcache_db,guild->expcache_db_final);
+ guild->infoevent_db->destroy(guild->infoevent_db,guild->eventlist_db_final);
+ ers_destroy(guild->expcache_ers);
+
+ if( guild->flags )
+ aFree(guild->flags);
}
void guild_defaults(void) {
guild = &guild_s;
@@ -2237,6 +2291,18 @@ void guild_defaults(void) {
guild->init = do_init_guild;
guild->final = do_final_guild;
/* */
+ guild->db = NULL;
+ guild->castle_db = NULL;
+ guild->expcache_db = NULL;
+ guild->infoevent_db = NULL;
+ /* */
+ guild->expcache_ers = NULL;
+ /* */
+ memset(guild->skill_tree, 0, sizeof(guild->skill_tree));
+ /* guild flags cache */
+ guild->flags = NULL;
+ guild->flags_count = 0;
+ /* */
guild->skill_get_max = guild_skill_get_max;
/* */
guild->checkskill = guild_checkskill;
@@ -2307,10 +2373,30 @@ void guild_defaults(void) {
guild->agit_end = guild_agit_end;
guild->agit2_start = guild_agit2_start;
guild->agit2_end = guild_agit2_end;
- /* guild flag cachin */
+ /* guild flag caching */
guild->flag_add = guild_flag_add;
guild->flag_remove = guild_flag_remove;
guild->flags_clear = guild_flags_clear;
- /* guild aura */
+ /* guild aura */
guild->aura_refresh = guild_guildaura_refresh;
+ /* */
+ guild->payexp_timer = guild_payexp_timer;
+ guild->sd_check = guild_sd_check;
+ guild->read_guildskill_tree_db = guild_read_guildskill_tree_db;
+ guild->read_castledb = guild_read_castledb;
+ guild->payexp_timer_sub = guild_payexp_timer_sub;
+ guild->send_xy_timer_sub = guild_send_xy_timer_sub;
+ guild->send_xy_timer = guild_send_xy_timer;
+ guild->create_expcache = create_expcache;
+ guild->eventlist_db_final = eventlist_db_final;
+ guild->expcache_db_final = guild_expcache_db_final;
+ guild->castle_db_final = guild_castle_db_final;
+ guild->broken_sub = guild_broken_sub;
+ guild->castle_broken_sub = castle_guild_broken_sub;
+ guild->makemember = guild_makemember;
+ guild->check_member = guild_check_member;
+ guild->get_alliance_count = guild_get_alliance_count;
+ guild->castle_reconnect_sub = guild_castle_reconnect_sub;
+ /* */
+ guild->retrieveitembound = guild_retrieveitembound;
}
diff --git a/src/map/guild.h b/src/map/guild.h
index 9841f5451..126325eef 100644
--- a/src/map/guild.h
+++ b/src/map/guild.h
@@ -2,32 +2,69 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _GUILD_H_
-#define _GUILD_H_
+#ifndef MAP_GUILD_H
+#define MAP_GUILD_H
-//#include "../common/mmo.h"
-struct guild;
-struct guild_member;
-struct guild_position;
-struct guild_castle;
-#include "map.h" // NAME_LENGTH
-struct map_session_data;
-struct mob_data;
+#include "map.h" // EVENT_NAME_LENGTH, TBL_PC
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/mmo.h"
-//For quick linking to a guardian's info. [Skotlex]
+/**
+ * Defines
+ **/
+#define GUILD_SEND_XY_INVERVAL 5000 // Interval of sending coordinates and HP
+#define GUILD_PAYEXP_INVERVAL 10000 //Interval (maximum survival time of the cache, in milliseconds)
+#define MAX_GUILD_SKILL_REQUIRE 5
+
+/**
+ * Structures
+ **/
+struct eventlist {
+ char name[EVENT_NAME_LENGTH];
+ struct eventlist *next;
+};
+
+/**
+ * Guardian data
+ * For quick linking to a guardian's info. [Skotlex]
+ **/
struct guardian_data {
int number; //0-MAX_GUARDIANS-1 = Guardians. MAX_GUARDIANS = Emperium.
- int guild_id;
- int emblem_id;
- int guardup_lv; //Level of GD_GUARDUP skill.
- char guild_name[NAME_LENGTH];
+
+ struct guild *g;
struct guild_castle* castle;
};
+struct guild_expcache {
+ int guild_id, account_id, char_id;
+ uint64 exp;
+};
+struct s_guild_skill_tree {
+ int id;
+ int max;
+ struct {
+ short id;
+ short lv;
+ } need[MAX_GUILD_SKILL_REQUIRE];
+};
+
struct guild_interface {
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
/* */
+ DBMap* db; // int guild_id -> struct guild*
+ DBMap* castle_db; // int castle_id -> struct guild_castle*
+ DBMap* expcache_db; // int char_id -> struct guild_expcache*
+ DBMap* infoevent_db; // int guild_id -> struct eventlist*
+ /* */
+ struct eri *expcache_ers; //For handling of guild exp payment.
+ /* */
+ struct s_guild_skill_tree skill_tree[MAX_GUILDSKILL];
+ /* guild flags cache */
+ struct npc_data **flags;
+ unsigned short flags_count;
+ /* */
int (*skill_get_max) (int id);
/* */
int (*checkskill) (struct guild *g,int id);
@@ -40,7 +77,7 @@ struct guild_interface {
struct guild_castle *(*castle_search) (int gcid);
/* */
struct guild_castle *(*mapname2gc) (const char* mapname);
- struct guild_castle *(*mapindex2gc) (short mapindex);
+ struct guild_castle *(*mapindex2gc) (short map_index);
/* */
struct map_session_data *(*getavailablesd) (struct guild *g);
int (*getindex) (struct guild *g,int account_id,int char_id);
@@ -104,10 +141,30 @@ struct guild_interface {
void (*flags_clear) (void);
/* guild aura */
void (*aura_refresh) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
-} guild_s;
+ /* item bound [Mhalicot]*/
+ void (*retrieveitembound) (int char_id,int aid,int guild_id);
+ /* */
+ int (*payexp_timer) (int tid, int64 tick, int id, intptr_t data);
+ TBL_PC* (*sd_check) (int guild_id, int account_id, int char_id);
+ bool (*read_guildskill_tree_db) (char* split[], int columns, int current);
+ bool (*read_castledb) (char* str[], int columns, int current);
+ int (*payexp_timer_sub) (DBKey key, DBData *data, va_list ap);
+ int (*send_xy_timer_sub) (DBKey key, DBData *data, va_list ap);
+ int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data);
+ DBData (*create_expcache) (DBKey key, va_list args);
+ int (*eventlist_db_final) (DBKey key, DBData *data, va_list ap);
+ int (*expcache_db_final) (DBKey key, DBData *data, va_list ap);
+ int (*castle_db_final) (DBKey key, DBData *data, va_list ap);
+ int (*broken_sub) (DBKey key, DBData *data, va_list ap);
+ int (*castle_broken_sub) (DBKey key, DBData *data, va_list ap);
+ void (*makemember) (struct guild_member *m,struct map_session_data *sd);
+ int (*check_member) (struct guild *g);
+ int (*get_alliance_count) (struct guild *g,int flag);
+ void (*castle_reconnect_sub) (void *key, void *data, va_list ap);
+};
struct guild_interface *guild;
void guild_defaults(void);
-#endif /* _GUILD_H_ */
+#endif /* MAP_GUILD_H */
diff --git a/src/map/homunculus.c b/src/map/homunculus.c
index efb5c0eb3..0f76fcf5f 100644
--- a/src/map/homunculus.c
+++ b/src/map/homunculus.c
@@ -2,43 +2,47 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/malloc.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/mmo.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
+#define HERCULES_CORE
-#include "log.h"
-#include "clif.h"
+#include "../config/core.h" // DBPATH
+#include "homunculus.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "atcommand.h"
+#include "battle.h"
#include "chrif.h"
+#include "clif.h"
+#include "guild.h"
#include "intif.h"
#include "itemdb.h"
+#include "log.h"
#include "map.h"
-#include "pc.h"
-#include "status.h"
-#include "skill.h"
#include "mob.h"
-#include "pet.h"
-#include "battle.h"
+#include "npc.h"
#include "party.h"
-#include "guild.h"
-#include "atcommand.h"
+#include "pc.h"
+#include "pet.h"
#include "script.h"
-#include "npc.h"
+#include "skill.h"
+#include "status.h"
#include "trade.h"
#include "unit.h"
+#include "../common/cbasetypes.h"
+#include "../common/malloc.h"
+#include "../common/mmo.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-#include "homunculus.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
+struct homunculus_interface homunculus_s;
//Returns the viewdata for homunculus
struct view_data* homunculus_get_viewdata(int class_) {
@@ -69,7 +73,7 @@ enum homun_type homunculus_class2type(int class_) {
case 6052:
return HT_S;
default:
- return -1;
+ return HT_INVALID;
}
}
@@ -132,30 +136,30 @@ int homunculus_dead(struct homun_data *hd) {
}
//Vaporize a character's homun. If flag, HP needs to be 80% or above.
-int homunculus_vaporize(struct map_session_data *sd, int flag) {
+int homunculus_vaporize(struct map_session_data *sd, enum homun_state flag) {
struct homun_data *hd;
nullpo_ret(sd);
hd = sd->hd;
- if (!hd || hd->homunculus.vaporize)
+ if (!hd || hd->homunculus.vaporize != HOM_ST_ACTIVE)
return 0;
- if (status_isdead(&hd->bl))
+ if (status->isdead(&hd->bl))
return 0; //Can't vaporize a dead homun.
- if (flag && get_percentage(hd->battle_status.hp, hd->battle_status.max_hp) < 80)
+ if (flag == HOM_ST_REST && get_percentage(hd->battle_status.hp, hd->battle_status.max_hp) < 80)
return 0;
hd->regen.state.block = 3; //Block regen while vaporized.
//Delete timers when vaporized.
homun->hunger_timer_delete(hd);
- hd->homunculus.vaporize = 1;
+ hd->homunculus.vaporize = flag;
if(battle_config.hom_setting&0x40)
memset(hd->blockskill, 0, sizeof(hd->blockskill));
clif->hominfo(sd, sd->hd, 0);
homun->save(hd);
- return unit_remove_map(&hd->bl, CLR_OUTSIGHT);
+ return unit->remove_map(&hd->bl, CLR_OUTSIGHT, ALC_MARK);
}
//delete a homunculus, completely "killing it".
@@ -166,7 +170,7 @@ int homunculus_delete(struct homun_data *hd, int emote) {
sd = hd->master;
if (!sd)
- return unit_free(&hd->bl,CLR_DEAD);
+ return unit->free(&hd->bl,CLR_DEAD);
if (emote >= 0)
clif->emotion(&sd->bl, emote);
@@ -176,7 +180,7 @@ int homunculus_delete(struct homun_data *hd, int emote) {
// Send homunculus_dead to client
hd->homunculus.hp = 0;
clif->hominfo(sd, hd, 0);
- return unit_remove_map(&hd->bl,CLR_OUTSIGHT);
+ return unit->remove_map(&hd->bl,CLR_OUTSIGHT, ALC_MARK);
}
int homunculus_calc_skilltree(struct homun_data *hd, int flag_evolve) {
@@ -258,7 +262,7 @@ void homunculus_skillup(struct homun_data *hd,uint16 skill_id) {
int i = 0 ;
nullpo_retv(hd);
- if(hd->homunculus.vaporize)
+ if(hd->homunculus.vaporize != HOM_ST_ACTIVE)
return;
i = skill_id - HM_SKILLBASE;
@@ -270,7 +274,7 @@ void homunculus_skillup(struct homun_data *hd,uint16 skill_id) {
{
hd->homunculus.hskill[i].lv++;
hd->homunculus.skillpts-- ;
- status_calc_homunculus(hd,0);
+ status_calc_homunculus(hd,SCO_NONE);
if (hd->master) {
clif->homskillup(hd->master, skill_id);
clif->hominfo(hd->master,hd,0);
@@ -286,7 +290,7 @@ bool homunculus_levelup(struct homun_data *hd) {
int growth_max_hp, growth_max_sp;
enum homun_type htype;
- if((htype = homun->class2type(hd->homunculus.class_)) == -1) {
+ if( (htype = homun->class2type(hd->homunculus.class_)) == HT_INVALID ) {
ShowError("homunculus_levelup: Invalid class %d. \n", hd->homunculus.class_);
return false;
}
@@ -350,7 +354,7 @@ bool homunculus_levelup(struct homun_data *hd) {
growth_max_hp, growth_max_sp,
growth_str/10.0, growth_agi/10.0, growth_vit/10.0,
growth_int/10.0, growth_dex/10.0, growth_luk/10.0);
- clif->disp_onlyself(hd->master,output,strlen(output));
+ clif_disp_onlyself(hd->master,output,strlen(output));
}
return true;
}
@@ -362,7 +366,7 @@ int homunculus_change_class(struct homun_data *hd, short class_) {
return 0;
hd->homunculusDB = &homun->db[i];
hd->homunculus.class_ = class_;
- status_set_viewdata(&hd->bl, class_);
+ status->set_viewdata(&hd->bl, class_);
homun->calc_skilltree(hd, 1);
return 1;
}
@@ -401,8 +405,8 @@ bool homunculus_evolve(struct homun_data *hd) {
hom->luk += 10*rnd_value(min->luk, max->luk);
hom->intimacy = 500;
- unit_remove_map(&hd->bl, CLR_OUTSIGHT);
- iMap->addblock(&hd->bl);
+ unit->remove_map(&hd->bl, CLR_OUTSIGHT, ALC_MARK);
+ map->addblock(&hd->bl);
clif->spawn(&hd->bl);
clif->emotion(&sd->bl, E_NO1);
@@ -411,10 +415,10 @@ bool homunculus_evolve(struct homun_data *hd) {
//status_Calc flag&1 will make current HP/SP be reloaded from hom structure
hom->hp = hd->battle_status.hp;
hom->sp = hd->battle_status.sp;
- status_calc_homunculus(hd,1);
+ status_calc_homunculus(hd,SCO_FIRST);
if (!(battle_config.hom_setting&0x2))
- skill->unit_move(&sd->hd->bl,iTimer->gettick(),1); // apply land skills immediately
+ skill->unit_move(&sd->hd->bl,timer->gettick(),1); // apply land skills immediately
return true;
}
@@ -433,20 +437,20 @@ bool homunculus_mutate(struct homun_data *hd, int homun_id) {
m_class = homun->class2type(hd->homunculus.class_);
m_id = homun->class2type(homun_id);
- if( m_class == -1 || m_id == -1 || m_class != HT_EVO || m_id != HT_S ) {
+ if( m_class == HT_INVALID || m_id == HT_INVALID || m_class != HT_EVO || m_id != HT_S ) {
clif->emotion(&hd->bl, E_SWT);
return false;
}
prev_class = hd->homunculus.class_;
- if (!homun->change_class(hd, homun_id)) {
+ if( !homun->change_class(hd, homun_id) ) {
ShowError("homunculus_mutate: Can't evolve homunc from %d to %d", hd->homunculus.class_, homun_id);
return false;
}
- unit_remove_map(&hd->bl, CLR_OUTSIGHT);
- iMap->addblock(&hd->bl);
+ unit->remove_map(&hd->bl, CLR_OUTSIGHT, ALC_MARK);
+ map->addblock(&hd->bl);
clif->spawn(&hd->bl);
clif->emotion(&sd->bl, E_NO1);
@@ -458,10 +462,10 @@ bool homunculus_mutate(struct homun_data *hd, int homun_id) {
hom->hp = hd->battle_status.hp;
hom->sp = hd->battle_status.sp;
hom->prev_class = prev_class;
- status_calc_homunculus(hd,1);
+ status_calc_homunculus(hd,SCO_FIRST);
if (!(battle_config.hom_setting&0x2))
- skill->unit_move(&sd->hd->bl,iTimer->gettick(),1); // apply land skills immediately
+ skill->unit_move(&sd->hd->bl,timer->gettick(),1); // apply land skills immediately
return true;
}
@@ -469,10 +473,10 @@ bool homunculus_mutate(struct homun_data *hd, int homun_id) {
int homunculus_gainexp(struct homun_data *hd,unsigned int exp) {
enum homun_type htype;
- if(hd->homunculus.vaporize)
+ if(hd->homunculus.vaporize != HOM_ST_ACTIVE)
return 1;
- if((htype = homun->class2type(hd->homunculus.class_)) == -1) {
+ if( (htype = homun->class2type(hd->homunculus.class_)) == HT_INVALID ) {
ShowError("homunculus_gainexp: Invalid class %d. \n", hd->homunculus.class_);
return 0;
}
@@ -503,7 +507,7 @@ int homunculus_gainexp(struct homun_data *hd,unsigned int exp) {
hd->homunculus.exp = 0;
clif->specialeffect(&hd->bl,568,AREA);
- status_calc_homunculus(hd,0);
+ status_calc_homunculus(hd,SCO_NONE);
status_percent_heal(&hd->bl, 100, 100);
return 0;
}
@@ -542,7 +546,7 @@ void homunculus_save(struct homun_data *hd) {
//calculation on login)
hd->homunculus.hp = hd->battle_status.hp;
hd->homunculus.sp = hd->battle_status.sp;
- intif_homunculus_requestsave(sd->status.account_id, &hd->homunculus);
+ intif->homunculus_requestsave(sd->status.account_id, &hd->homunculus);
}
unsigned char homunculus_menu(struct map_session_data *sd,unsigned char menu_num) {
@@ -569,12 +573,12 @@ unsigned char homunculus_menu(struct map_session_data *sd,unsigned char menu_num
bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd) {
int i, foodID, emotion;
- if(hd->homunculus.vaporize)
+ if(hd->homunculus.vaporize == HOM_ST_REST)
return false;
foodID = hd->homunculusDB->foodID;
i = pc->search_inventory(sd,foodID);
- if(i < 0) {
+ if (i == INDEX_NOT_FOUND) {
clif->hom_food(sd,foodID,0);
return false;
}
@@ -613,11 +617,11 @@ bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd) {
return true;
}
-int homunculus_hunger_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int homunculus_hunger_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
struct homun_data *hd;
- if(!(sd=iMap->id2sd(id)) || !sd->status.hom_id || !(hd=sd->hd))
+ if(!(sd=map->id2sd(id)) || !sd->status.hom_id || !(hd=sd->hd))
return 1;
if(hd->hungry_timer != tid){
@@ -645,14 +649,14 @@ int homunculus_hunger_timer(int tid, unsigned int tick, int id, intptr_t data) {
}
clif->send_homdata(sd,SP_HUNGRY,hd->homunculus.hunger);
- hd->hungry_timer = iTimer->add_timer(tick+hd->homunculusDB->hungryDelay,homun->hunger_timer,sd->bl.id,0); //simple Fix albator
+ hd->hungry_timer = timer->add(tick+hd->homunculusDB->hungryDelay,homun->hunger_timer,sd->bl.id,0); //simple Fix albator
return 0;
}
void homunculus_hunger_timer_delete(struct homun_data *hd) {
nullpo_retv(hd);
if(hd->hungry_timer != INVALID_TIMER) {
- iTimer->delete_timer(hd->hungry_timer,homun->hunger_timer);
+ timer->delete(hd->hungry_timer,homun->hunger_timer);
hd->hungry_timer = INVALID_TIMER;
}
}
@@ -729,33 +733,35 @@ bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) {
if(i < 0) {
ShowError("homunculus_create: unknown class [%d] for homunculus '%s', requesting deletion.\n", hom->class_, hom->name);
sd->status.hom_id = 0;
- intif_homunculus_requestdelete(hom->hom_id);
+ intif->homunculus_requestdelete(hom->hom_id);
return false;
}
sd->hd = hd = (struct homun_data*)aCalloc(1,sizeof(struct homun_data));
hd->bl.type = BL_HOM;
- hd->bl.id = npc_get_new_npc_id();
+ hd->bl.id = npc->get_new_npc_id();
hd->master = sd;
hd->homunculusDB = &homun->db[i];
memcpy(&hd->homunculus, hom, sizeof(struct s_homunculus));
hd->exp_next = homun->exptable[hd->homunculus.level - 1];
- status_set_viewdata(&hd->bl, hd->homunculus.class_);
- status_change_init(&hd->bl);
- unit_dataset(&hd->bl);
+ status->set_viewdata(&hd->bl, hd->homunculus.class_);
+ status->change_init(&hd->bl);
+ unit->dataset(&hd->bl);
hd->ud.dir = sd->ud.dir;
// Find a random valid pos around the player
hd->bl.m = sd->bl.m;
hd->bl.x = sd->bl.x;
hd->bl.y = sd->bl.y;
- unit_calc_pos(&hd->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
+ unit->calc_pos(&hd->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
hd->bl.x = hd->ud.to_x;
hd->bl.y = hd->ud.to_y;
-
- iMap->addiddb(&hd->bl);
- status_calc_homunculus(hd,1);
+ hd->masterteleport_timer = 0;
+
+ map->addiddb(&hd->bl);
+ status_calc_homunculus(hd,SCO_FIRST);
+ status_percent_heal(&hd->bl, 100, 100);
hd->hungry_timer = INVALID_TIMER;
return true;
@@ -763,7 +769,7 @@ bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) {
void homunculus_init_timers(struct homun_data * hd) {
if (hd->hungry_timer == INVALID_TIMER)
- hd->hungry_timer = iTimer->add_timer(iTimer->gettick()+hd->homunculusDB->hungryDelay,homun->hunger_timer,hd->master->bl.id,0);
+ hd->hungry_timer = timer->add(timer->gettick()+hd->homunculusDB->hungryDelay,homun->hunger_timer,hd->master->bl.id,0);
hd->regen.state.block = 0; //Restore HP/SP block.
}
@@ -775,20 +781,20 @@ bool homunculus_call(struct map_session_data *sd) {
// If homunc not yet loaded, load it
if (!sd->hd)
- return intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id);
+ return intif->homunculus_requestload(sd->status.account_id, sd->status.hom_id);
hd = sd->hd;
- if (!hd->homunculus.vaporize)
+ if (hd->homunculus.vaporize != HOM_ST_REST)
return false; //Can't use this if homun wasn't vaporized.
homun->init_timers(hd);
- hd->homunculus.vaporize = 0;
+ hd->homunculus.vaporize = HOM_ST_ACTIVE;
if (hd->bl.prev == NULL) { //Spawn him
hd->bl.x = sd->bl.x;
hd->bl.y = sd->bl.y;
hd->bl.m = sd->bl.m;
- iMap->addblock(&hd->bl);
+ map->addblock(&hd->bl);
clif->spawn(&hd->bl);
clif->send_homdata(sd,SP_ACK,0);
clif->hominfo(sd,hd,1);
@@ -799,16 +805,16 @@ bool homunculus_call(struct map_session_data *sd) {
homun->save(hd);
} else
//Warp him to master.
- unit_warp(&hd->bl,sd->bl.m, sd->bl.x, sd->bl.y,CLR_OUTSIGHT);
+ unit->warp(&hd->bl,sd->bl.m, sd->bl.x, sd->bl.y,CLR_OUTSIGHT);
return true;
}
-// Recv homunculus data from char server
+// Receive homunculus data from char server
bool homunculus_recv_data(int account_id, struct s_homunculus *sh, int flag) {
struct map_session_data *sd;
struct homun_data *hd;
- sd = iMap->id2sd(account_id);
+ sd = map->id2sd(account_id);
if(!sd)
return false;
if (sd->status.char_id != sh->char_id) {
@@ -831,10 +837,10 @@ bool homunculus_recv_data(int account_id, struct s_homunculus *sh, int flag) {
homun->create(sd, sh);
hd = sd->hd;
- if(hd && hd->homunculus.hp && !hd->homunculus.vaporize && hd->bl.prev == NULL && sd->bl.prev != NULL) {
+ if(hd && hd->homunculus.hp && hd->homunculus.vaporize == HOM_ST_ACTIVE && hd->bl.prev == NULL && sd->bl.prev != NULL) {
enum homun_type htype = homun->class2type(hd->homunculus.class_);
- iMap->addblock(&hd->bl);
+ map->addblock(&hd->bl);
clif->spawn(&hd->bl);
clif->send_homdata(sd,SP_ACK,0);
clif->hominfo(sd,hd,1);
@@ -890,7 +896,7 @@ bool homunculus_creation_request(struct map_session_data *sd, int class_) {
hom.luk = base->luk *10;
// Request homunculus creation
- intif_homunculus_create(sd->status.account_id, &hom);
+ intif->homunculus_create(sd->status.account_id, &hom);
return true;
}
@@ -902,14 +908,14 @@ bool homunculus_ressurect(struct map_session_data* sd, unsigned char per, short
return false; // no homunculus
if (!sd->hd) //Load homun data;
- return intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id);
+ return intif->homunculus_requestload(sd->status.account_id, sd->status.hom_id);
hd = sd->hd;
- if (hd->homunculus.vaporize)
+ if (hd->homunculus.vaporize != HOM_ST_ACTIVE)
return false; // vaporized homunculi need to be 'called'
- if (!status_isdead(&hd->bl))
+ if (!status->isdead(&hd->bl))
return false; // already alive
homun->init_timers(hd);
@@ -919,10 +925,10 @@ bool homunculus_ressurect(struct map_session_data* sd, unsigned char per, short
hd->bl.m = sd->bl.m;
hd->bl.x = x;
hd->bl.y = y;
- iMap->addblock(&hd->bl);
+ map->addblock(&hd->bl);
clif->spawn(&hd->bl);
}
- status_revive(&hd->bl, per, 0);
+ status->revive(&hd->bl, per, 0);
return true;
}
@@ -1001,7 +1007,7 @@ bool homunculus_shuffle(struct homun_data *hd) {
memcpy(&hd->homunculus.hskill, &b_skill, sizeof(b_skill));
hd->homunculus.skillpts = skillpts;
clif->homskillinfoblock(sd);
- status_calc_homunculus(hd,0);
+ status_calc_homunculus(hd,SCO_NONE);
status_percent_heal(&hd->bl, 100, 100);
clif->specialeffect(&hd->bl,568,AREA);
@@ -1125,16 +1131,16 @@ void homunculus_read_db(void) {
memset(homun->db,0,sizeof(homun->db));
for(i = 0; i<ARRAYLENGTH(filename); i++) {
if( i > 0 ) {
- char path[256];
+ char filepath[256];
- sprintf(path, "%s/%s", iMap->db_path, filename[i]);
+ sprintf(filepath, "%s/%s", map->db_path, filename[i]);
- if( !exists(path) ) {
+ if( !exists(filepath) ) {
continue;
}
}
- sv->readdb(iMap->db_path, filename[i], ',', 50, 50, MAX_HOMUNCULUS_CLASS, homun->read_db_sub);
+ sv->readdb(map->db_path, filename[i], ',', 50, 50, MAX_HOMUNCULUS_CLASS, homun->read_db_sub);
}
}
@@ -1144,14 +1150,14 @@ bool homunculus_read_skill_db_sub(char* split[], int columns, int current) {
int j;
int minJobLevelPresent = 0;
- if( columns == 14 )
- minJobLevelPresent = 1; // MinJobLvl has been added
+ if( columns == 15 )
+ minJobLevelPresent = 1; // MinJobLvl has been added - FIXME: is this extra field even needed anymore?
// check for bounds [celest]
classid = atoi(split[0]) - HM_CLASS_BASE;
if ( classid >= MAX_HOMUNCULUS_CLASS ) {
- ShowWarning("homunculus_read_skill_db_sub: Invalud homunculus class %d.\n", atoi(split[0]));
+ ShowWarning("homunculus_read_skill_db_sub: Invalid homunculus class %d.\n", atoi(split[0]));
return false;
}
@@ -1178,9 +1184,27 @@ bool homunculus_read_skill_db_sub(char* split[], int columns, int current) {
return true;
}
+int8 homunculus_get_intimacy_grade(struct homun_data *hd) {
+ unsigned int val = hd->homunculus.intimacy / 100;
+ if( val > 100 ) {
+ if( val > 250 ) {
+ if( val > 750 ) {
+ if ( val > 900 )
+ return 4;
+ else
+ return 3;
+ } else
+ return 2;
+ } else
+ return 1;
+ }
+
+ return 0;
+}
+
void homunculus_skill_db_read(void) {
memset(homun->skill_tree,0,sizeof(homun->skill_tree));
- sv->readdb(iMap->db_path, "homun_skill_tree.txt", ',', 13, 15, -1, homun->read_skill_db_sub);
+ sv->readdb(map->db_path, "homun_skill_tree.txt", ',', 13, 15, -1, homun->read_skill_db_sub);
}
@@ -1194,7 +1218,7 @@ void homunculus_exp_db_read(void) {
memset(homun->exptable,0,sizeof(homun->exptable));
for(i = 0; i < 2; i++) {
- sprintf(line, "%s/%s", iMap->db_path, filename[i]);
+ sprintf(line, "%s/%s", map->db_path, filename[i]);
if( (fp=fopen(line,"r")) == NULL) {
if(i != 0)
continue;
@@ -1205,7 +1229,7 @@ void homunculus_exp_db_read(void) {
if(line[0] == '/' && line[1] == '/')
continue;
- if (!(homun->exptable[j++] = strtoul(line, NULL, 10)))
+ if (!(homun->exptable[j++] = (unsigned int)strtoul(line, NULL, 10)))
break;
}
// Last permitted level have to be 0!
@@ -1227,13 +1251,17 @@ void homunculus_skill_reload(void) {
homun->skill_db_read();
}
-void do_init_homunculus(void) {
+void do_init_homunculus(bool minimal) {
int class_;
+
+ if (minimal)
+ return;
+
homun->read_db();
homun->exp_db_read();
homun->skill_db_read();
// Add homunc timer function to timer func list [Toms]
- iTimer->add_timer_func_list(homun->hunger_timer, "homunculus_hunger_timer");
+ timer->add_func_list(homun->hunger_timer, "homunculus_hunger_timer");
//Stock view data for homuncs
memset(&homun->viewdb, 0, sizeof(homun->viewdb));
@@ -1293,4 +1321,7 @@ void homunculus_defaults(void) {
homun->read_skill_db_sub = homunculus_read_skill_db_sub;
homun->skill_db_read = homunculus_skill_db_read;
homun->exp_db_read = homunculus_exp_db_read;
+ homun->addspiritball = homunculus_addspiritball;
+ homun->delspiritball = homunculus_delspiritball;
+ homun->get_intimacy_grade = homunculus_get_intimacy_grade;
}
diff --git a/src/map/homunculus.h b/src/map/homunculus.h
index 86d437e73..25ccabf48 100644
--- a/src/map/homunculus.h
+++ b/src/map/homunculus.h
@@ -2,16 +2,17 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _HOMUNCULUS_H_
-#define _HOMUNCULUS_H_
+#ifndef MAP_HOMUNCULUS_H
+#define MAP_HOMUNCULUS_H
+#include "pc.h"
#include "status.h" // struct status_data, struct status_change
#include "unit.h" // struct unit_data
-#include "pc.h"
+#include "../common/mmo.h"
#define MAX_HOM_SKILL_REQUIRE 5
-#define homdb_checkid(id) (id >= HM_CLASS_BASE && id <= HM_CLASS_MAX)
-#define homun_alive(x) ((x) && (x)->homunculus.vaporize != 1 && (x)->battle_status.hp > 0)
+#define homdb_checkid(id) ((id) >= HM_CLASS_BASE && (id) <= HM_CLASS_MAX)
+#define homun_alive(x) ((x) && (x)->homunculus.vaporize == HOM_ST_ACTIVE && (x)->battle_status.hp > 0)
struct h_stats {
unsigned int HP, SP;
@@ -28,8 +29,6 @@ struct s_homunculus_db {
unsigned char element, race, base_size, evo_size;
};
-extern struct s_homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS];
-
enum {
HOMUNCULUS_CLASS,
HOMUNCULUS_FOOD
@@ -46,6 +45,12 @@ enum {
SP_HUNGRY = 0x2,
};
+enum homun_state {
+ HOM_ST_ACTIVE = 0,/* either alive or dead */
+ HOM_ST_REST = 1,/* is resting (vaporized) */
+ HOM_ST_MORPH = 2,/* in morph state */
+};
+
struct homun_data {
struct block_list bl;
struct unit_data ud;
@@ -53,13 +58,15 @@ struct homun_data {
struct status_data base_status, battle_status;
struct status_change sc;
struct regen_data regen;
- struct s_homunculus_db *homunculusDB; //[orn]
- struct s_homunculus homunculus; //[orn]
+ struct s_homunculus_db *homunculusDB; //[orn]
+ struct s_homunculus homunculus; //[orn]
- struct map_session_data *master; //pointer back to its master
- int hungry_timer; //[orn]
+ struct map_session_data *master; //pointer back to its master
+ int hungry_timer; //[orn]
unsigned int exp_next;
- char blockskill[MAX_SKILL]; // [orn]
+ char blockskill[MAX_SKILL]; // [orn]
+
+ int64 masterteleport_timer;
};
struct homun_skill_tree_entry {
@@ -74,9 +81,10 @@ struct homun_skill_tree_entry {
}; // Celest
enum homun_type {
- HT_REG = 0x1,
- HT_EVO = 0x2,
- HT_S = 0x4,
+ HT_REG, // Regular Homunculus
+ HT_EVO, // Evolved Homunculus
+ HT_S, // Homunculus S
+ HT_INVALID = -1, // Invalid Homunculus
};
/* homunculus.c interface */
@@ -86,7 +94,7 @@ struct homunculus_interface {
struct s_homunculus_db db[MAX_HOMUNCULUS_CLASS];
struct homun_skill_tree_entry skill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE];
/* */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
void (*reload) (void);
void (*reload_skill) (void);
@@ -95,7 +103,7 @@ struct homunculus_interface {
enum homun_type (*class2type) (int class_);
void (*damaged) (struct homun_data *hd);
int (*dead) (struct homun_data *hd);
- int (*vaporize) (struct map_session_data *sd, int flag);
+ int (*vaporize) (struct map_session_data *sd, enum homun_state flag);
int (*delete) (struct homun_data *hd, int emote);
int (*checkskill) (struct homun_data *hd, uint16 skill_id);
int (*calc_skilltree) (struct homun_data *hd, int flag_evolve);
@@ -112,7 +120,7 @@ struct homunculus_interface {
void (*save) (struct homun_data *hd);
unsigned char (*menu) (struct map_session_data *sd,unsigned char menu_num);
bool (*feed) (struct map_session_data *sd, struct homun_data *hd);
- int (*hunger_timer) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*hunger_timer) (int tid, int64 tick, int id, intptr_t data);
void (*hunger_timer_delete) (struct homun_data *hd);
int (*change_name) (struct map_session_data *sd,char *name);
bool (*change_name_ack) (struct map_session_data *sd, char* name, int flag);
@@ -133,10 +141,11 @@ struct homunculus_interface {
void (*exp_db_read) (void);
void (*addspiritball) (struct homun_data *hd, int max);
void (*delspiritball) (struct homun_data *hd, int count, int type);
-} homunculus_s;
+ int8 (*get_intimacy_grade) (struct homun_data *hd);
+};
struct homunculus_interface *homun;
void homunculus_defaults(void);
-#endif /* _HOMUNCULUS_H_ */
+#endif /* MAP_HOMUNCULUS_H */
diff --git a/src/map/instance.c b/src/map/instance.c
index 690f14cfe..5789d7dd6 100644
--- a/src/map/instance.c
+++ b/src/map/instance.c
@@ -2,36 +2,41 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/malloc.h"
-#include "../common/nullpo.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
-#include "../common/db.h"
+#define HERCULES_CORE
-#include "clif.h"
#include "instance.h"
-#include "map.h"
-#include "npc.h"
-#include "party.h"
-#include "pc.h"
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdarg.h>
#include <time.h>
+#include "clif.h"
+#include "map.h"
+#include "npc.h"
+#include "party.h"
+#include "pc.h"
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
+
+struct instance_interface instance_s;
+
/// Checks whether given instance id is valid or not.
bool instance_is_valid(int instance_id) {
if( instance_id < 0 || instance_id >= instance->instances ) {// out of range
return false;
}
- if( instances[instance_id].state == INSTANCE_FREE ) {// uninitialized/freed instance slot
+ if( instance->list[instance_id].state == INSTANCE_FREE ) {// uninitialized/freed instance slot
return false;
}
@@ -46,17 +51,18 @@ bool instance_is_valid(int instance_id) {
* On success return instance_id
*--------------------------------------*/
int instance_create(int owner_id, const char *name, enum instance_owner_type type) {
- unsigned short *iptr = NULL, *icptr = NULL;
struct map_session_data *sd = NULL;
+ unsigned short *icptr = NULL;
struct party_data *p = NULL;
struct guild *g = NULL;
+ short *iptr = NULL;
int i, j;
switch ( type ) {
case IOT_NONE:
break;
case IOT_CHAR:
- if( ( sd = iMap->id2sd(owner_id) ) == NULL ) {
+ if( ( sd = map->id2sd(owner_id) ) == NULL ) {
ShowError("instance_create: character %d not found for instance '%s'.\n", owner_id, name);
return -2;
}
@@ -85,46 +91,49 @@ int instance_create(int owner_id, const char *name, enum instance_owner_type typ
}
if( type != IOT_NONE && *icptr ) {
- ARR_FIND(0, *icptr, i, strcmp(instances[iptr[i]].name,name) == 0 );
+ ARR_FIND(0, *icptr, i, strcmp(instance->list[iptr[i]].name,name) == 0 );
if( i != *icptr )
return -4;/* already got this instance */
}
- ARR_FIND(0, instance->instances, i, instances[i].state == INSTANCE_FREE);
-
+ ARR_FIND(0, instance->instances, i, instance->list[i].state == INSTANCE_FREE);
+
if( i == instance->instances )
- RECREATE(instances, struct instance_data, ++instance->instances);
-
- instances[i].state = INSTANCE_IDLE;
- instances[i].id = i;
- instances[i].idle_timer = INVALID_TIMER;
- instances[i].idle_timeout = instances[i].idle_timeoutval = 0;
- instances[i].progress_timer = INVALID_TIMER;
- instances[i].progress_timeout = 0;
- instances[i].users = 0;
- instances[i].map = NULL;
- instances[i].num_map = 0;
- instances[i].owner_id = owner_id;
- instances[i].owner_type = type;
- instances[i].vars = idb_alloc(DB_OPT_RELEASE_DATA);
-
- safestrncpy( instances[i].name, name, sizeof(instances[i].name) );
- instances[i].map = NULL;
+ RECREATE(instance->list, struct instance_data, ++instance->instances);
+
+ instance->list[i].state = INSTANCE_IDLE;
+ instance->list[i].id = i;
+ instance->list[i].idle_timer = INVALID_TIMER;
+ instance->list[i].idle_timeout = instance->list[i].idle_timeoutval = 0;
+ instance->list[i].progress_timer = INVALID_TIMER;
+ instance->list[i].progress_timeout = 0;
+ instance->list[i].users = 0;
+ instance->list[i].map = NULL;
+ instance->list[i].num_map = 0;
+ instance->list[i].owner_id = owner_id;
+ instance->list[i].owner_type = type;
+ instance->list[i].regs.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+ instance->list[i].regs.arrays = NULL;
+ instance->list[i].respawn.map = 0;
+ instance->list[i].respawn.y = 0;
+ instance->list[i].respawn.x = 0;
+
+ safestrncpy( instance->list[i].name, name, sizeof(instance->list[i].name) );
if( type != IOT_NONE ) {
- ARR_FIND(0, *icptr, j, iptr[j] == 0);
+ ARR_FIND(0, *icptr, j, iptr[j] == -1);
if( j == *icptr ) {
switch( type ) {
case IOT_CHAR:
- RECREATE(sd->instance, unsigned short, ++*icptr);
+ RECREATE(sd->instance, short, ++*icptr);
sd->instance[sd->instances-1] = i;
break;
case IOT_PARTY:
- RECREATE(p->instance, unsigned short, ++*icptr);
+ RECREATE(p->instance, short, ++*icptr);
p->instance[p->instances-1] = i;
break;
case IOT_GUILD:
- RECREATE(g->instance, unsigned short, ++*icptr);
+ RECREATE(g->instance, short, ++*icptr);
g->instance[g->instances-1] = i;
break;
}
@@ -140,7 +149,7 @@ int instance_create(int owner_id, const char *name, enum instance_owner_type typ
* Add a map to the instance using src map "name"
*--------------------------------------*/
int instance_add_map(const char *name, int instance_id, bool usebasename, const char *map_name) {
- int16 m = iMap->mapname2mapid(name);
+ int16 m = map->mapname2mapid(name);
int i, im = -1;
size_t num_cell, size;
@@ -152,68 +161,108 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const
return -1;
}
- if( map_name != NULL && strdb_iget(mapindex_db, map_name) ) {
+ if( map_name != NULL && strdb_iget(mapindex->db, map_name) ) {
ShowError("instance_add_map: trying to create instanced map with existent name '%s'\n", map_name);
return -2;
}
- if( map[m].instance_id >= 0 ) { // Source map already belong to a Instance.
+ if( map->list[m].instance_id >= 0 ) {
+ // Source map already belong to a Instance.
ShowError("instance_add_map: trying to instance already instanced map %s.\n", name);
return -4;
}
- ARR_FIND( instance->start_id, iMap->map_num, i, !map[i].name[0] ); // Searching for a Free Map
-
- if( i < iMap->map_num )
+ ARR_FIND( instance->start_id, map->count, i, map->list[i].name[0] == 0 ); // Searching for a Free Map
+
+ if( i < map->count )
im = i; // Unused map found (old instance)
else {
- im = iMap->map_num; // Using next map index
- RECREATE(map,struct map_data,++iMap->map_num);
+ im = map->count; // Using next map index
+ RECREATE(map->list,struct map_data,++map->count);
}
- if( map[m].cell == (struct mapcell *)0xdeadbeaf )
- iMap->cellfromcache(&map[m]);
+ if( map->list[m].cell == (struct mapcell *)0xdeadbeaf )
+ map->cellfromcache(&map->list[m]);
- memcpy( &map[im], &map[m], sizeof(struct map_data) ); // Copy source map
+ memcpy( &map->list[im], &map->list[m], sizeof(struct map_data) ); // Copy source map
if( map_name != NULL ) {
- snprintf(map[im].name, MAP_NAME_LENGTH, "%s", map_name);
- map[im].cName = map[m].name;
+ snprintf(map->list[im].name, MAP_NAME_LENGTH, "%s", map_name);
+ map->list[im].custom_name = true;
} else
- snprintf(map[im].name, MAP_NAME_LENGTH, (usebasename ? "%.3d#%s" : "%.3d%s"), instance_id, name); // Generate Name for Instance Map
- map[im].index = mapindex_addmap(-1, map[im].name); // Add map index
+ snprintf(map->list[im].name, MAP_NAME_LENGTH, (usebasename ? "%.3d#%s" : "%.3d%s"), instance_id, name); // Generate Name for Instance Map
+ map->list[im].index = mapindex->addmap(-1, map->list[im].name); // Add map index
- map[im].channel = NULL;
+ map->list[im].channel = NULL;
- if( !map[im].index ) {
- map[im].name[0] = '\0';
+ if( !map->list[im].index ) {
+ map->list[im].name[0] = '\0';
ShowError("instance_add_map: no more free map indexes.\n");
return -3; // No free map index
}
// Reallocate cells
- num_cell = map[im].xs * map[im].ys;
- CREATE( map[im].cell, struct mapcell, num_cell );
- memcpy( map[im].cell, map[m].cell, num_cell * sizeof(struct mapcell) );
+ num_cell = map->list[im].xs * map->list[im].ys;
+ CREATE( map->list[im].cell, struct mapcell, num_cell );
+ memcpy( map->list[im].cell, map->list[m].cell, num_cell * sizeof(struct mapcell) );
- size = map[im].bxs * map[im].bys * sizeof(struct block_list*);
- map[im].block = (struct block_list**)aCalloc(size, 1);
- map[im].block_mob = (struct block_list**)aCalloc(size, 1);
+ size = map->list[im].bxs * map->list[im].bys * sizeof(struct block_list*);
+ map->list[im].block = (struct block_list**)aCalloc(size, 1);
+ map->list[im].block_mob = (struct block_list**)aCalloc(size, 1);
- memset(map[im].npc, 0x00, sizeof(map[i].npc));
- map[im].npc_num = 0;
+ memset(map->list[im].npc, 0x00, sizeof(map->list[i].npc));
+ map->list[im].npc_num = 0;
- memset(map[im].moblist, 0x00, sizeof(map[im].moblist));
- map[im].mob_delete_timer = INVALID_TIMER;
+ memset(map->list[im].moblist, 0x00, sizeof(map->list[im].moblist));
+ map->list[im].mob_delete_timer = INVALID_TIMER;
- map[im].m = im;
- map[im].instance_id = instance_id;
- map[im].instance_src_map = m;
- map[m].flag.src4instance = 1; // Flag this map as a src map for instances
+ //Mimic unit
+ if( map->list[m].unit_count ) {
+ map->list[im].unit_count = map->list[m].unit_count;
+ CREATE( map->list[im].units, struct mapflag_skill_adjust*, map->list[im].unit_count );
+
+ for(i = 0; i < map->list[im].unit_count; i++) {
+ CREATE( map->list[im].units[i], struct mapflag_skill_adjust, 1);
+ memcpy( map->list[im].units[i],map->list[m].units[i],sizeof(struct mapflag_skill_adjust));
+ }
+ }
+ //Mimic skills
+ if( map->list[m].skill_count ) {
+ map->list[im].skill_count = map->list[m].skill_count;
+ CREATE( map->list[im].skills, struct mapflag_skill_adjust*, map->list[im].skill_count );
+
+ for(i = 0; i < map->list[im].skill_count; i++) {
+ CREATE( map->list[im].skills[i], struct mapflag_skill_adjust, 1);
+ memcpy( map->list[im].skills[i],map->list[m].skills[i],sizeof(struct mapflag_skill_adjust));
+ }
+ }
+ //Mimic zone mf
+ if( map->list[m].zone_mf_count ) {
+ map->list[im].zone_mf_count = map->list[m].zone_mf_count;
+ CREATE( map->list[im].zone_mf, char *, map->list[im].zone_mf_count );
+
+ for(i = 0; i < map->list[im].zone_mf_count; i++) {
+ CREATE(map->list[im].zone_mf[i], char, MAP_ZONE_MAPFLAG_LENGTH);
+ safestrncpy(map->list[im].zone_mf[i],map->list[m].zone_mf[i],MAP_ZONE_MAPFLAG_LENGTH);
+ }
+ }
+
+ //Mimic questinfo
+ if( map->list[m].qi_count ) {
+ map->list[im].qi_count = map->list[m].qi_count;
+ CREATE( map->list[im].qi_data, struct questinfo, map->list[im].qi_count );
+ memcpy( map->list[im].qi_data, map->list[m].qi_data, map->list[im].qi_count * sizeof(struct questinfo) );
+ }
+
+ map->list[im].m = im;
+ map->list[im].instance_id = instance_id;
+ map->list[im].instance_src_map = m;
+ map->list[im].flag.src4instance = 0; //clear
+ map->list[m].flag.src4instance = 1; // Flag this map as a src map for instances
- RECREATE(instances[instance_id].map, unsigned short, ++instances[instance_id].num_map);
+ RECREATE(instance->list[instance_id].map, unsigned short, ++instance->list[instance_id].num_map);
- instances[instance_id].map[instances[instance_id].num_map - 1] = im; // Attach to actual instance
- iMap->addmap2db(&map[im]);
+ instance->list[instance_id].map[instance->list[instance_id].num_map - 1] = im; // Attach to actual instance
+ map->addmap2db(&map->list[im]);
return im;
}
@@ -230,22 +279,37 @@ int instance_map2imap(int16 m, int instance_id) {
return -1;
}
- for( i = 0; i < instances[instance_id].num_map; i++ ) {
- if( instances[instance_id].map[i] && map[instances[instance_id].map[i]].instance_src_map == m )
- return instances[instance_id].map[i];
+ for( i = 0; i < instance->list[instance_id].num_map; i++ ) {
+ if( instance->list[instance_id].map[i] && map->list[instance->list[instance_id].map[i]].instance_src_map == m )
+ return instance->list[instance_id].map[i];
}
return -1;
}
+int instance_mapname2imap(const char *map_name, int instance_id) {
+ int i;
+
+ if( !instance->valid(instance_id) ) {
+ return -1;
+ }
+
+ for( i = 0; i < instance->list[instance_id].num_map; i++ ) {
+ if( instance->list[instance_id].map[i] && !strcmpi(map->list[map->list[instance->list[instance_id].map[i]].instance_src_map].name,map_name) )
+ return instance->list[instance_id].map[i];
+ }
+ return -1;
+}
+
+
/*--------------------------------------
* m : source map
* instance_id : where to search
* result : mapid of map "m" in this instance
*--------------------------------------*/
int instance_mapid2imapid(int16 m, int instance_id) {
- if( map[m].flag.src4instance == 0 )
+ if( map->list[m].flag.src4instance == 0 )
return m; // not instances found for this map
- else if( map[m].instance_id >= 0 ) { // This map is a instance, not a src map instance
+ else if( map->list[m].instance_id >= 0 ) { // This map is a instance, not a src map instance
ShowError("map_instance_mapid2imapid: already instanced (%d / %d)\n", m, instance_id);
return -1;
}
@@ -257,19 +321,31 @@ int instance_mapid2imapid(int16 m, int instance_id) {
}
/*--------------------------------------
- * map_instance_map_npcsub
* Used on Init instance. Duplicates each script on source map
*--------------------------------------*/
int instance_map_npcsub(struct block_list* bl, va_list args) {
struct npc_data* nd = (struct npc_data*)bl;
int16 m = va_arg(args, int); // Destination Map
- if ( npc_duplicate4instance(nd, m) )
+ if ( npc->duplicate4instance(nd, m) )
ShowDebug("instance_map_npcsub:npc_duplicate4instance failed (%s/%d)\n",nd->name,m);
return 1;
}
+int instance_init_npc(struct block_list* bl, va_list args) {
+ struct npc_data *nd = (struct npc_data*)bl;
+ struct event_data *ev;
+ char evname[EVENT_NAME_LENGTH];
+
+ snprintf(evname, EVENT_NAME_LENGTH, "%s::OnInstanceInit", nd->exname);
+
+ if( ( ev = strdb_get(npc->ev_db, evname) ) )
+ script->run(ev->nd->u.scr.script, ev->pos, 0, ev->nd->bl.id);
+
+ return 1;
+}
+
/*--------------------------------------
* Init all map on the instance. Npcs are created here
*--------------------------------------*/
@@ -279,10 +355,13 @@ void instance_init(int instance_id) {
if( !instance->valid(instance_id) )
return; // nothing to do
- for( i = 0; i < instances[instance_id].num_map; i++ )
- iMap->foreachinmap(instance_map_npcsub, map[instances[instance_id].map[i]].instance_src_map, BL_NPC, instances[instance_id].map[i]);
+ for( i = 0; i < instance->list[instance_id].num_map; i++ )
+ map->foreachinmap(instance->map_npcsub, map->list[instance->list[instance_id].map[i]].instance_src_map, BL_NPC, instance->list[instance_id].map[i]);
- instances[instance_id].state = INSTANCE_BUSY;
+ /* cant be together with the previous because it will rely on all of them being up */
+ map->foreachininstance(instance->init_npc, instance_id, BL_NPC);
+
+ instance->list[instance_id].state = INSTANCE_BUSY;
}
/*--------------------------------------
@@ -305,19 +384,19 @@ int instance_cleanup_sub(struct block_list *bl, va_list ap) {
switch(bl->type) {
case BL_PC:
- iMap->quit((struct map_session_data *) bl);
+ map->quit((struct map_session_data *) bl);
break;
case BL_NPC:
- npc_unload((struct npc_data *)bl,true);
+ npc->unload((struct npc_data *)bl,true);
break;
case BL_MOB:
- unit_free(bl,CLR_OUTSIGHT);
+ unit->free(bl,CLR_OUTSIGHT);
break;
case BL_PET:
//There is no need for this, the pet is removed together with the player. [Skotlex]
break;
case BL_ITEM:
- iMap->clearflooritem(bl);
+ map->clearflooritem(bl);
break;
case BL_SKILL:
skill->delunit((struct skill_unit *) bl);
@@ -333,51 +412,79 @@ int instance_cleanup_sub(struct block_list *bl, va_list ap) {
void instance_del_map(int16 m) {
int i;
- if( m <= 0 || map[m].instance_id == -1 ) {
+ if( m <= 0 || map->list[m].instance_id == -1 ) {
ShowError("instance_del_map: tried to remove non-existing instance map (%d)\n", m);
return;
}
- iMap->map_foreachpc(instance_del_load, m);
- iMap->foreachinmap(instance_cleanup_sub, m, BL_ALL);
+ map->foreachpc(instance_del_load, m);
+ map->foreachinmap(instance_cleanup_sub, m, BL_ALL);
- if( map[m].mob_delete_timer != INVALID_TIMER )
- iTimer->delete_timer(map[m].mob_delete_timer, iMap->removemobs_timer);
+ if( map->list[m].mob_delete_timer != INVALID_TIMER )
+ timer->delete(map->list[m].mob_delete_timer, map->removemobs_timer);
- mapindex_removemap( map[m].index );
+ mapindex->removemap(map_id2index(m));
// Free memory
- aFree(map[m].cell);
- aFree(map[m].block);
- aFree(map[m].block_mob);
+ aFree(map->list[m].cell);
+ aFree(map->list[m].block);
+ aFree(map->list[m].block_mob);
+
+ if( map->list[m].unit_count ) {
+ for(i = 0; i < map->list[m].unit_count; i++) {
+ aFree(map->list[m].units[i]);
+ }
+ if( map->list[m].units )
+ aFree(map->list[m].units);
+ }
+
+ if( map->list[m].skill_count ) {
+ for(i = 0; i < map->list[m].skill_count; i++) {
+ aFree(map->list[m].skills[i]);
+ }
+ if( map->list[m].skills )
+ aFree(map->list[m].skills);
+ }
+
+ if( map->list[m].zone_mf_count ) {
+ for(i = 0; i < map->list[m].zone_mf_count; i++) {
+ aFree(map->list[m].zone_mf[i]);
+ }
+ if( map->list[m].zone_mf )
+ aFree(map->list[m].zone_mf);
+ }
+
+ if( map->list[m].qi_data )
+ aFree(map->list[m].qi_data);
// Remove from instance
- for( i = 0; i < instances[map[m].instance_id].num_map; i++ ) {
- if( instances[map[m].instance_id].map[i] == m ) {
- instances[map[m].instance_id].num_map--;
- for( ; i < instances[map[m].instance_id].num_map; i++ )
- instances[map[m].instance_id].map[i] = instances[map[m].instance_id].map[i+1];
+ for( i = 0; i < instance->list[map->list[m].instance_id].num_map; i++ ) {
+ if( instance->list[map->list[m].instance_id].map[i] == m ) {
+ instance->list[map->list[m].instance_id].num_map--;
+ for( ; i < instance->list[map->list[m].instance_id].num_map; i++ )
+ instance->list[map->list[m].instance_id].map[i] = instance->list[map->list[m].instance_id].map[i+1];
i = -1;
break;
}
}
- if( i == instances[map[m].instance_id].num_map )
- ShowError("map_instance_del: failed to remove %s from instance list (%s): %d\n", map[m].name, instances[map[m].instance_id].name, m);
+ if( i == instance->list[map->list[m].instance_id].num_map )
+ ShowError("map_instance_del: failed to remove %s from instance list (%s): %d\n", map->list[m].name, instance->list[map->list[m].instance_id].name, m);
- if( map[m].channel )
- clif->chsys_delete(map[m].channel);
-
- iMap->removemapdb(&map[m]);
- memset(&map[m], 0x00, sizeof(map[0]));
- map[m].instance_id = -1;
- map[m].mob_delete_timer = INVALID_TIMER;
+ if( map->list[m].channel )
+ clif->chsys_delete(map->list[m].channel);
+
+ map->removemapdb(&map->list[m]);
+ memset(&map->list[m], 0x00, sizeof(map->list[0]));
+ map->list[m].name[0] = 0;
+ map->list[m].instance_id = -1;
+ map->list[m].mob_delete_timer = INVALID_TIMER;
}
/*--------------------------------------
* Timer to destroy instance by process or idle
*--------------------------------------*/
-int instance_destroy_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int instance_destroy_timer(int tid, int64 tick, int id, intptr_t data) {
instance->destroy(id);
return 0;
}
@@ -386,79 +493,96 @@ int instance_destroy_timer(int tid, unsigned int tick, int id, intptr_t data) {
* Removes a instance, all its maps and npcs.
*--------------------------------------*/
void instance_destroy(int instance_id) {
- unsigned short *iptr = NULL, *icptr = NULL;
struct map_session_data *sd = NULL;
+ unsigned short *icptr = NULL;
struct party_data *p = NULL;
struct guild *g = NULL;
- int last = 0, type, j;
+ short *iptr = NULL;
+ int type, j, last = 0;
unsigned int now = (unsigned int)time(NULL);
-
+
if( !instance->valid(instance_id) )
return; // nothing to do
- if( instances[instance_id].progress_timeout && instances[instance_id].progress_timeout <= now )
+ if( instance->list[instance_id].progress_timeout && instance->list[instance_id].progress_timeout <= now )
type = 1;
- else if( instances[instance_id].idle_timeout && instances[instance_id].idle_timeout <= now )
+ else if( instance->list[instance_id].idle_timeout && instance->list[instance_id].idle_timeout <= now )
type = 2;
else
type = 3;
-
+
clif->instance(instance_id, 5, type); // Report users this instance has been destroyed
- switch ( instances[instance_id].owner_type ) {
+ switch ( instance->list[instance_id].owner_type ) {
case IOT_NONE:
break;
case IOT_CHAR:
- if( ( sd = iMap->id2sd(instances[instance_id].owner_id) ) == NULL ) {
+ if( ( sd = map->id2sd(instance->list[instance_id].owner_id) ) == NULL ) {
break;
}
iptr = sd->instance;
icptr = &sd->instances;
break;
case IOT_PARTY:
- if( ( p = party->search(instances[instance_id].owner_id) ) == NULL ) {
+ if( ( p = party->search(instance->list[instance_id].owner_id) ) == NULL ) {
break;
}
iptr = p->instance;
icptr = &p->instances;
break;
case IOT_GUILD:
- if( ( g = guild->search(instances[instance_id].owner_id) ) == NULL ) {
+ if( ( g = guild->search(instance->list[instance_id].owner_id) ) == NULL ) {
break;
}
iptr = g->instance;
icptr = &g->instances;
break;
default:
- ShowError("instance_destroy: unknown type %d for owner_id %d and name %s.\n", instances[instance_id].owner_type,instances[instance_id].owner_id,instances[instance_id].name);
+ ShowError("instance_destroy: unknown type %d for owner_id %d and name '%s'.\n", instance->list[instance_id].owner_type,instance->list[instance_id].owner_id,instance->list[instance_id].name);
break;
}
if( iptr != NULL ) {
ARR_FIND(0, *icptr, j, iptr[j] == instance_id);
if( j != *icptr )
- iptr[j] = 0;
+ iptr[j] = -1;
}
- while( instances[instance_id].num_map && last != instances[instance_id].map[0] ) { // Remove all maps from instance
- last = instances[instance_id].map[0];
- instance->del_map( instances[instance_id].map[0] );
+ while( instance->list[instance_id].num_map && last != instance->list[instance_id].map[0] ) { // Remove all maps from instance
+ last = instance->list[instance_id].map[0];
+ instance->del_map( instance->list[instance_id].map[0] );
}
+
+ if( instance->list[instance_id].regs.vars )
+ db_destroy(instance->list[instance_id].regs.vars);
+ if( instance->list[instance_id].regs.arrays )
+ instance->list[instance_id].regs.arrays->destroy(instance->list[instance_id].regs.arrays, script->array_free_db);
- if( instances[instance_id].vars )
- db_destroy(instances[instance_id].vars);
-
- if( instances[instance_id].progress_timer != INVALID_TIMER )
- iTimer->delete_timer( instances[instance_id].progress_timer, instance_destroy_timer);
- if( instances[instance_id].idle_timer != INVALID_TIMER )
- iTimer->delete_timer( instances[instance_id].idle_timer, instance_destroy_timer);
+ if( instance->list[instance_id].progress_timer != INVALID_TIMER )
+ timer->delete( instance->list[instance_id].progress_timer, instance->destroy_timer);
+ if( instance->list[instance_id].idle_timer != INVALID_TIMER )
+ timer->delete( instance->list[instance_id].idle_timer, instance->destroy_timer);
- instances[instance_id].vars = NULL;
+ instance->list[instance_id].regs.vars = NULL;
- aFree(instances[instance_id].map);
+ if( instance->list[instance_id].map )
+ aFree(instance->list[instance_id].map);
- memset( &instances[instance_id], 0x00, sizeof(struct instance_data) );
-
+ instance->list[instance_id].map = NULL;
+ instance->list[instance_id].state = INSTANCE_FREE;
+ instance->list[instance_id].num_map = 0;
+
+ for( j = 0; j < instance->list[instance_id].hdatac; j++ ) {
+ if( instance->list[instance_id].hdata[j]->flag.free ) {
+ aFree(instance->list[instance_id].hdata[j]->data);
+ }
+ aFree(instance->list[instance_id].hdata[j]);
+ }
+ if( instance->list[instance_id].hdata )
+ aFree(instance->list[instance_id].hdata);
+
+ instance->list[instance_id].hdata = NULL;
+ instance->list[instance_id].hdatac = 0;
}
/*--------------------------------------
@@ -468,20 +592,20 @@ void instance_check_idle(int instance_id) {
bool idle = true;
unsigned int now = (unsigned int)time(NULL);
- if( !instance->valid(instance_id) || instances[instance_id].idle_timeoutval == 0 )
+ if( !instance->valid(instance_id) || instance->list[instance_id].idle_timeoutval == 0 )
return;
- if( instances[instance_id].users )
+ if( instance->list[instance_id].users )
idle = false;
- if( instances[instance_id].idle_timer != INVALID_TIMER && !idle ) {
- iTimer->delete_timer(instances[instance_id].idle_timer, instance_destroy_timer);
- instances[instance_id].idle_timer = INVALID_TIMER;
- instances[instance_id].idle_timeout = 0;
+ if( instance->list[instance_id].idle_timer != INVALID_TIMER && !idle ) {
+ timer->delete(instance->list[instance_id].idle_timer, instance->destroy_timer);
+ instance->list[instance_id].idle_timer = INVALID_TIMER;
+ instance->list[instance_id].idle_timeout = 0;
clif->instance(instance_id, 3, 0); // Notify instance users normal instance expiration
- } else if( instances[instance_id].idle_timer == INVALID_TIMER && idle ) {
- instances[instance_id].idle_timeout = now + instances[instance_id].idle_timeoutval;
- instances[instance_id].idle_timer = iTimer->add_timer( iTimer->gettick() + instances[instance_id].idle_timeoutval * 1000, instance_destroy_timer, instance_id, 0);
+ } else if( instance->list[instance_id].idle_timer == INVALID_TIMER && idle ) {
+ instance->list[instance_id].idle_timeout = now + instance->list[instance_id].idle_timeoutval;
+ instance->list[instance_id].idle_timer = timer->add( timer->gettick() + instance->list[instance_id].idle_timeoutval * 1000, instance->destroy_timer, instance_id, 0);
clif->instance(instance_id, 4, 0); // Notify instance users it will be destroyed of no user join it again in "X" time
}
}
@@ -496,30 +620,32 @@ void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsign
if( !instance->valid(instance_id) )
return;
- if( instances[instance_id].progress_timer != INVALID_TIMER )
- iTimer->delete_timer( instances[instance_id].progress_timer, instance_destroy_timer);
- if( instances[instance_id].idle_timer != INVALID_TIMER )
- iTimer->delete_timer( instances[instance_id].idle_timer, instance_destroy_timer);
+ if( instance->list[instance_id].progress_timer != INVALID_TIMER )
+ timer->delete( instance->list[instance_id].progress_timer, instance->destroy_timer);
+ if( instance->list[instance_id].idle_timer != INVALID_TIMER )
+ timer->delete( instance->list[instance_id].idle_timer, instance->destroy_timer);
if( progress_timeout ) {
- instances[instance_id].progress_timeout = now + progress_timeout;
- instances[instance_id].progress_timer = iTimer->add_timer( iTimer->gettick() + progress_timeout * 1000, instance_destroy_timer, instance_id, 0);
+ instance->list[instance_id].progress_timeout = now + progress_timeout;
+ instance->list[instance_id].progress_timer = timer->add( timer->gettick() + progress_timeout * 1000, instance->destroy_timer, instance_id, 0);
+ instance->list[instance_id].original_progress_timeout = progress_timeout;
} else {
- instances[instance_id].progress_timeout = 0;
- instances[instance_id].progress_timer = INVALID_TIMER;
+ instance->list[instance_id].progress_timeout = 0;
+ instance->list[instance_id].progress_timer = INVALID_TIMER;
+ instance->list[instance_id].original_progress_timeout = 0;
}
if( idle_timeout ) {
- instances[instance_id].idle_timeoutval = idle_timeout;
- instances[instance_id].idle_timer = INVALID_TIMER;
- instance_check_idle(instance_id);
+ instance->list[instance_id].idle_timeoutval = idle_timeout;
+ instance->list[instance_id].idle_timer = INVALID_TIMER;
+ instance->check_idle(instance_id);
} else {
- instances[instance_id].idle_timeoutval = 0;
- instances[instance_id].idle_timeout = 0;
- instances[instance_id].idle_timer = INVALID_TIMER;
+ instance->list[instance_id].idle_timeoutval = 0;
+ instance->list[instance_id].idle_timeout = 0;
+ instance->list[instance_id].idle_timer = INVALID_TIMER;
}
- if( instances[instance_id].idle_timer == INVALID_TIMER && instances[instance_id].progress_timer != INVALID_TIMER )
+ if( instance->list[instance_id].idle_timer == INVALID_TIMER && instance->list[instance_id].progress_timer != INVALID_TIMER )
clif->instance(instance_id, 3, 0);
}
@@ -530,26 +656,64 @@ void instance_check_kick(struct map_session_data *sd) {
int16 m = sd->bl.m;
clif->instance_leave(sd->fd);
- if( map[m].instance_id >= 0 ) { // User was on the instance map
- if( map[m].save.map )
- pc->setpos(sd, map[m].save.map, map[m].save.x, map[m].save.y, CLR_TELEPORT);
+ if( map->list[m].instance_id >= 0 ) { // User was on the instance map
+ if( map->list[m].save.map )
+ pc->setpos(sd, map->list[m].save.map, map->list[m].save.x, map->list[m].save.y, CLR_TELEPORT);
else
pc->setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
}
}
+void do_reload_instance(void) {
+ struct s_mapiterator *iter;
+ struct map_session_data *sd;
+ int i, k;
+
+ for(i = 0; i < instance->instances; i++) {
+ for(k = 0; k < instance->list[i].num_map; k++) {
+ if( !map->list[map->list[instance->list[i].map[k]].instance_src_map].flag.src4instance )
+ break;
+ }
+
+ if( k != instance->list[i].num_map ) /* any (or all) of them were disabled, we destroy */
+ instance->destroy(i);
+ else {
+ /* populate the instance again */
+ instance->start(i);
+ /* restart timers */
+ instance->set_timeout(i,instance->list[i].original_progress_timeout,instance->list[i].idle_timeoutval);
+ }
+ }
+
+ iter = mapit_getallusers();
+ for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) {
+ if(sd && map->list[sd->bl.m].instance_id >= 0) {
+ pc->setpos(sd,instance->list[map->list[sd->bl.m].instance_id].respawn.map,instance->list[map->list[sd->bl.m].instance_id].respawn.x,instance->list[map->list[sd->bl.m].instance_id].respawn.y,CLR_TELEPORT);
+ }
+ }
+ mapit->free(iter);
+}
+
+
void do_final_instance(void) {
int i;
-
+
for(i = 0; i < instance->instances; i++) {
- instance_destroy(i);
+ instance->destroy(i);
}
- aFree(instances);
+ if( instance->list )
+ aFree(instance->list);
+
+ instance->list = NULL;
+ instance->instances = 0;
}
-void do_init_instance(void) {
- iTimer->add_timer_func_list(instance_destroy_timer, "instance_destroy_timer");
+void do_init_instance(bool minimal) {
+ if (minimal)
+ return;
+
+ timer->add_func_list(instance->destroy_timer, "instance_destroy_timer");
}
void instance_defaults(void) {
@@ -557,22 +721,27 @@ void instance_defaults(void) {
instance->init = do_init_instance;
instance->final = do_final_instance;
-
+ instance->reload = do_reload_instance;
/* start point */
instance->start_id = 0;
/* count */
instance->instances = 0;
-
+ /* */
+ instance->list = NULL;
/* */
instance->create = instance_create;
instance->add_map = instance_add_map;
instance->del_map = instance_del_map;
instance->map2imap = instance_map2imap;
instance->mapid2imapid = instance_mapid2imapid;
+ instance->mapname2imap = instance_mapname2imap;
+ instance->map_npcsub = instance_map_npcsub;
+ instance->init_npc = instance_init_npc;
instance->destroy = instance_destroy;
instance->start = instance_init;
instance->check_idle = instance_check_idle;
instance->check_kick = instance_check_kick;
instance->set_timeout = instance_set_timeout;
instance->valid = instance_is_valid;
+ instance->destroy_timer = instance_destroy_timer;
}
diff --git a/src/map/instance.h b/src/map/instance.h
index e86586e44..2ee77d3e3 100644
--- a/src/map/instance.h
+++ b/src/map/instance.h
@@ -2,8 +2,15 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _INSTANCE_H_
-#define _INSTANCE_H_
+#ifndef MAP_INSTANCE_H
+#define MAP_INSTANCE_H
+
+#include "script.h" // struct reg_db
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h" // struct point
+
+struct block_list;
+struct map_session_data;
#define INSTANCE_NAME_LENGTH (60+1)
@@ -24,7 +31,7 @@ enum instance_owner_type {
struct instance_data {
unsigned short id;
- char name[INSTANCE_NAME_LENGTH]; // Instance Name - required for clif functions.
+ char name[INSTANCE_NAME_LENGTH]; ///< Instance Name - required for clif functions.
instance_state state;
enum instance_owner_type owner_type;
int owner_id;
@@ -33,39 +40,52 @@ struct instance_data {
unsigned short num_map;
unsigned short users;
- struct DBMap* vars; // Instance Variable for scripts
-
+ struct reg_db regs; ///< Instance variables for scripts
+
int progress_timer;
unsigned int progress_timeout;
int idle_timer;
unsigned int idle_timeout, idle_timeoutval;
+
+ unsigned int original_progress_timeout;
+
+ struct point respawn; ///< reload spawn
+
+ /** HPM Custom Struct */
+ struct HPluginData **hdata;
+ unsigned int hdatac;
};
-struct instance_data *instances;
-
struct instance_interface {
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
+ void (*reload) (void);
/* start point */
unsigned short start_id;
- unsigned short instances;
+ unsigned short instances;/* count */
+ /* */
+ struct instance_data *list;/* pointer to a chunk of consecutive memory, access via instance->list[0]..etc */
/* */
int (*create) (int party_id, const char *name, enum instance_owner_type type);
int (*add_map) (const char *name, int instance_id, bool usebasename, const char *map_name);
void (*del_map) (int16 m);
int (*map2imap) (int16 m, int instance_id);
int (*mapid2imapid) (int16 m, int instance_id);
+ int (*mapname2imap) (const char *map_name, int instance_id);
+ int (*map_npcsub) (struct block_list* bl, va_list args);
+ int (*init_npc) (struct block_list* bl, va_list args);
void (*destroy) (int instance_id);
void (*start) (int instance_id);
void (*check_idle) (int instance_id);
void (*check_kick) (struct map_session_data *sd);
void (*set_timeout) (int instance_id, unsigned int progress_timeout, unsigned int idle_timeout);
bool (*valid) (int instance_id);
-} instance_s;
+ int (*destroy_timer) (int tid, int64 tick, int id, intptr_t data);
+};
struct instance_interface *instance;
void instance_defaults(void);
-#endif
+#endif /* MAP_INSTANCE_H */
diff --git a/src/map/intif.c b/src/map/intif.c
index f3931e79e..be82a7583 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -1,67 +1,58 @@
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
// For more information, see LICENCE in the main folder
-#include "../common/showmsg.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/malloc.h"
-#include "../common/strlib.h"
-#include "map.h"
+#define HERCULES_CORE
+
+#include "../config/core.h" // GP_BOUND_ITEMS
+#include "intif.h"
+
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "atcommand.h"
#include "battle.h"
#include "chrif.h"
#include "clif.h"
-#include "pc.h"
-#include "intif.h"
-#include "log.h"
-#include "storage.h"
-#include "party.h"
+#include "elemental.h"
#include "guild.h"
-#include "pet.h"
-#include "atcommand.h"
-#include "mercenary.h"
#include "homunculus.h"
-#include "elemental.h"
+#include "log.h"
#include "mail.h"
+#include "map.h"
+#include "mercenary.h"
+#include "party.h"
+#include "pc.h"
+#include "pet.h"
#include "quest.h"
+#include "storage.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <string.h>
-
-
-static const int packet_len_table[]={
- -1,-1,27,-1, -1, 0,37,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f
- 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810
- 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820
- 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830
- -1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840
- -1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus]
- -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish]
- -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil]
- 11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880
- -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator]
-};
+struct intif_interface intif_s;
-extern int char_fd; // inter server Fd used for char_fd
-#define inter_fd char_fd // alias
+#define inter_fd (chrif->fd) // alias
//-----------------------------------------------------------------
// Send to inter server
int CheckForCharServer(void)
{
- return ((char_fd <= 0) || session[char_fd] == NULL || session[char_fd]->wdata == NULL);
+ return ((chrif->fd <= 0) || session[chrif->fd] == NULL || session[chrif->fd]->wdata == NULL);
}
// pet
int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id,
- short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name)
+ short pet_equip,short intimate,short hungry,char rename_flag,char incubate,char *pet_name)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, 24 + NAME_LENGTH);
WFIFOW(inter_fd,0) = 0x3080;
@@ -74,7 +65,7 @@ int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,sho
WFIFOW(inter_fd,18) = intimate;
WFIFOW(inter_fd,20) = hungry;
WFIFOB(inter_fd,22) = rename_flag;
- WFIFOB(inter_fd,23) = incuvate;
+ WFIFOB(inter_fd,23) = incubate;
memcpy(WFIFOP(inter_fd,24),pet_name,NAME_LENGTH);
WFIFOSET(inter_fd,24+NAME_LENGTH);
@@ -83,7 +74,7 @@ int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,sho
int intif_request_petdata(int account_id,int char_id,int pet_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, 14);
WFIFOW(inter_fd,0) = 0x3081;
@@ -97,7 +88,7 @@ int intif_request_petdata(int account_id,int char_id,int pet_id)
int intif_save_petdata(int account_id,struct s_pet *p)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, sizeof(struct s_pet) + 8);
WFIFOW(inter_fd,0) = 0x3082;
@@ -111,7 +102,7 @@ int intif_save_petdata(int account_id,struct s_pet *p)
int intif_delete_petdata(int pet_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,6);
WFIFOW(inter_fd,0) = 0x3083;
@@ -123,7 +114,7 @@ int intif_delete_petdata(int pet_id)
int intif_rename(struct map_session_data *sd, int type, char *name)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 1;
WFIFOHEAD(inter_fd,NAME_LENGTH+12);
@@ -137,17 +128,17 @@ int intif_rename(struct map_session_data *sd, int type, char *name)
}
// GM Send a message
-int intif_broadcast(const char* mes, int len, int type)
+int intif_broadcast(const char* mes, size_t len, int type)
{
- int lp = type ? 4 : 0;
+ int lp = (type|BC_COLOR_MASK) ? 4 : 0;
// Send to the local players
clif->broadcast(NULL, mes, len, type, ALL_CLIENT);
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
- if (other_mapserver_count < 1)
+ if (chrif->other_mapserver_count < 1)
return 0; //No need to send.
WFIFOHEAD(inter_fd, 16 + lp + len);
@@ -158,24 +149,24 @@ int intif_broadcast(const char* mes, int len, int type)
WFIFOW(inter_fd,10) = 0; // fontSize not used with standard broadcast
WFIFOW(inter_fd,12) = 0; // fontAlign not used with standard broadcast
WFIFOW(inter_fd,14) = 0; // fontY not used with standard broadcast
- if (type == 0x10) // bc_blue
+ if( type|BC_BLUE )
WFIFOL(inter_fd,16) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow.
- else if (type == 0x20) // bc_woe
+ else if( type|BC_WOE )
WFIFOL(inter_fd,16) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'.
memcpy(WFIFOP(inter_fd,16 + lp), mes, len);
WFIFOSET(inter_fd, WFIFOW(inter_fd,2));
return 0;
}
-int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY)
+int intif_broadcast2(const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY)
{
// Send to the local players
clif->broadcast2(NULL, mes, len, fontColor, fontType, fontSize, fontAlign, fontY, ALL_CLIENT);
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
- if (other_mapserver_count < 1)
+ if (chrif->other_mapserver_count < 1)
return 0; //No need to send.
WFIFOHEAD(inter_fd, 16 + len);
@@ -204,7 +195,7 @@ int intif_main_message(struct map_session_data* sd, const char* message)
snprintf( output, sizeof(output), msg_txt(386), sd->status.name, message );
// send the message using the inter-server broadcast service
- intif_broadcast2( output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0 );
+ intif->broadcast2( output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0 );
// log the chat message
logs->chat( LOG_CHAT_MAINCHAT, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message );
@@ -213,13 +204,13 @@ int intif_main_message(struct map_session_data* sd, const char* message)
}
// The transmission of Wisp/Page to inter-server (player not found on this server)
-int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int mes_len)
+int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, size_t mes_len)
{
nullpo_ret(sd);
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
- if (other_mapserver_count < 1)
+ if (chrif->other_mapserver_count < 1)
{ //Character not found.
clif->wis_end(sd->fd, 1);
return 0;
@@ -242,12 +233,12 @@ int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int me
// The reply of Wisp/page
int intif_wis_replay(int id, int flag)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,7);
WFIFOW(inter_fd,0) = 0x3002;
WFIFOL(inter_fd,2) = id;
- WFIFOB(inter_fd,6) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+ WFIFOB(inter_fd,6) = flag; // flag: 0: success to send whisper, 1: target character is not logged in?, 2: ignored by target
WFIFOSET(inter_fd,7);
if (battle_config.etc_log)
@@ -259,8 +250,8 @@ int intif_wis_replay(int id, int flag)
// The transmission of GM only Wisp/Page from server to inter-server
int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes)
{
- int mes_len;
- if (CheckForCharServer())
+ size_t mes_len;
+ if (intif->CheckForCharServer())
return 0;
mes_len = strlen(mes) + 1; // + null
WFIFOHEAD(inter_fd, mes_len + 32);
@@ -277,60 +268,117 @@ int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes)
return 0;
}
-int intif_regtostr(char* str, struct global_reg *reg, int qty)
-{
- int len =0, i;
-
- for (i = 0; i < qty; i++) {
- len+= sprintf(str+len, "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place.
- len+= sprintf(str+len, "%s", reg[i].value)+1;
- }
- return len;
-}
-
//Request for saving registry values.
-int intif_saveregistry(struct map_session_data *sd, int type)
-{
- struct global_reg *reg;
- int count;
- int i, p;
-
- if (CheckForCharServer())
+int intif_saveregistry(struct map_session_data *sd) {
+ DBIterator *iter;
+ DBKey key;
+ DBData *data;
+ int plen = 0;
+ size_t len;
+
+ if (intif->CheckForCharServer() || !sd->regs.vars)
return -1;
+
+ WFIFOHEAD(inter_fd, 60000 + 300);
+ WFIFOW(inter_fd,0) = 0x3004;
+ /* 0x2 = length (set later) */
+ WFIFOL(inter_fd,4) = sd->status.account_id;
+ WFIFOL(inter_fd,8) = sd->status.char_id;
+ WFIFOW(inter_fd,12) = 0;/* count */
+
+ plen = 14;
+
+ iter = db_iterator(sd->regs.vars);
+ for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) {
+ const char *varname = NULL;
+ struct script_reg_state *src = NULL;
+
+ if( data->type != DB_DATA_PTR ) /* its a @number */
+ continue;
+
+ varname = script->get_str(script_getvarid(key.i64));
+
+ if( varname[0] == '@' ) /* @string$ can get here, so we skip */
+ continue;
+
+ src = DB->data2ptr(data);
- switch (type) {
- case 3: //Character reg
- reg = sd->save_reg.global;
- count = sd->save_reg.global_num;
- sd->state.reg_dirty &= ~0x4;
- break;
- case 2: //Account reg
- reg = sd->save_reg.account;
- count = sd->save_reg.account_num;
- sd->state.reg_dirty &= ~0x2;
- break;
- case 1: //Account2 reg
- reg = sd->save_reg.account2;
- count = sd->save_reg.account2_num;
- sd->state.reg_dirty &= ~0x1;
- break;
- default: //Broken code?
- ShowError("intif_saveregistry: Invalid type %d\n", type);
- return -1;
- }
- WFIFOHEAD(inter_fd, 288 * MAX_REG_NUM+13);
- WFIFOW(inter_fd,0)=0x3004;
- WFIFOL(inter_fd,4)=sd->status.account_id;
- WFIFOL(inter_fd,8)=sd->status.char_id;
- WFIFOB(inter_fd,12)=type;
- for( p = 13, i = 0; i < count; i++ ) {
- if (reg[i].str[0] != '\0' && reg[i].value[0] != '\0') {
- p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place.
- p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].value)+1;
+ /* no need! */
+ if( !src->update )
+ continue;
+
+ src->update = false;
+
+ len = strlen(varname)+1;
+
+ WFIFOB(inter_fd, plen) = (unsigned char)len;/* won't be higher; the column size is 32 */
+ plen += 1;
+
+ safestrncpy((char*)WFIFOP(inter_fd,plen), varname, len);
+ plen += len;
+
+ WFIFOL(inter_fd, plen) = script_getvaridx(key.i64);
+ plen += 4;
+
+ if( src->type ) {
+ struct script_reg_str *p = (struct script_reg_str *)src;
+
+ WFIFOB(inter_fd, plen) = p->value ? 2 : 3;
+ plen += 1;
+
+ if( p->value ) {
+ len = strlen(p->value)+1;
+
+ WFIFOB(inter_fd, plen) = (unsigned char)len;/* won't be higher; the column size is 254 */
+ plen += 1;
+
+ safestrncpy((char*)WFIFOP(inter_fd,plen), p->value, len);
+ plen += len;
+ } else {
+ script->reg_destroy_single(sd,key.i64,&p->flag);
+ }
+
+ } else {
+ struct script_reg_num *p = (struct script_reg_num *)src;
+
+ WFIFOB(inter_fd, plen) = p->value ? 0 : 1;
+ plen += 1;
+
+ if( p->value ) {
+ WFIFOL(inter_fd, plen) = p->value;
+ plen += 4;
+ } else {
+ script->reg_destroy_single(sd,key.i64,&p->flag);
+ }
+
+ }
+
+ WFIFOW(inter_fd,12) += 1;
+
+ if( plen > 60000 ) {
+ WFIFOW(inter_fd, 2) = plen;
+ WFIFOSET(inter_fd, plen);
+
+ /* prepare follow up */
+ WFIFOHEAD(inter_fd, 60000 + 300);
+ WFIFOW(inter_fd,0) = 0x3004;
+ /* 0x2 = length (set later) */
+ WFIFOL(inter_fd,4) = sd->status.account_id;
+ WFIFOL(inter_fd,8) = sd->status.char_id;
+ WFIFOW(inter_fd,12) = 0;/* count */
+
+ plen = 14;
}
+
}
- WFIFOW(inter_fd,2)=p;
- WFIFOSET(inter_fd,WFIFOW(inter_fd,2));
+ dbi_destroy(iter);
+
+ /* mark & go. */
+ WFIFOW(inter_fd, 2) = plen;
+ WFIFOSET(inter_fd, plen);
+
+ sd->vars_dirty = false;
+
return 0;
}
@@ -339,11 +387,8 @@ int intif_request_registry(struct map_session_data *sd, int flag)
{
nullpo_ret(sd);
- sd->save_reg.account2_num = -1;
- sd->save_reg.account_num = -1;
- sd->save_reg.global_num = -1;
-
- if (CheckForCharServer())
+ /* if char server ain't online it doesn't load, shouldn't we kill the session then? */
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,6);
@@ -360,7 +405,7 @@ int intif_request_registry(struct map_session_data *sd, int flag)
int intif_request_guild_storage(int account_id,int guild_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,10);
WFIFOW(inter_fd,0) = 0x3018;
@@ -371,7 +416,7 @@ int intif_request_guild_storage(int account_id,int guild_id)
}
int intif_send_guild_storage(int account_id,struct guild_storage *gstor)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,sizeof(struct guild_storage)+12);
WFIFOW(inter_fd,0) = 0x3019;
@@ -386,7 +431,7 @@ int intif_send_guild_storage(int account_id,struct guild_storage *gstor)
// Party creation request
int intif_create_party(struct party_member *member,char *name,int item,int item2)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
nullpo_ret(member);
@@ -404,7 +449,7 @@ int intif_create_party(struct party_member *member,char *name,int item,int item2
// Party information request
int intif_request_partyinfo(int party_id, int char_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,10);
WFIFOW(inter_fd,0) = 0x3021;
@@ -417,7 +462,7 @@ int intif_request_partyinfo(int party_id, int char_id)
// Request to add a member to party
int intif_party_addmember(int party_id,struct party_member *member)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,42);
WFIFOW(inter_fd,0)=0x3022;
@@ -431,7 +476,7 @@ int intif_party_addmember(int party_id,struct party_member *member)
// Request to change party configuration (exp,item share)
int intif_party_changeoption(int party_id,int account_id,int exp,int item)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,14);
WFIFOW(inter_fd,0)=0x3023;
@@ -446,7 +491,7 @@ int intif_party_changeoption(int party_id,int account_id,int exp,int item)
// Request to leave party
int intif_party_leave(int party_id,int account_id, int char_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,14);
WFIFOW(inter_fd,0)=0x3024;
@@ -458,26 +503,25 @@ int intif_party_leave(int party_id,int account_id, int char_id)
}
// Request keeping party for new map ??
-int intif_party_changemap(struct map_session_data *sd,int online)
-{
- int16 m, mapindex;
+int intif_party_changemap(struct map_session_data *sd,int online) {
+ int16 m, map_index;
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
if(!sd)
return 0;
- if( (m=iMap->mapindex2mapid(sd->mapindex)) >= 0 && map[m].instance_id >= 0 )
- mapindex = map[map[m].instance_src_map].index;
+ if( (m=map->mapindex2mapid(sd->mapindex)) >= 0 && map->list[m].instance_id >= 0 )
+ map_index = map_id2index(map->list[m].instance_src_map);
else
- mapindex = sd->mapindex;
+ map_index = sd->mapindex;
WFIFOHEAD(inter_fd,19);
WFIFOW(inter_fd,0)=0x3025;
WFIFOL(inter_fd,2)=sd->status.party_id;
WFIFOL(inter_fd,6)=sd->status.account_id;
WFIFOL(inter_fd,10)=sd->status.char_id;
- WFIFOW(inter_fd,14)=mapindex;
+ WFIFOW(inter_fd,14)=map_index;
WFIFOB(inter_fd,16)=online;
WFIFOW(inter_fd,17)=sd->status.base_level;
WFIFOSET(inter_fd,19);
@@ -487,7 +531,7 @@ int intif_party_changemap(struct map_session_data *sd,int online)
// Request breaking party
int intif_break_party(int party_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,6);
WFIFOW(inter_fd,0)=0x3026;
@@ -499,10 +543,10 @@ int intif_break_party(int party_id)
// Sending party chat
int intif_party_message(int party_id,int account_id,const char *mes,int len)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
- if (other_mapserver_count < 1)
+ if (chrif->other_mapserver_count < 1)
return 0; //No need to send.
WFIFOHEAD(inter_fd,len + 12);
@@ -518,7 +562,7 @@ int intif_party_message(int party_id,int account_id,const char *mes,int len)
// Request a new leader for party
int intif_party_leaderchange(int party_id,int account_id,int char_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,14);
WFIFOW(inter_fd,0)=0x3029;
@@ -532,7 +576,7 @@ int intif_party_leaderchange(int party_id,int account_id,int char_id)
// Request a Guild creation
int intif_guild_create(const char *name,const struct guild_member *master)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
nullpo_ret(master);
@@ -549,7 +593,7 @@ int intif_guild_create(const char *name,const struct guild_member *master)
// Request Guild information
int intif_guild_request_info(int guild_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,6);
WFIFOW(inter_fd,0) = 0x3031;
@@ -561,7 +605,7 @@ int intif_guild_request_info(int guild_id)
// Request to add member to the guild
int intif_guild_addmember(int guild_id,struct guild_member *m)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,sizeof(struct guild_member)+8);
WFIFOW(inter_fd,0) = 0x3032;
@@ -573,9 +617,9 @@ int intif_guild_addmember(int guild_id,struct guild_member *m)
}
// Request a new leader for guild
-int intif_guild_change_gm(int guild_id, const char* name, int len)
+int intif_guild_change_gm(int guild_id, const char* name, size_t len)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, len + 8);
WFIFOW(inter_fd, 0)=0x3033;
@@ -589,7 +633,7 @@ int intif_guild_change_gm(int guild_id, const char* name, int len)
// Request to leave guild
int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const char *mes)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, 55);
WFIFOW(inter_fd, 0) = 0x3034;
@@ -605,7 +649,7 @@ int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const cha
//Update request / Lv online status of the guild members
int intif_guild_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, 19);
WFIFOW(inter_fd, 0) = 0x3035;
@@ -622,7 +666,7 @@ int intif_guild_memberinfoshort(int guild_id,int account_id,int char_id,int onli
//Guild disbanded notification
int intif_guild_break(int guild_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, 6);
WFIFOW(inter_fd, 0) = 0x3036;
@@ -634,10 +678,10 @@ int intif_guild_break(int guild_id)
// Send a guild message
int intif_guild_message(int guild_id,int account_id,const char *mes,int len)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
- if (other_mapserver_count < 1)
+ if (chrif->other_mapserver_count < 1)
return 0; //No need to send.
WFIFOHEAD(inter_fd, len + 12);
@@ -651,10 +695,13 @@ int intif_guild_message(int guild_id,int account_id,const char *mes,int len)
return 0;
}
-// Request a change of Guild basic information
+/**
+ * Requests to change a basic guild information, it is parsed via mapif_parse_GuildBasicInfoChange
+ * To see the information types that can be changed see mmo.h::guild_basic_info
+ **/
int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, len + 10);
WFIFOW(inter_fd,0)=0x3039;
@@ -670,7 +717,7 @@ int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len)
int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id,
int type,const void *data,int len)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, len + 18);
WFIFOW(inter_fd, 0)=0x303a;
@@ -687,7 +734,7 @@ int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id,
// Request a change of Guild title
int intif_guild_position(int guild_id,int idx,struct guild_position *p)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, sizeof(struct guild_position)+12);
WFIFOW(inter_fd,0)=0x303b;
@@ -702,7 +749,7 @@ int intif_guild_position(int guild_id,int idx,struct guild_position *p)
// Request an update of Guildskill skill_id
int intif_guild_skillup(int guild_id, uint16 skill_id, int account_id, int max)
{
- if( CheckForCharServer() )
+ if( intif->CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd, 18);
WFIFOW(inter_fd, 0) = 0x303c;
@@ -717,7 +764,7 @@ int intif_guild_skillup(int guild_id, uint16 skill_id, int account_id, int max)
// Request a new guild relationship
int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,19);
WFIFOW(inter_fd, 0)=0x303d;
@@ -733,7 +780,7 @@ int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account
// Request to change guild notice
int intif_guild_notice(int guild_id,const char *mes1,const char *mes2)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,186);
WFIFOW(inter_fd,0)=0x303e;
@@ -747,7 +794,7 @@ int intif_guild_notice(int guild_id,const char *mes1,const char *mes2)
// Request to change guild emblem
int intif_guild_emblem(int guild_id,int len,const char *data)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
if(guild_id<=0 || len<0 || len>2000)
return 0;
@@ -768,7 +815,7 @@ int intif_guild_emblem(int guild_id,int len,const char *data)
*/
int intif_guild_castle_dataload(int num, int *castle_ids)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, 4 + num * sizeof(int));
WFIFOW(inter_fd, 0) = 0x3040;
@@ -782,7 +829,7 @@ int intif_guild_castle_dataload(int num, int *castle_ids)
// Request change castle guild owner and save data
int intif_guild_castle_datasave(int castle_id,int index, int value)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,9);
WFIFOW(inter_fd,0)=0x3041;
@@ -799,7 +846,7 @@ int intif_guild_castle_datasave(int castle_id,int index, int value)
int intif_homunculus_create(int account_id, struct s_homunculus *sh)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8);
WFIFOW(inter_fd,0) = 0x3090;
@@ -811,7 +858,7 @@ int intif_homunculus_create(int account_id, struct s_homunculus *sh)
}
bool intif_homunculus_requestload(int account_id, int homun_id) {
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return false;
WFIFOHEAD(inter_fd, 10);
WFIFOW(inter_fd,0) = 0x3091;
@@ -823,7 +870,7 @@ bool intif_homunculus_requestload(int account_id, int homun_id) {
int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8);
WFIFOW(inter_fd,0) = 0x3092;
@@ -837,7 +884,7 @@ int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh)
int intif_homunculus_requestdelete(int homun_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd, 6);
WFIFOW(inter_fd, 0) = 0x3093;
@@ -852,8 +899,7 @@ int intif_homunculus_requestdelete(int homun_id)
// Packets receive from inter server
// Wisp/Page reception // rewritten by [Yor]
-int intif_parse_WisMessage(int fd)
-{
+void intif_parse_WisMessage(int fd) {
struct map_session_data* sd;
char *wisp_source;
char name[NAME_LENGTH];
@@ -862,15 +908,15 @@ int intif_parse_WisMessage(int fd)
id=RFIFOL(fd,4);
safestrncpy(name, (char*)RFIFOP(fd,32), NAME_LENGTH);
- sd = iMap->nick2sd(name);
- if(sd == NULL || strcmp(sd->status.name, name) != 0)
- { //Not found
+ sd = map->nick2sd(name);
+ if(sd == NULL || strcmp(sd->status.name, name) != 0) {
+ //Not found
intif_wis_replay(id,1);
- return 0;
+ return;
}
if(sd->state.ignoreAll) {
intif_wis_replay(id, 2);
- return 0;
+ return;
}
wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor]
for(i=0; i < MAX_IGNORE_LIST &&
@@ -881,30 +927,27 @@ int intif_parse_WisMessage(int fd)
if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0')
{ //Ignored
intif_wis_replay(id, 2);
- return 0;
+ return;
}
//Success to send whisper.
clif->wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56);
- intif_wis_replay(id,0); // succes
- return 0;
+ intif_wis_replay(id,0); // success
}
// Wisp/page transmission result reception
-int intif_parse_WisEnd(int fd)
-{
+void intif_parse_WisEnd(int fd) {
struct map_session_data* sd;
if (battle_config.etc_log)
- ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
- sd = (struct map_session_data *)iMap->nick2sd((char *) RFIFOP(fd,2));
+ ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send whisper, 1: target character is not logged in?, 2: ignored by target
+ sd = (struct map_session_data *)map->nick2sd((char *) RFIFOP(fd,2));
if (sd != NULL)
clif->wis_end(sd->fd, RFIFOB(fd,26));
- return 0;
+ return;
}
-static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va)
-{
+int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) {
int permission = va_arg(va, int);
char *wisp_name;
char *message;
@@ -921,7 +964,7 @@ static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va)
// Received wisp message from map-server via char-server for ALL gm
// 0x3003/0x3803 <packet_len>.w <wispname>.24B <permission>.l <message>.?B
-int mapif_parse_WisToGM(int fd)
+void mapif_parse_WisToGM(int fd)
{
int permission, mes_len;
char Wisp_name[NAME_LENGTH];
@@ -935,238 +978,259 @@ int mapif_parse_WisToGM(int fd)
safestrncpy(Wisp_name, (char*)RFIFOP(fd,4), NAME_LENGTH);
safestrncpy(message, (char*)RFIFOP(fd,32), mes_len);
// information is sent to all online GM
- iMap->map_foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len);
+ map->foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len);
if (message != mbuf)
aFree(message);
- return 0;
}
// Request player registre
-int intif_parse_Registers(int fd)
+void intif_parse_Registers(int fd)
{
- int j,p,len,max, flag;
+ int i, flag;
struct map_session_data *sd;
- struct global_reg *reg;
- int *qty;
int account_id = RFIFOL(fd,4), char_id = RFIFOL(fd,8);
- struct auth_node *node = chrif_auth_check(account_id, char_id, ST_LOGIN);
+ struct auth_node *node = chrif->auth_check(account_id, char_id, ST_LOGIN);
+ char type = RFIFOB(fd, 13);
+
if (node)
sd = node->sd;
else { //Normally registries should arrive for in log-in chars.
- sd = iMap->id2sd(account_id);
- if (sd && RFIFOB(fd,12) == 3 && sd->status.char_id != char_id)
- sd = NULL; //Character registry from another character.
+ sd = map->id2sd(account_id);
}
- if (!sd) return 1;
-
- flag = (sd->save_reg.global_num == -1 || sd->save_reg.account_num == -1 || sd->save_reg.account2_num == -1);
-
+
+ if (!sd || sd->status.char_id != char_id) {
+ return; //Character registry from another character.
+ }
+
+ flag = ( sd->vars_received&PRL_ACCG && sd->vars_received&PRL_ACCL && sd->vars_received&PRL_CHAR ) ? 0 : 1;
+
switch (RFIFOB(fd,12)) {
case 3: //Character Registry
- reg = sd->save_reg.global;
- qty = &sd->save_reg.global_num;
- max = GLOBAL_REG_NUM;
- break;
+ sd->vars_received |= PRL_CHAR;
+ break;
case 2: //Account Registry
- reg = sd->save_reg.account;
- qty = &sd->save_reg.account_num;
- max = ACCOUNT_REG_NUM;
- break;
+ sd->vars_received |= PRL_ACCL;
+ break;
case 1: //Account2 Registry
- reg = sd->save_reg.account2;
- qty = &sd->save_reg.account2_num;
- max = ACCOUNT_REG2_NUM;
- break;
+ sd->vars_received |= PRL_ACCG;
+ break;
+ case 0:
+ break;
default:
ShowError("intif_parse_Registers: Unrecognized type %d\n",RFIFOB(fd,12));
- return 0;
+ return;
}
- for(j=0,p=13;j<max && p<RFIFOW(fd,2);j++){
- sscanf((char*)RFIFOP(fd,p), "%31c%n", reg[j].str,&len);
- reg[j].str[len]='\0';
- p += len+1; //+1 to skip the '\0' between strings.
- sscanf((char*)RFIFOP(fd,p), "%255c%n", reg[j].value,&len);
- reg[j].value[len]='\0';
- p += len+1;
+ /* have it not complain about insertion of vars before loading, and not set those vars as new or modified */
+ pc->reg_load = true;
+
+ if( RFIFOW(fd, 14) ) {
+ char key[32], sval[254];
+ unsigned int index;
+ int max = RFIFOW(fd, 14), cursor = 16, ival;
+
+ script->parser_current_file = "loading char/acc variables";//for script_add_str to refer to here in case errors occur
+
+ /**
+ * Vessel!char_reg_num_db
+ *
+ * str type
+ * { keyLength(B), key(<keyLength>), index(L), valLength(B), val(<valLength>) }
+ **/
+ if( type ) {
+ for(i = 0; i < max; i++) {
+ safestrncpy(key, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor));
+ cursor += RFIFOB(fd, cursor) + 1;
+
+ index = RFIFOL(fd, cursor);
+ cursor += 4;
+
+ safestrncpy(sval, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor));
+ cursor += RFIFOB(fd, cursor) + 1;
+
+ script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, (void*)sval, NULL);
+ }
+ /**
+ * Vessel!
+ *
+ * int type
+ * { keyLength(B), key(<keyLength>), index(L), value(L) }
+ **/
+ } else {
+ for(i = 0; i < max; i++) {
+ safestrncpy(key, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor));
+ cursor += RFIFOB(fd, cursor) + 1;
+
+ index = RFIFOL(fd, cursor);
+ cursor += 4;
+
+ ival = RFIFOL(fd, cursor);
+ cursor += 4;
+
+ script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, (void*)h64BPTRSIZE(ival), NULL);
+ }
+ }
+
+ script->parser_current_file = NULL;/* reset */
}
- *qty = j;
-
- if (flag && sd->save_reg.global_num > -1 && sd->save_reg.account_num > -1 && sd->save_reg.account2_num > -1)
+
+ /* flag it back */
+ pc->reg_load = false;
+
+ if (flag && sd->vars_received&PRL_ACCG && sd->vars_received&PRL_ACCL && sd->vars_received&PRL_CHAR)
pc->reg_received(sd); //Received all registry values, execute init scripts and what-not. [Skotlex]
- return 1;
}
-int intif_parse_LoadGuildStorage(int fd)
+void intif_parse_LoadGuildStorage(int fd)
{
struct guild_storage *gstor;
struct map_session_data *sd;
- int guild_id;
+ int guild_id, flag;
guild_id = RFIFOL(fd,8);
+ flag = RFIFOL(fd,12);
if(guild_id <= 0)
- return 1;
- sd=iMap->id2sd( RFIFOL(fd,4) );
- if(sd==NULL){
- ShowError("intif_parse_LoadGuildStorage: user not found %d\n",RFIFOL(fd,4));
- return 1;
+ return;
+ sd=map->id2sd( RFIFOL(fd,4) );
+ if( flag ){ //If flag != 0, we attach a player and open the storage
+ if(sd==NULL){
+ ShowError("intif_parse_LoadGuildStorage: user not found %d\n",RFIFOL(fd,4));
+ return;
+ }
}
- gstor=guild2storage(guild_id);
+ gstor=gstorage->id2storage(guild_id);
if(!gstor) {
ShowWarning("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",guild_id);
- return 1;
+ return;
}
if (gstor->storage_status == 1) { // Already open.. lets ignore this update
- ShowWarning("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id);
- return 1;
+ ShowWarning("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n", flag?sd->status.account_id:0, flag?sd->status.char_id:0);
+ return;
}
if (gstor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex]
- ShowWarning("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id);
- return 1;
+ ShowWarning("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", flag?sd->status.account_id:0, flag?sd->status.char_id:0);
+ return;
}
- if( RFIFOW(fd,2)-12 != sizeof(struct guild_storage) ){
- ShowError("intif_parse_LoadGuildStorage: data size error %d %d\n",RFIFOW(fd,2)-12 , sizeof(struct guild_storage));
- gstor->storage_status = 0;
- return 1;
+ if (RFIFOW(fd,2)-13 != sizeof(struct guild_storage)) {
+ ShowError("intif_parse_LoadGuildStorage: data size mismatch %d != %"PRIuS"\n", RFIFOW(fd,2)-13, sizeof(struct guild_storage));
+ gstor->storage_status = 0;
+ return;
}
- memcpy(gstor,RFIFOP(fd,12),sizeof(struct guild_storage));
- storage_guild_storageopen(sd);
- return 0;
+ memcpy(gstor,RFIFOP(fd,13),sizeof(struct guild_storage));
+ if( flag )
+ gstorage->open(sd);
}
// ACK guild_storage saved
-int intif_parse_SaveGuildStorage(int fd)
+void intif_parse_SaveGuildStorage(int fd)
{
- storage_guild_storagesaved(/*RFIFOL(fd,2), */RFIFOL(fd,6));
- return 0;
+ gstorage->saved(/*RFIFOL(fd,2), */RFIFOL(fd,6));
}
// ACK party creation
-int intif_parse_PartyCreated(int fd)
+void intif_parse_PartyCreated(int fd)
{
if(battle_config.etc_log)
ShowInfo("intif: party created by account %d\n\n", RFIFOL(fd,2));
party->created(RFIFOL(fd,2), RFIFOL(fd,6),RFIFOB(fd,10),RFIFOL(fd,11), (char *)RFIFOP(fd,15));
- return 0;
}
// Receive party info
-int intif_parse_PartyInfo(int fd)
-{
- if( RFIFOW(fd,2) == 12 ){
+void intif_parse_PartyInfo(int fd) {
+ if (RFIFOW(fd,2) == 12) {
ShowWarning("intif: party noinfo (char_id=%d party_id=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8));
party->recv_noinfo(RFIFOL(fd,8), RFIFOL(fd,4));
- return 0;
+ return;
}
- if( RFIFOW(fd,2) != 8+sizeof(struct party) )
- ShowError("intif: party info : data size error (char_id=%d party_id=%d packet_len=%d expected_len=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8), RFIFOW(fd,2), 8+sizeof(struct party));
+ if (RFIFOW(fd,2) != 8+sizeof(struct party))
+ ShowError("intif: party info: data size mismatch (char_id=%d party_id=%d packet_len=%d expected_len=%"PRIuS")\n",
+ RFIFOL(fd,4), RFIFOL(fd,8), RFIFOW(fd,2), 8+sizeof(struct party));
party->recv_info((struct party *)RFIFOP(fd,8), RFIFOL(fd,4));
- return 0;
}
// ACK adding party member
-int intif_parse_PartyMemberAdded(int fd)
+void intif_parse_PartyMemberAdded(int fd)
{
if(battle_config.etc_log)
ShowInfo("intif: party member added Party (%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10));
party->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10), RFIFOB(fd, 14));
- return 0;
}
// ACK changing party option
-int intif_parse_PartyOptionChanged(int fd)
+void intif_parse_PartyOptionChanged(int fd)
{
party->optionchanged(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12),RFIFOB(fd,14));
- return 0;
}
// ACK member leaving party
-int intif_parse_PartyMemberWithdraw(int fd)
+void intif_parse_PartyMemberWithdraw(int fd)
{
if(battle_config.etc_log)
ShowInfo("intif: party member withdraw: Party(%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10));
party->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10));
- return 0;
}
// ACK party break
-int intif_parse_PartyBroken(int fd)
-{
+void intif_parse_PartyBroken(int fd) {
party->broken(RFIFOL(fd,2));
- return 0;
}
// ACK party on new map
-int intif_parse_PartyMove(int fd)
+void intif_parse_PartyMove(int fd)
{
party->recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOW(fd,14),RFIFOB(fd,16),RFIFOW(fd,17));
- return 0;
}
// ACK party messages
-int intif_parse_PartyMessage(int fd)
-{
+void intif_parse_PartyMessage(int fd) {
party->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12);
- return 0;
}
// ACK guild creation
-int intif_parse_GuildCreated(int fd)
-{
+void intif_parse_GuildCreated(int fd) {
guild->created(RFIFOL(fd,2),RFIFOL(fd,6));
- return 0;
}
// ACK guild infos
-int intif_parse_GuildInfo(int fd)
-{
- if(RFIFOW(fd,2) == 8) {
+void intif_parse_GuildInfo(int fd) {
+ if (RFIFOW(fd,2) == 8) {
ShowWarning("intif: guild noinfo %d\n",RFIFOL(fd,4));
guild->recv_noinfo(RFIFOL(fd,4));
- return 0;
+ return;
}
- if( RFIFOW(fd,2)!=sizeof(struct guild)+4 )
- ShowError("intif: guild info : data size error Gid: %d recv size: %d Expected size: %d\n",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild)+4);
+ if (RFIFOW(fd,2)!=sizeof(struct guild)+4)
+ ShowError("intif: guild info: data size mismatch - Gid: %d recv size: %d Expected size: %"PRIuS"\n",
+ RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild)+4);
guild->recv_info((struct guild *)RFIFOP(fd,4));
- return 0;
}
// ACK adding guild member
-int intif_parse_GuildMemberAdded(int fd)
-{
+void intif_parse_GuildMemberAdded(int fd) {
if(battle_config.etc_log)
ShowInfo("intif: guild member added %d %d %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14));
guild->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14));
- return 0;
}
// ACK member leaving guild
-int intif_parse_GuildMemberWithdraw(int fd)
-{
+void intif_parse_GuildMemberWithdraw(int fd) {
guild->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(char *)RFIFOP(fd,55),(char *)RFIFOP(fd,15));
- return 0;
}
// ACK guild member basic info
-int intif_parse_GuildMemberInfoShort(int fd)
-{
+void intif_parse_GuildMemberInfoShort(int fd) {
guild->recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17));
- return 0;
}
// ACK guild break
-int intif_parse_GuildBroken(int fd)
-{
+void intif_parse_GuildBroken(int fd) {
guild->broken(RFIFOL(fd,2),RFIFOB(fd,6));
- return 0;
}
// basic guild info change notice
// 0x3839 <packet len>.w <guild id>.l <type>.w <data>.?b
-int intif_parse_GuildBasicInfoChanged(int fd)
-{
+void intif_parse_GuildBasicInfoChanged(int fd) {
//int len = RFIFOW(fd,2) - 10;
int guild_id = RFIFOL(fd,4);
int type = RFIFOW(fd,8);
@@ -1174,21 +1238,33 @@ int intif_parse_GuildBasicInfoChanged(int fd)
struct guild* g = guild->search(guild_id);
if( g == NULL )
- return 0;
+ return;
switch(type) {
- case GBI_EXP: g->exp = RFIFOQ(fd,10); break;
- case GBI_GUILDLV: g->guild_lv = RFIFOW(fd,10); break;
- case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break;
+ case GBI_EXP: g->exp = RFIFOQ(fd,10); break;
+ case GBI_GUILDLV: g->guild_lv = RFIFOW(fd,10); break;
+ case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break;
+ case GBI_SKILLLV: {
+ int idx, max;
+ struct guild_skill *gs = (struct guild_skill *)RFIFOP(fd,10);
+
+ if( gs == NULL )
+ return;
+
+ idx = gs->id - GD_SKILLBASE;
+ max = guild->skill_get_max(gs->id);
+ if( gs->lv > max )
+ gs->lv = max;
+
+ memcpy(&(g->skill[idx]), gs, sizeof(g->skill[idx]));
+ break;
+ }
}
-
- return 0;
}
// guild member info change notice
// 0x383a <packet len>.w <guild id>.l <account id>.l <char id>.l <type>.w <data>.?b
-int intif_parse_GuildMemberInfoChanged(int fd)
-{
+void intif_parse_GuildMemberInfoChanged(int fd) {
//int len = RFIFOW(fd,2) - 18;
int guild_id = RFIFOL(fd,4);
int account_id = RFIFOL(fd,8);
@@ -1201,189 +1277,152 @@ int intif_parse_GuildMemberInfoChanged(int fd)
g = guild->search(guild_id);
if( g == NULL )
- return 0;
+ return;
idx = guild->getindex(g,account_id,char_id);
if( idx == -1 )
- return 0;
+ return;
switch( type ) {
- case GMI_POSITION: g->member[idx].position = RFIFOW(fd,18); guild->memberposition_changed(g,idx,RFIFOW(fd,18)); break;
- case GMI_EXP: g->member[idx].exp = RFIFOQ(fd,18); break;
- case GMI_HAIR: g->member[idx].hair = RFIFOW(fd,18); break;
- case GMI_HAIR_COLOR: g->member[idx].hair_color = RFIFOW(fd,18); break;
- case GMI_GENDER: g->member[idx].gender = RFIFOW(fd,18); break;
- case GMI_CLASS: g->member[idx].class_ = RFIFOW(fd,18); break;
- case GMI_LEVEL: g->member[idx].lv = RFIFOW(fd,18); break;
+ case GMI_POSITION: g->member[idx].position = RFIFOW(fd,18); guild->memberposition_changed(g,idx,RFIFOW(fd,18)); break;
+ case GMI_EXP: g->member[idx].exp = RFIFOQ(fd,18); break;
+ case GMI_HAIR: g->member[idx].hair = RFIFOW(fd,18); break;
+ case GMI_HAIR_COLOR: g->member[idx].hair_color = RFIFOW(fd,18); break;
+ case GMI_GENDER: g->member[idx].gender = RFIFOW(fd,18); break;
+ case GMI_CLASS: g->member[idx].class_ = RFIFOW(fd,18); break;
+ case GMI_LEVEL: g->member[idx].lv = RFIFOW(fd,18); break;
}
- return 0;
}
// ACK change of guild title
-int intif_parse_GuildPosition(int fd)
-{
- if( RFIFOW(fd,2)!=sizeof(struct guild_position)+12 )
- ShowError("intif: guild info : data size error\n %d %d %d",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild_position)+12);
+void intif_parse_GuildPosition(int fd) {
+ if (RFIFOW(fd,2)!=sizeof(struct guild_position)+12)
+ ShowError("intif: guild info: data size mismatch (%d) %d != %"PRIuS"\n",
+ RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild_position)+12);
guild->position_changed(RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12));
- return 0;
}
// ACK change of guild skill update
-int intif_parse_GuildSkillUp(int fd)
-{
+void intif_parse_GuildSkillUp(int fd) {
guild->skillupack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10));
- return 0;
}
// ACK change of guild relationship
-int intif_parse_GuildAlliance(int fd)
-{
+void intif_parse_GuildAlliance(int fd) {
guild->allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43));
- return 0;
}
// ACK change of guild notice
-int intif_parse_GuildNotice(int fd)
-{
+void intif_parse_GuildNotice(int fd) {
guild->notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66));
- return 0;
}
// ACK change of guild emblem
-int intif_parse_GuildEmblem(int fd)
-{
+void intif_parse_GuildEmblem(int fd) {
guild->emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12));
- return 0;
}
// ACK guild message
-int intif_parse_GuildMessage(int fd)
-{
+void intif_parse_GuildMessage(int fd) {
guild->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12);
- return 0;
}
// Reply guild castle data request
-int intif_parse_GuildCastleDataLoad(int fd)
-{
- return guild->castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4));
+void intif_parse_GuildCastleDataLoad(int fd) {
+ guild->castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4));
}
// ACK change of guildmaster
-int intif_parse_GuildMasterChanged(int fd)
-{
- return guild->gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10));
+void intif_parse_GuildMasterChanged(int fd) {
+ guild->gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10));
}
// Request pet creation
-int intif_parse_CreatePet(int fd)
-{
- pet_get_egg(RFIFOL(fd,2),RFIFOL(fd,7),RFIFOB(fd,6));
- return 0;
+void intif_parse_CreatePet(int fd) {
+ pet->get_egg(RFIFOL(fd,2), RFIFOW(fd,6), RFIFOL(fd,8));
}
// ACK pet data
-int intif_parse_RecvPetData(int fd)
-{
+void intif_parse_RecvPetData(int fd) {
struct s_pet p;
int len;
len=RFIFOW(fd,2);
- if(sizeof(struct s_pet)!=len-9) {
- if(battle_config.etc_log)
- ShowError("intif: pet data: data size error %d %d\n",sizeof(struct s_pet),len-9);
- }
- else{
+ if (sizeof(struct s_pet) != len-9) {
+ if (battle_config.etc_log)
+ ShowError("intif: pet data: data size mismatch %d != %"PRIuS"\n", len-9, sizeof(struct s_pet));
+ } else {
memcpy(&p,RFIFOP(fd,9),sizeof(struct s_pet));
- pet_recv_petdata(RFIFOL(fd,4),&p,RFIFOB(fd,8));
+ pet->recv_petdata(RFIFOL(fd,4),&p,RFIFOB(fd,8));
}
-
- return 0;
}
-
+/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
// ACK pet save data
-int intif_parse_SavePetOk(int fd)
-{
+void intif_parse_SavePetOk(int fd) {
if(RFIFOB(fd,6) == 1)
ShowError("pet data save failure\n");
-
- return 0;
}
-
+/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
// ACK deleting pet
-int intif_parse_DeletePetOk(int fd)
-{
+void intif_parse_DeletePetOk(int fd) {
if(RFIFOB(fd,2) == 1)
ShowError("pet data delete failure\n");
-
- return 0;
}
-// ACK changing name resquest, players,pets,hommon
-int intif_parse_ChangeNameOk(int fd)
+// ACK changing name request, players,pets,homun
+void intif_parse_ChangeNameOk(int fd)
{
struct map_session_data *sd = NULL;
- if((sd=iMap->id2sd(RFIFOL(fd,2)))==NULL ||
+ if((sd=map->id2sd(RFIFOL(fd,2)))==NULL ||
sd->status.char_id != RFIFOL(fd,6))
- return 0;
+ return;
switch (RFIFOB(fd,10)) {
case 0: //Players [NOT SUPPORTED YET]
break;
case 1: //Pets
- pet_change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11));
+ pet->change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11));
break;
case 2: //Hom
homun->change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11));
break;
}
- return 0;
+ return;
}
//----------------------------------------------------------------
// Homunculus recv packets [albator]
-int intif_parse_CreateHomunculus(int fd)
-{
- int len;
- len=RFIFOW(fd,2)-9;
- if(sizeof(struct s_homunculus)!=len) {
- if(battle_config.etc_log)
- ShowError("intif: create homun data: data size error %d != %d\n",sizeof(struct s_homunculus),len);
- return 0;
+void intif_parse_CreateHomunculus(int fd) {
+ int len = RFIFOW(fd,2)-9;
+ if (sizeof(struct s_homunculus) != len) {
+ if (battle_config.etc_log)
+ ShowError("intif: create homun data: data size mismatch %d != %"PRIuS"\n", len, sizeof(struct s_homunculus));
+ return;
}
homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)) ;
- return 0;
}
-int intif_parse_RecvHomunculusData(int fd)
-{
- int len;
-
- len=RFIFOW(fd,2)-9;
+void intif_parse_RecvHomunculusData(int fd) {
+ int len = RFIFOW(fd,2)-9;
- if(sizeof(struct s_homunculus)!=len) {
- if(battle_config.etc_log)
- ShowError("intif: homun data: data size error %d %d\n",sizeof(struct s_homunculus),len);
- return 0;
+ if (sizeof(struct s_homunculus) != len) {
+ if (battle_config.etc_log)
+ ShowError("intif: homun data: data size mismatch %d != %"PRIuS"\n", len, sizeof(struct s_homunculus));
+ return;
}
homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8));
- return 0;
}
-int intif_parse_SaveHomunculusOk(int fd)
-{
+/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
+void intif_parse_SaveHomunculusOk(int fd) {
if(RFIFOB(fd,6) != 1)
ShowError("homunculus data save failure for account %d\n", RFIFOL(fd,2));
-
- return 0;
}
-int intif_parse_DeleteHomunculusOk(int fd)
-{
+/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
+void intif_parse_DeleteHomunculusOk(int fd) {
if(RFIFOB(fd,2) != 1)
ShowError("Homunculus data delete failure\n");
-
- return 0;
}
/**************************************
@@ -1392,81 +1431,108 @@ QUESTLOG SYSTEM FUNCTIONS
***************************************/
-int intif_request_questlog(TBL_PC *sd)
-{
+/**
+ * Requests a character's quest log entries to the inter server.
+ *
+ * @param sd Character's data
+ */
+void intif_request_questlog(TBL_PC *sd) {
WFIFOHEAD(inter_fd,6);
WFIFOW(inter_fd,0) = 0x3060;
WFIFOL(inter_fd,2) = sd->status.char_id;
WFIFOSET(inter_fd,6);
- return 0;
}
-int intif_parse_questlog(int fd)
-{
- int char_id = RFIFOL(fd, 4);
- int i;
- TBL_PC * sd = iMap->charid2sd(char_id);
-
- //User not online anymore
- if(!sd)
- return -1;
-
- sd->avail_quests = sd->num_quests = (RFIFOW(fd, 2)-8)/sizeof(struct quest);
-
- memset(&sd->quest_log, 0, sizeof(sd->quest_log));
+/**
+ * Parses the received quest log entries for a character from the inter server.
+ *
+ * Received in reply to the requests made by intif_request_questlog.
+ *
+ * @see intif_parse
+ */
+void intif_parse_QuestLog(int fd) {
+ int char_id = RFIFOL(fd, 4), num_received = (RFIFOW(fd, 2)-8)/sizeof(struct quest);
+ TBL_PC *sd = map->charid2sd(char_id);
- for( i = 0; i < sd->num_quests; i++ )
- {
- memcpy(&sd->quest_log[i], RFIFOP(fd, i*sizeof(struct quest)+8), sizeof(struct quest));
+ if (!sd) // User not online anymore
+ return;
- sd->quest_index[i] = quest_search_db(sd->quest_log[i].quest_id);
+ sd->num_quests = sd->avail_quests = 0;
- if( sd->quest_index[i] < 0 )
- {
- ShowError("intif_parse_questlog: quest %d not found in DB.\n",sd->quest_log[i].quest_id);
- sd->avail_quests--;
- sd->num_quests--;
- i--;
- continue;
+ if (num_received == 0) {
+ if (sd->quest_log) {
+ aFree(sd->quest_log);
+ sd->quest_log = NULL;
+ }
+ } else {
+ struct quest *received = (struct quest *)RFIFOP(fd, 8);
+ int i, k = num_received;
+ if (sd->quest_log) {
+ RECREATE(sd->quest_log, struct quest, num_received);
+ } else {
+ CREATE(sd->quest_log, struct quest, num_received);
}
- if( sd->quest_log[i].state == Q_COMPLETE )
- sd->avail_quests--;
+ for (i = 0; i < num_received; i++) {
+ if( quest->db(received[i].quest_id) == &quest->dummy ) {
+ ShowError("intif_parse_QuestLog: quest %d not found in DB.\n", received[i].quest_id);
+ continue;
+ }
+ if (received[i].state != Q_COMPLETE) {
+ // Insert at the beginning
+ memcpy(&sd->quest_log[sd->avail_quests++], &received[i], sizeof(struct quest));
+ } else {
+ // Insert at the end
+ memcpy(&sd->quest_log[--k], &received[i], sizeof(struct quest));
+ }
+ sd->num_quests++;
+ }
+ if (sd->avail_quests < k) {
+ // sd->avail_quests and k didn't meet in the middle: some entries were skipped
+ if (k < num_received) // Move the entries at the end to fill the gap
+ memmove(&sd->quest_log[k], &sd->quest_log[sd->avail_quests], sizeof(struct quest)*(num_received - k));
+ sd->quest_log = aRealloc(sd->quest_log, sizeof(struct quest)*sd->num_quests);
+ }
}
- quest_pc_login(sd);
-
- return 0;
+ quest->pc_login(sd);
}
-int intif_parse_questsave(int fd)
-{
+/**
+ * Parses the quest log save ack for a character from the inter server.
+ *
+ * Received in reply to the requests made by intif_quest_save.
+ *
+ * @see intif_parse
+ */
+void intif_parse_QuestSave(int fd) {
int cid = RFIFOL(fd, 2);
- TBL_PC *sd = iMap->id2sd(cid);
+ TBL_PC *sd = map->id2sd(cid);
if( !RFIFOB(fd, 6) )
- ShowError("intif_parse_questsave: Failed to save quest(s) for character %d!\n", cid);
+ ShowError("intif_parse_QuestSave: Failed to save quest(s) for character %d!\n", cid);
else if( sd )
sd->save_quest = false;
-
- return 0;
}
-int intif_quest_save(TBL_PC *sd)
-{
- int len;
-
- if(CheckForCharServer())
- return 0;
+/**
+ * Requests to the inter server to save a character's quest log entries.
+ *
+ * @param sd Character's data
+ * @return 0 in case of success, nonzero otherwise
+ */
+int intif_quest_save(TBL_PC *sd) {
+ int len = sizeof(struct quest)*sd->num_quests + 8;
- len = sizeof(struct quest)*sd->num_quests + 8;
+ if(intif->CheckForCharServer())
+ return 1;
WFIFOHEAD(inter_fd, len);
WFIFOW(inter_fd,0) = 0x3061;
WFIFOW(inter_fd,2) = len;
WFIFOL(inter_fd,4) = sd->status.char_id;
if( sd->num_quests )
- memcpy(WFIFOP(inter_fd,8), &sd->quest_log, sizeof(struct quest)*sd->num_quests);
+ memcpy(WFIFOP(inter_fd,8), sd->quest_log, sizeof(struct quest)*sd->num_quests);
WFIFOSET(inter_fd, len);
return 0;
@@ -1483,7 +1549,7 @@ int intif_quest_save(TBL_PC *sd)
*------------------------------------------*/
int intif_Mail_requestinbox(int char_id, unsigned char flag)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,7);
@@ -1495,23 +1561,20 @@ int intif_Mail_requestinbox(int char_id, unsigned char flag)
return 0;
}
-int intif_parse_Mail_inboxreceived(int fd)
-{
+void intif_parse_MailInboxReceived(int fd) {
struct map_session_data *sd;
unsigned char flag = RFIFOB(fd,8);
- sd = iMap->charid2sd(RFIFOL(fd,4));
+ sd = map->charid2sd(RFIFOL(fd,4));
- if (sd == NULL)
- {
- ShowError("intif_parse_Mail_inboxreceived: char not found %d\n",RFIFOL(fd,4));
- return 1;
+ if (sd == NULL) {
+ ShowError("intif_parse_MailInboxReceived: char not found %d\n",RFIFOL(fd,4));
+ return;
}
- if (RFIFOW(fd,2) - 9 != sizeof(struct mail_data))
- {
- ShowError("intif_parse_Mail_inboxreceived: data size error %d %d\n", RFIFOW(fd,2) - 9, sizeof(struct mail_data));
- return 1;
+ if (RFIFOW(fd,2) - 9 != sizeof(struct mail_data)) {
+ ShowError("intif_parse_MailInboxReceived: data size mismatch %d != %"PRIuS"\n", RFIFOW(fd,2) - 9, sizeof(struct mail_data));
+ return;
}
//FIXME: this operation is not safe [ultramage]
@@ -1520,20 +1583,18 @@ int intif_parse_Mail_inboxreceived(int fd)
if (flag)
clif->mail_refreshinbox(sd);
- else if( battle_config.mail_show_status && ( battle_config.mail_show_status == 1 || sd->mail.inbox.unread ) )
- {
+ else if( battle_config.mail_show_status && ( battle_config.mail_show_status == 1 || sd->mail.inbox.unread ) ) {
char output[128];
sprintf(output, msg_txt(510), sd->mail.inbox.unchecked, sd->mail.inbox.unread + sd->mail.inbox.unchecked);
- clif->disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
}
- return 0;
}
/*------------------------------------------
* Mail Read
*------------------------------------------*/
int intif_Mail_read(int mail_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,6);
@@ -1548,7 +1609,7 @@ int intif_Mail_read(int mail_id)
*------------------------------------------*/
int intif_Mail_getattach(int char_id, int mail_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,10);
@@ -1560,37 +1621,33 @@ int intif_Mail_getattach(int char_id, int mail_id)
return 0;
}
-int intif_parse_Mail_getattach(int fd)
-{
+void intif_parse_MailGetAttach(int fd) {
struct map_session_data *sd;
struct item item;
int zeny = RFIFOL(fd,8);
- sd = iMap->charid2sd( RFIFOL(fd,4) );
+ sd = map->charid2sd( RFIFOL(fd,4) );
- if (sd == NULL)
- {
- ShowError("intif_parse_Mail_getattach: char not found %d\n",RFIFOL(fd,4));
- return 1;
+ if (sd == NULL) {
+ ShowError("intif_parse_MailGetAttach: char not found %d\n",RFIFOL(fd,4));
+ return;
}
- if (RFIFOW(fd,2) - 12 != sizeof(struct item))
- {
- ShowError("intif_parse_Mail_getattach: data size error %d %d\n", RFIFOW(fd,2) - 16, sizeof(struct item));
- return 1;
+ if (RFIFOW(fd,2) - 12 != sizeof(struct item)) {
+ ShowError("intif_parse_MailGetAttach: data size mismatch %d != %"PRIuS"\n", RFIFOW(fd,2) - 16, sizeof(struct item));
+ return;
}
memcpy(&item, RFIFOP(fd,12), sizeof(struct item));
mail->getattachment(sd, zeny, &item);
- return 0;
}
/*------------------------------------------
* Delete Message
*------------------------------------------*/
int intif_Mail_delete(int char_id, int mail_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,10);
@@ -1602,42 +1659,37 @@ int intif_Mail_delete(int char_id, int mail_id)
return 0;
}
-int intif_parse_Mail_delete(int fd)
-{
+void intif_parse_MailDelete(int fd) {
+ struct map_session_data *sd;
int char_id = RFIFOL(fd,2);
int mail_id = RFIFOL(fd,6);
bool failed = RFIFOB(fd,10);
-
- struct map_session_data *sd = iMap->charid2sd(char_id);
- if (sd == NULL)
- {
- ShowError("intif_parse_Mail_delete: char not found %d\n", char_id);
- return 1;
+
+ if ( (sd = map->charid2sd(char_id)) == NULL) {
+ ShowError("intif_parse_MailDelete: char not found %d\n", char_id);
+ return;
}
- if (!failed)
- {
+ if (!failed) {
int i;
ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
- if( i < MAIL_MAX_INBOX )
- {
+ if( i < MAIL_MAX_INBOX ) {
memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message));
sd->mail.inbox.amount--;
}
if( sd->mail.inbox.full )
- intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails
+ intif->Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails
}
clif->mail_delete(sd->fd, mail_id, failed);
- return 0;
}
/*------------------------------------------
* Return Message
*------------------------------------------*/
int intif_Mail_return(int char_id, int mail_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,10);
@@ -1649,34 +1701,29 @@ int intif_Mail_return(int char_id, int mail_id)
return 0;
}
-int intif_parse_Mail_return(int fd)
-{
- struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2));
+void intif_parse_MailReturn(int fd) {
+ struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
int mail_id = RFIFOL(fd,6);
short fail = RFIFOB(fd,10);
- if( sd == NULL )
- {
- ShowError("intif_parse_Mail_return: char not found %d\n",RFIFOL(fd,2));
- return 1;
+ if( sd == NULL ) {
+ ShowError("intif_parse_MailReturn: char not found %d\n",RFIFOL(fd,2));
+ return;
}
- if( !fail )
- {
+ if( !fail ) {
int i;
ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id);
- if( i < MAIL_MAX_INBOX )
- {
+ if( i < MAIL_MAX_INBOX ) {
memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message));
sd->mail.inbox.amount--;
}
if( sd->mail.inbox.full )
- intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails
+ intif->Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails
}
clif->mail_return(sd->fd, mail_id, fail);
- return 0;
}
/*------------------------------------------
* Send Mail
@@ -1685,7 +1732,7 @@ int intif_Mail_send(int account_id, struct mail_message *msg)
{
int len = sizeof(struct mail_message) + 8;
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,len);
@@ -1698,15 +1745,13 @@ int intif_Mail_send(int account_id, struct mail_message *msg)
return 1;
}
-static void intif_parse_Mail_send(int fd)
-{
+void intif_parse_MailSend(int fd) {
struct mail_message msg;
struct map_session_data *sd;
bool fail;
- if( RFIFOW(fd,2) - 4 != sizeof(struct mail_message) )
- {
- ShowError("intif_parse_Mail_send: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct mail_message));
+ if( RFIFOW(fd,2) - 4 != sizeof(struct mail_message) ) {
+ ShowError("intif_parse_MailSend: data size mismatch %d != %"PRIuS"\n", RFIFOW(fd,2) - 4, sizeof(struct mail_message));
return;
}
@@ -1714,23 +1759,20 @@ static void intif_parse_Mail_send(int fd)
fail = (msg.id == 0);
// notify sender
- sd = iMap->charid2sd(msg.send_id);
- if( sd != NULL )
- {
+ sd = map->charid2sd(msg.send_id);
+ if( sd != NULL ) {
if( fail )
mail->deliveryfail(sd, &msg);
- else
- {
+ else {
clif->mail_send(sd->fd, false);
- if( iMap->save_settings&16 )
- chrif_save(sd, 0);
+ if( map->save_settings&16 )
+ chrif->save(sd, 0);
}
}
}
-static void intif_parse_Mail_new(int fd)
-{
- struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2));
+void intif_parse_MailNew(int fd) {
+ struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
int mail_id = RFIFOL(fd,6);
const char* sender_name = (char*)RFIFOP(fd,10);
const char* title = (char*)RFIFOP(fd,34);
@@ -1750,7 +1792,7 @@ int intif_Auction_requestlist(int char_id, short type, int price, const char* se
{
int len = NAME_LENGTH + 16;
- if( CheckForCharServer() )
+ if( intif->CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd,len);
@@ -1766,9 +1808,8 @@ int intif_Auction_requestlist(int char_id, short type, int price, const char* se
return 0;
}
-static void intif_parse_Auction_results(int fd)
-{
- struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,4));
+void intif_parse_AuctionResults(int fd) {
+ struct map_session_data *sd = map->charid2sd(RFIFOL(fd,4));
short count = RFIFOW(fd,8);
short pages = RFIFOW(fd,10);
uint8* data = RFIFOP(fd,12);
@@ -1783,7 +1824,7 @@ int intif_Auction_register(struct auction_data *auction)
{
int len = sizeof(struct auction_data) + 4;
- if( CheckForCharServer() )
+ if( intif->CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd,len);
@@ -1795,29 +1836,24 @@ int intif_Auction_register(struct auction_data *auction)
return 1;
}
-static void intif_parse_Auction_register(int fd)
-{
+void intif_parse_AuctionRegister(int fd) {
struct map_session_data *sd;
struct auction_data auction;
- if( RFIFOW(fd,2) - 4 != sizeof(struct auction_data) )
- {
- ShowError("intif_parse_Auction_register: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct auction_data));
+ if (RFIFOW(fd,2) - 4 != sizeof(struct auction_data)) {
+ ShowError("intif_parse_AuctionRegister: data size mismatch %d != %"PRIuS"\n", RFIFOW(fd,2) - 4, sizeof(struct auction_data));
return;
}
memcpy(&auction, RFIFOP(fd,4), sizeof(struct auction_data));
- if( (sd = iMap->charid2sd(auction.seller_id)) == NULL )
+ if( (sd = map->charid2sd(auction.seller_id)) == NULL )
return;
- if( auction.auction_id > 0 )
- {
+ if( auction.auction_id > 0 ) {
clif->auction_message(sd->fd, 1); // Confirmation Packet ??
- if( iMap->save_settings&32 )
- chrif_save(sd,0);
- }
- else
- {
+ if( map->save_settings&32 )
+ chrif->save(sd,0);
+ } else {
int zeny = auction.hours*battle_config.auction_feeperhour;
clif->auction_message(sd->fd, 4);
@@ -1829,7 +1865,7 @@ static void intif_parse_Auction_register(int fd)
int intif_Auction_cancel(int char_id, unsigned int auction_id)
{
- if( CheckForCharServer() )
+ if( intif->CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd,10);
@@ -1841,26 +1877,24 @@ int intif_Auction_cancel(int char_id, unsigned int auction_id)
return 0;
}
-static void intif_parse_Auction_cancel(int fd)
-{
- struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2));
+void intif_parse_AuctionCancel(int fd) {
+ struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
int result = RFIFOB(fd,6);
if( sd == NULL )
return;
- switch( result )
- {
- case 0: clif->auction_message(sd->fd, 2); break;
- case 1: clif->auction_close(sd->fd, 2); break;
- case 2: clif->auction_close(sd->fd, 1); break;
- case 3: clif->auction_message(sd->fd, 3); break;
+ switch( result ) {
+ case 0: clif->auction_message(sd->fd, 2); break;
+ case 1: clif->auction_close(sd->fd, 2); break;
+ case 2: clif->auction_close(sd->fd, 1); break;
+ case 3: clif->auction_message(sd->fd, 3); break;
}
}
int intif_Auction_close(int char_id, unsigned int auction_id)
{
- if( CheckForCharServer() )
+ if( intif->CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd,10);
@@ -1872,20 +1906,18 @@ int intif_Auction_close(int char_id, unsigned int auction_id)
return 0;
}
-static void intif_parse_Auction_close(int fd)
-{
- struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2));
+void intif_parse_AuctionClose(int fd) {
+ struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
unsigned char result = RFIFOB(fd,6);
if( sd == NULL )
return;
clif->auction_close(sd->fd, result);
- if( result == 0 )
- {
+ if( result == 0 ) {
// FIXME: Leeching off a parse function
clif->pAuction_cancelreg(fd, sd);
- intif_Auction_requestlist(sd->status.char_id, 6, 0, "", 1);
+ intif->Auction_requestlist(sd->status.char_id, 6, 0, "", 1);
}
}
@@ -1893,7 +1925,7 @@ int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, in
{
int len = 16 + NAME_LENGTH;
- if( CheckForCharServer() )
+ if( intif->CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd,len);
@@ -1908,9 +1940,8 @@ int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, in
return 0;
}
-static void intif_parse_Auction_bid(int fd)
-{
- struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2));
+void intif_parse_AuctionBid(int fd) {
+ struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
int bid = RFIFOL(fd,6);
unsigned char result = RFIFOB(fd,10);
@@ -1923,14 +1954,13 @@ static void intif_parse_Auction_bid(int fd)
}
if( result == 1 ) { // To update the list, display your buy list
clif->pAuction_cancelreg(fd, sd);
- intif_Auction_requestlist(sd->status.char_id, 7, 0, "", 1);
+ intif->Auction_requestlist(sd->status.char_id, 7, 0, "", 1);
}
}
// Used to send 'You have won the auction' and 'You failed to won the auction' messages
-static void intif_parse_Auction_message(int fd)
-{
- struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2));
+void intif_parse_AuctionMessage(int fd) {
+ struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2));
unsigned char result = RFIFOB(fd,6);
if( sd == NULL )
@@ -1946,7 +1976,7 @@ int intif_mercenary_create(struct s_mercenary *merc)
{
int size = sizeof(struct s_mercenary) + 4;
- if( CheckForCharServer() )
+ if( intif->CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd,size);
@@ -1957,23 +1987,21 @@ int intif_mercenary_create(struct s_mercenary *merc)
return 0;
}
-int intif_parse_mercenary_received(int fd)
-{
+void intif_parse_MercenaryReceived(int fd) {
int len = RFIFOW(fd,2) - 5;
- if( sizeof(struct s_mercenary) != len )
- {
- if( battle_config.etc_log )
- ShowError("intif: create mercenary data size error %d != %d\n", sizeof(struct s_mercenary), len);
- return 0;
+
+ if (sizeof(struct s_mercenary) != len) {
+ if (battle_config.etc_log)
+ ShowError("intif: create mercenary data size mismatch %d != %"PRIuS"\n", len, sizeof(struct s_mercenary));
+ return;
}
- merc_data_received((struct s_mercenary*)RFIFOP(fd,5), RFIFOB(fd,4));
- return 0;
+ mercenary->data_received((struct s_mercenary*)RFIFOP(fd,5), RFIFOB(fd,4));
}
int intif_mercenary_request(int merc_id, int char_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,10);
@@ -1986,7 +2014,7 @@ int intif_mercenary_request(int merc_id, int char_id)
int intif_mercenary_delete(int merc_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,6);
@@ -1995,20 +2023,17 @@ int intif_mercenary_delete(int merc_id)
WFIFOSET(inter_fd,6);
return 0;
}
-
-int intif_parse_mercenary_deleted(int fd)
-{
+/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
+void intif_parse_MercenaryDeleted(int fd) {
if( RFIFOB(fd,2) != 1 )
ShowError("Mercenary data delete failure\n");
-
- return 0;
}
int intif_mercenary_save(struct s_mercenary *merc)
{
int size = sizeof(struct s_mercenary) + 4;
- if( CheckForCharServer() )
+ if( intif->CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd,size);
@@ -2018,13 +2043,10 @@ int intif_mercenary_save(struct s_mercenary *merc)
WFIFOSET(inter_fd,size);
return 0;
}
-
-int intif_parse_mercenary_saved(int fd)
-{
+/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
+void intif_parse_MercenarySaved(int fd) {
if( RFIFOB(fd,2) != 1 )
ShowError("Mercenary data save failure\n");
-
- return 0;
}
/*==========================================
@@ -2034,7 +2056,7 @@ int intif_elemental_create(struct s_elemental *ele)
{
int size = sizeof(struct s_elemental) + 4;
- if( CheckForCharServer() )
+ if( intif->CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd,size);
@@ -2045,23 +2067,21 @@ int intif_elemental_create(struct s_elemental *ele)
return 0;
}
-int intif_parse_elemental_received(int fd)
-{
+void intif_parse_ElementalReceived(int fd) {
int len = RFIFOW(fd,2) - 5;
- if( sizeof(struct s_elemental) != len )
- {
- if( battle_config.etc_log )
- ShowError("intif: create elemental data size error %d != %d\n", sizeof(struct s_elemental), len);
- return 0;
+
+ if (sizeof(struct s_elemental) != len) {
+ if (battle_config.etc_log)
+ ShowError("intif: create elemental data size mismatch %d != %"PRIuS"\n", len, sizeof(struct s_elemental));
+ return;
}
- elemental_data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4));
- return 0;
+ elemental->data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4));
}
int intif_elemental_request(int ele_id, int char_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,10);
@@ -2074,7 +2094,7 @@ int intif_elemental_request(int ele_id, int char_id)
int intif_elemental_delete(int ele_id)
{
- if (CheckForCharServer())
+ if (intif->CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,6);
@@ -2083,20 +2103,17 @@ int intif_elemental_delete(int ele_id)
WFIFOSET(inter_fd,6);
return 0;
}
-
-int intif_parse_elemental_deleted(int fd)
-{
+/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
+void intif_parse_ElementalDeleted(int fd) {
if( RFIFOB(fd,2) != 1 )
ShowError("Elemental data delete failure\n");
-
- return 0;
}
int intif_elemental_save(struct s_elemental *ele)
{
int size = sizeof(struct s_elemental) + 4;
- if( CheckForCharServer() )
+ if( intif->CheckForCharServer() )
return 0;
WFIFOHEAD(inter_fd,size);
@@ -2106,13 +2123,10 @@ int intif_elemental_save(struct s_elemental *ele)
WFIFOSET(inter_fd,size);
return 0;
}
-
-int intif_parse_elemental_saved(int fd)
-{
+/* Really? Whats the point, shouldn't be sent when successful then [Ind] */
+void intif_parse_ElementalSaved(int fd) {
if( RFIFOB(fd,2) != 1 )
ShowError("Elemental data save failure\n");
-
- return 0;
}
void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) {
@@ -2138,7 +2152,7 @@ void intif_parse_MessageToFD(int fd) {
int aid = RFIFOL(fd,8);
struct map_session_data * sd = session[u_fd]->session_data;
/* matching e.g. previous fd owner didn't dc during request or is still the same */
- if( sd->bl.id == aid ) {
+ if( sd && sd->bl.id == aid ) {
char msg[512];
safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12);
clif->message(u_fd,msg);
@@ -2148,7 +2162,34 @@ void intif_parse_MessageToFD(int fd) {
return;
}
+/*==========================================
+ * Item Bound System [Xantara][Mhalicot]
+ *------------------------------------------*/
+void intif_itembound_req(int char_id,int aid,int guild_id) {
+#ifdef GP_BOUND_ITEMS
+ struct guild_storage *gstor = gstorage->id2storage2(guild_id);
+ WFIFOHEAD(inter_fd,12);
+ WFIFOW(inter_fd,0) = 0x3056;
+ WFIFOL(inter_fd,2) = char_id;
+ WFIFOL(inter_fd,6) = aid;
+ WFIFOW(inter_fd,10) = guild_id;
+ WFIFOSET(inter_fd,12);
+ if(gstor)
+ gstor->lock = 1; //Lock for retrieval process
+#endif
+}
+
+//3856
+void intif_parse_Itembound_ack(int fd) {
+#ifdef GP_BOUND_ITEMS
+ struct guild_storage *gstor;
+ int guild_id = RFIFOW(fd,6);
+ gstor = gstorage->id2storage2(guild_id);
+ if(gstor)
+ gstor->lock = 0; //Unlock now that operation is completed
+#endif
+}
//-----------------------------------------------------------------
// Communication from the inter server
// Return a 0 (false) if there were any errors.
@@ -2158,12 +2199,12 @@ int intif_parse(int fd)
int packet_len, cmd;
cmd = RFIFOW(fd,0);
// Verify ID of the packet
- if(cmd<0x3800 || cmd>=0x3800+(sizeof(packet_len_table)/sizeof(packet_len_table[0])) ||
- packet_len_table[cmd-0x3800]==0){
+ if(cmd<0x3800 || cmd>=0x3800+(sizeof(intif->packet_len_table)/sizeof(intif->packet_len_table[0])) ||
+ intif->packet_len_table[cmd-0x3800]==0){
return 0;
}
// Check the length of the packet
- packet_len = packet_len_table[cmd-0x3800];
+ packet_len = intif->packet_len_table[cmd-0x3800];
if(packet_len==-1){
if(RFIFOREST(fd)<4)
return 2;
@@ -2174,81 +2215,88 @@ int intif_parse(int fd)
}
// Processing branch
switch(cmd){
- case 0x3800:
- if (RFIFOL(fd,4) == 0xFF000000) //Normal announce.
- clif->broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, 0, ALL_CLIENT);
- else //Color announce.
- clif->broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT);
- break;
- case 0x3801: intif_parse_WisMessage(fd); break;
- case 0x3802: intif_parse_WisEnd(fd); break;
- case 0x3803: mapif_parse_WisToGM(fd); break;
- case 0x3804: intif_parse_Registers(fd); break;
- case 0x3806: intif_parse_ChangeNameOk(fd); break;
- case 0x3807: intif_parse_MessageToFD(fd); break;
- case 0x3818: intif_parse_LoadGuildStorage(fd); break;
- case 0x3819: intif_parse_SaveGuildStorage(fd); break;
- case 0x3820: intif_parse_PartyCreated(fd); break;
- case 0x3821: intif_parse_PartyInfo(fd); break;
- case 0x3822: intif_parse_PartyMemberAdded(fd); break;
- case 0x3823: intif_parse_PartyOptionChanged(fd); break;
- case 0x3824: intif_parse_PartyMemberWithdraw(fd); break;
- case 0x3825: intif_parse_PartyMove(fd); break;
- case 0x3826: intif_parse_PartyBroken(fd); break;
- case 0x3827: intif_parse_PartyMessage(fd); break;
- case 0x3830: intif_parse_GuildCreated(fd); break;
- case 0x3831: intif_parse_GuildInfo(fd); break;
- case 0x3832: intif_parse_GuildMemberAdded(fd); break;
- case 0x3834: intif_parse_GuildMemberWithdraw(fd); break;
- case 0x3835: intif_parse_GuildMemberInfoShort(fd); break;
- case 0x3836: intif_parse_GuildBroken(fd); break;
- case 0x3837: intif_parse_GuildMessage(fd); break;
- case 0x3839: intif_parse_GuildBasicInfoChanged(fd); break;
- case 0x383a: intif_parse_GuildMemberInfoChanged(fd); break;
- case 0x383b: intif_parse_GuildPosition(fd); break;
- case 0x383c: intif_parse_GuildSkillUp(fd); break;
- case 0x383d: intif_parse_GuildAlliance(fd); break;
- case 0x383e: intif_parse_GuildNotice(fd); break;
- case 0x383f: intif_parse_GuildEmblem(fd); break;
- case 0x3840: intif_parse_GuildCastleDataLoad(fd); break;
- case 0x3843: intif_parse_GuildMasterChanged(fd); break;
-
- //Quest system
- case 0x3860: intif_parse_questlog(fd); break;
- case 0x3861: intif_parse_questsave(fd); break;
-
-// Mail System
- case 0x3848: intif_parse_Mail_inboxreceived(fd); break;
- case 0x3849: intif_parse_Mail_new(fd); break;
- case 0x384a: intif_parse_Mail_getattach(fd); break;
- case 0x384b: intif_parse_Mail_delete(fd); break;
- case 0x384c: intif_parse_Mail_return(fd); break;
- case 0x384d: intif_parse_Mail_send(fd); break;
-// Auction System
- case 0x3850: intif_parse_Auction_results(fd); break;
- case 0x3851: intif_parse_Auction_register(fd); break;
- case 0x3852: intif_parse_Auction_cancel(fd); break;
- case 0x3853: intif_parse_Auction_close(fd); break;
- case 0x3854: intif_parse_Auction_message(fd); break;
- case 0x3855: intif_parse_Auction_bid(fd); break;
-
-// Mercenary System
- case 0x3870: intif_parse_mercenary_received(fd); break;
- case 0x3871: intif_parse_mercenary_deleted(fd); break;
- case 0x3872: intif_parse_mercenary_saved(fd); break;
-// Elemental System
- case 0x387c: intif_parse_elemental_received(fd); break;
- case 0x387d: intif_parse_elemental_deleted(fd); break;
- case 0x387e: intif_parse_elemental_saved(fd); break;
-
- case 0x3880: intif_parse_CreatePet(fd); break;
- case 0x3881: intif_parse_RecvPetData(fd); break;
- case 0x3882: intif_parse_SavePetOk(fd); break;
- case 0x3883: intif_parse_DeletePetOk(fd); break;
- case 0x3890: intif_parse_CreateHomunculus(fd); break;
- case 0x3891: intif_parse_RecvHomunculusData(fd); break;
- case 0x3892: intif_parse_SaveHomunculusOk(fd); break;
- case 0x3893: intif_parse_DeleteHomunculusOk(fd); break;
+ case 0x3800:
+ if (RFIFOL(fd,4) == 0xFF000000) //Normal announce.
+ clif->broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, BC_DEFAULT, ALL_CLIENT);
+ else //Color announce.
+ clif->broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT);
+ break;
+ case 0x3801: intif->pWisMessage(fd); break;
+ case 0x3802: intif->pWisEnd(fd); break;
+ case 0x3803: intif->pWisToGM(fd); break;
+ case 0x3804: intif->pRegisters(fd); break;
+ case 0x3806: intif->pChangeNameOk(fd); break;
+ case 0x3807: intif->pMessageToFD(fd); break;
+ case 0x3818: intif->pLoadGuildStorage(fd); break;
+ case 0x3819: intif->pSaveGuildStorage(fd); break;
+ case 0x3820: intif->pPartyCreated(fd); break;
+ case 0x3821: intif->pPartyInfo(fd); break;
+ case 0x3822: intif->pPartyMemberAdded(fd); break;
+ case 0x3823: intif->pPartyOptionChanged(fd); break;
+ case 0x3824: intif->pPartyMemberWithdraw(fd); break;
+ case 0x3825: intif->pPartyMove(fd); break;
+ case 0x3826: intif->pPartyBroken(fd); break;
+ case 0x3827: intif->pPartyMessage(fd); break;
+ case 0x3830: intif->pGuildCreated(fd); break;
+ case 0x3831: intif->pGuildInfo(fd); break;
+ case 0x3832: intif->pGuildMemberAdded(fd); break;
+ case 0x3834: intif->pGuildMemberWithdraw(fd); break;
+ case 0x3835: intif->pGuildMemberInfoShort(fd); break;
+ case 0x3836: intif->pGuildBroken(fd); break;
+ case 0x3837: intif->pGuildMessage(fd); break;
+ case 0x3839: intif->pGuildBasicInfoChanged(fd); break;
+ case 0x383a: intif->pGuildMemberInfoChanged(fd); break;
+ case 0x383b: intif->pGuildPosition(fd); break;
+ case 0x383c: intif->pGuildSkillUp(fd); break;
+ case 0x383d: intif->pGuildAlliance(fd); break;
+ case 0x383e: intif->pGuildNotice(fd); break;
+ case 0x383f: intif->pGuildEmblem(fd); break;
+ case 0x3840: intif->pGuildCastleDataLoad(fd); break;
+ case 0x3843: intif->pGuildMasterChanged(fd); break;
+
+ //Quest system
+ case 0x3860: intif->pQuestLog(fd); break;
+ case 0x3861: intif->pQuestSave(fd); break;
+
+ // Mail System
+ case 0x3848: intif->pMailInboxReceived(fd); break;
+ case 0x3849: intif->pMailNew(fd); break;
+ case 0x384a: intif->pMailGetAttach(fd); break;
+ case 0x384b: intif->pMailDelete(fd); break;
+ case 0x384c: intif->pMailReturn(fd); break;
+ case 0x384d: intif->pMailSend(fd); break;
+ // Auction System
+ case 0x3850: intif->pAuctionResults(fd); break;
+ case 0x3851: intif->pAuctionRegister(fd); break;
+ case 0x3852: intif->pAuctionCancel(fd); break;
+ case 0x3853: intif->pAuctionClose(fd); break;
+ case 0x3854: intif->pAuctionMessage(fd); break;
+ case 0x3855: intif->pAuctionBid(fd); break;
+ //Bound items
+ case 0x3856:
+#ifdef GP_BOUND_ITEMS
+ intif->pItembound_ack(fd);
+#else
+ ShowWarning("intif_parse: Received 0x3856 with GP_BOUND_ITEMS disabled !!!\n");
+#endif
+ break;
+ // Mercenary System
+ case 0x3870: intif->pMercenaryReceived(fd); break;
+ case 0x3871: intif->pMercenaryDeleted(fd); break;
+ case 0x3872: intif->pMercenarySaved(fd); break;
+ // Elemental System
+ case 0x387c: intif->pElementalReceived(fd); break;
+ case 0x387d: intif->pElementalDeleted(fd); break;
+ case 0x387e: intif->pElementalSaved(fd); break;
+
+ case 0x3880: intif->pCreatePet(fd); break;
+ case 0x3881: intif->pRecvPetData(fd); break;
+ case 0x3882: intif->pSavePetOk(fd); break;
+ case 0x3883: intif->pDeletePetOk(fd); break;
+ case 0x3890: intif->pCreateHomunculus(fd); break;
+ case 0x3891: intif->pRecvHomunculusData(fd); break;
+ case 0x3892: intif->pSaveHomunculusOk(fd); break;
+ case 0x3893: intif->pDeleteHomunculusOk(fd); break;
default:
ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0));
return 0;
@@ -2257,3 +2305,170 @@ int intif_parse(int fd)
RFIFOSKIP(fd,packet_len);
return 1;
}
+
+/*=====================================
+* Default Functions : intif.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+void intif_defaults(void) {
+ const int packet_len_table [INTIF_PACKET_LEN_TABLE_SIZE] = {
+ -1,-1,27,-1, -1, 0,37,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f
+ 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810
+ 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820
+ 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830
+ -1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840
+ -1,-1, 7, 7, 7,11, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] itembound[Akinari]
+ -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish]
+ -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil]
+ 12,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880
+ -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator]
+ };
+
+ intif = &intif_s;
+
+ /* */
+ memcpy(intif->packet_len_table,&packet_len_table,sizeof(intif->packet_len_table));
+
+ /* funcs */
+ intif->parse = intif_parse;
+ intif->create_pet = intif_create_pet;
+ intif->broadcast = intif_broadcast;
+ intif->broadcast2 = intif_broadcast2;
+ intif->main_message = intif_main_message;
+ intif->wis_message = intif_wis_message;
+ intif->wis_message_to_gm = intif_wis_message_to_gm;
+ intif->saveregistry = intif_saveregistry;
+ intif->request_registry = intif_request_registry;
+ intif->request_guild_storage = intif_request_guild_storage;
+ intif->send_guild_storage = intif_send_guild_storage;
+ intif->create_party = intif_create_party;
+ intif->request_partyinfo = intif_request_partyinfo;
+ intif->party_addmember = intif_party_addmember;
+ intif->party_changeoption = intif_party_changeoption;
+ intif->party_leave = intif_party_leave;
+ intif->party_changemap = intif_party_changemap;
+ intif->break_party = intif_break_party;
+ intif->party_message = intif_party_message;
+ intif->party_leaderchange = intif_party_leaderchange;
+ intif->guild_create = intif_guild_create;
+ intif->guild_request_info = intif_guild_request_info;
+ intif->guild_addmember = intif_guild_addmember;
+ intif->guild_leave = intif_guild_leave;
+ intif->guild_memberinfoshort = intif_guild_memberinfoshort;
+ intif->guild_break = intif_guild_break;
+ intif->guild_message = intif_guild_message;
+ intif->guild_change_gm = intif_guild_change_gm;
+ intif->guild_change_basicinfo = intif_guild_change_basicinfo;
+ intif->guild_change_memberinfo = intif_guild_change_memberinfo;
+ intif->guild_position = intif_guild_position;
+ intif->guild_skillup = intif_guild_skillup;
+ intif->guild_alliance = intif_guild_alliance;
+ intif->guild_notice = intif_guild_notice;
+ intif->guild_emblem = intif_guild_emblem;
+ intif->guild_castle_dataload = intif_guild_castle_dataload;
+ intif->guild_castle_datasave = intif_guild_castle_datasave;
+ intif->request_petdata = intif_request_petdata;
+ intif->save_petdata = intif_save_petdata;
+ intif->delete_petdata = intif_delete_petdata;
+ intif->rename = intif_rename;
+ intif->homunculus_create = intif_homunculus_create;
+ intif->homunculus_requestload = intif_homunculus_requestload;
+ intif->homunculus_requestsave = intif_homunculus_requestsave;
+ intif->homunculus_requestdelete = intif_homunculus_requestdelete;
+ /******QUEST SYTEM*******/
+ intif->request_questlog = intif_request_questlog;
+ intif->quest_save = intif_quest_save;
+ // MERCENARY SYSTEM
+ intif->mercenary_create = intif_mercenary_create;
+ intif->mercenary_request = intif_mercenary_request;
+ intif->mercenary_delete = intif_mercenary_delete;
+ intif->mercenary_save = intif_mercenary_save;
+ // MAIL SYSTEM
+ intif->Mail_requestinbox = intif_Mail_requestinbox;
+ intif->Mail_read = intif_Mail_read;
+ intif->Mail_getattach = intif_Mail_getattach;
+ intif->Mail_delete = intif_Mail_delete;
+ intif->Mail_return = intif_Mail_return;
+ intif->Mail_send = intif_Mail_send;
+ // AUCTION SYSTEM
+ intif->Auction_requestlist = intif_Auction_requestlist;
+ intif->Auction_register = intif_Auction_register;
+ intif->Auction_cancel = intif_Auction_cancel;
+ intif->Auction_close = intif_Auction_close;
+ intif->Auction_bid = intif_Auction_bid;
+ // ELEMENTAL SYSTEM
+ intif->elemental_create = intif_elemental_create;
+ intif->elemental_request = intif_elemental_request;
+ intif->elemental_delete = intif_elemental_delete;
+ intif->elemental_save = intif_elemental_save;
+ /* @accinfo */
+ intif->request_accinfo = intif_request_accinfo;
+ /* */
+ intif->CheckForCharServer = CheckForCharServer;
+ /* */
+ intif->itembound_req = intif_itembound_req;
+ /* parse functions */
+ intif->pWisMessage = intif_parse_WisMessage;
+ intif->pWisEnd = intif_parse_WisEnd;
+ intif->pWisToGM_sub = mapif_parse_WisToGM_sub;
+ intif->pWisToGM = mapif_parse_WisToGM;
+ intif->pRegisters = intif_parse_Registers;
+ intif->pChangeNameOk = intif_parse_ChangeNameOk;
+ intif->pMessageToFD = intif_parse_MessageToFD;
+ intif->pLoadGuildStorage = intif_parse_LoadGuildStorage;
+ intif->pSaveGuildStorage = intif_parse_SaveGuildStorage;
+ intif->pPartyCreated = intif_parse_PartyCreated;
+ intif->pPartyInfo = intif_parse_PartyInfo;
+ intif->pPartyMemberAdded = intif_parse_PartyMemberAdded;
+ intif->pPartyOptionChanged = intif_parse_PartyOptionChanged;
+ intif->pPartyMemberWithdraw = intif_parse_PartyMemberWithdraw;
+ intif->pPartyMove = intif_parse_PartyMove;
+ intif->pPartyBroken = intif_parse_PartyBroken;
+ intif->pPartyMessage = intif_parse_PartyMessage;
+ intif->pGuildCreated = intif_parse_GuildCreated;
+ intif->pGuildInfo = intif_parse_GuildInfo;
+ intif->pGuildMemberAdded = intif_parse_GuildMemberAdded;
+ intif->pGuildMemberWithdraw = intif_parse_GuildMemberWithdraw;
+ intif->pGuildMemberInfoShort = intif_parse_GuildMemberInfoShort;
+ intif->pGuildBroken = intif_parse_GuildBroken;
+ intif->pGuildMessage = intif_parse_GuildMessage;
+ intif->pGuildBasicInfoChanged = intif_parse_GuildBasicInfoChanged;
+ intif->pGuildMemberInfoChanged = intif_parse_GuildMemberInfoChanged;
+ intif->pGuildPosition = intif_parse_GuildPosition;
+ intif->pGuildSkillUp = intif_parse_GuildSkillUp;
+ intif->pGuildAlliance = intif_parse_GuildAlliance;
+ intif->pGuildNotice = intif_parse_GuildNotice;
+ intif->pGuildEmblem = intif_parse_GuildEmblem;
+ intif->pGuildCastleDataLoad = intif_parse_GuildCastleDataLoad;
+ intif->pGuildMasterChanged = intif_parse_GuildMasterChanged;
+ intif->pQuestLog = intif_parse_QuestLog;
+ intif->pQuestSave = intif_parse_QuestSave;
+ intif->pMailInboxReceived = intif_parse_MailInboxReceived;
+ intif->pMailNew = intif_parse_MailNew;
+ intif->pMailGetAttach = intif_parse_MailGetAttach;
+ intif->pMailDelete = intif_parse_MailDelete;
+ intif->pMailReturn = intif_parse_MailReturn;
+ intif->pMailSend = intif_parse_MailSend;
+ intif->pAuctionResults = intif_parse_AuctionResults;
+ intif->pAuctionRegister = intif_parse_AuctionRegister;
+ intif->pAuctionCancel = intif_parse_AuctionCancel;
+ intif->pAuctionClose = intif_parse_AuctionClose;
+ intif->pAuctionMessage = intif_parse_AuctionMessage;
+ intif->pAuctionBid = intif_parse_AuctionBid;
+ intif->pItembound_ack = intif_parse_Itembound_ack;
+ intif->pMercenaryReceived = intif_parse_MercenaryReceived;
+ intif->pMercenaryDeleted = intif_parse_MercenaryDeleted;
+ intif->pMercenarySaved = intif_parse_MercenarySaved;
+ intif->pElementalReceived = intif_parse_ElementalReceived;
+ intif->pElementalDeleted = intif_parse_ElementalDeleted;
+ intif->pElementalSaved = intif_parse_ElementalSaved;
+ intif->pCreatePet = intif_parse_CreatePet;
+ intif->pRecvPetData = intif_parse_RecvPetData;
+ intif->pSavePetOk = intif_parse_SavePetOk;
+ intif->pDeletePetOk = intif_parse_DeletePetOk;
+ intif->pCreateHomunculus = intif_parse_CreateHomunculus;
+ intif->pRecvHomunculusData = intif_parse_RecvHomunculusData;
+ intif->pSaveHomunculusOk = intif_parse_SaveHomunculusOk;
+ intif->pDeleteHomunculusOk = intif_parse_DeleteHomunculusOk;
+}
diff --git a/src/map/intif.h b/src/map/intif.h
index 43bbc0859..fe47d6537 100644
--- a/src/map/intif.h
+++ b/src/map/intif.h
@@ -1,112 +1,189 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _INTIF_H_
-#define _INFIF_H_
+#ifndef MAP_INTIF_H
+#define MAP_INTIF_H
-//#include "../common/mmo.h"
-struct party_member;
+#include "../common/cbasetypes.h"
+
+/**
+ * Declarations
+ **/
+struct auction_data;
struct guild_member;
struct guild_position;
-struct s_pet;
+struct guild_storage;
+struct mail_message;
+struct map_session_data;
+struct party_member;
+struct s_elemental;
struct s_homunculus;
struct s_mercenary;
-struct s_elemental;
-struct mail_message;
-struct auction_data;
-
-int intif_parse(int fd);
-
-int intif_broadcast(const char* mes, int len, int type);
-int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY);
-int intif_main_message(struct map_session_data* sd, const char* message);
-
-int intif_wis_message(struct map_session_data *sd,char *nick,char *mes,int mes_len);
-int intif_wis_message_to_gm(char *Wisp_name, int permission, char *mes);
-
-int intif_saveregistry(struct map_session_data *sd, int type);
-int intif_request_registry(struct map_session_data *sd, int flag);
-
-int intif_request_guild_storage(int account_id, int guild_id);
-int intif_send_guild_storage(int account_id, struct guild_storage *gstor);
-
-
-int intif_create_party(struct party_member *member,char *name,int item,int item2);
-int intif_request_partyinfo(int party_id, int char_id);
-
-int intif_party_addmember(int party_id,struct party_member *member);
-int intif_party_changeoption(int party_id, int account_id, int exp, int item);
-int intif_party_leave(int party_id,int account_id, int char_id);
-int intif_party_changemap(struct map_session_data *sd, int online);
-int intif_break_party(int party_id);
-int intif_party_message(int party_id, int account_id, const char *mes,int len);
-int intif_party_leaderchange(int party_id,int account_id,int char_id);
-
-
-int intif_guild_create(const char *name, const struct guild_member *master);
-int intif_guild_request_info(int guild_id);
-int intif_guild_addmember(int guild_id, struct guild_member *m);
-int intif_guild_leave(int guild_id, int account_id, int char_id, int flag, const char *mes);
-int intif_guild_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int class_);
-int intif_guild_break(int guild_id);
-int intif_guild_message(int guild_id, int account_id, const char *mes, int len);
-int intif_guild_change_gm(int guild_id, const char* name, int len);
-int intif_guild_change_basicinfo(int guild_id, int type, const void *data, int len);
-int intif_guild_change_memberinfo(int guild_id, int account_id, int char_id, int type, const void *data, int len);
-int intif_guild_position(int guild_id, int idx, struct guild_position *p);
-int intif_guild_skillup(int guild_id, uint16 skill_id, int account_id, int max);
-int intif_guild_alliance(int guild_id1, int guild_id2, int account_id1, int account_id2, int flag);
-int intif_guild_notice(int guild_id, const char *mes1, const char *mes2);
-int intif_guild_emblem(int guild_id, int len, const char *data);
-int intif_guild_castle_dataload(int num, int *castle_ids);
-int intif_guild_castle_datasave(int castle_id, int index, int value);
-
-int intif_create_pet(int account_id, int char_id, short pet_type, short pet_lv, short pet_egg_id,
- short pet_equip, short intimate, short hungry, char rename_flag, char incuvate, char *pet_name);
-int intif_request_petdata(int account_id, int char_id, int pet_id);
-int intif_save_petdata(int account_id, struct s_pet *p);
-int intif_delete_petdata(int pet_id);
-int intif_rename(struct map_session_data *sd, int type, char *name);
-#define intif_rename_pc(sd, name) intif_rename(sd, 0, name)
-#define intif_rename_pet(sd, name) intif_rename(sd, 1, name)
-#define intif_rename_hom(sd, name) intif_rename(sd, 2, name)
-int intif_homunculus_create(int account_id, struct s_homunculus *sh);
-bool intif_homunculus_requestload(int account_id, int homun_id);
-int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh);
-int intif_homunculus_requestdelete(int homun_id);
-
-/******QUEST SYTEM*******/
-int intif_request_questlog(struct map_session_data * sd);
-int intif_quest_save(struct map_session_data * sd);
-
-// MERCENARY SYSTEM
-int intif_mercenary_create(struct s_mercenary *merc);
-int intif_mercenary_request(int merc_id, int char_id);
-int intif_mercenary_delete(int merc_id);
-int intif_mercenary_save(struct s_mercenary *merc);
-
-// MAIL SYSTEM
-int intif_Mail_requestinbox(int char_id, unsigned char flag);
-int intif_Mail_read(int mail_id);
-int intif_Mail_getattach(int char_id, int mail_id);
-int intif_Mail_delete(int char_id, int mail_id);
-int intif_Mail_return(int char_id, int mail_id);
-int intif_Mail_send(int account_id, struct mail_message *msg);
-// AUCTION SYSTEM
-int intif_Auction_requestlist(int char_id, short type, int price, const char* searchtext, short page);
-int intif_Auction_register(struct auction_data *auction);
-int intif_Auction_cancel(int char_id, unsigned int auction_id);
-int intif_Auction_close(int char_id, unsigned int auction_id);
-int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, int bid);
-// ELEMENTAL SYSTEM
-int intif_elemental_create(struct s_elemental *ele);
-int intif_elemental_request(int ele_id, int char_id);
-int intif_elemental_delete(int ele_id);
-int intif_elemental_save(struct s_elemental *ele);
-
-/* @accinfo */
-void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query );
-
-int CheckForCharServer(void);
+struct s_pet;
-#endif /* _INTIF_H_ */
+/**
+ * Defines
+ **/
+#define intif_rename_pc(sd, name) (intif->rename((sd), 0, (name)))
+#define intif_rename_pet(sd, name) (intif->rename((sd), 1, (name)))
+#define intif_rename_hom(sd, name) (intif->rename((sd), 2, (name)))
+#define INTIF_PACKET_LEN_TABLE_SIZE 161
+
+
+/*=====================================
+* Interface : intif.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+struct intif_interface {
+ /* */
+ int packet_len_table[INTIF_PACKET_LEN_TABLE_SIZE];
+ /* funcs */
+ int (*parse) (int fd);
+ int (*create_pet)(int account_id, int char_id, short pet_type, short pet_lv, short pet_egg_id,
+ short pet_equip, short intimate, short hungry, char rename_flag, char incubate, char *pet_name);
+ int (*broadcast) (const char* mes, size_t len, int type);
+ int (*broadcast2) (const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY);
+ int (*main_message) (struct map_session_data* sd, const char* message);
+ int (*wis_message) (struct map_session_data *sd,char *nick,char *mes,size_t mes_len);
+ int (*wis_message_to_gm) (char *Wisp_name, int permission, char *mes);
+ int (*saveregistry) (struct map_session_data *sd);
+ int (*request_registry) (struct map_session_data *sd, int flag);
+ int (*request_guild_storage) (int account_id, int guild_id);
+ int (*send_guild_storage) (int account_id, struct guild_storage *gstor);
+ int (*create_party) (struct party_member *member,char *name,int item,int item2);
+ int (*request_partyinfo) (int party_id, int char_id);
+ int (*party_addmember) (int party_id,struct party_member *member);
+ int (*party_changeoption) (int party_id, int account_id, int exp, int item);
+ int (*party_leave) (int party_id,int account_id, int char_id);
+ int (*party_changemap) (struct map_session_data *sd, int online);
+ int (*break_party) (int party_id);
+ int (*party_message) (int party_id, int account_id, const char *mes,int len);
+ int (*party_leaderchange) (int party_id,int account_id,int char_id);
+ int (*guild_create) (const char *name, const struct guild_member *master);
+ int (*guild_request_info) (int guild_id);
+ int (*guild_addmember) (int guild_id, struct guild_member *m);
+ int (*guild_leave) (int guild_id, int account_id, int char_id, int flag, const char *mes);
+ int (*guild_memberinfoshort) (int guild_id, int account_id, int char_id, int online, int lv, int class_);
+ int (*guild_break) (int guild_id);
+ int (*guild_message) (int guild_id, int account_id, const char *mes, int len);
+ int (*guild_change_gm) (int guild_id, const char* name, size_t len);
+ int (*guild_change_basicinfo) (int guild_id, int type, const void *data, int len);
+ int (*guild_change_memberinfo) (int guild_id, int account_id, int char_id, int type, const void *data, int len);
+ int (*guild_position) (int guild_id, int idx, struct guild_position *p);
+ int (*guild_skillup) (int guild_id, uint16 skill_id, int account_id, int max);
+ int (*guild_alliance) (int guild_id1, int guild_id2, int account_id1, int account_id2, int flag);
+ int (*guild_notice) (int guild_id, const char *mes1, const char *mes2);
+ int (*guild_emblem) (int guild_id, int len, const char *data);
+ int (*guild_castle_dataload) (int num, int *castle_ids);
+ int (*guild_castle_datasave) (int castle_id, int index, int value);
+ void (*itembound_req) (int char_id, int aid, int guild_id);
+ int (*request_petdata) (int account_id, int char_id, int pet_id);
+ int (*save_petdata) (int account_id, struct s_pet *p);
+ int (*delete_petdata) (int pet_id);
+ int (*rename) (struct map_session_data *sd, int type, char *name);
+ int (*homunculus_create) (int account_id, struct s_homunculus *sh);
+ bool (*homunculus_requestload) (int account_id, int homun_id);
+ int (*homunculus_requestsave) (int account_id, struct s_homunculus* sh);
+ int (*homunculus_requestdelete) (int homun_id);
+ /******QUEST SYTEM*******/
+ void (*request_questlog) (struct map_session_data * sd);
+ int (*quest_save) (struct map_session_data * sd);
+ // MERCENARY SYSTEM
+ int (*mercenary_create) (struct s_mercenary *merc);
+ int (*mercenary_request) (int merc_id, int char_id);
+ int (*mercenary_delete) (int merc_id);
+ int (*mercenary_save) (struct s_mercenary *merc);
+ // MAIL SYSTEM
+ int (*Mail_requestinbox) (int char_id, unsigned char flag);
+ int (*Mail_read) (int mail_id);
+ int (*Mail_getattach) (int char_id, int mail_id);
+ int (*Mail_delete) (int char_id, int mail_id);
+ int (*Mail_return) (int char_id, int mail_id);
+ int (*Mail_send) (int account_id, struct mail_message *msg);
+ // AUCTION SYSTEM
+ int (*Auction_requestlist) (int char_id, short type, int price, const char* searchtext, short page);
+ int (*Auction_register) (struct auction_data *auction);
+ int (*Auction_cancel) (int char_id, unsigned int auction_id);
+ int (*Auction_close) (int char_id, unsigned int auction_id);
+ int (*Auction_bid) (int char_id, const char* name, unsigned int auction_id, int bid);
+ // ELEMENTAL SYSTEM
+ int (*elemental_create) (struct s_elemental *ele);
+ int (*elemental_request) (int ele_id, int char_id);
+ int (*elemental_delete) (int ele_id);
+ int (*elemental_save) (struct s_elemental *ele);
+ /* @accinfo */
+ void (*request_accinfo) (int u_fd, int aid, int group_lv, char* query);
+ /* */
+ int (*CheckForCharServer) (void);
+ /* */
+ void (*pWisMessage) (int fd);
+ void (*pWisEnd) (int fd);
+ int (*pWisToGM_sub) (struct map_session_data* sd,va_list va);
+ void (*pWisToGM) (int fd);
+ void (*pRegisters) (int fd);
+ void (*pChangeNameOk) (int fd);
+ void (*pMessageToFD) (int fd);
+ void (*pLoadGuildStorage) (int fd);
+ void (*pSaveGuildStorage) (int fd);
+ void (*pPartyCreated) (int fd);
+ void (*pPartyInfo) (int fd);
+ void (*pPartyMemberAdded) (int fd);
+ void (*pPartyOptionChanged) (int fd);
+ void (*pPartyMemberWithdraw) (int fd);
+ void (*pPartyMove) (int fd);
+ void (*pPartyBroken) (int fd);
+ void (*pPartyMessage) (int fd);
+ void (*pGuildCreated) (int fd);
+ void (*pGuildInfo) (int fd);
+ void (*pGuildMemberAdded) (int fd);
+ void (*pGuildMemberWithdraw) (int fd);
+ void (*pGuildMemberInfoShort) (int fd);
+ void (*pGuildBroken) (int fd);
+ void (*pGuildMessage) (int fd);
+ void (*pGuildBasicInfoChanged) (int fd);
+ void (*pGuildMemberInfoChanged) (int fd);
+ void (*pGuildPosition) (int fd);
+ void (*pGuildSkillUp) (int fd);
+ void (*pGuildAlliance) (int fd);
+ void (*pGuildNotice) (int fd);
+ void (*pGuildEmblem) (int fd);
+ void (*pGuildCastleDataLoad) (int fd);
+ void (*pGuildMasterChanged) (int fd);
+ void (*pQuestLog) (int fd);
+ void (*pQuestSave) (int fd);
+ void (*pMailInboxReceived) (int fd);
+ void (*pMailNew) (int fd);
+ void (*pMailGetAttach) (int fd);
+ void (*pMailDelete) (int fd);
+ void (*pMailReturn) (int fd);
+ void (*pMailSend) (int fd);
+ void (*pAuctionResults) (int fd);
+ void (*pAuctionRegister) (int fd);
+ void (*pAuctionCancel) (int fd);
+ void (*pAuctionClose) (int fd);
+ void (*pAuctionMessage) (int fd);
+ void (*pAuctionBid) (int fd);
+ void (*pItembound_ack) (int fd);
+ void (*pMercenaryReceived) (int fd);
+ void (*pMercenaryDeleted) (int fd);
+ void (*pMercenarySaved) (int fd);
+ void (*pElementalReceived) (int fd);
+ void (*pElementalDeleted) (int fd);
+ void (*pElementalSaved) (int fd);
+ void (*pCreatePet) (int fd);
+ void (*pRecvPetData) (int fd);
+ void (*pSavePetOk) (int fd);
+ void (*pDeletePetOk) (int fd);
+ void (*pCreateHomunculus) (int fd);
+ void (*pRecvHomunculusData) (int fd);
+ void (*pSaveHomunculusOk) (int fd);
+ void (*pDeleteHomunculusOk) (int fd);
+};
+
+struct intif_interface *intif;
+
+void intif_defaults(void);
+
+#endif /* MAP_INTIF_H */
diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c
index 7f03ed8d4..6f016697f 100644
--- a/src/map/irc-bot.c
+++ b/src/map/irc-bot.c
@@ -2,26 +2,36 @@
// See the LICENSE file
// Base Author: shennetsind @ http://hercules.ws
+#define HERCULES_CORE
+
+#include "irc-bot.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "clif.h"
+#include "map.h"
+#include "pc.h"
#include "../common/cbasetypes.h"
#include "../common/malloc.h"
-#include "../common/strlib.h"
+#include "../common/random.h"
#include "../common/showmsg.h"
#include "../common/socket.h"
+#include "../common/strlib.h"
#include "../common/timer.h"
-#include "../common/random.h"
-#include "map.h"
-#include "pc.h"
-#include "clif.h"
-#include "irc-bot.h"
+//#define IRCBOT_DEBUG
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+struct irc_bot_interface irc_bot_s;
-char send_string[200];
+char send_string[IRC_MESSAGE_LENGTH];
-int irc_connect_timer(int tid, unsigned int tick, int id, intptr_t data) {
+/**
+ * Timer callback to (re-)connect to an IRC server
+ * @see timer->do_timer
+ */
+int irc_connect_timer(int tid, int64 tick, int id, intptr_t data) {
struct hSockOpt opt;
if( ircbot->isOn || ++ircbot->fails >= 3 )
return 0;
@@ -29,18 +39,22 @@ int irc_connect_timer(int tid, unsigned int tick, int id, intptr_t data) {
opt.silent = 1;
opt.setTimeo = 0;
- ircbot->last_try = iTimer->gettick();
+ ircbot->last_try = timer->gettick();
if( ( ircbot->fd = make_connection(ircbot->ip,hChSys.irc_server_port,&opt) ) > 0 ){
session[ircbot->fd]->func_parse = ircbot->parse;
session[ircbot->fd]->flag.server = 1;
- iTimer->add_timer(iTimer->gettick() + 3000, ircbot->identify_timer, 0, 0);
+ timer->add(timer->gettick() + 3000, ircbot->identify_timer, 0, 0);
ircbot->isOn = true;
}
return 0;
}
-int irc_identify_timer(int tid, unsigned int tick, int id, intptr_t data) {
+/**
+ * Timer callback to send identification commands to an IRC server
+ * @see timer->do_timer
+ */
+int irc_identify_timer(int tid, int64 tick, int id, intptr_t data) {
if( !ircbot->isOn )
return 0;
@@ -49,18 +63,25 @@ int irc_identify_timer(int tid, unsigned int tick, int id, intptr_t data) {
sprintf(send_string, "NICK %s", hChSys.irc_nick);
ircbot->send(send_string);
- iTimer->add_timer(iTimer->gettick() + 3000, ircbot->join_timer, 0, 0);
+ timer->add(timer->gettick() + 3000, ircbot->join_timer, 0, 0);
return 0;
}
-int irc_join_timer(int tid, unsigned int tick, int id, intptr_t data) {
+/**
+ * Timer callback to join channels (and optionally send NickServ commands)
+ * @see timer->do_timer
+ */
+int irc_join_timer(int tid, int64 tick, int id, intptr_t data) {
if( !ircbot->isOn )
return 0;
if( hChSys.irc_nick_pw[0] != '\0' ) {
sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", hChSys.irc_nick_pw);
ircbot->send(send_string);
+ if( hChSys.irc_use_ghost ) {
+ sprintf(send_string, "PRIVMSG NICKSERV : GHOST %s %s", hChSys.irc_nick, hChSys.irc_nick_pw);
+ }
}
sprintf(send_string, "JOIN %s", hChSys.irc_channel);
@@ -70,6 +91,12 @@ int irc_join_timer(int tid, unsigned int tick, int id, intptr_t data) {
return 0;
}
+/**
+ * Search the handler for a given IRC received command
+ * @param function_name Name of the received IRC command
+ * @return Function pointer to the command handler, NULL in case
+ * of unhandled commands
+ */
struct irc_func* irc_func_search(char* function_name) {
int i;
for(i = 0; i < ircbot->funcs.size; i++) {
@@ -80,6 +107,10 @@ struct irc_func* irc_func_search(char* function_name) {
return NULL;
}
+/**
+ * Parser for the IRC server connection
+ * @see do_sockets
+ */
int irc_parse(int fd) {
char *parse_string = NULL, *str_safe = NULL;
@@ -90,7 +121,7 @@ int irc_parse(int fd) {
ircbot->isIn = false;
ircbot->fails = 0;
ircbot->ip = host2ip(hChSys.irc_server);
- iTimer->add_timer(iTimer->gettick() + 120000, ircbot->connect_timer, 0, 0);
+ timer->add(timer->gettick() + 120000, ircbot->connect_timer, 0, 0);
return 0;
}
@@ -112,83 +143,156 @@ int irc_parse(int fd) {
return 0;
}
+/**
+ * Parse the source from a received irc message
+ * @param source Source string, as reported by the server
+ * @param nick Pointer to a string where to return the nick (may not be NULL,
+ * needs to be able to fit an IRC_NICK_LENGTH long string)
+ * @param ident Pointer to a string where to return the ident (may not be
+ * NULL, needs to be able to fit an IRC_IDENT_LENGTH long string)
+ * @param host Pointer to a string where to return the hostname (may not be
+ * NULL, needs to be able to fit an IRC_HOST_LENGTH long string)
+ */
void irc_parse_source(char *source, char *nick, char *ident, char *host) {
- int i, len = strlen(source), pos = 0;
+ int i, pos = 0;
+ size_t len = strlen(source);
unsigned char stage = 0;
for(i = 0; i < len; i++) {
if( stage == 0 && source[i] == '!' ) {
- memcpy(nick, &source[0], min(i,IRC_NICK_LENGTH));
- nick[i] = '\0';
+ safestrncpy(nick, &source[0], min(i + 1, IRC_NICK_LENGTH));
pos = i+1;
stage = 1;
} else if( stage == 1 && source[i] == '@' ) {
- memcpy(ident, &source[pos], min(i - pos,IRC_IDENT_LENGTH));
- ident[i-pos] = '\0';
- memcpy(host, &source[i+1], min(len - i,IRC_HOST_LENGTH));
- host[len] = '\0';
+ safestrncpy(ident, &source[pos], min(i - pos + 1, IRC_IDENT_LENGTH));
+ safestrncpy(host, &source[i+1], min(len - i, IRC_HOST_LENGTH));
break;
}
}
}
+
+/**
+ * Parse a received message from the irc server, and do the appropriate action
+ * for the detected command
+ * @param fd IRC server connection file descriptor
+ * @param str Raw received message
+ */
void irc_parse_sub(int fd, char *str) {
- char source[180], command[60], target[60], message[200];
+ char source[180], command[60], buf1[IRC_MESSAGE_LENGTH], buf2[IRC_MESSAGE_LENGTH];
+ char *target = buf1, *message = buf2;
struct irc_func *func;
- source[0] = command[0] = target[0] = message[0] = '\0';
+ source[0] = command[0] = buf1[0] = buf2[0] = '\0';
if( str[0] == ':' )
str++;
- sscanf(str, "%179s %59s %59s :%199[^\r\n]", source, command, target, message);
+ if (sscanf(str, "%179s %59s %499s :%499[^\r\n]", source, command, buf1, buf2) == 3 && buf1[0] == ':') {
+ // source command :message (i.e. QUIT)
+ message = buf1+1;
+ target = buf2;
+ }
if( command[0] == '\0' )
return;
if( !(func = ircbot->func_search(command)) && !(func = ircbot->func_search(source)) ) {
- //ShowWarning("Unknown command received %s from %s\n",command,source);
+#ifdef IRCBOT_DEBUG
+ ShowWarning("Unknown command received %s from %s\n",command,source);
+#endif // IRCBOT_DEBUG
return;
}
func->func(fd,command,source,target,message);
}
+/**
+ * Send a raw command to the irc server
+ * @param str Command to send
+ */
void irc_send(char *str) {
- int len = strlen(str) + 2;
+ size_t len = strlen(str) + 2;
+ if (len > IRC_MESSAGE_LENGTH-3)
+ len = IRC_MESSAGE_LENGTH-3;
WFIFOHEAD(ircbot->fd, len);
- snprintf((char*)WFIFOP(ircbot->fd,0),200, "%s\r\n", str);
+ snprintf((char*)WFIFOP(ircbot->fd,0),IRC_MESSAGE_LENGTH, "%s\r\n", str);
WFIFOSET(ircbot->fd, len);
}
+/**
+ * Handler for the PING IRC command (send back a PONG)
+ * @see irc_parse_sub
+ */
void irc_pong(int fd, char *cmd, char *source, char *target, char *msg) {
sprintf(send_string, "PONG %s", cmd);
ircbot->send(send_string);
}
-void irc_join(int fd, char *cmd, char *source, char *target, char *msg) {
- if( ircbot->isIn )
- return;
- sprintf(send_string, "JOIN %s", hChSys.irc_channel);
- ircbot->send(send_string);
- ircbot->isIn = true;
+/**
+ * Handler for CTCP commands received via PRIVMSG
+ * @see irc_privmsg
+ */
+void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg) {
+ char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
+
+ source_nick[0] = source_ident[0] = source_host[0] = '\0';
+
+ if( source[0] != '\0' )
+ ircbot->parse_source(source,source_nick,source_ident,source_host);
+
+ if( strcmpi(cmd,"ACTION") == 0 ) {
+ if( ircbot->channel ) {
+ snprintf(send_string, 150, "[ #%s ] * IRC.%s %s *",ircbot->channel->name,source_nick,msg);
+ clif->chsys_msg2(ircbot->channel,send_string);
+ }
+ } else if( strcmpi(cmd,"ERRMSG") == 0 ) {
+ // Ignore it
+ } else if( strcmpi(cmd,"FINGER") == 0 ) {
+ // Ignore it
+ } else if( strcmpi(cmd,"PING") == 0 ) {
+ sprintf(send_string, "NOTICE %s :\001PING %s\001",source_nick,msg);
+ ircbot->send(send_string);
+ } else if( strcmpi(cmd,"TIME") == 0 ) {
+ time_t time_server; // variable for number of seconds (used with time() function)
+ struct tm *datetime; // variable for time in structure ->tm_mday, ->tm_sec, ...
+ char temp[CHAT_SIZE_MAX];
+
+ memset(temp, '\0', sizeof(temp));
+
+ time(&time_server); // get time in seconds since 1/1/1970
+ datetime = localtime(&time_server); // convert seconds in structure
+ // like sprintf, but only for date/time (Sunday, November 02 2003 15:12:52)
+ strftime(temp, sizeof(temp)-1, msg_txt(230), datetime); // Server time (normal time): %A, %B %d %Y %X.
+
+ sprintf(send_string, "NOTICE %s :\001TIME %s\001",source_nick,temp);
+ ircbot->send(send_string);
+ } else if( strcmpi(cmd,"VERSION") == 0 ) {
+ sprintf(send_string, "NOTICE %s :\001VERSION Hercules.ws IRC Bridge\001",source_nick);
+ ircbot->send(send_string);
+#ifdef IRCBOT_DEBUG
+ } else {
+ ShowWarning("Unknown CTCP command received %s (%s) from %s\n",cmd,msg,source);
+#endif // IRCBOT_DEBUG
+ }
}
+/**
+ * Handler for the PRIVMSG IRC command (action depends on the message contents)
+ * @see irc_parse_sub
+ */
void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) {
- if( strcmpi(target,hChSys.irc_nick) == 0 ) {
- if( msg[0] == ':' ) msg++;
- if( strcmpi(msg,"VERSION") == 0 ) {
- char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
-
- source_nick[0] = source_ident[0] = source_host[0] = '\0';
-
- if( source[0] != '\0' )
- ircbot->parse_source(source,source_nick,source_ident,source_host);
-
- sprintf(send_string, "NOTICE %s :Hercules.ws IRC Bridge",source_nick);
- ircbot->send(send_string);
- return;
- }
- } else if( strcmpi(target,hChSys.irc_channel) == 0 ) {
+ if( msg && *msg == '\001' && strlen(msg) > 2 && msg[strlen(msg)-1] == '\001' ) {
+ // CTCP
+ char command[IRC_MESSAGE_LENGTH], message[IRC_MESSAGE_LENGTH];
+ command[0] = message[0] = '\0';
+ sscanf(msg, "\001%499[^\001\r\n ] %499[^\r\n\001]\001", command, message);
+
+ irc_privmsg_ctcp(fd, command, source, target, message);
+#ifdef IRCBOT_DEBUG
+ } else if( strcmpi(target,hChSys.irc_nick) == 0 ) {
+ ShowDebug("irc_privmsg: Received message from %s: '%s'\n", source ? source : "(null)", msg);
+#endif // IRCBOT_DEBUG
+ } else if( msg && strcmpi(target,hChSys.irc_channel) == 0 ) {
char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
source_nick[0] = source_ident[0] = source_host[0] = '\0';
@@ -197,26 +301,110 @@ void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) {
ircbot->parse_source(source,source_nick,source_ident,source_host);
if( ircbot->channel ) {
- snprintf(send_string, 150, "[ #%s ] IRC.%s : %s",ircbot->channel->name,source_nick,msg);
- clif->chsys_msg2(ircbot->channel,send_string);
+ size_t padding_len = strlen(ircbot->channel->name) + strlen(source_nick) + 13;
+ while (1) {
+ snprintf(send_string, 150, "[ #%s ] IRC.%s : %s",ircbot->channel->name,source_nick,msg);
+ clif->chsys_msg2(ircbot->channel,send_string);
+ //break; // Uncomment this line to truncate long messages instead of posting them as multiple lines
+ if (strlen(msg) <= 149 - padding_len)
+ break;
+ msg += 149 - padding_len;
+ }
}
}
}
-void irc_relay (char *name, char *msg) {
+/**
+ * Handler for the JOIN IRC command (notify an in-game channel of users joining
+ * the IRC channel)
+ * @see irc_parse_sub
+ */
+void irc_userjoin(int fd, char *cmd, char *source, char *target, char *msg) {
+ char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
+
+ source_nick[0] = source_ident[0] = source_host[0] = '\0';
+
+ if( source[0] != '\0' )
+ ircbot->parse_source(source,source_nick,source_ident,source_host);
+
+ if( ircbot->channel ) {
+ snprintf(send_string, 150, "[ #%s ] User IRC.%s joined the channel.",ircbot->channel->name,source_nick);
+ clif->chsys_msg2(ircbot->channel,send_string);
+ }
+}
+
+/**
+ * Handler for the PART and QUIT IRC commands (notify an in-game channel of
+ * users leaving the IRC channel)
+ * @see irc_parse_sub
+ */
+void irc_userleave(int fd, char *cmd, char *source, char *target, char *msg) {
+ char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
+
+ source_nick[0] = source_ident[0] = source_host[0] = '\0';
+
+ if( source[0] != '\0' )
+ ircbot->parse_source(source,source_nick,source_ident,source_host);
+
+ if( ircbot->channel ) {
+ if (!strcmpi(cmd, "QUIT"))
+ snprintf(send_string, 150, "[ #%s ] User IRC.%s left the channel. [Quit: %s]",ircbot->channel->name,source_nick,msg);
+ else
+ snprintf(send_string, 150, "[ #%s ] User IRC.%s left the channel. [%s]",ircbot->channel->name,source_nick,msg);
+ clif->chsys_msg2(ircbot->channel,send_string);
+ }
+}
+
+/**
+ * Handler for the NICK IRC commands (notify an in-game channel of users
+ * changing their name while in the IRC channel)
+ * @see irc_parse_sub
+ */
+void irc_usernick(int fd, char *cmd, char *source, char *target, char *msg) {
+ char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
+
+ source_nick[0] = source_ident[0] = source_host[0] = '\0';
+
+ if( source[0] != '\0' )
+ ircbot->parse_source(source,source_nick,source_ident,source_host);
+
+ if( ircbot->channel ) {
+ snprintf(send_string, 150, "[ #%s ] User IRC.%s is now known as IRC.%s",ircbot->channel->name,source_nick,msg);
+ clif->chsys_msg2(ircbot->channel,send_string);
+ }
+}
+
+/**
+ * Relay a chat message to the irc channel the bot is connected to
+ * @param name Sender's name
+ * @param msg Message text
+ */
+void irc_relay(char *name, const char *msg) {
if( !ircbot->isIn )
return;
sprintf(send_string,"PRIVMSG %s :[ %s ] : %s",hChSys.irc_channel,name,msg);
ircbot->send(send_string);
}
-void irc_bot_init(void) {
+
+/**
+ * IRC bot initializer
+ */
+void irc_bot_init(bool minimal) {
+ /// Command handlers
const struct irc_func irc_func_base[] = {
{ "PING" , ircbot->pong },
{ "PRIVMSG", ircbot->privmsg },
+ { "JOIN", ircbot->userjoin },
+ { "QUIT", ircbot->userleave },
+ { "PART", ircbot->userleave },
+ { "NICK", ircbot->usernick },
};
struct irc_func* function;
int i;
+ if (minimal)
+ return;
+
if( !hChSys.irc )
return;
@@ -245,10 +433,13 @@ void irc_bot_init(void) {
ircbot->isIn = false;
ircbot->isOn = false;
- iTimer->add_timer_func_list(ircbot->connect_timer, "irc_connect_timer");
- iTimer->add_timer(iTimer->gettick() + 7000, ircbot->connect_timer, 0, 0);
+ timer->add_func_list(ircbot->connect_timer, "irc_connect_timer");
+ timer->add(timer->gettick() + 7000, ircbot->connect_timer, 0, 0);
}
+/**
+ * IRC bot finalizer
+ */
void irc_bot_final(void) {
int i;
@@ -265,6 +456,9 @@ void irc_bot_final(void) {
aFree(ircbot->funcs.list);
}
+/**
+ * IRC bot interface defaults initializer
+ */
void ircbot_defaults(void) {
ircbot = &irc_bot_s;
@@ -287,6 +481,9 @@ void ircbot_defaults(void) {
ircbot->relay = irc_relay;
ircbot->pong = irc_pong;
- ircbot->join = irc_join;
ircbot->privmsg = irc_privmsg;
+
+ ircbot->userjoin = irc_userjoin;
+ ircbot->userleave = irc_userleave;
+ ircbot->usernick = irc_usernick;
}
diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h
index 911a15b0e..0c26c3cd8 100644
--- a/src/map/irc-bot.h
+++ b/src/map/irc-bot.h
@@ -3,13 +3,16 @@
// Base Author: shennetsind @ http://hercules.ws
-#ifndef _IRC_BOT_H_
-#define _IRC_BOT_H_
+#ifndef MAP_IRC_BOT_H
+#define MAP_IRC_BOT_H
+
+#include "../common/cbasetypes.h"
#define IRC_NICK_LENGTH 40
#define IRC_IDENT_LENGTH 40
#define IRC_HOST_LENGTH 63
#define IRC_FUNC_LENGTH 30
+#define IRC_MESSAGE_LENGTH 500
struct hChSysCh;
@@ -21,9 +24,9 @@ struct irc_func {
struct irc_bot_interface {
int fd;
bool isIn, isOn;
- unsigned int last_try;
+ int64 last_try;
unsigned char fails;
- unsigned long ip;
+ uint32 ip;
unsigned short port;
/* */
struct hChSysCh *channel;
@@ -33,7 +36,7 @@ struct irc_bot_interface {
unsigned int size;
} funcs;
/* */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
/* */
int (*parse) (int fd);
@@ -42,20 +45,22 @@ struct irc_bot_interface {
/* */
struct irc_func* (*func_search) (char* function_name);
/* */
- int (*connect_timer) (int tid, unsigned int tick, int id, intptr_t data);
- int (*identify_timer) (int tid, unsigned int tick, int id, intptr_t data);
- int (*join_timer) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*connect_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*identify_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*join_timer) (int tid, int64 tick, int id, intptr_t data);
/* */
void (*send)(char *str);
- void (*relay) (char *name, char *msg);
+ void (*relay) (char *name, const char *msg);
/* */
void (*pong) (int fd, char *cmd, char *source, char *target, char *msg);
- void (*join) (int fd, char *cmd, char *source, char *target, char *msg);
void (*privmsg) (int fd, char *cmd, char *source, char *target, char *msg);
-} irc_bot_s;
+ void (*userjoin) (int fd, char *cmd, char *source, char *target, char *msg);
+ void (*userleave) (int fd, char *cmd, char *source, char *target, char *msg);
+ void (*usernick) (int fd, char *cmd, char *source, char *target, char *msg);
+};
struct irc_bot_interface *ircbot;
void ircbot_defaults(void);
-#endif /* _IRC_BOT_H_ */
+#endif /* MAP_IRC_BOT_H */
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 859b19aac..0d3146191 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -2,44 +2,49 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/nullpo.h"
-#include "../common/malloc.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
+#define HERCULES_CORE
+
+#include "../config/core.h" // DBPATH, RENEWAL
#include "itemdb.h"
-#include "map.h"
-#include "battle.h" // struct battle_config
-#include "script.h" // item script processing
-#include "pc.h" // W_MUSICAL, W_WHIP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-static struct item_data* itemdb_array[MAX_ITEMDB];
-static DBMap* itemdb_other;// int nameid -> struct item_data*
+#include "battle.h" // struct battle_config
+#include "map.h"
+#include "mob.h" // MAX_MOB_DB
+#include "pc.h" // W_MUSICAL, W_WHIP
+#include "script.h" // item script processing
+#include "../common/conf.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
+#include "../common/utils.h"
-struct item_data dummy_item; //This is the default dummy item used for non-existant items. [Skotlex]
+struct itemdb_interface itemdb_s;
/**
- * Search for item name
+ * Search for item name
* name = item alias, so we should find items aliases first. if not found then look for "jname" (full name)
* @see DBApply
*/
-static int itemdb_searchname_sub(DBKey key, DBData *data, va_list ap)
+int itemdb_searchname_sub(DBKey key, DBData *data, va_list ap)
{
struct item_data *item = DB->data2ptr(data), **dst, **dst2;
char *str;
str=va_arg(ap,char *);
dst=va_arg(ap,struct item_data **);
dst2=va_arg(ap,struct item_data **);
- if(item == &dummy_item) return 0;
+ if (item == &itemdb->dummy) return 0;
//Absolute priority to Aegis code name.
if (*dst != NULL) return 0;
- if( strcmpi(item->name,str)==0 )
+ if ( battle_config.case_sensitive_aegisnames && strcmp(item->name,str) == 0 )
+ *dst=item;
+ else if ( !battle_config.case_sensitive_aegisnames && strcasecmp(item->name,str) == 0 )
*dst=item;
//Second priority to Client displayed name.
@@ -50,22 +55,22 @@ static int itemdb_searchname_sub(DBKey key, DBData *data, va_list ap)
}
/*==========================================
- * Return item data from item name. (lookup)
+ * Return item data from item name. (lookup)
*------------------------------------------*/
-struct item_data* itemdb_searchname(const char *str)
-{
+struct item_data* itemdb_searchname(const char *str) {
struct item_data* item;
struct item_data* item2=NULL;
int i;
- for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
- {
- item = itemdb_array[i];
+ for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) {
+ item = itemdb->array[i];
if( item == NULL )
continue;
// Absolute priority to Aegis code name.
- if( strcasecmp(item->name,str) == 0 )
+ if ( battle_config.case_sensitive_aegisnames && strcmp(item->name,str) == 0 )
+ return item;
+ else if ( !battle_config.case_sensitive_aegisnames && strcasecmp(item->name,str) == 0 )
return item;
//Second priority to Client displayed name.
@@ -74,45 +79,63 @@ struct item_data* itemdb_searchname(const char *str)
}
item = NULL;
- itemdb_other->foreach(itemdb_other,itemdb_searchname_sub,str,&item,&item2);
+ itemdb->other->foreach(itemdb->other,itemdb->searchname_sub,str,&item,&item2);
return item?item:item2;
}
+/* name to item data */
+struct item_data* itemdb_name2id(const char *str) {
+ return strdb_get(itemdb->names,str);
+}
/**
* @see DBMatcher
*/
-static int itemdb_searchname_array_sub(DBKey key, DBData data, va_list ap)
+int itemdb_searchname_array_sub(DBKey key, DBData data, va_list ap)
{
struct item_data *item = DB->data2ptr(&data);
char *str;
str=va_arg(ap,char *);
- if (item == &dummy_item)
+ if (item == &itemdb->dummy)
return 1; //Invalid item.
if(stristr(item->jname,str))
return 0;
- if(stristr(item->name,str))
+ if(battle_config.case_sensitive_aegisnames && strstr(item->name,str))
+ return 0;
+ if(!battle_config.case_sensitive_aegisnames && stristr(item->name,str))
return 0;
return strcmpi(item->jname,str);
}
/*==========================================
* Founds up to N matches. Returns number of matches [Skotlex]
+ * search flag :
+ * 0 - approximate match
+ * 1 - exact match
*------------------------------------------*/
-int itemdb_searchname_array(struct item_data** data, int size, const char *str)
-{
+int itemdb_searchname_array(struct item_data** data, int size, const char *str, int flag) {
struct item_data* item;
int i;
int count=0;
// Search in the array
- for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
+ for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i )
{
- item = itemdb_array[i];
+ item = itemdb->array[i];
if( item == NULL )
continue;
- if( stristr(item->jname,str) || stristr(item->name,str) )
- {
+ if(
+ (!flag
+ && (stristr(item->jname,str)
+ || (battle_config.case_sensitive_aegisnames && strstr(item->name,str))
+ || (!battle_config.case_sensitive_aegisnames && stristr(item->name,str))
+ ))
+ || (flag
+ && (strcmp(item->jname,str) == 0
+ || (battle_config.case_sensitive_aegisnames && strcmp(item->name,str) == 0)
+ || (!battle_config.case_sensitive_aegisnames && strcasecmp(item->name,str) == 0)
+ ))
+ ) {
if( count < size )
data[count] = item;
++count;
@@ -125,45 +148,132 @@ int itemdb_searchname_array(struct item_data** data, int size, const char *str)
DBData *db_data[MAX_SEARCH];
int db_count = 0;
size -= count;
- db_count = itemdb_other->getall(itemdb_other, (DBData**)&db_data, size, itemdb_searchname_array_sub, str);
+ db_count = itemdb->other->getall(itemdb->other, (DBData**)&db_data, size, itemdb->searchname_array_sub, str);
for (i = 0; i < db_count; i++)
data[count++] = DB->data2ptr(db_data[i]);
count += db_count;
}
return count;
}
-
-
-/*==========================================
- * Return a random item id from group. (takes into account % chance giving/tot group)
- *------------------------------------------*/
-int itemdb_searchrandomid(int group)
-{
- if(group<1 || group>=MAX_ITEMGROUP) {
- ShowError("itemdb_searchrandomid: Invalid group id %d\n", group);
+/* [Ind/Hercules] */
+int itemdb_chain_item(unsigned short chain_id, int *rate) {
+ struct item_chain_entry *entry;
+
+ if( chain_id >= itemdb->chain_count ) {
+ ShowError("itemdb_chain_item: unknown chain id %d\n", chain_id);
return UNKNOWN_ITEM_ID;
}
- if (itemgroup_db[group].qty)
- return itemgroup_db[group].nameid[rnd()%itemgroup_db[group].qty];
- ShowError("itemdb_searchrandomid: No item entries for group id %d\n", group);
- return UNKNOWN_ITEM_ID;
+ entry = &itemdb->chains[chain_id].items[ rnd()%itemdb->chains[chain_id].qty ];
+
+ if( rnd()%10000 >= entry->rate )
+ return 0;
+
+ if( rate )
+ rate[0] = entry->rate;
+ return entry->id;
}
+/* [Ind/Hercules] */
+void itemdb_package_item(struct map_session_data *sd, struct item_package *package) {
+ int i = 0, get_count, j, flag;
+
+ for( i = 0; i < package->must_qty; i++ ) {
+ struct item it;
+ memset(&it, 0, sizeof(it));
+ it.nameid = package->must_items[i].id;
+ it.identify = 1;
+
+ if( package->must_items[i].hours ) {
+ it.expire_time = (unsigned int)(time(NULL) + ((package->must_items[i].hours*60)*60));
+ }
+
+ if( package->must_items[i].named ) {
+ it.card[0] = CARD0_FORGE;
+ it.card[1] = 0;
+ it.card[2] = GetWord(sd->status.char_id, 0);
+ it.card[3] = GetWord(sd->status.char_id, 1);
+ }
+
+ if( package->must_items[i].announce )
+ clif->package_announce(sd,package->must_items[i].id,package->id);
+
+ get_count = itemdb->isstackable(package->must_items[i].id) ? package->must_items[i].qty : 1;
+
+ it.amount = get_count == 1 ? 1 : get_count;
+
+ for( j = 0; j < package->must_items[i].qty; j += get_count ) {
+ if ( ( flag = pc->additem(sd, &it, get_count, LOG_TYPE_SCRIPT) ) )
+ clif->additem(sd, 0, 0, flag);
+ }
+ }
+
+ if( package->random_qty ) {
+ for( i = 0; i < package->random_qty; i++ ) {
+ struct item_package_rand_entry *entry;
+
+ entry = &package->random_groups[i].random_list[rnd()%package->random_groups[i].random_qty];
+
+ while( 1 ) {
+ if( rnd()%10000 >= entry->rate ) {
+ entry = entry->next;
+ continue;
+ } else {
+ struct item it;
+ memset(&it, 0, sizeof(it));
+
+ it.nameid = entry->id;
+ it.identify = 1;
+
+ if( entry->hours ) {
+ it.expire_time = (unsigned int)(time(NULL) + ((entry->hours*60)*60));
+ }
+
+ if( entry->named ) {
+ it.card[0] = CARD0_FORGE;
+ it.card[1] = 0;
+ it.card[2] = GetWord(sd->status.char_id, 0);
+ it.card[3] = GetWord(sd->status.char_id, 1);
+ }
+
+ if( entry->announce )
+ clif->package_announce(sd,entry->id,package->id);
+
+ get_count = itemdb->isstackable(entry->id) ? entry->qty : 1;
+
+ it.amount = get_count == 1 ? 1 : get_count;
+
+ for( j = 0; j < entry->qty; j += get_count ) {
+ if ( ( flag = pc->additem(sd, &it, get_count, LOG_TYPE_SCRIPT) ) )
+ clif->additem(sd, 0, 0, flag);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return;
+}
/*==========================================
- * Calculates total item-group related bonuses for the given item
+ * Return a random item id from group. (takes into account % chance giving/tot group)
*------------------------------------------*/
-int itemdb_group_bonus(struct map_session_data* sd, int itemid)
-{
- int bonus = 0, i, j;
- for (i=0; i < MAX_ITEMGROUP; i++) {
- if (!sd->itemgrouphealrate[i])
- continue;
- ARR_FIND( 0, itemgroup_db[i].qty, j, itemgroup_db[i].nameid[j] == itemid );
- if( j < itemgroup_db[i].qty )
- bonus += sd->itemgrouphealrate[i];
- }
- return bonus;
+int itemdb_searchrandomid(struct item_group *group) {
+
+ if (group->qty)
+ return group->nameid[rnd()%group->qty];
+
+ ShowError("itemdb_searchrandomid: No item entries for group id %d\n", group->id);
+ return UNKNOWN_ITEM_ID;
+}
+bool itemdb_in_group(struct item_group *group, int nameid) {
+ int i;
+
+ for( i = 0; i < group->qty; i++ )
+ if( group->nameid[i] == nameid )
+ return true;
+
+ return false;
}
/// Searches for the item_data.
@@ -172,10 +282,10 @@ struct item_data* itemdb_exists(int nameid)
{
struct item_data* item;
- if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
- return itemdb_array[nameid];
- item = (struct item_data*)idb_get(itemdb_other,nameid);
- if( item == &dummy_item )
+ if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb->array) )
+ return itemdb->array[nameid];
+ item = (struct item_data*)idb_get(itemdb->other,nameid);
+ if( item == &itemdb->dummy )
return NULL;// dummy data, doesn't exist
return item;
}
@@ -202,10 +312,10 @@ const char* itemdb_typename(int type)
}
/*==========================================
- * Converts the jobid from the format in itemdb
+ * Converts the jobid from the format in itemdb
* to the format used by the map server. [Skotlex]
*------------------------------------------*/
-static void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask)
+void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask)
{
int i;
bclass[0]= bclass[1]= bclass[2]= 0;
@@ -257,7 +367,10 @@ static void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask)
if (jobmask & 1<<23) //Soul Linker
bclass[2] |= 1<<MAPID_TAEKWON;
if (jobmask & 1<<JOB_GUNSLINGER)
+ {//Rebellion job can equip Gunslinger equips. [Rytech]
bclass[0] |= 1<<MAPID_GUNSLINGER;
+ bclass[1] |= 1<<MAPID_GUNSLINGER;
+ }
if (jobmask & 1<<JOB_NINJA)
{bclass[0] |= 1<<MAPID_NINJA;
bclass[1] |= 1<<MAPID_NINJA;}//Kagerou/Oboro jobs can equip Ninja equips. [Rytech]
@@ -269,21 +382,23 @@ static void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask)
bclass[2] |= 1<<MAPID_GANGSI;
if (jobmask & 1<<29) //Kagerou / Oboro
bclass[1] |= 1<<MAPID_NINJA;
+ if (jobmask & 1<<30) //Rebellion
+ bclass[1] |= 1<<MAPID_GUNSLINGER;
}
-static void create_dummy_data(void)
+void create_dummy_data(void)
{
- memset(&dummy_item, 0, sizeof(struct item_data));
- dummy_item.nameid=500;
- dummy_item.weight=1;
- dummy_item.value_sell=1;
- dummy_item.type=IT_ETC; //Etc item
- safestrncpy(dummy_item.name,"UNKNOWN_ITEM",sizeof(dummy_item.name));
- safestrncpy(dummy_item.jname,"UNKNOWN_ITEM",sizeof(dummy_item.jname));
- dummy_item.view_id=UNKNOWN_ITEM_ID;
+ memset(&itemdb->dummy, 0, sizeof(struct item_data));
+ itemdb->dummy.nameid=500;
+ itemdb->dummy.weight=1;
+ itemdb->dummy.value_sell=1;
+ itemdb->dummy.type=IT_ETC; //Etc item
+ safestrncpy(itemdb->dummy.name,"UNKNOWN_ITEM",sizeof(itemdb->dummy.name));
+ safestrncpy(itemdb->dummy.jname,"UNKNOWN_ITEM",sizeof(itemdb->dummy.jname));
+ itemdb->dummy.view_id=UNKNOWN_ITEM_ID;
}
-static struct item_data* create_item_data(int nameid)
+struct item_data* create_item_data(int nameid)
{
struct item_data *id;
CREATE(id, struct item_data, 1);
@@ -299,19 +414,19 @@ static struct item_data* create_item_data(int nameid)
struct item_data* itemdb_load(int nameid) {
struct item_data *id;
- if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
+ if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb->array) )
{
- id = itemdb_array[nameid];
- if( id == NULL || id == &dummy_item )
- id = itemdb_array[nameid] = create_item_data(nameid);
+ id = itemdb->array[nameid];
+ if( id == NULL || id == &itemdb->dummy )
+ id = itemdb->array[nameid] = itemdb->create_item_data(nameid);
return id;
}
- id = (struct item_data*)idb_get(itemdb_other, nameid);
- if( id == NULL || id == &dummy_item )
+ id = (struct item_data*)idb_get(itemdb->other, nameid);
+ if( id == NULL || id == &itemdb->dummy )
{
- id = create_item_data(nameid);
- idb_put(itemdb_other, nameid, id);
+ id = itemdb->create_item_data(nameid);
+ idb_put(itemdb->other, nameid, id);
}
return id;
}
@@ -322,16 +437,16 @@ struct item_data* itemdb_load(int nameid) {
struct item_data* itemdb_search(int nameid)
{
struct item_data* id;
- if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) )
- id = itemdb_array[nameid];
+ if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb->array) )
+ id = itemdb->array[nameid];
else
- id = (struct item_data*)idb_get(itemdb_other, nameid);
+ id = (struct item_data*)idb_get(itemdb->other, nameid);
if( id == NULL )
{
ShowWarning("itemdb_search: Item ID %d does not exists in the item_db. Using dummy data.\n", nameid);
- id = &dummy_item;
- dummy_item.nameid = nameid;
+ id = &itemdb->dummy;
+ itemdb->dummy.nameid = nameid;
}
return id;
}
@@ -355,8 +470,7 @@ int itemdb_isequip(int nameid)
/*==========================================
* Alternate version of itemdb_isequip
*------------------------------------------*/
-int itemdb_isequip2(struct item_data *data)
-{
+int itemdb_isequip2(struct item_data *data) {
nullpo_ret(data);
switch(data->type) {
case IT_WEAPON:
@@ -407,44 +521,44 @@ int itemdb_isstackable2(struct item_data *data)
* Trade Restriction functions [Skotlex]
*------------------------------------------*/
int itemdb_isdropable_sub(struct item_data *item, int gmlv, int unused) {
- return (item && (!(item->flag.trade_restriction&1) || gmlv >= item->gm_lv_trade_override));
+ return (item && (!(item->flag.trade_restriction&ITR_NODROP) || gmlv >= item->gm_lv_trade_override));
}
int itemdb_cantrade_sub(struct item_data* item, int gmlv, int gmlv2) {
- return (item && (!(item->flag.trade_restriction&2) || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override));
+ return (item && (!(item->flag.trade_restriction&ITR_NOTRADE) || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override));
}
int itemdb_canpartnertrade_sub(struct item_data* item, int gmlv, int gmlv2) {
- return (item && (item->flag.trade_restriction&4 || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override));
+ return (item && (item->flag.trade_restriction&ITR_PARTNEROVERRIDE || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override));
}
int itemdb_cansell_sub(struct item_data* item, int gmlv, int unused) {
- return (item && (!(item->flag.trade_restriction&8) || gmlv >= item->gm_lv_trade_override));
+ return (item && (!(item->flag.trade_restriction&ITR_NOSELLTONPC) || gmlv >= item->gm_lv_trade_override));
}
int itemdb_cancartstore_sub(struct item_data* item, int gmlv, int unused) {
- return (item && (!(item->flag.trade_restriction&16) || gmlv >= item->gm_lv_trade_override));
+ return (item && (!(item->flag.trade_restriction&ITR_NOCART) || gmlv >= item->gm_lv_trade_override));
}
int itemdb_canstore_sub(struct item_data* item, int gmlv, int unused) {
- return (item && (!(item->flag.trade_restriction&32) || gmlv >= item->gm_lv_trade_override));
+ return (item && (!(item->flag.trade_restriction&ITR_NOSTORAGE) || gmlv >= item->gm_lv_trade_override));
}
int itemdb_canguildstore_sub(struct item_data* item, int gmlv, int unused) {
- return (item && (!(item->flag.trade_restriction&64) || gmlv >= item->gm_lv_trade_override));
+ return (item && (!(item->flag.trade_restriction&ITR_NOGSTORAGE) || gmlv >= item->gm_lv_trade_override));
}
int itemdb_canmail_sub(struct item_data* item, int gmlv, int unused) {
- return (item && (!(item->flag.trade_restriction&128) || gmlv >= item->gm_lv_trade_override));
+ return (item && (!(item->flag.trade_restriction&ITR_NOMAIL) || gmlv >= item->gm_lv_trade_override));
}
int itemdb_canauction_sub(struct item_data* item, int gmlv, int unused) {
- return (item && (!(item->flag.trade_restriction&256) || gmlv >= item->gm_lv_trade_override));
+ return (item && (!(item->flag.trade_restriction&ITR_NOAUCTION) || gmlv >= item->gm_lv_trade_override));
}
int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(struct item_data*, int, int))
{
- struct item_data* item_data = itemdb_search(item->nameid);
+ struct item_data* item_data = itemdb->search(item->nameid);
int i;
if (!func(item_data, gmlv, gmlv2))
@@ -455,7 +569,7 @@ int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(stru
for(i = 0; i < item_data->slot; i++) {
if (!item->card[i]) continue;
- if (!func(itemdb_search(item->card[i]), gmlv, gmlv2))
+ if (!func(itemdb->search(item->card[i]), gmlv, gmlv2))
return 0;
}
return 1;
@@ -487,269 +601,589 @@ int itemdb_isidentified2(struct item_data *data) {
}
}
+void itemdb_read_groups(void) {
+ config_t item_group_conf;
+ config_setting_t *itg = NULL, *it = NULL;
+#ifdef RENEWAL
+ const char *config_filename = "db/re/item_group.conf"; // FIXME hardcoded name
+#else
+ const char *config_filename = "db/pre-re/item_group.conf"; // FIXME hardcoded name
+#endif
+ const char *itname;
+ int i = 0, count = 0, c;
+ unsigned int *gsize = NULL;
-/*==========================================
- * Search by name for the override flags available items
- * (Give item another sprite)
- *------------------------------------------*/
-static bool itemdb_read_itemavail(char* str[], int columns, int current)
-{// <nameid>,<sprite>
- int nameid, sprite;
- struct item_data *id;
-
- nameid = atoi(str[0]);
-
- if( ( id = itemdb_exists(nameid) ) == NULL )
- {
- ShowWarning("itemdb_read_itemavail: Invalid item id %d.\n", nameid);
- return false;
- }
-
- sprite = atoi(str[1]);
-
- if( sprite > 0 )
- {
- id->flag.available = 1;
- id->view_id = sprite;
- }
- else
- {
- id->flag.available = 0;
- }
-
- return true;
-}
-
-/*==========================================
- * read item group data
- *------------------------------------------*/
-static unsigned int itemdb_read_itemgroup_sub(const char* filename) {
- FILE *fp;
- char line[1024];
- int ln=0;
- unsigned int count = 0;
- int groupid,j,k,nameid;
- char *str[3],*p;
- char w1[1024], w2[1024];
-
- if( (fp=fopen(filename,"r"))==NULL ){
- ShowError("can't read %s\n", filename);
- return 0;
+ if (libconfig->read_file(&item_group_conf, config_filename)) {
+ ShowError("can't read %s\n", config_filename);
+ return;
}
-
- while(fgets(line, sizeof(line), fp))
- {
- ln++;
- if(line[0]=='/' && line[1]=='/')
- continue;
- if(strstr(line,"import")) {
- if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 &&
- strcmpi(w1, "import") == 0) {
- count += itemdb_read_itemgroup_sub(w2);
- continue;
- }
- }
- memset(str,0,sizeof(str));
- for(j=0,p=line;j<3 && p;j++){
- str[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
- }
- if(str[0]==NULL)
- continue;
- if (j<3) {
- if (j>1) //Or else it barks on blank lines...
- ShowWarning("itemdb_read_itemgroup: Insufficient fields for entry at %s:%d\n", filename, ln);
- continue;
- }
- groupid = atoi(str[0]);
- if (groupid < 0 || groupid >= MAX_ITEMGROUP) {
- ShowWarning("itemdb_read_itemgroup: Invalid group %d in %s:%d\n", groupid, filename, ln);
+
+ gsize = aMalloc( libconfig->setting_length(item_group_conf.root) * sizeof(unsigned int) );
+
+ for(i = 0; i < libconfig->setting_length(item_group_conf.root); i++)
+ gsize[i] = 0;
+
+ i = 0;
+ while( (itg = libconfig->setting_get_elem(item_group_conf.root,i++)) ) {
+ const char *name = config_setting_name(itg);
+
+ if( !itemdb->name2id(name) ) {
+ ShowWarning("itemdb_read_groups: unknown group item '%s', skipping..\n",name);
+ config_setting_remove(item_group_conf.root, name);
+ --i;
continue;
}
- nameid = atoi(str[1]);
- if (!itemdb_exists(nameid)) {
- ShowWarning("itemdb_read_itemgroup: Non-existant item %d in %s:%d\n", nameid, filename, ln);
- continue;
+
+ c = 0;
+ while( (it = libconfig->setting_get_elem(itg,c++)) ) {
+ if( config_setting_is_list(it) )
+ gsize[ i - 1 ] += libconfig->setting_get_int_elem(it,1);
+ else
+ gsize[ i - 1 ] += 1;
}
- k = atoi(str[2]);
- if (itemgroup_db[groupid].qty+k >= MAX_RANDITEM) {
- ShowWarning("itemdb_read_itemgroup: Group %d is full (%d entries) in %s:%d\n", groupid, MAX_RANDITEM, filename, ln);
- continue;
+
+ }
+
+ i = 0;
+ CREATE(itemdb->groups, struct item_group, libconfig->setting_length(item_group_conf.root));
+ itemdb->group_count = (unsigned short)libconfig->setting_length(item_group_conf.root);
+
+ while( (itg = libconfig->setting_get_elem(item_group_conf.root,i++)) ) {
+ struct item_data *data = itemdb->name2id(config_setting_name(itg));
+ int ecount = 0;
+
+ data->group = &itemdb->groups[count];
+
+ itemdb->groups[count].id = data->nameid;
+ itemdb->groups[count].qty = gsize[ count ];
+
+ CREATE(itemdb->groups[count].nameid, unsigned short, gsize[ count ] + 1);
+ c = 0;
+ while( (it = libconfig->setting_get_elem(itg,c++)) ) {
+ int repeat = 1;
+ if( config_setting_is_list(it) ) {
+ itname = libconfig->setting_get_string_elem(it,0);
+ repeat = libconfig->setting_get_int_elem(it,1);
+ } else
+ itname = libconfig->setting_get_string_elem(itg,c - 1);
+
+ if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) {
+ if( !( data = itemdb->exists(atoi(itname+2)) ) )
+ ShowWarning("itemdb_read_groups: unknown item ID '%d' in group '%s'!\n",atoi(itname+2),config_setting_name(itg));
+ } else if( !( data = itemdb->name2id(itname) ) )
+ ShowWarning("itemdb_read_groups: unknown item '%s' in group '%s'!\n",itname,config_setting_name(itg));
+
+ itemdb->groups[count].nameid[ecount] = data ? data->nameid : 0;
+ if( repeat > 1 ) {
+ //memset would be better? I failed to get the following to work though hu
+ //memset(&itemdb->groups[count].nameid[ecount+1],itemdb->groups[count].nameid[ecount],sizeof(itemdb->groups[count].nameid[0])*repeat);
+ int z;
+ for( z = ecount+1; z < ecount+repeat; z++ )
+ itemdb->groups[count].nameid[z] = itemdb->groups[count].nameid[ecount];
+ }
+ ecount += repeat;
}
- for(j=0;j<k;j++)
- itemgroup_db[groupid].nameid[itemgroup_db[groupid].qty++] = nameid;
+
count++;
}
- fclose(fp);
- return count;
-}
-
-static void itemdb_read_itemgroup(void)
-{
- char path[256];
- unsigned int count;
- snprintf(path, 255, "%s/"DBPATH"item_group_db.txt", iMap->db_path);
- memset(&itemgroup_db, 0, sizeof(itemgroup_db));
- count = itemdb_read_itemgroup_sub(path);
- ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, "item_group_db.txt");
- return;
+
+ libconfig->destroy(&item_group_conf);
+ aFree(gsize);
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename);
}
-
-/*==========================================
- * Reads item trade restrictions [Skotlex]
- *------------------------------------------*/
-static bool itemdb_read_itemtrade(char* str[], int columns, int current)
-{// <nameid>,<mask>,<gm level>
- int nameid, flag, gmlv;
- struct item_data *id;
-
- nameid = atoi(str[0]);
-
- if( ( id = itemdb_exists(nameid) ) == NULL )
- {
- //ShowWarning("itemdb_read_itemtrade: Invalid item id %d.\n", nameid);
- //return false;
- // FIXME: item_trade.txt contains items, which are commented in item database.
- return true;
- }
-
- flag = atoi(str[1]);
- gmlv = atoi(str[2]);
-
- if( flag < 0 || flag > 511 ) {//Check range
- ShowWarning("itemdb_read_itemtrade: Invalid trading mask %d for item id %d.\n", flag, nameid);
- return false;
+/* [Ind/Hercules] - HCache for Packages */
+void itemdb_write_cached_packages(const char *config_filename) {
+ FILE *file;
+ unsigned short pcount = itemdb->package_count;
+ unsigned short i;
+
+ if( !(file = HCache->open(config_filename,"wb")) ) {
+ return;
}
- if( gmlv < 1 )
- {
- ShowWarning("itemdb_read_itemtrade: Invalid override GM level %d for item id %d.\n", gmlv, nameid);
- return false;
+
+ // first 2 bytes = package count
+ hwrite(&pcount,sizeof(pcount),1,file);
+
+ for(i = 0; i < pcount; i++) {
+ unsigned short id = itemdb->packages[i].id, random_qty = itemdb->packages[i].random_qty, must_qty = itemdb->packages[i].must_qty;
+ unsigned short c;
+ //into a package, first 2 bytes = id.
+ hwrite(&id,sizeof(id),1,file);
+ //next 2 bytes = must count
+ hwrite(&must_qty,sizeof(must_qty),1,file);
+ //next 2 bytes = random count
+ hwrite(&random_qty,sizeof(random_qty),1,file);
+ //now we loop into must
+ for(c = 0; c < must_qty; c++) {
+ struct item_package_must_entry *entry = &itemdb->packages[i].must_items[c];
+ unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0;
+ //first 2 byte = item id
+ hwrite(&entry->id,sizeof(entry->id),1,file);
+ //next 2 byte = qty
+ hwrite(&entry->qty,sizeof(entry->qty),1,file);
+ //next 2 byte = hours
+ hwrite(&entry->hours,sizeof(entry->hours),1,file);
+ //next 1 byte = announce (1:0)
+ hwrite(&announce,sizeof(announce),1,file);
+ //next 1 byte = named (1:0)
+ hwrite(&named,sizeof(announce),1,file);
+ }
+ //now we loop into random groups
+ for(c = 0; c < random_qty; c++) {
+ struct item_package_rand_group *group = &itemdb->packages[i].random_groups[c];
+ unsigned short group_qty = group->random_qty, h;
+
+ //next 2 bytes = how many entries in this group
+ hwrite(&group_qty,sizeof(group_qty),1,file);
+ //now we loop into the group's list
+ for(h = 0; h < group_qty; h++) {
+ struct item_package_rand_entry *entry = &itemdb->packages[i].random_groups[c].random_list[h];
+ unsigned char announce = entry->announce == 1 ? 1 : 0, named = entry->named == 1 ? 1 : 0;
+ //first 2 byte = item id
+ hwrite(&entry->id,sizeof(entry->id),1,file);
+ //next 2 byte = qty
+ hwrite(&entry->qty,sizeof(entry->qty),1,file);
+ //next 2 byte = rate
+ hwrite(&entry->rate,sizeof(entry->rate),1,file);
+ //next 2 byte = hours
+ hwrite(&entry->hours,sizeof(entry->hours),1,file);
+ //next 1 byte = announce (1:0)
+ hwrite(&announce,sizeof(announce),1,file);
+ //next 1 byte = named (1:0)
+ hwrite(&named,sizeof(announce),1,file);
+ }
+ }
}
-
- id->flag.trade_restriction = flag;
- id->gm_lv_trade_override = gmlv;
-
- return true;
+
+ fclose(file);
+
+ return;
}
+bool itemdb_read_cached_packages(const char *config_filename) {
+ FILE *file;
+ unsigned short pcount;
+ unsigned short i;
-/*==========================================
- * Reads item delay amounts [Paradox924X]
- *------------------------------------------*/
-static bool itemdb_read_itemdelay(char* str[], int columns, int current)
-{// <nameid>,<delay>
- int nameid, delay;
- struct item_data *id;
-
- nameid = atoi(str[0]);
-
- if( ( id = itemdb_exists(nameid) ) == NULL )
- {
- ShowWarning("itemdb_read_itemdelay: Invalid item id %d.\n", nameid);
+ if( !(file = HCache->open(config_filename,"rb")) ) {
return false;
}
+
+ // first 2 bytes = package count
+ hread(&pcount,sizeof(pcount),1,file);
- delay = atoi(str[1]);
+ CREATE(itemdb->packages, struct item_package, pcount);
+ itemdb->package_count = pcount;
- if( delay < 0 )
- {
- ShowWarning("itemdb_read_itemdelay: Invalid delay %d for item id %d.\n", id->delay, nameid);
- return false;
+ for( i = 0; i < pcount; i++ ) {
+ unsigned short id = 0, random_qty = 0, must_qty = 0;
+ struct item_data *pdata;
+ struct item_package *package = &itemdb->packages[i];
+ unsigned short c;
+
+ //into a package, first 2 bytes = id.
+ hread(&id,sizeof(id),1,file);
+ //next 2 bytes = must count
+ hread(&must_qty,sizeof(must_qty),1,file);
+ //next 2 bytes = random count
+ hread(&random_qty,sizeof(random_qty),1,file);
+
+ if( !(pdata = itemdb->exists(id)) )
+ ShowWarning("itemdb_read_cached_packages: unknown package item '%d', skipping..\n",id);
+ else
+ pdata->package = &itemdb->packages[i];
+
+ package->id = id;
+ package->random_qty = random_qty;
+ package->must_qty = must_qty;
+ package->must_items = NULL;
+ package->random_groups = NULL;
+
+ if( package->must_qty ) {
+ CREATE(package->must_items, struct item_package_must_entry, package->must_qty);
+ //now we loop into must
+ for(c = 0; c < package->must_qty; c++) {
+ struct item_package_must_entry *entry = &itemdb->packages[i].must_items[c];
+ unsigned short mid = 0, qty = 0, hours = 0;
+ unsigned char announce = 0, named = 0;
+ struct item_data *data;
+ //first 2 byte = item id
+ hread(&mid,sizeof(mid),1,file);
+ //next 2 byte = qty
+ hread(&qty,sizeof(qty),1,file);
+ //next 2 byte = hours
+ hread(&hours,sizeof(hours),1,file);
+ //next 1 byte = announce (1:0)
+ hread(&announce,sizeof(announce),1,file);
+ //next 1 byte = named (1:0)
+ hread(&named,sizeof(announce),1,file);
+
+ if( !(data = itemdb->exists(mid)) )
+ ShowWarning("itemdb_read_cached_packages: unknown item '%d' in package '%s'!\n",mid,itemdb_name(package->id));
+
+ entry->id = data ? data->nameid : 0;
+ entry->hours = hours;
+ entry->qty = qty;
+ entry->announce = announce ? 1 : 0;
+ entry->named = named ? 1 : 0;
+ }
+ }
+ if( package->random_qty ) {
+ //now we loop into random groups
+ CREATE(package->random_groups, struct item_package_rand_group, package->random_qty);
+ for(c = 0; c < package->random_qty; c++) {
+ unsigned short group_qty = 0, h;
+ struct item_package_rand_entry *prev = NULL;
+
+ //next 2 bytes = how many entries in this group
+ hread(&group_qty,sizeof(group_qty),1,file);
+
+ package->random_groups[c].random_qty = group_qty;
+ CREATE(package->random_groups[c].random_list, struct item_package_rand_entry, package->random_groups[c].random_qty);
+
+ //now we loop into the group's list
+ for(h = 0; h < group_qty; h++) {
+ struct item_package_rand_entry *entry = &itemdb->packages[i].random_groups[c].random_list[h];
+ unsigned short mid = 0, qty = 0, hours = 0, rate = 0;
+ unsigned char announce = 0, named = 0;
+ struct item_data *data;
+
+ if( prev ) prev->next = entry;
+
+ //first 2 byte = item id
+ hread(&mid,sizeof(mid),1,file);
+ //next 2 byte = qty
+ hread(&qty,sizeof(qty),1,file);
+ //next 2 byte = rate
+ hread(&rate,sizeof(rate),1,file);
+ //next 2 byte = hours
+ hread(&hours,sizeof(hours),1,file);
+ //next 1 byte = announce (1:0)
+ hread(&announce,sizeof(announce),1,file);
+ //next 1 byte = named (1:0)
+ hread(&named,sizeof(announce),1,file);
+
+ if( !(data = itemdb->exists(mid)) )
+ ShowWarning("itemdb_read_cached_packages: unknown item '%d' in package '%s'!\n",mid,itemdb_name(package->id));
+
+ entry->id = data ? data->nameid : 0;
+ entry->rate = rate;
+ entry->hours = hours;
+ entry->qty = qty;
+ entry->announce = announce ? 1 : 0;
+ entry->named = named ? 1 : 0;
+
+ prev = entry;
+ }
+ if( prev )
+ prev->next = &itemdb->packages[i].random_groups[c].random_list[0];
+ }
+ }
}
-
- id->delay = delay;
+
+ fclose(file);
+
+ ShowStatus("Done reading '"CL_WHITE"%hu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"' ("CL_GREEN"C"CL_RESET").\n", pcount, config_filename);
return true;
}
-
-/*==================================================================
- * Reads item stacking restrictions
- *----------------------------------------------------------------*/
-static bool itemdb_read_stack(char* fields[], int columns, int current)
-{// <item id>,<stack limit amount>,<type>
- unsigned short nameid, amount;
- unsigned int type;
- struct item_data* id;
-
- nameid = (unsigned short)strtoul(fields[0], NULL, 10);
-
- if( ( id = itemdb_exists(nameid) ) == NULL )
- {
- ShowWarning("itemdb_read_stack: Unknown item id '%hu'.\n", nameid);
- return false;
+void itemdb_read_packages(void) {
+ config_t item_packages_conf;
+ config_setting_t *itg = NULL, *it = NULL, *t = NULL;
+#ifdef RENEWAL
+ const char *config_filename = "db/re/item_packages.conf"; // FIXME hardcoded name
+#else
+ const char *config_filename = "db/pre-re/item_packages.conf"; // FIXME hardcoded name
+#endif
+ const char *itname;
+ int i = 0, count = 0, c = 0, highest_gcount = 0;
+ unsigned int *must = NULL, *random = NULL, *rgroup = NULL, **rgroups = NULL;
+ struct item_package_rand_entry **prev = NULL;
+
+ if( HCache->check(config_filename) ) {
+ if( itemdb->read_cached_packages(config_filename) )
+ return;
}
-
- if( !itemdb_isstackable2(id) )
- {
- ShowWarning("itemdb_read_stack: Item id '%hu' is not stackable.\n", nameid);
- return false;
+
+ if (libconfig->read_file(&item_packages_conf, config_filename)) {
+ ShowError("can't read %s\n", config_filename);
+ return;
}
+
+ must = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int) );
+ random = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int) );
+ rgroup = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int) );
+ rgroups = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int *) );
- amount = (unsigned short)strtoul(fields[1], NULL, 10);
- type = strtoul(fields[2], NULL, 10);
-
- if( !amount )
- {// ignore
- return true;
+
+ for(i = 0; i < libconfig->setting_length(item_packages_conf.root); i++) {
+ must[i] = 0;
+ random[i] = 0;
+ rgroup[i] = 0;
+ rgroups[i] = NULL;
+ }
+
+ /* validate tree, drop poisonous fruits! */
+ i = 0;
+ while( (itg = libconfig->setting_get_elem(item_packages_conf.root,i++)) ) {
+ const char *name = config_setting_name(itg);
+
+ if( !itemdb->name2id(name) ) {
+ ShowWarning("itemdb_read_packages: unknown package item '%s', skipping..\n",name);
+ libconfig->setting_remove(item_packages_conf.root, name);
+ --i;
+ continue;
+ }
+
+ c = 0;
+ while( (it = libconfig->setting_get_elem(itg,c++)) ) {
+ int rval = 0;
+ if( !( t = libconfig->setting_get_member(it, "Random") ) || (rval = libconfig->setting_get_int(t)) < 0 ) {
+ ShowWarning("itemdb_read_packages: invalid 'Random' value (%d) for item '%s' in package '%s', defaulting to must!\n",rval,config_setting_name(it),name);
+ libconfig->setting_remove(it, config_setting_name(it));
+ --c;
+ continue;
+ }
+
+ if( rval == 0 )
+ must[ i - 1 ] += 1;
+ else {
+ random[ i - 1 ] += 1;
+ if( rval > rgroup[i - 1] )
+ rgroup[i - 1] = rval;
+ if( rval > highest_gcount )
+ highest_gcount = rval;
+ }
+ }
}
- id->stack.amount = amount;
- id->stack.inventory = (type&1)!=0;
- id->stack.cart = (type&2)!=0;
- id->stack.storage = (type&4)!=0;
- id->stack.guildstorage = (type&8)!=0;
-
- return true;
-}
-
+ CREATE(prev, struct item_package_rand_entry *, highest_gcount);
+ for(i = 0; i < highest_gcount; i++) {
+ prev[i] = NULL;
+ }
+
+ for(i = 0; i < libconfig->setting_length(item_packages_conf.root); i++ ) {
+ rgroups[i] = aMalloc( rgroup[i] * sizeof(unsigned int) );
+ for( c = 0; c < rgroup[i]; c++ ) {
+ rgroups[i][c] = 0;
+ }
+ }
-/// Reads items allowed to be sold in buying stores
-static bool itemdb_read_buyingstore(char* fields[], int columns, int current)
-{// <nameid>
- int nameid;
- struct item_data* id;
+ /* grab the known sizes */
+ i = 0;
+ while( (itg = libconfig->setting_get_elem(item_packages_conf.root,i++)) ) {
+ c = 0;
+ while( (it = libconfig->setting_get_elem(itg,c++)) ) {
+ int rval = 0;
+ if( ( t = libconfig->setting_get_member(it, "Random")) && ( rval = libconfig->setting_get_int(t) ) > 0 ) {
+ rgroups[i - 1][rval - 1] += 1;
+ }
+ }
+ }
+
+ CREATE(itemdb->packages, struct item_package, libconfig->setting_length(item_packages_conf.root));
+ itemdb->package_count = (unsigned short)libconfig->setting_length(item_packages_conf.root);
+
+ /* write */
+ i = 0;
+ while( (itg = libconfig->setting_get_elem(item_packages_conf.root,i++)) ) {
+ struct item_data *data = itemdb->name2id(config_setting_name(itg));
+ int r = 0, m = 0;
+
+ for(r = 0; r < highest_gcount; r++) {
+ prev[r] = NULL;
+ }
+
+ data->package = &itemdb->packages[count];
+
+ itemdb->packages[count].id = data->nameid;
+ itemdb->packages[count].random_groups = NULL;
+ itemdb->packages[count].must_items = NULL;
+ itemdb->packages[count].random_qty = rgroup[ i - 1 ];
+ itemdb->packages[count].must_qty = must[ i - 1 ];
+
+ if( itemdb->packages[count].random_qty ) {
+ CREATE(itemdb->packages[count].random_groups, struct item_package_rand_group, itemdb->packages[count].random_qty);
+ for( c = 0; c < itemdb->packages[count].random_qty; c++ ) {
+ if( !rgroups[ i - 1 ][c] )
+ ShowError("itemdb_read_packages: package '%s' missing 'Random' field %d! there must not be gaps!\n",config_setting_name(itg),c+1);
+ else
+ CREATE(itemdb->packages[count].random_groups[c].random_list, struct item_package_rand_entry, rgroups[ i - 1 ][c]);
+ itemdb->packages[count].random_groups[c].random_qty = 0;
+ }
+ }
+ if( itemdb->packages[count].must_qty )
+ CREATE(itemdb->packages[count].must_items, struct item_package_must_entry, itemdb->packages[count].must_qty);
+
+ c = 0;
+ while( (it = libconfig->setting_get_elem(itg,c++)) ) {
+ int icount = 1, expire = 0, rate = 10000, gid = 0;
+ bool announce = false, named = false;
+
+ itname = config_setting_name(it);
+
+ if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) {
+ if( !( data = itemdb->exists(atoi(itname+2)) ) )
+ ShowWarning("itemdb_read_packages: unknown item ID '%d' in package '%s'!\n",atoi(itname+2),config_setting_name(itg));
+ } else if( !( data = itemdb->name2id(itname) ) )
+ ShowWarning("itemdb_read_packages: unknown item '%s' in package '%s'!\n",itname,config_setting_name(itg));
+
+ if( ( t = libconfig->setting_get_member(it, "Count")) )
+ icount = libconfig->setting_get_int(t);
+
+ if( ( t = libconfig->setting_get_member(it, "Expire")) )
+ expire = libconfig->setting_get_int(t);
+
+ if( ( t = libconfig->setting_get_member(it, "Rate")) ) {
+ if( (rate = (unsigned short)libconfig->setting_get_int(t)) > 10000 ) {
+ ShowWarning("itemdb_read_packages: invalid rate (%d) for item '%s' in package '%s'!\n",rate,itname,config_setting_name(itg));
+ rate = 10000;
+ }
+ }
- nameid = atoi(fields[0]);
+ if( ( t = libconfig->setting_get_member(it, "Announce")) && libconfig->setting_get_bool(t) )
+ announce = true;
- if( ( id = itemdb_exists(nameid) ) == NULL )
- {
- ShowWarning("itemdb_read_buyingstore: Invalid item id %d.\n", nameid);
- return false;
+ if( ( t = libconfig->setting_get_member(it, "Named")) && libconfig->setting_get_bool(t) )
+ named = true;
+
+ if( !( t = libconfig->setting_get_member(it, "Random") ) ) {
+ ShowWarning("itemdb_read_packages: missing 'Random' field for item '%s' in package '%s', defaulting to must!\n",itname,config_setting_name(itg));
+ gid = 0;
+ } else
+ gid = libconfig->setting_get_int(t);
+
+ if( gid == 0 ) {
+ itemdb->packages[count].must_items[m].id = data ? data->nameid : 0;
+ itemdb->packages[count].must_items[m].qty = icount;
+ itemdb->packages[count].must_items[m].hours = expire;
+ itemdb->packages[count].must_items[m].announce = announce == true ? 1 : 0;
+ itemdb->packages[count].must_items[m].named = named == true ? 1 : 0;
+ m++;
+ } else {
+ int gidx = gid - 1;
+
+ r = itemdb->packages[count].random_groups[gidx].random_qty;
+
+ if( prev[gidx] )
+ prev[gidx]->next = &itemdb->packages[count].random_groups[gidx].random_list[r];
+
+ itemdb->packages[count].random_groups[gidx].random_list[r].id = data ? data->nameid : 0;
+ itemdb->packages[count].random_groups[gidx].random_list[r].qty = icount;
+ if( (itemdb->packages[count].random_groups[gidx].random_list[r].rate = rate) == 10000 ) {
+ ShowWarning("itemdb_read_packages: item '%s' in '%s' has 100%% drop rate!! set this item as 'Random: 0' or other items won't drop!!!\n",itname,config_setting_name(itg));
+ }
+ itemdb->packages[count].random_groups[gidx].random_list[r].hours = expire;
+ itemdb->packages[count].random_groups[gidx].random_list[r].announce = announce == true ? 1 : 0;
+ itemdb->packages[count].random_groups[gidx].random_list[r].named = named == true ? 1 : 0;
+ itemdb->packages[count].random_groups[gidx].random_qty += 1;
+
+ prev[gidx] = &itemdb->packages[count].random_groups[gidx].random_list[r];
+ }
+
+ }
+
+ for(r = 0; r < highest_gcount; r++) {
+ if( prev[r] )
+ prev[r]->next = &itemdb->packages[count].random_groups[r].random_list[0];
+ }
+
+ for( r = 0; r < itemdb->packages[count].random_qty; r++ ) {
+ if( itemdb->packages[count].random_groups[r].random_qty == 1 ) {
+ //item packages don't stop looping until something comes out of them, so if you have only one item in it the drop is guaranteed.
+ ShowWarning("itemdb_read_packages: in '%s' 'Random: %d' group has only 1 random option, drop rate will be 100%%!\n",
+ itemdb_name(itemdb->packages[count].id),r+1);
+ itemdb->packages[count].random_groups[r].random_list[0].rate = 10000;
+ }
+ }
+
+ count++;
}
-
- if( !itemdb_isstackable2(id) )
- {
- ShowWarning("itemdb_read_buyingstore: Non-stackable item id %d cannot be enabled for buying store.\n", nameid);
- return false;
+
+
+ aFree(must);
+ aFree(random);
+ for(i = 0; i < libconfig->setting_length(item_packages_conf.root); i++ ) {
+ aFree(rgroups[i]);
}
+ aFree(rgroups);
+ aFree(rgroup);
+ aFree(prev);
+
+ libconfig->destroy(&item_packages_conf);
- id->flag.buyingstore = true;
-
- return true;
+ if( HCache->enabled )
+ itemdb->write_cached_packages(config_filename);
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename);
}
-/*******************************************
-** Item usage restriction (item_nouse.txt)
-********************************************/
-static bool itemdb_read_nouse(char* fields[], int columns, int current)
-{// <nameid>,<flag>,<override>
- int nameid, flag, override;
- struct item_data* id;
+void itemdb_read_chains(void) {
+ config_t item_chain_conf;
+ config_setting_t *itc = NULL, *entry = NULL;
+#ifdef RENEWAL
+ const char *config_filename = "db/re/item_chain.conf"; // FIXME hardcoded name
+#else
+ const char *config_filename = "db/pre-re/item_chain.conf"; // FIXME hardcoded name
+#endif
+ int i = 0, count = 0;
+
+ if (libconfig->read_file(&item_chain_conf, config_filename)) {
+ ShowError("can't read %s\n", config_filename);
+ return;
+ }
- nameid = atoi(fields[0]);
+ CREATE(itemdb->chains, struct item_chain, libconfig->setting_length(item_chain_conf.root));
+ itemdb->chain_count = (unsigned short)libconfig->setting_length(item_chain_conf.root);
- if( ( id = itemdb_exists(nameid) ) == NULL ) {
- ShowWarning("itemdb_read_nouse: Invalid item id %d.\n", nameid);
- return false;
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = config_filename;
+#endif // ENABLE_CASE_CHECK
+ while( (itc = libconfig->setting_get_elem(item_chain_conf.root,i++)) ) {
+ struct item_data *data = NULL;
+ struct item_chain_entry *prev = NULL;
+ const char *name = config_setting_name(itc);
+ int c = 0;
+
+ script->set_constant2(name,i-1,0);
+ itemdb->chains[count].qty = (unsigned short)libconfig->setting_length(itc);
+
+ CREATE(itemdb->chains[count].items, struct item_chain_entry, libconfig->setting_length(itc));
+
+ while( (entry = libconfig->setting_get_elem(itc,c++)) ) {
+ const char *itname = config_setting_name(entry);
+ if( itname[0] == 'I' && itname[1] == 'D' && strlen(itname) < 8 ) {
+ if( !( data = itemdb->exists(atoi(itname+2)) ) )
+ ShowWarning("itemdb_read_chains: unknown item ID '%d' in chain '%s'!\n",atoi(itname+2),name);
+ } else if( !( data = itemdb->name2id(itname) ) )
+ ShowWarning("itemdb_read_chains: unknown item '%s' in chain '%s'!\n",itname,name);
+
+ if( prev )
+ prev->next = &itemdb->chains[count].items[c - 1];
+
+ itemdb->chains[count].items[c - 1].id = data ? data->nameid : 0;
+ itemdb->chains[count].items[c - 1].rate = data ? libconfig->setting_get_int(entry) : 0;
+
+ prev = &itemdb->chains[count].items[c - 1];
+ }
+
+ if( prev )
+ prev->next = &itemdb->chains[count].items[0];
+
+ count++;
}
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = NULL;
+#endif // ENABLE_CASE_CHECK
- flag = atoi(fields[1]);
- override = atoi(fields[2]);
-
- id->item_usage.flag = flag;
- id->item_usage.override = override;
-
- return true;
+ libconfig->destroy(&item_chain_conf);
+
+ if( !script->get_constant("ITMCHAIN_ORE",&i) )
+ ShowWarning("itemdb_read_chains: failed to find 'ITMCHAIN_ORE' chain to link to cache!\n");
+ else
+ itemdb->chain_cache[ECC_ORE] = i;
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, config_filename);
}
/**
@@ -781,13 +1215,13 @@ void itemdb_read_combos() {
uint32 lines = 0, count = 0;
char line[1024];
- char path[256];
+ char filepath[256];
FILE* fp;
- sprintf(path, "%s/%s", iMap->db_path, DBPATH"item_combo_db.txt");
+ sprintf(filepath, "%s/%s", map->db_path, DBPATH"item_combo_db.txt");
- if ((fp = fopen(path, "r")) == NULL) {
- ShowError("itemdb_read_combos: File not found \"%s\".\n", path);
+ if ((fp = fopen(filepath, "r")) == NULL) {
+ ShowError("itemdb_read_combos: File not found \"%s\".\n", filepath);
return;
}
@@ -809,10 +1243,9 @@ void itemdb_read_combos() {
if (*p == '\0')
continue;// empty line
- if (!strchr(p,','))
- {
+ if (!strchr(p,',')) {
/* is there even a single column? */
- ShowError("itemdb_read_combos: Insufficient columns in line %d of \"%s\", skipping.\n", lines, path);
+ ShowError("itemdb_read_combos: Insufficient columns in line %d of \"%s\", skipping.\n", lines, filepath);
continue;
}
@@ -822,86 +1255,65 @@ void itemdb_read_combos() {
p++;
str[1] = p;
- p = strchr(p,',');
+ p = strchr(p,',');
p++;
if (str[1][0] != '{') {
- ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
+ ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, filepath);
continue;
}
/* no ending key anywhere (missing \}\) */
if ( str[1][strlen(str[1])-1] != '}' ) {
- ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path);
+ ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, filepath);
continue;
} else {
int items[MAX_ITEMS_PER_COMBO];
int v = 0, retcount = 0;
- struct item_data * id = NULL;
- int idx = 0;
+ struct item_combo *combo = NULL;
- if((retcount = itemdb_combo_split_atoi(str[0], items)) < 2) {
- ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, path);
+ if((retcount = itemdb->combo_split_atoi(str[0], items)) < 2) {
+ ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, filepath);
continue;
}
/* validate */
for(v = 0; v < retcount; v++) {
- if( !itemdb_exists(items[v]) ) {
- ShowError("itemdb_read_combos: line %d of \"%s\" contains unknown item ID %d, skipping.\n", lines, path,items[v]);
+ if( !itemdb->exists(items[v]) ) {
+ ShowError("itemdb_read_combos: line %d of \"%s\" contains unknown item ID %d, skipping.\n", lines, filepath,items[v]);
break;
}
}
/* failed at some item */
if( v < retcount )
continue;
-
- id = itemdb_exists(items[0]);
- idx = id->combos_count;
-
- /* first entry, create */
- if( id->combos == NULL ) {
- CREATE(id->combos, struct item_combo*, 1);
- id->combos_count = 1;
- } else {
- RECREATE(id->combos, struct item_combo*, ++id->combos_count);
- }
+ RECREATE(itemdb->combos, struct item_combo*, ++itemdb->combo_count);
- CREATE(id->combos[idx],struct item_combo,1);
+ CREATE(combo, struct item_combo, 1);
- id->combos[idx]->nameid = aMalloc( retcount * sizeof(unsigned short) );
- id->combos[idx]->count = retcount;
- id->combos[idx]->script = parse_script(str[1], path, lines, 0);
- id->combos[idx]->id = count;
- id->combos[idx]->isRef = false;
+ combo->count = retcount;
+ combo->script = script->parse(str[1], filepath, lines, 0, NULL);
+ combo->id = itemdb->combo_count - 1;
/* populate ->nameid field */
for( v = 0; v < retcount; v++ ) {
- id->combos[idx]->nameid[v] = items[v];
+ combo->nameid[v] = items[v];
}
- /* populate the children to refer to this combo */
- for( v = 1; v < retcount; v++ ) {
+ itemdb->combos[itemdb->combo_count - 1] = combo;
+
+ /* populate the items to refer to this combo */
+ for( v = 0; v < retcount; v++ ) {
struct item_data * it;
int index;
- it = itemdb_exists(items[v]);
+ it = itemdb->exists(items[v]);
index = it->combos_count;
- if( it->combos == NULL ) {
- CREATE(it->combos, struct item_combo*, 1);
- it->combos_count = 1;
- } else {
- RECREATE(it->combos, struct item_combo*, ++it->combos_count);
- }
+ RECREATE(it->combos, struct item_combo*, ++it->combos_count);
- CREATE(it->combos[index],struct item_combo,1);
-
- /* we copy previously alloc'd pointers and just set it to reference */
- memcpy(it->combos[index],id->combos[idx],sizeof(struct item_combo));
- /* we flag this way to ensure we don't double-dealloc same data */
- it->combos[index]->isRef = true;
+ it->combos[index] = combo;
}
}
@@ -911,7 +1323,7 @@ void itemdb_read_combos() {
fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"item_combo_db"CL_RESET"'.\n", count);
+ ShowStatus("Done reading '"CL_WHITE"%"PRIu32""CL_RESET"' entries in '"CL_WHITE"item_combo_db"CL_RESET"'.\n", count);
return;
}
@@ -921,7 +1333,7 @@ void itemdb_read_combos() {
/*======================================
* Applies gender restrictions according to settings. [Skotlex]
*======================================*/
-static int itemdb_gendercheck(struct item_data *id)
+int itemdb_gendercheck(struct item_data *id)
{
if (id->nameid == WEDDING_RING_M) //Grom Ring
return 1;
@@ -934,409 +1346,708 @@ static int itemdb_gendercheck(struct item_data *id)
return (battle_config.ignore_items_gender) ? 2 : id->sex;
}
-/**
- * [RRInd]
- * For backwards compatibility, in Renewal mode, MATK from weapons comes from the atk slot
- * We use a ':' delimiter which, if not found, assumes the weapon does not provide any matk.
- **/
-void itemdb_re_split_atoi(char *str, int *atk, int *matk) {
- int i, val[2];
- for (i=0; i<2; i++) {
- if (!str) break;
- val[i] = atoi(str);
- str = strchr(str,':');
- if (str)
- *str++=0;
+/**
+ * Validates an item DB entry and inserts it into the database.
+ * This function is called after preparing the item entry data, and it takes
+ * care of inserting it and cleaning up any remainders of the previous one.
+ *
+ * @param *entry Pointer to the new item_data entry. Ownership is NOT taken,
+ * but the content is modified to reflect the validation.
+ * @param n Ordinal number of the entry, to be displayed in case of
+ * validation errors.
+ * @param *source Source of the entry (table or file name), to be displayed in
+ * case of validation errors.
+ * @return Nameid of the validated entry, or 0 in case of failure.
+ *
+ * Note: This is safe to call if the new entry is a copy of the old one (i.e.
+ * item_db2 inheritance), as it will make sure not to free any scripts still in
+ * use in the new entry.
+ */
+int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
+ struct item_data *item;
+
+ if( entry->nameid <= 0 || entry->nameid >= MAX_ITEMDB ) {
+ ShowWarning("itemdb_validate_entry: Invalid item ID %d in entry %d of '%s', allowed values 0 < ID < %d (MAX_ITEMDB), skipping.\n",
+ entry->nameid, n, source, MAX_ITEMDB);
+ if (entry->script) {
+ script->free_code(entry->script);
+ entry->script = NULL;
+ }
+ if (entry->equip_script) {
+ script->free_code(entry->equip_script);
+ entry->equip_script = NULL;
+ }
+ if (entry->unequip_script) {
+ script->free_code(entry->unequip_script);
+ entry->unequip_script = NULL;
+ }
+ return 0;
}
- if( i == 0 ) {
- *atk = *matk = 0;
- return;//no data found
+
+ if( entry->type < 0 || entry->type == IT_UNKNOWN || entry->type == IT_UNKNOWN2
+ || (entry->type > IT_DELAYCONSUME && entry->type < IT_CASH ) || entry->type >= IT_MAX
+ ) {
+ // catch invalid item types
+ ShowWarning("itemdb_validate_entry: Invalid item type %d for item %d in '%s'. IT_ETC will be used.\n",
+ entry->type, entry->nameid, source);
+ entry->type = IT_ETC;
+ } else if( entry->type == IT_DELAYCONSUME ) {
+ //Items that are consumed only after target confirmation
+ entry->type = IT_USABLE;
+ entry->flag.delay_consume = 1;
}
- if( i == 1 ) {//Single Value, we assume it's the ATK
- *atk = val[0];
- *matk = 0;
- return;
+
+ //When a particular price is not given, we should base it off the other one
+ //(it is important to make a distinction between 'no price' and 0z)
+ if( entry->value_buy < 0 && entry->value_sell < 0 ) {
+ entry->value_buy = entry->value_sell = 0;
+ } else if( entry->value_buy < 0 ) {
+ entry->value_buy = entry->value_sell * 2;
+ } else if( entry->value_sell < 0 ) {
+ entry->value_sell = entry->value_buy / 2;
}
- //We assume we have 2 values.
- *atk = val[0];
- *matk = val[1];
- return;
-}
-/*==========================================
- * processes one itemdb entry
- *------------------------------------------*/
-int itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt) {
- /*
- +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+
- | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
- +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+
- | id | name_english | name_japanese | type | price_buy | price_sell | weight | attack | defence | range | slots | equip_jobs | equip_upper | equip_genders | equip_locations | weapon_level | equip_level | refineable | view | script | equip_script | unequip_script |
- +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+
- */
- int nameid;
- struct item_data* id;
- unsigned char offset = 0;
-
- nameid = atoi(str[0]);
- if( nameid <= 0 ) {
- ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", nameid, line, source);
- return 0;
+ if( entry->value_buy/124. < entry->value_sell/75. ) {
+ ShowWarning("itemdb_validate_entry: Buying/Selling [%d/%d] price of item %d (%s) in '%s' "
+ "allows Zeny making exploit through buying/selling at discounted/overcharged prices!\n",
+ entry->value_buy, entry->value_sell, entry->nameid, entry->jname, source);
}
- //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View
- id = itemdb_load(nameid);
- safestrncpy(id->name, str[1], sizeof(id->name));
- safestrncpy(id->jname, str[2], sizeof(id->jname));
+ if( entry->slot > MAX_SLOTS ) {
+ ShowWarning("itemdb_validate_entry: Item %d (%s) in '%s' specifies %d slots, but the server only supports up to %d. Using %d slots.\n",
+ entry->nameid, entry->jname, source, entry->slot, MAX_SLOTS, MAX_SLOTS);
+ entry->slot = MAX_SLOTS;
+ }
- id->type = atoi(str[3]);
+ if (!entry->equip && itemdb->isequip2(entry)) {
+ ShowWarning("itemdb_validate_entry: Item %d (%s) in '%s' is an equipment with no equip-field! Making it an etc item.\n",
+ entry->nameid, entry->jname, source);
+ entry->type = IT_ETC;
+ }
- if( id->type < 0 || id->type == IT_UNKNOWN || id->type == IT_UNKNOWN2 || ( id->type > IT_DELAYCONSUME && id->type < IT_CASH ) || id->type >= IT_MAX )
- {// catch invalid item types
- ShowWarning("itemdb_parse_dbrow: Invalid item type %d for item %d. IT_ETC will be used.\n", id->type, nameid);
- id->type = IT_ETC;
+ if (entry->flag.trade_restriction < 0 || entry->flag.trade_restriction > ITR_ALL) {
+ ShowWarning("itemdb_validate_entry: Invalid trade restriction flag 0x%x for item %d (%s) in '%s', defaulting to none.\n",
+ entry->flag.trade_restriction, entry->nameid, entry->jname, source);
+ entry->flag.trade_restriction = ITR_NONE;
}
- if (id->type == IT_DELAYCONSUME)
- { //Items that are consumed only after target confirmation
- id->type = IT_USABLE;
- id->flag.delay_consume = 1;
- } else //In case of an itemdb reload and the item type changed.
- id->flag.delay_consume = 0;
+ if (entry->gm_lv_trade_override < 0 || entry->gm_lv_trade_override > 100) {
+ ShowWarning("itemdb_validate_entry: Invalid trade-override GM level %d for item %d (%s) in '%s', defaulting to none.\n",
+ entry->gm_lv_trade_override, entry->nameid, entry->jname, source);
+ entry->gm_lv_trade_override = 0;
+ }
+ if (entry->gm_lv_trade_override == 0) {
+ // Default value if none or an ivalid one was specified
+ entry->gm_lv_trade_override = 100;
+ }
- //When a particular price is not given, we should base it off the other one
- //(it is important to make a distinction between 'no price' and 0z)
- if ( str[4][0] )
- id->value_buy = atoi(str[4]);
- else
- id->value_buy = atoi(str[5]) * 2;
+ if (entry->item_usage.flag > INR_ALL) {
+ ShowWarning("itemdb_validate_entry: Invalid nouse flag 0x%x for item %d (%s) in '%s', defaulting to none.\n",
+ entry->item_usage.flag, entry->nameid, entry->jname, source);
+ entry->item_usage.flag = INR_NONE;
+ }
- if ( str[5][0] )
- id->value_sell = atoi(str[5]);
- else
- id->value_sell = id->value_buy / 2;
- /*
- if ( !str[4][0] && !str[5][0])
- {
- ShowWarning("itemdb_parse_dbrow: No buying/selling price defined for item %d (%s), using 20/10z\n", nameid, id->jname);
- id->value_buy = 20;
- id->value_sell = 10;
- } else
- */
- if (id->value_buy/124. < id->value_sell/75.)
- ShowWarning("itemdb_parse_dbrow: Buying/Selling [%d/%d] price of item %d (%s) allows Zeny making exploit through buying/selling at discounted/overcharged prices!\n",
- id->value_buy, id->value_sell, nameid, id->jname);
-
- id->weight = atoi(str[6]);
-#ifdef RENEWAL
- if( iMap->db_use_sqldbs ) {
- id->atk = atoi(str[7]);
- id->matk = atoi(str[8]);
- offset += 1;
- } else
- itemdb_re_split_atoi(str[7],&id->atk,&id->matk);
-#else
- id->atk = atoi(str[7]);
-#endif
- id->def = atoi(str[8+offset]);
- id->range = atoi(str[9+offset]);
- id->slot = atoi(str[10+offset]);
+ if (entry->item_usage.override > 100) {
+ ShowWarning("itemdb_validate_entry: Invalid nouse-override GM level %d for item %d (%s) in '%s', defaulting to none.\n",
+ entry->item_usage.override, entry->nameid, entry->jname, source);
+ entry->item_usage.override = 0;
+ }
+ if (entry->item_usage.override == 0) {
+ // Default value if none or an ivalid one was specified
+ entry->item_usage.override = 100;
+ }
- if (id->slot > MAX_SLOTS) {
- ShowWarning("itemdb_parse_dbrow: Item %d (%s) specifies %d slots, but the server only supports up to %d. Using %d slots.\n", nameid, id->jname, id->slot, MAX_SLOTS, MAX_SLOTS);
- id->slot = MAX_SLOTS;
+ if (entry->stack.amount > 0 && !itemdb->isstackable2(entry)) {
+ ShowWarning("itemdb_validate_entry: Item %d (%s) of type %d is not stackable, ignoring stack settings in '%s'.\n",
+ entry->nameid, entry->jname, entry->type, source);
+ memset(&entry->stack, '\0', sizeof(entry->stack));
}
- itemdb_jobid2mapid(id->class_base, (unsigned int)strtoul(str[11+offset],NULL,0));
- id->class_upper = atoi(str[12+offset]);
- id->sex = atoi(str[13+offset]);
- id->equip = atoi(str[14+offset]);
+ entry->wlv = cap_value(entry->wlv, REFINE_TYPE_ARMOR, REFINE_TYPE_MAX);
- if (!id->equip && itemdb_isequip2(id)) {
- ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname);
- id->type = IT_ETC;
- }
+ if( !entry->elvmax )
+ entry->elvmax = MAX_LEVEL;
+ else if( entry->elvmax < entry->elv )
+ entry->elvmax = entry->elv;
- id->wlv = cap_value(atoi(str[15+offset]), REFINE_TYPE_ARMOR, REFINE_TYPE_MAX);
-#ifdef RENEWAL
- if( iMap->db_use_sqldbs ) {
- id->elv = atoi(str[16+offset]);
- id->elvmax = atoi(str[17+offset]);
- offset += 1;
- } else
- itemdb_re_split_atoi(str[16],&id->elv,&id->elvmax);
-#else
- id->elv = atoi(str[16]);
-#endif
- id->flag.no_refine = atoi(str[17+offset]) ? 0 : 1; //FIXME: verify this
- id->look = atoi(str[18+offset]);
+ if( entry->type != IT_ARMOR && entry->type != IT_WEAPON && !entry->flag.no_refine )
+ entry->flag.no_refine = 1;
- id->flag.available = 1;
- id->view_id = 0;
- id->sex = itemdb_gendercheck(id); //Apply gender filtering.
+ if (entry->flag.available != 1) {
+ entry->flag.available = 1;
+ entry->view_id = 0;
+ }
+
+ entry->sex = itemdb->gendercheck(entry); //Apply gender filtering.
- if (id->script) {
- script_free_code(id->script);
- id->script = NULL;
+ // Validated. Finally insert it
+ item = itemdb->load(entry->nameid);
+
+ if (item->script && item->script != entry->script) { // Don't free if it's inheriting the same script
+ script->free_code(item->script);
+ item->script = NULL;
}
- if (id->equip_script) {
- script_free_code(id->equip_script);
- id->equip_script = NULL;
+ if (item->equip_script && item->equip_script != entry->equip_script) { // Don't free if it's inheriting the same script
+ script->free_code(item->equip_script);
+ item->equip_script = NULL;
}
- if (id->unequip_script) {
- script_free_code(id->unequip_script);
- id->unequip_script = NULL;
+ if (item->unequip_script && item->unequip_script != entry->unequip_script) { // Don't free if it's inheriting the same script
+ script->free_code(item->unequip_script);
+ item->unequip_script = NULL;
}
- if (*str[19+offset])
- id->script = parse_script(str[19+offset], source, line, scriptopt);
- if (*str[20+offset])
- id->equip_script = parse_script(str[20+offset], source, line, scriptopt);
- if (*str[21+offset])
- id->unequip_script = parse_script(str[21+offset], source, line, scriptopt);
+ *item = *entry;
+ return item->nameid;
+}
+
+/**
+ * Processes one itemdb entry from the sql backend, loading and inserting it
+ * into the item database.
+ *
+ * @param *handle MySQL connection handle. It is expected to have data
+ * available (i.e. already queried) and it won't be freed (it
+ * is care of the caller to do so)
+ * @param n Ordinal number of the entry, to be displayed in case of
+ * validation errors.
+ * @param *source Source of the entry (table name), to be displayed in case of
+ * validation errors.
+ * @return Nameid of the validated entry, or 0 in case of failure.
+ */
+int itemdb_readdb_sql_sub(Sql *handle, int n, const char *source) {
+ struct item_data id = { 0 };
+ char *data = NULL;
+
+ /*
+ * `id` smallint(5) unsigned NOT NULL DEFAULT '0'
+ * `name_english` varchar(50) NOT NULL DEFAULT ''
+ * `name_japanese` varchar(50) NOT NULL DEFAULT ''
+ * `type` tinyint(2) unsigned NOT NULL DEFAULT '0'
+ * `price_buy` mediumint(10) DEFAULT NULL
+ * `price_sell` mediumint(10) DEFAULT NULL
+ * `weight` smallint(5) unsigned DEFAULT NULL
+ * `atk` smallint(5) unsigned DEFAULT NULL
+ * `matk` smallint(5) unsigned DEFAULT NULL
+ * `defence` smallint(5) unsigned DEFAULT NULL
+ * `range` tinyint(2) unsigned DEFAULT NULL
+ * `slots` tinyint(2) unsigned DEFAULT NULL
+ * `equip_jobs` int(12) unsigned DEFAULT NULL
+ * `equip_upper` tinyint(8) unsigned DEFAULT NULL
+ * `equip_genders` tinyint(2) unsigned DEFAULT NULL
+ * `equip_locations` smallint(4) unsigned DEFAULT NULL
+ * `weapon_level` tinyint(2) unsigned DEFAULT NULL
+ * `equip_level_min` smallint(5) unsigned DEFAULT NULL
+ * `equip_level_max` smallint(5) unsigned DEFAULT NULL
+ * `refineable` tinyint(1) unsigned DEFAULT NULL
+ * `view` smallint(3) unsigned DEFAULT NULL
+ * `bindonequip` tinyint(1) unsigned DEFAULT NULL
+ * `buyingstore` tinyint(1) NOT NULL DEFAULT NULL
+ * `delay` mediumint(9) NOT NULL DEFAULT NULL
+ * `trade_flag` smallint(4) NOT NULL DEFAULT NULL
+ * `trade_group` smallint(4) NOT NULL DEFAULT NULL
+ * `nouse_flag` smallint(4) NOT NULL DEFAULT NULL
+ * `nouse_group` smallint(4) NOT NULL DEFAULT NULL
+ * `stack_amount` mediumint(6) NOT NULL DEFAULT NULL
+ * `stack_flag` smallint(2) NOT NULL DEFAULT NULL
+ * `sprite` mediumint(6) NOT NULL DEFAULT NULL
+ * `script` text
+ * `equip_script` text
+ * `unequip_script` text
+ */
+ SQL->GetData(handle, 0, &data, NULL); id.nameid = (uint16)atoi(data);
+ SQL->GetData(handle, 1, &data, NULL); safestrncpy(id.name, data, sizeof(id.name));
+ SQL->GetData(handle, 2, &data, NULL); safestrncpy(id.jname, data, sizeof(id.jname));
+ SQL->GetData(handle, 3, &data, NULL); id.type = atoi(data);
+ SQL->GetData(handle, 4, &data, NULL); id.value_buy = data ? atoi(data) : -1; // Using invalid price -1 when missing, it'll be validated later
+ SQL->GetData(handle, 5, &data, NULL); id.value_sell = data ? atoi(data) : -1;
+ SQL->GetData(handle, 6, &data, NULL); id.weight = data ? atoi(data) : 0;
+ SQL->GetData(handle, 7, &data, NULL); id.atk = data ? atoi(data) : 0;
+ SQL->GetData(handle, 8, &data, NULL); id.matk = data ? atoi(data) : 0;
+ SQL->GetData(handle, 9, &data, NULL); id.def = data ? atoi(data) : 0;
+ SQL->GetData(handle, 10, &data, NULL); id.range = data ? atoi(data) : 0;
+ SQL->GetData(handle, 11, &data, NULL); id.slot = data ? atoi(data) : 0;
+ SQL->GetData(handle, 12, &data, NULL); itemdb->jobid2mapid(id.class_base, data ? (unsigned int)strtoul(data,NULL,0) : UINT_MAX);
+ SQL->GetData(handle, 13, &data, NULL); id.class_upper = data ? (unsigned int)atoi(data) : ITEMUPPER_ALL;
+ SQL->GetData(handle, 14, &data, NULL); id.sex = data ? atoi(data) : 2;
+ SQL->GetData(handle, 15, &data, NULL); id.equip = data ? atoi(data) : 0;
+ SQL->GetData(handle, 16, &data, NULL); id.wlv = data ? atoi(data) : 0;
+ SQL->GetData(handle, 17, &data, NULL); id.elv = data ? atoi(data) : 0;
+ SQL->GetData(handle, 18, &data, NULL); id.elvmax = data ? atoi(data) : 0;
+ SQL->GetData(handle, 19, &data, NULL); id.flag.no_refine = data && atoi(data) ? 0 : 1;
+ SQL->GetData(handle, 20, &data, NULL); id.look = data ? atoi(data) : 0;
+ SQL->GetData(handle, 21, &data, NULL); id.flag.bindonequip = data && atoi(data) ? 1 : 0;
+ SQL->GetData(handle, 22, &data, NULL); id.flag.buyingstore = data && atoi(data) ? 1 : 0;
+ SQL->GetData(handle, 23, &data, NULL); id.delay = data ? atoi(data) : 0;
+ SQL->GetData(handle, 24, &data, NULL); id.flag.trade_restriction = data ? atoi(data) : ITR_NONE;
+ SQL->GetData(handle, 25, &data, NULL); id.gm_lv_trade_override = data ? atoi(data) : 0;
+ SQL->GetData(handle, 26, &data, NULL); id.item_usage.flag = data ? atoi(data) : INR_NONE;
+ SQL->GetData(handle, 27, &data, NULL); id.item_usage.override = data ? atoi(data) : 0;
+ SQL->GetData(handle, 28, &data, NULL); id.stack.amount = data ? atoi(data) : 0;
+ SQL->GetData(handle, 29, &data, NULL);
+ if (data) {
+ int stack_flag = atoi(data);
+ id.stack.inventory = (stack_flag&1)!=0;
+ id.stack.cart = (stack_flag&2)!=0;
+ id.stack.storage = (stack_flag&4)!=0;
+ id.stack.guildstorage = (stack_flag&8)!=0;
+ }
+ SQL->GetData(handle, 30, &data, NULL);
+ if (data) {
+ id.view_id = atoi(data);
+ if (id.view_id)
+ id.flag.available = 1;
+ }
+ SQL->GetData(handle, 31, &data, NULL); id.script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ SQL->GetData(handle, 32, &data, NULL); id.equip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ SQL->GetData(handle, 33, &data, NULL); id.unequip_script = data && *data ? script->parse(data, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
- return id->nameid;
+ return itemdb->validate_entry(&id, n, source);
}
-/*==========================================
- * Reading item from item db
- * item_db2 overwriting item_db
- *------------------------------------------*/
-static int itemdb_readdb(void)
-{
- const char* filename[] = {
- DBPATH"item_db.txt",
- "item_db2.txt" };
+/**
+ * Processes one itemdb entry from the sql backend, loading and inserting it
+ * into the item database.
+ *
+ * @param *it Libconfig setting entry. It is expected to be valid and it
+ * won't be freed (it is care of the caller to do so if
+ * necessary)
+ * @param n Ordinal number of the entry, to be displayed in case of
+ * validation errors.
+ * @param *source Source of the entry (file name), to be displayed in case of
+ * validation errors.
+ * @return Nameid of the validated entry, or 0 in case of failure.
+ */
+int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) {
+ struct item_data id = { 0 };
+ config_setting_t *t = NULL;
+ const char *str = NULL;
+ int i32 = 0;
+ bool inherit = false;
- int fi;
+ /*
+ * // Mandatory fields
+ * Id: ID
+ * AegisName: "Aegis_Name"
+ * Name: "Item Name"
+ * // Optional fields
+ * Type: Item Type
+ * Buy: Buy Price
+ * Sell: Sell Price
+ * Weight: Item Weight
+ * Atk: Attack
+ * Matk: Attack
+ * Def: Defense
+ * Range: Attack Range
+ * Slots: Slots
+ * Job: Job mask
+ * Upper: Upper mask
+ * Gender: Gender
+ * Loc: Equip location
+ * WeaponLv: Weapon Level
+ * EquipLv: Equip required level or [min, max]
+ * Refine: Refineable
+ * View: View ID
+ * BindOnEquip: (true or false)
+ * BuyingStore: (true or false)
+ * Delay: Delay to use item
+ * Trade: {
+ * override: Group to override
+ * nodrop: (true or false)
+ * notrade: (true or false)
+ * partneroverride: (true or false)
+ * noselltonpc: (true or false)
+ * nocart: (true or false)
+ * nostorage: (true or false)
+ * nogstorage: (true or false)
+ * nomail: (true or false)
+ * noauction: (true or false)
+ * }
+ * Nouse: {
+ * override: Group to override
+ * sitting: (true or false)
+ * }
+ * Stack: [Stackable Amount, Stack Type]
+ * Sprite: SpriteID
+ * Script: <"
+ * Script
+ * (it can be multi-line)
+ * ">
+ * OnEquipScript: <" OnEquip Script ">
+ * OnUnequipScript: <" OnUnequip Script ">
+ * Inherit: inherit or override
+ */
+ if( !libconfig->setting_lookup_int(it, "Id", &i32) ) {
+ ShowWarning("itemdb_readdb_libconfig_sub: Invalid or missing id in \"%s\", entry #%d, skipping.\n", source, n);
+ return 0;
+ }
+ id.nameid = (uint16)i32;
- for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) {
- uint32 lines = 0, count = 0;
- char line[1024];
+ if( (t = libconfig->setting_get_member(it, "Inherit")) && (inherit = libconfig->setting_get_bool(t)) ) {
+ if( !itemdb->exists(id.nameid) ) {
+ ShowWarning("itemdb_readdb_libconfig_sub: Trying to inherit nonexistent item %d, default values will be used instead.\n", id.nameid);
+ inherit = false;
+ } else {
+ // Use old entry as default
+ struct item_data *old_entry = itemdb->load(id.nameid);
+ memcpy(&id, old_entry, sizeof(struct item_data));
+ }
+ }
- char path[256];
- FILE* fp;
+ if( !libconfig->setting_lookup_string(it, "AegisName", &str) || !*str ) {
+ if( !inherit ) {
+ ShowWarning("itemdb_readdb_libconfig_sub: Missing AegisName in item %d of \"%s\", skipping.\n", id.nameid, source);
+ return 0;
+ }
+ } else {
+ safestrncpy(id.name, str, sizeof(id.name));
+ }
- sprintf(path, "%s/%s", iMap->db_path, filename[fi]);
- fp = fopen(path, "r");
- if( fp == NULL ) {
- ShowWarning("itemdb_readdb: File not found \"%s\", skipping.\n", path);
- continue;
+ if( !libconfig->setting_lookup_string(it, "Name", &str) || !*str ) {
+ if( !inherit ) {
+ ShowWarning("itemdb_readdb_libconfig_sub: Missing Name in item %d of \"%s\", skipping.\n", id.nameid, source);
+ return 0;
}
+ } else {
+ safestrncpy(id.jname, str, sizeof(id.jname));
+ }
- // process rows one by one
- while(fgets(line, sizeof(line), fp))
- {
- char *str[32], *p;
- int i;
- lines++;
- if(line[0] == '/' && line[1] == '/')
- continue;
- memset(str, 0, sizeof(str));
-
- p = line;
- while( ISSPACE(*p) )
- ++p;
- if( *p == '\0' )
- continue;// empty line
- for( i = 0; i < 19; ++i )
- {
- str[i] = p;
- p = strchr(p,',');
- if( p == NULL )
- break;// comma not found
- *p = '\0';
- ++p;
+ if( libconfig->setting_lookup_int(it, "Type", &i32) )
+ id.type = i32;
+ else if( !inherit )
+ id.type = IT_UNKNOWN;
+
+ if( libconfig->setting_lookup_int(it, "Buy", &i32) )
+ id.value_buy = i32;
+ else if( !inherit )
+ id.value_buy = -1;
+ if( libconfig->setting_lookup_int(it, "Sell", &i32) )
+ id.value_sell = i32;
+ else if( !inherit )
+ id.value_sell = -1;
+
+ if( libconfig->setting_lookup_int(it, "Weight", &i32) && i32 >= 0 )
+ id.weight = i32;
+
+ if( libconfig->setting_lookup_int(it, "Atk", &i32) && i32 >= 0 )
+ id.atk = i32;
+
+ if( libconfig->setting_lookup_int(it, "Matk", &i32) && i32 >= 0 )
+ id.matk = i32;
+
+ if( libconfig->setting_lookup_int(it, "Def", &i32) && i32 >= 0 )
+ id.def = i32;
+
+ if( libconfig->setting_lookup_int(it, "Range", &i32) && i32 >= 0 )
+ id.range = i32;
+
+ if( libconfig->setting_lookup_int(it, "Slots", &i32) && i32 >= 0 )
+ id.slot = i32;
+
+ if( libconfig->setting_lookup_int(it, "Job", &i32) ) // This is an unsigned value, do not check for >= 0
+ itemdb->jobid2mapid(id.class_base, (unsigned int)i32);
+ else if( !inherit )
+ itemdb->jobid2mapid(id.class_base, UINT_MAX);
+
+ if( libconfig->setting_lookup_int(it, "Upper", &i32) && i32 >= 0 )
+ id.class_upper = (unsigned int)i32;
+ else if( !inherit )
+ id.class_upper = ITEMUPPER_ALL;
+
+ if( libconfig->setting_lookup_int(it, "Gender", &i32) && i32 >= 0 )
+ id.sex = i32;
+ else if( !inherit )
+ id.sex = 2;
+
+ if( libconfig->setting_lookup_int(it, "Loc", &i32) && i32 >= 0 )
+ id.equip = i32;
+
+ if( libconfig->setting_lookup_int(it, "WeaponLv", &i32) && i32 >= 0 )
+ id.wlv = i32;
+
+ if( (t = libconfig->setting_get_member(it, "EquipLv")) ) {
+ if( config_setting_is_aggregate(t) ) {
+ if( libconfig->setting_length(t) >= 2 )
+ id.elvmax = libconfig->setting_get_int_elem(t, 1);
+ if( libconfig->setting_length(t) >= 1 )
+ id.elv = libconfig->setting_get_int_elem(t, 0);
+ } else {
+ id.elv = libconfig->setting_get_int(t);
+ }
+ }
+
+ if( (t = libconfig->setting_get_member(it, "Refine")) )
+ id.flag.no_refine = libconfig->setting_get_bool(t) ? 0 : 1;
+
+ if( libconfig->setting_lookup_int(it, "View", &i32) && i32 >= 0 )
+ id.look = i32;
+
+ if( (t = libconfig->setting_get_member(it, "BindOnEquip")) )
+ id.flag.bindonequip = libconfig->setting_get_bool(t) ? 1 : 0;
+
+ if ( (t = libconfig->setting_get_member(it, "BuyingStore")) )
+ id.flag.buyingstore = libconfig->setting_get_bool(t) ? 1 : 0;
+
+ if (libconfig->setting_lookup_int(it, "Delay", &i32) && i32 >= 0)
+ id.delay = i32;
+
+ if ( (t = libconfig->setting_get_member(it, "Trade")) ) {
+ if (config_setting_is_group(t)) {
+ config_setting_t *tt = NULL;
+
+ if ((tt = libconfig->setting_get_member(t, "override"))) {
+ id.gm_lv_trade_override = libconfig->setting_get_int(tt);
}
- if( p == NULL )
- {
- ShowError("itemdb_readdb: Insufficient columns in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
- continue;
+ if ((tt = libconfig->setting_get_member(t, "nodrop"))) {
+ id.flag.trade_restriction &= ~ITR_NODROP;
+ if (libconfig->setting_get_bool(tt))
+ id.flag.trade_restriction |= ITR_NODROP;
}
- // Script
- if( *p != '{' )
- {
- ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
- continue;
+ if ((tt = libconfig->setting_get_member(t, "notrade"))) {
+ id.flag.trade_restriction &= ~ITR_NOTRADE;
+ if (libconfig->setting_get_bool(tt))
+ id.flag.trade_restriction |= ITR_NOTRADE;
}
- str[19] = p;
- p = strstr(p+1,"},");
- if( p == NULL )
- {
- ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
- continue;
+
+ if ((tt = libconfig->setting_get_member(t, "partneroverride"))) {
+ id.flag.trade_restriction &= ~ITR_PARTNEROVERRIDE;
+ if (libconfig->setting_get_bool(tt))
+ id.flag.trade_restriction |= ITR_PARTNEROVERRIDE;
}
- p[1] = '\0';
- p += 2;
- // OnEquip_Script
- if( *p != '{' )
- {
- ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
- continue;
+ if ((tt = libconfig->setting_get_member(t, "noselltonpc"))) {
+ id.flag.trade_restriction &= ~ITR_NOSELLTONPC;
+ if (libconfig->setting_get_bool(tt))
+ id.flag.trade_restriction |= ITR_NOSELLTONPC;
}
- str[20] = p;
- p = strstr(p+1,"},");
- if( p == NULL )
- {
- ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
- continue;
+
+ if ((tt = libconfig->setting_get_member(t, "nocart"))) {
+ id.flag.trade_restriction &= ~ITR_NOCART;
+ if (libconfig->setting_get_bool(tt))
+ id.flag.trade_restriction |= ITR_NOCART;
}
- p[1] = '\0';
- p += 2;
- // OnUnequip_Script (last column)
- if( *p != '{' )
- {
- ShowError("itemdb_readdb: Invalid format (OnUnequip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
- continue;
+ if ((tt = libconfig->setting_get_member(t, "nostorage"))) {
+ id.flag.trade_restriction &= ~ITR_NOSTORAGE;
+ if (libconfig->setting_get_bool(tt))
+ id.flag.trade_restriction |= ITR_NOSTORAGE;
}
- str[21] = p;
-
- if ( str[21][strlen(str[21])-2] != '}' ) {
- /* lets count to ensure it's not something silly e.g. a extra space at line ending */
- int v, lcurly = 0, rcurly = 0;
-
- for( v = 0; v < strlen(str[21]); v++ ) {
- if( str[21][v] == '{' )
- lcurly++;
- else if ( str[21][v] == '}' )
- rcurly++;
- }
-
- if( lcurly != rcurly ) {
- ShowError("itemdb_readdb: Mismatching curly braces in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0]));
- continue;
- }
+
+ if ((tt = libconfig->setting_get_member(t, "nogstorage"))) {
+ id.flag.trade_restriction &= ~ITR_NOGSTORAGE;
+ if (libconfig->setting_get_bool(tt))
+ id.flag.trade_restriction |= ITR_NOGSTORAGE;
}
- if (!itemdb->parse_dbrow(str, path, lines, 0))
- continue;
-
- count++;
+ if ((tt = libconfig->setting_get_member(t, "nomail"))) {
+ id.flag.trade_restriction &= ~ITR_NOMAIL;
+ if (libconfig->setting_get_bool(tt))
+ id.flag.trade_restriction |= ITR_NOMAIL;
+ }
+
+ if ((tt = libconfig->setting_get_member(t, "noauction"))) {
+ id.flag.trade_restriction &= ~ITR_NOAUCTION;
+ if (libconfig->setting_get_bool(tt))
+ id.flag.trade_restriction |= ITR_NOAUCTION;
+ }
+ } else { // Fallback to int if it's not a group
+ id.flag.trade_restriction = libconfig->setting_get_int(t);
}
+ }
- fclose(fp);
+ if ((t = libconfig->setting_get_member(it, "Nouse"))) {
+ if (config_setting_is_group(t)) {
+ config_setting_t *nt = NULL;
+
+ if ((nt = libconfig->setting_get_member(t, "override"))) {
+ id.item_usage.override = libconfig->setting_get_int(nt);
+ }
+
+ if ((nt = libconfig->setting_get_member(t, "sitting"))) {
+ id.item_usage.flag &= ~INR_SITTING;
+ if (libconfig->setting_get_bool(nt))
+ id.item_usage.flag |= INR_SITTING;
+ }
- ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename[fi]);
+ } else { // Fallback to int if it's not a group
+ id.item_usage.flag = libconfig->setting_get_int(t);
+ }
}
- return 0;
+ if ((t = libconfig->setting_get_member(it, "Stack"))) {
+ if (config_setting_is_aggregate(t) && libconfig->setting_length(t) >= 1) {
+ int stack_flag = libconfig->setting_get_int_elem(t, 1);
+ int stack_amount = libconfig->setting_get_int_elem(t, 0);
+ if (stack_amount >= 0) {
+ id.stack.amount = cap_value(stack_amount, 0, USHRT_MAX);
+ id.stack.inventory = (stack_flag&1)!=0;
+ id.stack.cart = (stack_flag&2)!=0;
+ id.stack.storage = (stack_flag&4)!=0;
+ id.stack.guildstorage = (stack_flag&8)!=0;
+ }
+ }
+ }
+
+ if (libconfig->setting_lookup_int(it, "Sprite", &i32) && i32 >= 0) {
+ id.flag.available = 1;
+ id.view_id = i32;
+ }
+
+ if( libconfig->setting_lookup_string(it, "Script", &str) )
+ id.script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+
+ if( libconfig->setting_lookup_string(it, "OnEquipScript", &str) )
+ id.equip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+
+ if( libconfig->setting_lookup_string(it, "OnUnequipScript", &str) )
+ id.unequip_script = *str ? script->parse(str, source, -id.nameid, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+
+ return itemdb->validate_entry(&id, n, source);
}
-/*======================================
- * item_db table reading
- *======================================*/
-static int itemdb_read_sqldb(void) {
-
- const char* item_db_name[] = {
- #ifdef RENEWAL
- iMap->item_db_re_db,
- #else
- iMap->item_db_db,
- #endif
- iMap->item_db2_db };
- int fi;
-
- for( fi = 0; fi < ARRAYLENGTH(item_db_name); ++fi ) {
- uint32 count = 0;
-
- // retrieve all rows from the item database
- if( SQL_ERROR == SQL->Query(mmysql_handle, "SELECT * FROM `%s`", item_db_name[fi]) ) {
- Sql_ShowDebug(mmysql_handle);
+
+/**
+ * Reads from a libconfig-formatted itemdb file and inserts the found entries into the
+ * item database, overwriting duplicate ones (i.e. item_db2 overriding item_db.)
+ *
+ * @param *filename File name, relative to the database path.
+ * @return The number of found entries.
+ */
+int itemdb_readdb_libconfig(const char *filename) {
+ bool duplicate[MAX_ITEMDB];
+ config_t item_db_conf;
+ config_setting_t *itdb, *it;
+ char filepath[256];
+ int i = 0, count = 0;
+
+ sprintf(filepath, "%s/%s", map->db_path, filename);
+ memset(&duplicate,0,sizeof(duplicate));
+ if( libconfig->read_file(&item_db_conf, filepath) || !(itdb = libconfig->setting_get_member(item_db_conf.root, "item_db")) ) {
+ ShowError("can't read %s\n", filepath);
+ return 0;
+ }
+
+ while( (it = libconfig->setting_get_elem(itdb,i++)) ) {
+ int nameid = itemdb->readdb_libconfig_sub(it, i-1, filename);
+
+ if( !nameid )
continue;
- }
- // process rows one by one
- while( SQL_SUCCESS == SQL->NextRow(mmysql_handle) ) {// wrap the result into a TXT-compatible format
- char* str[ITEMDB_SQL_COLUMNS];
- char* dummy = "";
- int i;
- for( i = 0; i < ITEMDB_SQL_COLUMNS; ++i ) {
- SQL->GetData(mmysql_handle, i, &str[i], NULL);
- if( str[i] == NULL )
- str[i] = dummy; // get rid of NULL columns
- }
+ count++;
- if (!itemdb->parse_dbrow(str, item_db_name[fi], -(atoi(str[0])), SCRIPT_IGNORE_EXTERNAL_BRACKETS))
- continue;
- ++count;
- }
+ if( duplicate[nameid] ) {
+ ShowWarning("itemdb_readdb:%s: duplicate entry of ID #%d (%s/%s)\n",
+ filename, nameid, itemdb_name(nameid), itemdb_jname(nameid));
+ } else
+ duplicate[nameid] = true;
+ }
+ libconfig->destroy(&item_db_conf);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename);
+
+ return count;
+}
- // free the query result
- SQL->FreeResult(mmysql_handle);
+/**
+ * Reads from a sql itemdb table and inserts the found entries into the item
+ * database, overwriting duplicate ones (i.e. item_db2 overriding item_db.)
+ *
+ * @param *tablename Table name to query.
+ * @return The number of found entries.
+ */
+int itemdb_readdb_sql(const char *tablename) {
+ int i = 0, count = 0;
+
+ // retrieve all rows from the item database
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `id`, `name_english`, `name_japanese`, `type`,"
+ " `price_buy`, `price_sell`, `weight`, `atk`,"
+ " `matk`, `defence`, `range`, `slots`,"
+ " `equip_jobs`, `equip_upper`, `equip_genders`, `equip_locations`,"
+ " `weapon_level`, `equip_level_min`, `equip_level_max`, `refineable`,"
+ " `view`, `bindonequip`, `buyingstore`, `delay`,"
+ " `trade_flag`, `trade_group`, `nouse_flag`, `nouse_group`,"
+ " `stack_amount`, `stack_flag`, `sprite`, `script`,"
+ " `equip_script`, `unequip_script`"
+ "FROM `%s`", tablename) ) {
+ Sql_ShowDebug(map->mysql_handle);
+ return 0;
+ }
- ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, item_db_name[fi]);
+ // process rows one by one
+ while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) {
+ if( itemdb->readdb_sql_sub(map->mysql_handle, i++, tablename) )
+ count++;
}
- return 0;
+ // free the query result
+ SQL->FreeResult(map->mysql_handle);
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, tablename);
+
+ return count;
}
/*==========================================
* Unique item ID function
* Only one operation by once
-* Flag:
-* 0 return new id
-* 1 set new value, checked with current value
-* 2 set new value bypassing anything
-* 3/other return last value
*------------------------------------------*/
-uint64 itemdb_unique_id(int8 flag, int64 value) {
- static uint64 item_uid = 0;
-
- if(flag)
- {
- if(flag == 1)
- { if(item_uid < value)
- return (item_uid = value);
- }else if(flag == 2)
- return (item_uid = value);
-
- return item_uid;
- }
+uint64 itemdb_unique_id(struct map_session_data *sd) {
- return ++item_uid;
+ return ((uint64)sd->status.char_id << 32) | sd->status.uniqueitem_counter++;
}
-int itemdb_uid_load() {
-
- char * uid;
- if (SQL_ERROR == SQL->Query(mmysql_handle, "SELECT `value` FROM `%s` WHERE `varname`='unique_id'",iMap->interreg_db))
- Sql_ShowDebug(mmysql_handle);
- if( SQL_SUCCESS != SQL->NextRow(mmysql_handle) ) {
- ShowError("itemdb_uid_load: Unable to fetch unique_id data\n");
- SQL->FreeResult(mmysql_handle);
- return -1;
+/**
+ * Reads all item-related databases.
+ */
+void itemdb_read(bool minimal) {
+ int i;
+ DBData prev;
+
+ if (map->db_use_sql_item_db) {
+ const char* item_db_name[] = {
+#ifdef RENEWAL
+ map->item_db_re_db,
+#else // not RENEWAL
+ map->item_db_db,
+#endif // RENEWAL
+ map->item_db2_db
+ };
+ for(i = 0; i < ARRAYLENGTH(item_db_name); i++)
+ itemdb->readdb_sql(item_db_name[i]);
+ } else {
+ const char* filename[] = {
+ DBPATH"item_db.conf",
+ "item_db2.conf",
+ };
+
+ for(i = 0; i < ARRAYLENGTH(filename); i++)
+ itemdb->readdb_libconfig(filename[i]);
}
+
+ for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) {
+ if( itemdb->array[i] ) {
+ if( itemdb->names->put(itemdb->names,DB->str2key(itemdb->array[i]->name),DB->ptr2data(itemdb->array[i]),&prev) ) {
+ struct item_data *data = DB->data2ptr(&prev);
+ ShowError("itemdb_read: duplicate AegisName '%s' in item ID %d and %d\n",itemdb->array[i]->name,itemdb->array[i]->nameid,data->nameid);
+ }
+ }
+ }
+
+ if (minimal)
+ return;
- SQL->GetData(mmysql_handle, 0, &uid, NULL);
- itemdb_unique_id(1, (uint64)strtoull(uid, NULL, 10));
- SQL->FreeResult(mmysql_handle);
+ itemdb->read_combos();
+ itemdb->read_groups();
+ itemdb->read_chains();
+ itemdb->read_packages();
- return 0;
}
-/*====================================
- * read all item-related databases
- *------------------------------------*/
-static void itemdb_read(void) {
-
- if (iMap->db_use_sqldbs)
- itemdb_read_sqldb();
- else
- itemdb_readdb();
-
- itemdb_read_combos();
- itemdb_read_itemgroup();
- sv->readdb(iMap->db_path, "item_avail.txt", ',', 2, 2, -1, &itemdb_read_itemavail);
- sv->readdb(iMap->db_path, DBPATH"item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade);
- sv->readdb(iMap->db_path, "item_delay.txt", ',', 2, 2, -1, &itemdb_read_itemdelay);
- sv->readdb(iMap->db_path, "item_stack.txt", ',', 3, 3, -1, &itemdb_read_stack);
- sv->readdb(iMap->db_path, DBPATH"item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore);
- sv->readdb(iMap->db_path, "item_nouse.txt", ',', 3, 3, -1, &itemdb_read_nouse);
-
- itemdb_uid_load();
+/**
+ * retrieves item_combo data by combo id
+ **/
+struct item_combo * itemdb_id2combo( unsigned short id ) {
+ if( id > itemdb->combo_count )
+ return NULL;
+ return itemdb->combos[id];
}
/*==========================================
@@ -1344,28 +2055,19 @@ static void itemdb_read(void) {
*------------------------------------------*/
/// Destroys the item_data.
-static void destroy_item_data(struct item_data* self, int free_self)
+void destroy_item_data(struct item_data* self, int free_self)
{
if( self == NULL )
return;
// free scripts
if( self->script )
- script_free_code(self->script);
+ script->free_code(self->script);
if( self->equip_script )
- script_free_code(self->equip_script);
+ script->free_code(self->equip_script);
if( self->unequip_script )
- script_free_code(self->unequip_script);
- if( self->combos_count ) {
- int i;
- for( i = 0; i < self->combos_count; i++ ) {
- if( !self->combos[i]->isRef ) {
- aFree(self->combos[i]->nameid);
- script_free_code(self->combos[i]->script);
- }
- aFree(self->combos[i]);
- }
+ script->free_code(self->unequip_script);
+ if( self->combos )
aFree(self->combos);
- }
#if defined(DEBUG)
// trash item
memset(self, 0xDD, sizeof(struct item_data));
@@ -1378,34 +2080,92 @@ static void destroy_item_data(struct item_data* self, int free_self)
/**
* @see DBApply
*/
-static int itemdb_final_sub(DBKey key, DBData *data, va_list ap)
+int itemdb_final_sub(DBKey key, DBData *data, va_list ap)
{
struct item_data *id = DB->data2ptr(data);
- if( id != &dummy_item )
- destroy_item_data(id, 1);
+ if( id != &itemdb->dummy )
+ itemdb->destroy_item_data(id, 1);
return 0;
}
+void itemdb_clear(bool total) {
+ int i;
+ // clear the previous itemdb data
+ for( i = 0; i < ARRAYLENGTH(itemdb->array); ++i ) {
+ if( itemdb->array[i] )
+ itemdb->destroy_item_data(itemdb->array[i], 1);
+ }
+
+ for( i = 0; i < itemdb->group_count; i++ ) {
+ if( itemdb->groups[i].nameid )
+ aFree(itemdb->groups[i].nameid);
+ }
+
+ if( itemdb->groups )
+ aFree(itemdb->groups);
+
+ itemdb->groups = NULL;
+ itemdb->group_count = 0;
+
+ for( i = 0; i < itemdb->chain_count; i++ ) {
+ if( itemdb->chains[i].items )
+ aFree(itemdb->chains[i].items);
+ }
+
+ if( itemdb->chains )
+ aFree(itemdb->chains);
+
+ itemdb->chains = NULL;
+ itemdb->chain_count = 0;
+
+ for( i = 0; i < itemdb->package_count; i++ ) {
+ int c;
+ for( c = 0; c < itemdb->packages[i].random_qty; c++ )
+ aFree(itemdb->packages[i].random_groups[c].random_list);
+ if( itemdb->packages[i].random_groups )
+ aFree(itemdb->packages[i].random_groups);
+ if( itemdb->packages[i].must_items )
+ aFree(itemdb->packages[i].must_items);
+ }
+
+ if( itemdb->packages )
+ aFree(itemdb->packages);
+
+ itemdb->packages = NULL;
+ itemdb->package_count = 0;
+
+ for(i = 0; i < itemdb->combo_count; i++) {
+ if( itemdb->combos[i]->script ) // Check if script was loaded
+ script->free_code(itemdb->combos[i]->script);
+ aFree(itemdb->combos[i]);
+ }
+ if( itemdb->combos )
+ aFree(itemdb->combos);
+
+ itemdb->combos = NULL;
+ itemdb->combo_count = 0;
+
+ if( total )
+ return;
+
+ itemdb->other->clear(itemdb->other, itemdb->final_sub);
+
+ memset(itemdb->array, 0, sizeof(itemdb->array));
+
+ db_clear(itemdb->names);
-void itemdb_reload(void)
-{
+}
+void itemdb_reload(void) {
struct s_mapiterator* iter;
struct map_session_data* sd;
int i,d,k;
- // clear the previous itemdb data
- for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
- if( itemdb_array[i] )
- destroy_item_data(itemdb_array[i], 1);
+ itemdb->clear(false);
- itemdb_other->clear(itemdb_other, itemdb_final_sub);
-
- memset(itemdb_array, 0, sizeof(itemdb_array));
-
// read new data
- itemdb_read();
+ itemdb->read(false);
//Epoque's awesome @reloaditemdb fix - thanks! [Ind]
//- Fixes the need of a @reloadmobdb after a @reloaditemdb to re-link monster drop data
@@ -1413,12 +2173,12 @@ void itemdb_reload(void)
struct mob_db *entry;
if( !((i < 1324 || i > 1363) && (i < 1938 || i > 1946)) )
continue;
- entry = mob_db(i);
+ entry = mob->db(i);
for(d = 0; d < MAX_MOB_DROP; d++) {
struct item_data *id;
if( !entry->dropitem[d].nameid )
continue;
- id = itemdb_search(entry->dropitem[d].nameid);
+ id = itemdb->search(entry->dropitem[d].nameid);
for (k = 0; k < MAX_SEARCH; k++) {
if (id->mob[k].chance <= entry->dropitem[d].p)
@@ -1440,48 +2200,133 @@ void itemdb_reload(void)
for( sd = (struct map_session_data*)mapit->first(iter); mapit->exists(iter); sd = (struct map_session_data*)mapit->next(iter) ) {
memset(sd->item_delay, 0, sizeof(sd->item_delay)); // reset item delays
pc->setinventorydata(sd);
+ if( battle_config.item_check )
+ sd->state.itemcheck = 1;
/* clear combo bonuses */
- if( sd->combos.count ) {
- aFree(sd->combos.bonus);
- aFree(sd->combos.id);
- sd->combos.bonus = NULL;
- sd->combos.id = NULL;
- sd->combos.count = 0;
+ if( sd->combo_count ) {
+ aFree(sd->combos);
+ sd->combos = NULL;
+ sd->combo_count = 0;
if( pc->load_combo(sd) > 0 )
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
}
-
+ pc->checkitem(sd);
}
mapit->free(iter);
}
+void itemdb_name_constants(void) {
+ DBIterator *iter = db_iterator(itemdb->names);
+ struct item_data *data;
+
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = "Item Database (Likely an invalid or conflicting AegisName)";
+#endif // ENABLE_CASE_CHECK
+ for( data = dbi_first(iter); dbi_exists(iter); data = dbi_next(iter) )
+ script->set_constant2(data->name,data->nameid,0);
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = NULL;
+#endif // ENABLE_CASE_CHECK
+
+ dbi_destroy(iter);
+}
+void do_final_itemdb(void) {
+ itemdb->clear(true);
+
+ itemdb->other->destroy(itemdb->other, itemdb->final_sub);
+ itemdb->destroy_item_data(&itemdb->dummy, 0);
+ db_destroy(itemdb->names);
+}
-void do_final_itemdb(void)
-{
- int i;
-
- for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i )
- if( itemdb_array[i] )
- destroy_item_data(itemdb_array[i], 1);
+void do_init_itemdb(bool minimal) {
+ memset(itemdb->array, 0, sizeof(itemdb->array));
+ itemdb->other = idb_alloc(DB_OPT_BASE);
+ itemdb->names = strdb_alloc(DB_OPT_BASE,ITEM_NAME_LENGTH);
+ itemdb->create_dummy_data(); //Dummy data item.
+ itemdb->read(minimal);
- itemdb_other->destroy(itemdb_other, itemdb_final_sub);
- destroy_item_data(&dummy_item, 0);
-}
+ if (minimal)
+ return;
-int do_init_itemdb(void) {
- memset(itemdb_array, 0, sizeof(itemdb_array));
- itemdb_other = idb_alloc(DB_OPT_BASE);
- create_dummy_data(); //Dummy data item.
- itemdb_read();
clif->cashshop_load();
-
- return 0;
}
-/* incomplete */
void itemdb_defaults(void) {
itemdb = &itemdb_s;
- itemdb->reload = itemdb_reload;//incomplet=e
+ itemdb->init = do_init_itemdb;
+ itemdb->final = do_final_itemdb;
+ itemdb->reload = itemdb_reload;
+ itemdb->name_constants = itemdb_name_constants;
+ /* */
+ itemdb->groups = NULL;
+ itemdb->group_count = 0;
+ /* */
+ itemdb->chains = NULL;
+ itemdb->chain_count = 0;
+ /* */
+ itemdb->packages = NULL;
+ itemdb->package_count = 0;
+ /* */
+ itemdb->combos = NULL;
+ itemdb->combo_count = 0;
+ /* */
+ itemdb->names = NULL;
+ /* */
+ /* itemdb->array is cleared on itemdb->init() */
+ itemdb->other = NULL;
+ memset(&itemdb->dummy, 0, sizeof(struct item_data));
+ /* */
+ itemdb->read_groups = itemdb_read_groups;
+ itemdb->read_chains = itemdb_read_chains;
+ itemdb->read_packages = itemdb_read_packages;
+ /* */
+ itemdb->write_cached_packages = itemdb_write_cached_packages;
+ itemdb->read_cached_packages = itemdb_read_cached_packages;
/* */
- itemdb->parse_dbrow = itemdb_parse_dbrow;
- itemdb->exists = itemdb_exists;//incomplete
+ itemdb->name2id = itemdb_name2id;
+ itemdb->search_name = itemdb_searchname;
+ itemdb->search_name_array = itemdb_searchname_array;
+ itemdb->load = itemdb_load;
+ itemdb->search = itemdb_search;
+ itemdb->exists = itemdb_exists;
+ itemdb->in_group = itemdb_in_group;
+ itemdb->group_item = itemdb_searchrandomid;
+ itemdb->chain_item = itemdb_chain_item;
+ itemdb->package_item = itemdb_package_item;
+ itemdb->searchname_sub = itemdb_searchname_sub;
+ itemdb->searchname_array_sub = itemdb_searchname_array_sub;
+ itemdb->searchrandomid = itemdb_searchrandomid;
+ itemdb->typename = itemdb_typename;
+ itemdb->jobid2mapid = itemdb_jobid2mapid;
+ itemdb->create_dummy_data = create_dummy_data;
+ itemdb->create_item_data = create_item_data;
+ itemdb->isequip = itemdb_isequip;
+ itemdb->isequip2 = itemdb_isequip2;
+ itemdb->isstackable = itemdb_isstackable;
+ itemdb->isstackable2 = itemdb_isstackable2;
+ itemdb->isdropable_sub = itemdb_isdropable_sub;
+ itemdb->cantrade_sub = itemdb_cantrade_sub;
+ itemdb->canpartnertrade_sub = itemdb_canpartnertrade_sub;
+ itemdb->cansell_sub = itemdb_cansell_sub;
+ itemdb->cancartstore_sub = itemdb_cancartstore_sub;
+ itemdb->canstore_sub = itemdb_canstore_sub;
+ itemdb->canguildstore_sub = itemdb_canguildstore_sub;
+ itemdb->canmail_sub = itemdb_canmail_sub;
+ itemdb->canauction_sub = itemdb_canauction_sub;
+ itemdb->isrestricted = itemdb_isrestricted;
+ itemdb->isidentified = itemdb_isidentified;
+ itemdb->isidentified2 = itemdb_isidentified2;
+ itemdb->combo_split_atoi = itemdb_combo_split_atoi;
+ itemdb->read_combos = itemdb_read_combos;
+ itemdb->gendercheck = itemdb_gendercheck;
+ itemdb->validate_entry = itemdb_validate_entry;
+ itemdb->readdb_sql_sub = itemdb_readdb_sql_sub;
+ itemdb->readdb_libconfig_sub = itemdb_readdb_libconfig_sub;
+ itemdb->readdb_libconfig = itemdb_readdb_libconfig;
+ itemdb->readdb_sql = itemdb_readdb_sql;
+ itemdb->unique_id = itemdb_unique_id;
+ itemdb->read = itemdb_read;
+ itemdb->destroy_item_data = destroy_item_data;
+ itemdb->final_sub = itemdb_final_sub;
+ itemdb->clear = itemdb_clear;
+ itemdb->id2combo = itemdb_id2combo;
}
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 44b455d80..198d7a542 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -2,95 +2,372 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _ITEMDB_H_
-#define _ITEMDB_H_
+#ifndef MAP_ITEMDB_H
+#define MAP_ITEMDB_H
+#include "map.h"
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
#include "../common/db.h"
#include "../common/mmo.h" // ITEM_NAME_LENGTH
-#include "map.h"
+#include "../common/sql.h"
-// 32k array entries in array (the rest goes to the db)
-#define MAX_ITEMDB 0x8000
+/**
+ * Declarations
+ **/
+struct item_group;
+struct item_package;
-#define MAX_RANDITEM 11000
+/**
+ * Defines
+ **/
+#define MAX_ITEMDB 0x8000 // 32k array entries in array (the rest goes to the db)
+#define MAX_ITEMDELAYS 10 // The maximum number of item delays
+#define MAX_SEARCH 5 //Designed for search functions, species max number of matches to display.
+#define MAX_ITEMS_PER_COMBO 6 /* maximum amount of items a combo may require */
-// The maximum number of item delays
-#define MAX_ITEMDELAYS 10
+#define CARD0_FORGE 0x00FF
+#define CARD0_CREATE 0x00FE
+#define CARD0_PET ((short)0xFF00)
-#define MAX_SEARCH 5 //Designed for search functions, species max number of matches to display.
+//Marks if the card0 given is "special" (non-item id used to mark pets/created items. [Skotlex]
+#define itemdb_isspecial(i) ((i) == CARD0_FORGE || (i) == CARD0_CREATE || (i) == CARD0_PET)
-/* maximum amount of items a combo may require */
-#define MAX_ITEMS_PER_COMBO 6
+//Use apple for unknown items.
+#define UNKNOWN_ITEM_ID 512
enum item_itemid {
- ITEMID_HOLY_WATER = 523,
- ITEMID_EMPERIUM = 714,
- ITEMID_YELLOW_GEMSTONE = 715,
- ITEMID_RED_GEMSTONE = 716,
- ITEMID_BLUE_GEMSTONE = 717,
- ITEMID_TRAP = 1065,
- ITEMID_FACE_PAINT = 6120,
- ITEMID_STONE = 7049,
- ITEMID_SKULL_ = 7420,
- ITEMID_TOKEN_OF_SIEGFRIED = 7621,
- ITEMID_TRAP_ALLOY = 7940,
- ITEMID_ANCILLA = 12333,
- ITEMID_REINS_OF_MOUNT = 12622,
+ ITEMID_RED_POTION = 501,
+ ITEMID_YELLOW_POTION = 503,
+ ITEMID_WHITE_POTION = 504,
+ ITEMID_BLUE_POTION = 505,
+ ITEMID_HOLY_WATER = 523,
+ ITEMID_RED_SLIM_POTION = 545,
+ ITEMID_YELLOW_SLIM_POTION = 546,
+ ITEMID_WHITE_SLIM_POTION = 547,
+ ITEMID_WING_OF_FLY = 601,
+ ITEMID_WING_OF_BUTTERFLY = 602,
+ ITEMID_BRANCH_OF_DEAD_TREE = 604,
+ ITEMID_ANODYNE = 605,
+ ITEMID_ALOEBERA = 606,
+ ITEMID_EMPTY_BOTTLE = 713,
+ ITEMID_EMPERIUM = 714,
+ ITEMID_YELLOW_GEMSTONE = 715,
+ ITEMID_RED_GEMSTONE = 716,
+ ITEMID_BLUE_GEMSTONE = 717,
+ ITEMID_ORIDECON_STONE = 756,
+ ITEMID_ALCHOL = 970,
+ ITEMID_ORIDECON = 984,
+ ITEMID_ANVIL = 986,
+ ITEMID_ORIDECON_ANVIL = 987,
+ ITEMID_GOLDEN_ANVIL = 988,
+ ITEMID_EMPERIUM_ANVIL = 989,
+ ITEMID_BOODY_RED = 990,
+ ITEMID_CRYSTAL_BLUE = 991,
+ ITEMID_WIND_OF_VERDURE = 992,
+ ITEMID_YELLOW_LIVE = 993,
+ ITEMID_FLAME_HEART = 994,
+ ITEMID_MISTIC_FROZEN = 995,
+ ITEMID_ROUGH_WIND = 996,
+ ITEMID_GREAT_NATURE = 997,
+ ITEMID_IRON = 998,
+ ITEMID_STEEL = 999,
+ ITEMID_STAR_CRUMB = 1000,
+ ITEMID_IRON_ORE = 1002,
+ ITEMID_PHRACON = 1010,
+ ITEMID_EMVERETARCON = 1011,
+ ITEMID_TRAP = 1065,
+ ITEMID_PILEBUNCKER = 1549,
+ ITEMID_ANGRA_MANYU = 1599,
+ ITEMID_STRANGE_EMBRYO = 6415,
+ ITEMID_FACE_PAINT = 6120,
+ ITEMID_STONE = 7049,
+ ITEMID_FIRE_BOTTLE = 7135,
+ ITEMID_ACID_BOTTLE = 7136,
+ ITEMID_MENEATER_PLANT_BOTTLE = 7137,
+ ITEMID_MINI_BOTTLE = 7138,
+ ITEMID_COATING_BOTTLE = 7139,
+ ITEMID_FRAGMENT_OF_CRYSTAL = 7321,
+ ITEMID_SKULL_ = 7420,
+ ITEMID_TOKEN_OF_SIEGFRIED = 7621,
+ ITEMID_TRAP_ALLOY = 7940,
+ ITEMID_RED_POUCH_OF_SURPRISE = 12024,
+ ITEMID_BLOODY_DEAD_BRANCH = 12103,
+ ITEMID_PORING_BOX = 12109,
+ ITEMID_MERCENARY_RED_POTION = 12184,
+ ITEMID_MERCENARY_BLUE_POTION = 12185,
+ ITEMID_BATTLE_MANUAL = 12208,
+ ITEMID_BUBBLE_GUM = 12210,
+ ITEMID_GIANT_FLY_WING = 12212,
+ ITEMID_NEURALIZER = 12213,
+ ITEMID_M_CENTER_POTION = 12241,
+ ITEMID_M_AWAKENING_POTION = 12242,
+ ITEMID_M_BERSERK_POTION = 12243,
+ ITEMID_COMP_BATTLE_MANUAL = 12263,
+ ITEMID_COMP_BUBBLE_GUM = 12264,
+ ITEMID_LOVE_ANGEL = 12287,
+ ITEMID_SQUIRREL = 12288,
+ ITEMID_GOGO = 12289,
+ ITEMID_PICTURE_DIARY = 12304,
+ ITEMID_MINI_HEART = 12305,
+ ITEMID_NEWCOMER = 12306,
+ ITEMID_KID = 12307,
+ ITEMID_MAGIC_CASTLE = 12308,
+ ITEMID_BULGING_HEAD = 12309,
+ ITEMID_THICK_MANUAL50 = 12312,
+ ITEMID_ANCILLA = 12333,
+ ITEMID_REPAIR_A = 12392,
+ ITEMID_REPAIR_B = 12393,
+ ITEMID_REPAIR_C = 12394,
+ ITEMID_BLACK_THING = 12435,
+ ITEMID_REINS_OF_MOUNT = 12622,
+ ITEMID_NOBLE_NAMEPLATE = 12705,
+ ITEMID_DUN_TELE_SCROLL1 = 14527,
+ ITEMID_BATTLE_MANUAL25 = 14532,
+ ITEMIDBATTLE_MANUAL100 = 14533,
+ ITEMID_BATTLE_MANUAL_X3 = 14545,
+ ITEMID_DUN_TELE_SCROLL2 = 14581,
+ ITEMID_WOB_RUNE = 14582,
+ ITEMID_WOB_SCHWALTZ = 14583,
+ ITEMID_WOB_RACHEL = 14584,
+ ITEMID_WOB_LOCAL = 14585,
+ ITEMID_SIEGE_TELEPORT_SCROLL = 14591,
+ ITEMID_JOB_MANUAL50 = 14592,
+};
+
+enum cards_item_list {
+ ITEMID_GHOSTRING_CARD = 4047,
+ ITEMID_PHREEONI_CARD = 4121,
+ ITEMID_MISTRESS_CARD = 4132,
+ ITEMID_ORC_LOAD_CARD = 4135,
+ ITEMID_ORC_HERO_CARD = 4143,
+ ITEMID_TAO_GUNKA_CARD = 4302,
};
/**
- * Rune Knight
+ * Mechanic
**/
+enum mechanic_item_list {
+ ITEMID_ACCELERATOR = 2800,
+ ITEMID_HOVERING_BOOSTER, // 2801
+ ITEMID_SUICIDAL_DEVICE, // 2802
+ ITEMID_SHAPE_SHIFTER, // 2803
+ ITEMID_COOLING_DEVICE, // 2804
+ ITEMID_MAGNETIC_FIELD_GENERATOR, // 2805
+ ITEMID_BARRIER_BUILDER, // 2806
+ ITEMID_REPAIR_KIT, // 2807
+ ITEMID_CAMOUFLAGE_GENERATOR, // 2808
+ ITEMID_HIGH_QUALITY_COOLER, // 2809
+ ITEMID_SPECIAL_COOLER, // 2810
+ ITEMID_MONKEY_SPANNER = 6186,
+};
-enum {
- ITEMID_NAUTHIZ = 12725,
- ITEMID_RAIDO,
- ITEMID_BERKANA,
- ITEMID_ISA,
- ITEMID_OTHILA,
- ITEMID_URUZ,
- ITEMID_THURISAZ,
- ITEMID_WYRD,
- ITEMID_HAGALAZ,
-} rune_list;
+/**
+ * Spell Books
+ */
+enum spell_book_item_list {
+ ITEMID_MAGIC_BOOK_FB = 6189,
+ ITEMID_MAGIC_BOOK_CB, // 6190
+ ITEMID_MAGIC_BOOK_LB, // 6191
+ ITEMID_MAGIC_BOOK_SG, // 6192
+ ITEMID_MAGIC_BOOK_LOV, // 6193
+ ITEMID_MAGIC_BOOK_MS, // 6194
+ ITEMID_MAGIC_BOOK_CM, // 6195
+ ITEMID_MAGIC_BOOK_TV, // 6196
+ ITEMID_MAGIC_BOOK_TS, // 6197
+ ITEMID_MAGIC_BOOK_JT, // 6198
+ ITEMID_MAGIC_BOOK_WB, // 6199
+ ITEMID_MAGIC_BOOK_HD, // 6200
+ ITEMID_MAGIC_BOOK_ES, // 6201
+ ITEMID_MAGIC_BOOK_ES_, // 6202
+ ITEMID_MAGIC_BOOK_CL, // 6203
+ ITEMID_MAGIC_BOOK_CR, // 6204
+ ITEMID_MAGIC_BOOK_DL, // 6205
+};
/**
- * Mechanic
+ * Mercenary Scrolls
+ */
+enum mercenary_scroll_item_list {
+ ITEMID_BOW_MERCENARY_SCROLL1 = 12153,
+ ITEMID_BOW_MERCENARY_SCROLL2, // 12154
+ ITEMID_BOW_MERCENARY_SCROLL3, // 12155
+ ITEMID_BOW_MERCENARY_SCROLL4, // 12156
+ ITEMID_BOW_MERCENARY_SCROLL5, // 12157
+ ITEMID_BOW_MERCENARY_SCROLL6, // 12158
+ ITEMID_BOW_MERCENARY_SCROLL7, // 12159
+ ITEMID_BOW_MERCENARY_SCROLL8, // 12160
+ ITEMID_BOW_MERCENARY_SCROLL9, // 12161
+ ITEMID_BOW_MERCENARY_SCROLL10, // 12162
+ ITEMID_SWORDMERCENARY_SCROLL1, // 12163
+ ITEMID_SWORDMERCENARY_SCROLL2, // 12164
+ ITEMID_SWORDMERCENARY_SCROLL3, // 12165
+ ITEMID_SWORDMERCENARY_SCROLL4, // 12166
+ ITEMID_SWORDMERCENARY_SCROLL5, // 12167
+ ITEMID_SWORDMERCENARY_SCROLL6, // 12168
+ ITEMID_SWORDMERCENARY_SCROLL7, // 12169
+ ITEMID_SWORDMERCENARY_SCROLL8, // 12170
+ ITEMID_SWORDMERCENARY_SCROLL9, // 12171
+ ITEMID_SWORDMERCENARY_SCROLL10, // 12172
+ ITEMID_SPEARMERCENARY_SCROLL1, // 12173
+ ITEMID_SPEARMERCENARY_SCROLL2, // 12174
+ ITEMID_SPEARMERCENARY_SCROLL3, // 12175
+ ITEMID_SPEARMERCENARY_SCROLL4, // 12176
+ ITEMID_SPEARMERCENARY_SCROLL5, // 12177
+ ITEMID_SPEARMERCENARY_SCROLL6, // 12178
+ ITEMID_SPEARMERCENARY_SCROLL7, // 12179
+ ITEMID_SPEARMERCENARY_SCROLL8, // 12180
+ ITEMID_SPEARMERCENARY_SCROLL9, // 12181
+ ITEMID_SPEARMERCENARY_SCROLL10, // 12182
+};
+
+/**
+ * Cash Food
+ */
+enum cash_food_item_list {
+ ITEMID_STR_DISH10_ = 12202,
+ ITEMID_AGI_DISH10_, // 12203
+ ITEMID_INT_DISH10_, // 12204
+ ITEMID_DEX_DISH10_, // 12205
+ ITEMID_LUK_DISH10_, // 12206
+ ITEMID_VIT_DISH10_, // 12207
+};
+
+/**
+ * GC Poison
+ */
+enum poison_item_list {
+ ITEMID_POISON_PARALYSIS = 12717,
+ ITEMID_POISON_LEECH, // 12718
+ ITEMID_POISON_OBLIVION, // 12719
+ ITEMID_POISON_CONTAMINATION, // 12720
+ ITEMID_POISON_NUMB, // 12721
+ ITEMID_POISON_FEVER, // 12722
+ ITEMID_POISON_LAUGHING, // 12723
+ ITEMID_POISON_FATIGUE, // 12724
+};
+
+
+/**
+ * Rune Knight
**/
-enum {
- ITEMID_ACCELERATOR = 2800,
- ITEMID_HOVERING_BOOSTER,
- ITEMID_SUICIDAL_DEVICE,
- ITEMID_SHAPE_SHIFTER,
- ITEMID_COOLING_DEVICE,
- ITEMID_MAGNETIC_FIELD_GENERATOR,
- ITEMID_BARRIER_BUILDER,
- ITEMID_REPAIR_KIT,
- ITEMID_CAMOUFLAGE_GENERATOR,
- ITEMID_HIGH_QUALITY_COOLER,
- ITEMID_SPECIAL_COOLER,
- ITEMID_MONKEY_SPANNER = 6186,
-} mecha_item_list;
-
-enum {
- NOUSE_SITTING = 0x01,
-} item_nouse_list;
-
-//The only item group required by the code to be known. See const.txt for the full list.
-#define IG_FINDINGORE 6
-#define IG_POTION 37
-//The max. item group count (increase this when needed).
-#define MAX_ITEMGROUP 63
+enum rune_item_list {
+ ITEMID_NAUTHIZ = 12725,
+ ITEMID_RAIDO, // 12726
+ ITEMID_BERKANA, // 12727
+ ITEMID_ISA, // 12728
+ ITEMID_OTHILA, // 12729
+ ITEMID_URUZ, // 12730
+ ITEMID_THURISAZ, // 12731
+ ITEMID_WYRD, // 12732
+ ITEMID_HAGALAZ, // 12733
+ ITEMID_LUX_ANIMA = 22540,
+};
-#define CARD0_FORGE 0x00FF
-#define CARD0_CREATE 0x00FE
-#define CARD0_PET ((short)0xFF00)
+/**
+ * Geneticist
+ */
+enum geneticist_item_list {
+ /// Pharmacy / Cooking
+ ITEMID_SEED_OF_HORNY_PLANT = 6210,
+ ITEMID_BLOODSUCK_PLANT_SEED, // 6211
+ ITEMID_BOMB_MUSHROOM_SPORE, // 6212
+ ITEMID_HP_INCREASE_POTIONS = 12422,
+ ITEMID_HP_INCREASE_POTIONM, // 12423
+ ITEMID_HP_INCREASE_POTIONL, // 12424
+ ITEMID_SP_INCREASE_POTIONS, // 12425
+ ITEMID_SP_INCREASE_POTIONM, // 12426
+ ITEMID_SP_INCREASE_POTIONL, // 12427
+ ITEMID_ENRICH_WHITE_POTIONZ, // 12428
+ ITEMID_SAVAGE_BBQ, // 12429
+ ITEMID_WUG_BLOOD_COCKTAIL, // 12430
+ ITEMID_MINOR_BRISKET, // 12431
+ ITEMID_SIROMA_ICETEA, // 12432
+ ITEMID_DROCERA_HERB_STEW, // 12433
+ ITEMID_PETTI_TAIL_NOODLE, // 12434
+ ITEMID_VITATA500, // 12436
+ ITEMID_ENRICH_CELERMINE_JUICE, // 12437
+ ITEMID_CURE_FREE, // 12475
+ /// Bombs
+ ITEMID_APPLE_BOMB = 13260,
+ ITEMID_COCONUT_BOMB, // 13261
+ ITEMID_MELON_BOMB, // 13262
+ ITEMID_PINEAPPLE_BOMB, // 13263
+ ITEMID_BANANA_BOMB, // 13264
+ ITEMID_BLACK_LUMP, // 13265
+ ITEMID_BLACK_HARD_LUMP, // 13266
+ ITEMID_VERY_HARD_LUMP, // 13267
+ /// Throwables
+ ITEMID_MYSTERIOUS_POWDER, // 13268
+ ITEMID_BOOST500_TO_THROW, // 13269
+ ITEMID_FULL_SWINGK_TO_THROW, // 13270
+ ITEMID_MANA_PLUS_TO_THROW, // 13271
+ ITEMID_CURE_FREE_TO_THROW, // 13272
+ ITEMID_STAMINA_UP_M_TO_THROW, // 13273
+ ITEMID_DIGESTIVE_F_TO_THROW, // 13274
+ ITEMID_HP_INC_POTS_TO_THROW, // 13275
+ ITEMID_HP_INC_POTM_TO_THROW, // 13276
+ ITEMID_HP_INC_POTL_TO_THROW, // 13277
+ ITEMID_SP_INC_POTS_TO_THROW, // 13278
+ ITEMID_SP_INC_POTM_TO_THROW, // 13279
+ ITEMID_SP_INC_POTL_TO_THROW, // 13280
+ ITEMID_EN_WHITE_POTZ_TO_THROW, // 13281
+ ITEMID_VITATA500_TO_THROW, // 13282
+ ITEMID_EN_CEL_JUICE_TO_THROW, // 13283
+ ITEMID_SAVAGE_BBQ_TO_THROW, // 13284
+ ITEMID_WUG_COCKTAIL_TO_THROW, // 13285
+ ITEMID_M_BRISKET_TO_THROW, // 13286
+ ITEMID_SIROMA_ICETEA_TO_THROW, // 13287
+ ITEMID_DROCERA_STEW_TO_THROW, // 13288
+ ITEMID_PETTI_NOODLE_TO_THROW, // 13289
+ ITEMID_BLACK_THING_TO_THROW, // 13290
+};
-//Marks if the card0 given is "special" (non-item id used to mark pets/created items. [Skotlex]
-#define itemdb_isspecial(i) (i == CARD0_FORGE || i == CARD0_CREATE || i == CARD0_PET)
+//
+enum e_chain_cache {
+ ECC_ORE,
+ /* */
+ ECC_MAX,
+};
-//Use apple for unknown items.
-#define UNKNOWN_ITEM_ID 512
+enum item_class_upper {
+ ITEMUPPER_NONE = 0x00,
+ ITEMUPPER_NORMAL = 0x01,
+ ITEMUPPER_UPPER = 0x02,
+ ITEMUPPER_BABY = 0x04,
+ ITEMUPPER_THIRD = 0x08,
+ ITEMUPPER_THURDUPPER = 0x10,
+ ITEMUPPER_THIRDBABY = 0x20,
+ ITEMUPPER_ALL = 0x3f, // Sum of all the above
+};
+
+/**
+ * Item Trade restrictions
+ */
+enum ItemTradeRestrictions {
+ ITR_NONE = 0x000, ///< No restrictions
+ ITR_NODROP = 0x001, ///< Item can't be dropped
+ ITR_NOTRADE = 0x002, ///< Item can't be traded (nor vended)
+ ITR_PARTNEROVERRIDE = 0x004, ///< Wedded partner can override ITR_NOTRADE restriction
+ ITR_NOSELLTONPC = 0x008, ///< Item can't be sold to NPCs
+ ITR_NOCART = 0x010, ///< Item can't be placed in the cart
+ ITR_NOSTORAGE = 0x020, ///< Item can't be placed in the storage
+ ITR_NOGSTORAGE = 0x040, ///< Item can't be placed in the guild storage
+ ITR_NOMAIL = 0x080, ///< Item can't be attached to mail messages
+ ITR_NOAUCTION = 0x100, ///< Item can't be auctioned
+
+ ITR_ALL = 0x1ff ///< Sum of all the above values
+};
+
+/**
+ * Iten No-use restrictions
+ */
+enum ItemNouseRestrictions {
+ INR_NONE = 0x0, ///< No restrictions
+ INR_SITTING = 0x1, ///< Item can't be used while sitting
+
+ INR_ALL = 0x1 ///< Sum of all the above values
+};
struct item_data {
uint16 nameid;
@@ -112,16 +389,14 @@ struct item_data {
int elv;
int wlv;
int view_id;
-#ifdef RENEWAL
int matk;
int elvmax;/* maximum level for this item */
-#endif
int delay;
//Lupus: I rearranged order of these fields due to compatibility with ITEMINFO script command
// some script commands should be revised as well...
unsigned int class_base[3]; //Specifies if the base can wear this item (split in 3 indexes per type: 1-1, 2-1, 2-2)
- unsigned class_upper : 4; //Specifies if the upper-type can equip it (bitfield, 1: normal, 2: upper, 3: baby,4:third)
+ unsigned class_upper : 6; //Specifies if the upper-type can equip it (bitfield, 0x01: normal, 0x02: upper, 0x04: baby normal, 0x08: third normal, 0x10: third upper, 0x20: third baby)
struct {
unsigned short chance;
int id;
@@ -133,9 +408,10 @@ struct item_data {
unsigned available : 1;
unsigned no_refine : 1; // [celest]
unsigned delay_consume : 1; // Signifies items that are not consumed immediately upon double-click [Skotlex]
- unsigned trade_restriction : 9; //Item restrictions mask [Skotlex]
+ unsigned trade_restriction : 9; ///< Item trade restrictions mask (@see enum ItemTradeRestrictions)
unsigned autoequip: 1;
unsigned buyingstore : 1;
+ unsigned bindonequip : 1;
} flag;
struct {// item stacking limitation
unsigned short amount;
@@ -144,112 +420,197 @@ struct item_data {
unsigned int storage:1;
unsigned int guildstorage:1;
} stack;
- struct {// used by item_nouse.txt
- unsigned int flag;
+ struct {
+ unsigned int flag; ///< Item nouse restriction mask (@see enum ItemNouseRestrictions)
unsigned short override;
} item_usage;
short gm_lv_trade_override; //GM-level to override trade_restriction
/* bugreport:309 */
struct item_combo **combos;
unsigned char combos_count;
-};
-
-struct item_group {
- int nameid[MAX_RANDITEM];
- int qty; //Counts amount of items in the group.
+ /* TODO add a pointer to some sort of (struct extra) and gather all the not-common vals into it to save memory */
+ struct item_group *group;
+ struct item_package *package;
};
struct item_combo {
struct script_code *script;
- unsigned short *nameid;/* nameid array */
+ unsigned short nameid[MAX_ITEMS_PER_COMBO];/* nameid array */
unsigned char count;
unsigned short id;/* id of this combo */
- bool isRef;/* whether this struct is a reference or the master */
-};
-
-struct item_group itemgroup_db[MAX_ITEMGROUP];
-
-struct item_data* itemdb_searchname(const char *name);
-int itemdb_searchname_array(struct item_data** data, int size, const char *str);
-struct item_data* itemdb_load(int nameid);
-struct item_data* itemdb_search(int nameid);
-struct item_data* itemdb_exists(int nameid);
-#define itemdb_name(n) itemdb_search(n)->name
-#define itemdb_jname(n) itemdb_search(n)->jname
-#define itemdb_type(n) itemdb_search(n)->type
-#define itemdb_atk(n) itemdb_search(n)->atk
-#define itemdb_def(n) itemdb_search(n)->def
-#define itemdb_look(n) itemdb_search(n)->look
-#define itemdb_weight(n) itemdb_search(n)->weight
-#define itemdb_equip(n) itemdb_search(n)->equip
-#define itemdb_usescript(n) itemdb_search(n)->script
-#define itemdb_equipscript(n) itemdb_search(n)->script
-#define itemdb_wlv(n) itemdb_search(n)->wlv
-#define itemdb_range(n) itemdb_search(n)->range
-#define itemdb_slot(n) itemdb_search(n)->slot
-#define itemdb_available(n) (itemdb_search(n)->flag.available)
-#define itemdb_viewid(n) (itemdb_search(n)->view_id)
-#define itemdb_autoequip(n) (itemdb_search(n)->flag.autoequip)
-#define itemdb_is_rune(n) (n >= ITEMID_NAUTHIZ && n <= ITEMID_HAGALAZ)
-#define itemdb_is_element(n) (n >= 990 && n <= 993)
-#define itemdb_is_spellbook(n) (n >= 6188 && n <= 6205)
-#define itemdb_is_poison(n) (n >= 12717 && n <= 12724)
-#define itemid_isgemstone(id) ( (id) >= ITEMID_YELLOW_GEMSTONE && (id) <= ITEMID_BLUE_GEMSTONE )
-#define itemdb_iscashfood(id) ( (id) >= 12202 && (id) <= 12207 )
-#define itemdb_is_GNbomb(n) (n >= 13260 && n <= 13267)
-#define itemdb_is_GNthrowable(n) (n >= 13268 && n <= 13290)
-const char* itemdb_typename(int type);
-
-int itemdb_group_bonus(struct map_session_data* sd, int itemid);
-int itemdb_searchrandomid(int flags);
-
-#define itemdb_value_buy(n) itemdb_search(n)->value_buy
-#define itemdb_value_sell(n) itemdb_search(n)->value_sell
-#define itemdb_canrefine(n) (!itemdb_search(n)->flag.no_refine)
+};
+
+struct item_group {
+ unsigned short id;
+ unsigned short *nameid;
+ unsigned short qty;
+};
+
+struct item_chain_entry {
+ unsigned short id;
+ unsigned short rate;
+ struct item_chain_entry *next;
+};
+
+struct item_chain {
+ struct item_chain_entry *items;
+ unsigned short qty;
+};
+
+struct item_package_rand_entry {
+ unsigned short id;
+ unsigned short qty;
+ unsigned short rate;
+ unsigned short hours;
+ unsigned int announce : 1;
+ unsigned int named : 1;
+ struct item_package_rand_entry *next;
+};
+
+struct item_package_must_entry {
+ unsigned short id;
+ unsigned short qty;
+ unsigned short hours;
+ unsigned int announce : 1;
+ unsigned int named : 1;
+};
+
+struct item_package_rand_group {
+ struct item_package_rand_entry *random_list;
+ unsigned short random_qty;
+};
+
+struct item_package {
+ unsigned short id;
+ struct item_package_rand_group *random_groups;
+ struct item_package_must_entry *must_items;
+ unsigned short random_qty;
+ unsigned short must_qty;
+};
+
+#define itemdb_name(n) (itemdb->search(n)->name)
+#define itemdb_jname(n) (itemdb->search(n)->jname)
+#define itemdb_type(n) (itemdb->search(n)->type)
+#define itemdb_atk(n) (itemdb->search(n)->atk)
+#define itemdb_def(n) (itemdb->search(n)->def)
+#define itemdb_look(n) (itemdb->search(n)->look)
+#define itemdb_weight(n) (itemdb->search(n)->weight)
+#define itemdb_equip(n) (itemdb->search(n)->equip)
+#define itemdb_usescript(n) (itemdb->search(n)->script)
+#define itemdb_equipscript(n) (itemdb->search(n)->script)
+#define itemdb_wlv(n) (itemdb->search(n)->wlv)
+#define itemdb_range(n) (itemdb->search(n)->range)
+#define itemdb_slot(n) (itemdb->search(n)->slot)
+#define itemdb_available(n) (itemdb->search(n)->flag.available)
+#define itemdb_viewid(n) (itemdb->search(n)->view_id)
+#define itemdb_autoequip(n) (itemdb->search(n)->flag.autoequip)
+#define itemdb_value_buy(n) (itemdb->search(n)->value_buy)
+#define itemdb_value_sell(n) (itemdb->search(n)->value_sell)
+#define itemdb_canrefine(n) (!itemdb->search(n)->flag.no_refine)
+
+#define itemdb_is_rune(n) (((n) >= ITEMID_NAUTHIZ && (n) <= ITEMID_HAGALAZ) || (n) == ITEMID_LUX_ANIMA)
+#define itemdb_is_element(n) ((n) >= ITEMID_BOODY_RED && (n) <= ITEMID_YELLOW_LIVE)
+#define itemdb_is_spellbook(n) ((n) >= ITEMID_MAGIC_BOOK_FB && (n) <= ITEMID_MAGIC_BOOK_DL)
+#define itemdb_is_poison(n) ((n) >= ITEMID_POISON_PARALYSIS && (n) <= ITEMID_POISON_FATIGUE)
+#define itemid_isgemstone(n) ((n) >= ITEMID_YELLOW_GEMSTONE && (n) <= ITEMID_BLUE_GEMSTONE)
+#define itemdb_iscashfood(n) ((n) >= ITEMID_STR_DISH10_ && (n) <= ITEMID_VIT_DISH10_)
+#define itemdb_is_GNbomb(n) ((n) >= ITEMID_APPLE_BOMB && (n) <= ITEMID_VERY_HARD_LUMP)
+#define itemdb_is_GNthrowable(n) ((n) >= ITEMID_MYSTERIOUS_POWDER && (n) <= ITEMID_BLACK_THING_TO_THROW)
+
//Item trade restrictions [Skotlex]
-int itemdb_isdropable_sub(struct item_data *, int, int);
-int itemdb_cantrade_sub(struct item_data*, int, int);
-int itemdb_canpartnertrade_sub(struct item_data*, int, int);
-int itemdb_cansell_sub(struct item_data*,int, int);
-int itemdb_cancartstore_sub(struct item_data*, int, int);
-int itemdb_canstore_sub(struct item_data*, int, int);
-int itemdb_canguildstore_sub(struct item_data*, int, int);
-int itemdb_canmail_sub(struct item_data*, int, int);
-int itemdb_canauction_sub(struct item_data*, int, int);
-int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(struct item_data*, int, int));
-#define itemdb_isdropable(item, gmlv) itemdb_isrestricted(item, gmlv, 0, itemdb_isdropable_sub)
-#define itemdb_cantrade(item, gmlv, gmlv2) itemdb_isrestricted(item, gmlv, gmlv2, itemdb_cantrade_sub)
-#define itemdb_canpartnertrade(item, gmlv, gmlv2) itemdb_isrestricted(item, gmlv, gmlv2, itemdb_canpartnertrade_sub)
-#define itemdb_cansell(item, gmlv) itemdb_isrestricted(item, gmlv, 0, itemdb_cansell_sub)
-#define itemdb_cancartstore(item, gmlv) itemdb_isrestricted(item, gmlv, 0, itemdb_cancartstore_sub)
-#define itemdb_canstore(item, gmlv) itemdb_isrestricted(item, gmlv, 0, itemdb_canstore_sub)
-#define itemdb_canguildstore(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canguildstore_sub)
-#define itemdb_canmail(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canmail_sub)
-#define itemdb_canauction(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canauction_sub)
-
-int itemdb_isequip(int);
-int itemdb_isequip2(struct item_data *);
-int itemdb_isidentified(int);
-int itemdb_isidentified2(struct item_data *data);
-int itemdb_isstackable(int);
-int itemdb_isstackable2(struct item_data *);
-uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID
-
-void itemdb_reload(void);
-
-void do_final_itemdb(void);
-int do_init_itemdb(void);
-
-/* incomplete */
+#define itemdb_isdropable(item, gmlv) (itemdb->isrestricted((item), (gmlv), 0, itemdb->isdropable_sub))
+#define itemdb_cantrade(item, gmlv, gmlv2) (itemdb->isrestricted((item), (gmlv), (gmlv2), itemdb->cantrade_sub))
+#define itemdb_canpartnertrade(item, gmlv, gmlv2) (itemdb->isrestricted((item), (gmlv), (gmlv2), itemdb->canpartnertrade_sub))
+#define itemdb_cansell(item, gmlv) (itemdb->isrestricted((item), (gmlv), 0, itemdb->cansell_sub))
+#define itemdb_cancartstore(item, gmlv) (itemdb->isrestricted((item), (gmlv), 0, itemdb->cancartstore_sub))
+#define itemdb_canstore(item, gmlv) (itemdb->isrestricted((item), (gmlv), 0, itemdb->canstore_sub))
+#define itemdb_canguildstore(item, gmlv) (itemdb->isrestricted((item), (gmlv), 0, itemdb->canguildstore_sub))
+#define itemdb_canmail(item, gmlv) (itemdb->isrestricted((item), (gmlv), 0, itemdb->canmail_sub))
+#define itemdb_canauction(item, gmlv) (itemdb->isrestricted((item), (gmlv), 0, itemdb->canauction_sub))
+
struct itemdb_interface {
+ void (*init) (bool minimal);
+ void (*final) (void);
void (*reload) (void);
+ void (*name_constants) (void);
+ /* */
+ struct item_group *groups;
+ unsigned short group_count;
+ /* */
+ struct item_chain *chains;
+ unsigned short chain_count;
+ unsigned short chain_cache[ECC_MAX];
+ /* */
+ struct item_package *packages;
+ unsigned short package_count;
+ /* list of item combos loaded */
+ struct item_combo **combos;
+ unsigned short combo_count;
/* */
- int (*parse_dbrow) (char** str, const char* source, int line, int scriptopt);
+ DBMap *names;
+ /* */
+ struct item_data *array[MAX_ITEMDB];
+ DBMap *other;// int nameid -> struct item_data*
+ struct item_data dummy; //This is the default dummy item used for non-existant items. [Skotlex]
+ /* */
+ void (*read_groups) (void);
+ void (*read_chains) (void);
+ void (*read_packages) (void);
+ /* */
+ void (*write_cached_packages) (const char *config_filename);
+ bool (*read_cached_packages) (const char *config_filename);
+ /* */
+ struct item_data* (*name2id) (const char *str);
+ struct item_data* (*search_name) (const char *name);
+ int (*search_name_array) (struct item_data** data, int size, const char *str, int flag);
+ struct item_data* (*load)(int nameid);
+ struct item_data* (*search)(int nameid);
struct item_data* (*exists) (int nameid);
-} itemdb_s;
+ bool (*in_group) (struct item_group *group, int nameid);
+ int (*group_item) (struct item_group *group);
+ int (*chain_item) (unsigned short chain_id, int *rate);
+ void (*package_item) (struct map_session_data *sd, struct item_package *package);
+ int (*searchname_sub) (DBKey key, DBData *data, va_list ap);
+ int (*searchname_array_sub) (DBKey key, DBData data, va_list ap);
+ int (*searchrandomid) (struct item_group *group);
+ const char* (*typename) (int type);
+ void (*jobid2mapid) (unsigned int *bclass, unsigned int jobmask);
+ void (*create_dummy_data) (void);
+ struct item_data* (*create_item_data) (int nameid);
+ int (*isequip) (int nameid);
+ int (*isequip2) (struct item_data *data);
+ int (*isstackable) (int nameid);
+ int (*isstackable2) (struct item_data *data);
+ int (*isdropable_sub) (struct item_data *item, int gmlv, int unused);
+ int (*cantrade_sub) (struct item_data *item, int gmlv, int gmlv2);
+ int (*canpartnertrade_sub) (struct item_data *item, int gmlv, int gmlv2);
+ int (*cansell_sub) (struct item_data *item, int gmlv, int unused);
+ int (*cancartstore_sub) (struct item_data *item, int gmlv, int unused);
+ int (*canstore_sub) (struct item_data *item, int gmlv, int unused);
+ int (*canguildstore_sub) (struct item_data *item, int gmlv, int unused);
+ int (*canmail_sub) (struct item_data *item, int gmlv, int unused);
+ int (*canauction_sub) (struct item_data *item, int gmlv, int unused);
+ int (*isrestricted) (struct item *item, int gmlv, int gmlv2, int(*func)(struct item_data *, int, int));
+ int (*isidentified) (int nameid);
+ int (*isidentified2) (struct item_data *data);
+ int (*combo_split_atoi) (char *str, int *val);
+ void (*read_combos) ();
+ int (*gendercheck) (struct item_data *id);
+ int (*validate_entry) (struct item_data *entry, int n, const char *source);
+ int (*readdb_sql_sub) (Sql *handle, int n, const char *source);
+ int (*readdb_libconfig_sub) (config_setting_t *it, int n, const char *source);
+ int (*readdb_libconfig) (const char *filename);
+ int (*readdb_sql) (const char *tablename);
+ uint64 (*unique_id) (struct map_session_data *sd);
+ void (*read) (bool minimal);
+ void (*destroy_item_data) (struct item_data *self, int free_self);
+ int (*final_sub) (DBKey key, DBData *data, va_list ap);
+ void (*clear) (bool total);
+ struct item_combo * (*id2combo) (unsigned short id);
+};
struct itemdb_interface *itemdb;
void itemdb_defaults(void);
-#endif /* _ITEMDB_H_ */
+#endif /* MAP_ITEMDB_H */
diff --git a/src/map/log.c b/src/map/log.c
index dfb4c4a61..b5179e16b 100644
--- a/src/map/log.c
+++ b/src/map/log.c
@@ -2,53 +2,29 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/sql.h" // SQL_INNODB
-#include "../common/strlib.h"
-#include "../common/nullpo.h"
-#include "../common/showmsg.h"
-#include "battle.h"
-#include "itemdb.h"
+#define HERCULES_CORE
+
#include "log.h"
-#include "map.h"
-#include "mob.h"
-#include "pc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "battle.h"
+#include "itemdb.h"
+#include "map.h"
+#include "mob.h"
+#include "pc.h"
+#include "../common/cbasetypes.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/sql.h" // SQL_INNODB
+#include "../common/strlib.h"
-/// filters for item logging
-typedef enum e_log_filter {
- LOG_FILTER_NONE = 0x000,
- LOG_FILTER_ALL = 0x001,
- // bits
- LOG_FILTER_HEALING = 0x002, // Healing items (0)
- LOG_FILTER_ETC_AMMO = 0x004, // Etc Items(3) + Arrows (10)
- LOG_FILTER_USABLE = 0x008, // Usable Items(2) + Scrolls, Lures(11) + Usable Cash Items(18)
- LOG_FILTER_WEAPON = 0x010, // Weapons(4)
- LOG_FILTER_ARMOR = 0x020, // Shields, Armors, Headgears, Accessories, Garments and Shoes(5)
- LOG_FILTER_CARD = 0x040, // Cards(6)
- LOG_FILTER_PETITEM = 0x080, // Pet Accessories(8) + Eggs(7) (well, monsters don't drop 'em but we'll use the same system for ALL logs)
- LOG_FILTER_PRICE = 0x100, // Log expensive items ( >= price_log )
- LOG_FILTER_AMOUNT = 0x200, // Log large amount of items ( >= amount_log )
- LOG_FILTER_REFINE = 0x400, // Log refined items ( refine >= refine_log ) [not implemented]
- LOG_FILTER_CHANCE = 0x800, // Log rare items and Emperium ( drop chance <= rare_log )
-}
-e_log_filter;
-
-#ifdef SQL_INNODB
-// database is using an InnoDB engine so do not use DELAYED
-#define LOG_QUERY "INSERT"
-#else
-// database is using a MyISAM engine so use DELAYED
-#define LOG_QUERY "INSERT DELAYED"
-#endif
-
+struct log_interface log_s;
/// obtain log type character for item/zeny logs
-static char log_picktype2char(e_log_pick_type type) {
+char log_picktype2char(e_log_pick_type type) {
switch( type ) {
case LOG_TYPE_TRADE: return 'T'; // (T)rade
case LOG_TYPE_VENDING: return 'V'; // (V)ending
@@ -67,6 +43,7 @@ static char log_picktype2char(e_log_pick_type type) {
case LOG_TYPE_AUCTION: return 'I'; // Auct(I)on
case LOG_TYPE_BUYING_STORE: return 'B'; // (B)uying Store
case LOG_TYPE_LOOT: return 'L'; // (L)oot (consumed monster pick/drop)
+ case LOG_TYPE_BANK: return 'K'; // Ban(K) Transactions
case LOG_TYPE_OTHER: return 'X'; // Other
}
@@ -77,7 +54,7 @@ static char log_picktype2char(e_log_pick_type type) {
/// obtain log type character for chat logs
-static char log_chattype2char(e_log_chat_type type) {
+char log_chattype2char(e_log_chat_type type) {
switch( type ) {
case LOG_CHAT_GLOBAL: return 'O'; // Gl(O)bal
case LOG_CHAT_WHISPER: return 'W'; // (W)hisper
@@ -93,7 +70,7 @@ static char log_chattype2char(e_log_chat_type type) {
/// check if this item should be logged according the settings
-static bool should_log_item(int nameid, int amount, int refine, struct item_data *id) {
+bool should_log_item(int nameid, int amount, int refine, struct item_data *id) {
int filter = logs->config.filter;
if( id == NULL )
@@ -118,7 +95,7 @@ static bool should_log_item(int nameid, int amount, int refine, struct item_data
}
void log_branch_sub_sql(struct map_session_data* sd) {
SqlStmt* stmt;
- stmt = SQL->StmtMalloc(logmysql_handle);
+ stmt = SQL->StmtMalloc(logs->mysql_handle);
if( SQL_SUCCESS != SQL->StmtPrepare(stmt, LOG_QUERY " INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', ?, '%s')", logs->config.log_branch, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) )
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH))
|| SQL_SUCCESS != SQL->StmtExecute(stmt) )
@@ -152,10 +129,13 @@ void log_branch(struct map_session_data* sd) {
logs->branch_sub(sd);
}
void log_pick_sub_sql(int id, int16 m, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) {
- if( SQL_ERROR == SQL->Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `unique_id`) VALUES (NOW(), '%d', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%"PRIu64"')",
- logs->config.log_pick, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"", itm->unique_id) )
- {
- Sql_ShowDebug(logmysql_handle);
+ if( SQL_ERROR == SQL->Query(logs->mysql_handle,
+ LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `unique_id`) "
+ "VALUES (NOW(), '%d', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%"PRIu64"')",
+ logs->config.log_pick, id, logs->picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3],
+ map->list[m].name?map->list[m].name:"", itm->unique_id)
+ ) {
+ Sql_ShowDebug(logs->mysql_handle);
return;
}
}
@@ -168,7 +148,9 @@ void log_pick_sub_txt(int id, int16 m, e_log_pick_type type, int amount, struct
return;
time(&curtime);
strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime));
- fprintf(logfp,"%s - %d\t%c\t%d,%d,%d,%d,%d,%d,%d,%s,'%"PRIu64"'\n", timestring, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"", itm->unique_id);
+ fprintf(logfp,"%s - %d\t%c\t%d,%d,%d,%d,%d,%d,%d,%s,'%"PRIu64"'\n",
+ timestring, id, logs->picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3],
+ map->list[m].name?map->list[m].name:"", itm->unique_id);
fclose(logfp);
}
/// logs item transactions (generic)
@@ -178,7 +160,7 @@ void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item* it
return;
}
- if( !should_log_item(itm->nameid, amount, itm->refine, data) )
+ if( !logs->should_log_item(itm->nameid, amount, itm->refine, data) )
return; //we skip logging this item set - it doesn't meet our logging conditions [Lupus]
logs->pick_sub(id,m,type,amount,itm,data);
@@ -187,20 +169,20 @@ void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item* it
/// logs item transactions (players)
void log_pick_pc(struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) {
nullpo_retv(sd);
- log_pick(sd->status.char_id, sd->bl.m, type, amount, itm, data ? data : itemdb_exists(itm->nameid));
+ log_pick(sd->status.char_id, sd->bl.m, type, amount, itm, data ? data : itemdb->exists(itm->nameid));
}
/// logs item transactions (monsters)
void log_pick_mob(struct mob_data* md, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) {
nullpo_retv(md);
- log_pick(md->class_, md->bl.m, type, amount, itm, data ? data : itemdb_exists(itm->nameid));
+ log_pick(md->class_, md->bl.m, type, amount, itm, data ? data : itemdb->exists(itm->nameid));
}
void log_zeny_sub_sql(struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount) {
- if( SQL_ERROR == SQL->Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')",
- logs->config.log_zeny, sd->status.char_id, src_sd->status.char_id, log_picktype2char(type), amount, mapindex_id2name(sd->mapindex)) )
+ if( SQL_ERROR == SQL->Query(logs->mysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')",
+ logs->config.log_zeny, sd->status.char_id, src_sd->status.char_id, logs->picktype2char(type), amount, mapindex_id2name(sd->mapindex)) )
{
- Sql_ShowDebug(logmysql_handle);
+ Sql_ShowDebug(logs->mysql_handle);
return;
}
}
@@ -227,10 +209,10 @@ void log_zeny(struct map_session_data* sd, e_log_pick_type type, struct map_sess
logs->zeny_sub(sd,type,src_sd,amount);
}
void log_mvpdrop_sub_sql(struct map_session_data* sd, int monster_id, int* log_mvp) {
- if( SQL_ERROR == SQL->Query(logmysql_handle, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ",
+ if( SQL_ERROR == SQL->Query(logs->mysql_handle, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ",
logs->config.log_mvpdrop, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)) )
{
- Sql_ShowDebug(logmysql_handle);
+ Sql_ShowDebug(logs->mysql_handle);
return;
}
}
@@ -260,7 +242,7 @@ void log_mvpdrop(struct map_session_data* sd, int monster_id, int* log_mvp)
void log_atcommand_sub_sql(struct map_session_data* sd, const char* message) {
SqlStmt* stmt;
- stmt = SQL->StmtMalloc(logmysql_handle);
+ stmt = SQL->StmtMalloc(logs->mysql_handle);
if( SQL_SUCCESS != SQL->StmtPrepare(stmt, LOG_QUERY " INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", logs->config.log_gm, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) )
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, 255))
@@ -290,7 +272,7 @@ void log_atcommand(struct map_session_data* sd, const char* message)
nullpo_retv(sd);
if( !logs->config.commands ||
- !pc_should_log_commands(sd) )
+ !pc->should_log_commands(sd) )
return;
logs->atcommand_sub(sd,message);
@@ -298,7 +280,7 @@ void log_atcommand(struct map_session_data* sd, const char* message)
void log_npc_sub_sql(struct map_session_data *sd, const char *message) {
SqlStmt* stmt;
- stmt = SQL->StmtMalloc(logmysql_handle);
+ stmt = SQL->StmtMalloc(logs->mysql_handle);
if( SQL_SUCCESS != SQL->StmtPrepare(stmt, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", logs->config.log_npc, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) )
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH))
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, 255))
@@ -333,22 +315,22 @@ void log_npc(struct map_session_data* sd, const char* message)
logs->npc_sub(sd,message);
}
-void log_chat_sub_sql(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message) {
+void log_chat_sub_sql(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char* dst_charname, const char* message) {
SqlStmt* stmt;
- stmt = SQL->StmtMalloc(logmysql_handle);
- if( SQL_SUCCESS != SQL->StmtPrepare(stmt, LOG_QUERY " INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%c', '%d', '%d', '%d', '%s', '%d', '%d', ?, ?)", logs->config.log_chat, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y)
- || SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, (char*)dst_charname, safestrnlen(dst_charname, NAME_LENGTH))
- || SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, CHAT_SIZE_MAX))
- || SQL_SUCCESS != SQL->StmtExecute(stmt) )
- {
+ stmt = SQL->StmtMalloc(logs->mysql_handle);
+ if( SQL_SUCCESS != SQL->StmtPrepare(stmt, LOG_QUERY " INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%c', '%d', '%d', '%d', '%s', '%d', '%d', ?, ?)", logs->config.log_chat, logs->chattype2char(type), type_id, src_charid, src_accid, mapname, x, y)
+ || SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, (char*)dst_charname, safestrnlen(dst_charname, NAME_LENGTH))
+ || SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, CHAT_SIZE_MAX))
+ || SQL_SUCCESS != SQL->StmtExecute(stmt)
+ ) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
return;
}
SQL->StmtFree(stmt);
}
-void log_chat_sub_txt(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message) {
+void log_chat_sub_txt(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char* dst_charname, const char* message) {
char timestring[255];
time_t curtime;
FILE* logfp;
@@ -357,26 +339,43 @@ void log_chat_sub_txt(e_log_chat_type type, int type_id, int src_charid, int src
return;
time(&curtime);
strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime));
- fprintf(logfp, "%s - %c,%d,%d,%d,%s,%d,%d,%s,%s\n", timestring, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y, dst_charname, message);
+ fprintf(logfp, "%s - %c,%d,%d,%d,%s,%d,%d,%s,%s\n", timestring, logs->chattype2char(type), type_id, src_charid, src_accid, mapname, x, y, dst_charname, message);
fclose(logfp);
}
/// logs chat
-void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message)
-{
- if( ( logs->config.chat&type ) == 0 )
- {// disabled
+void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char* dst_charname, const char* message) {
+ if( ( logs->config.chat&type ) == 0 ) {
+ // disabled
return;
}
- if( logs->config.log_chat_woe_disable && ( iMap->agit_flag || iMap->agit2_flag ) )
- {// no chat logging during woe
+ if( logs->config.log_chat_woe_disable && ( map->agit_flag || map->agit2_flag ) ) {
+ // no chat logging during woe
return;
}
- logs->chat_sub(type,type_id,src_charid,src_accid,map,x,y,dst_charname,message);
+ logs->chat_sub(type,type_id,src_charid,src_accid,mapname,x,y,dst_charname,message);
}
+void log_sql_init(void) {
+ // log db connection
+ logs->mysql_handle = SQL->Malloc();
+
+ ShowInfo(""CL_WHITE"[SQL]"CL_RESET": Connecting to the Log Database "CL_WHITE"%s"CL_RESET" At "CL_WHITE"%s"CL_RESET"...\n",logs->db_name,logs->db_ip);
+ if ( SQL_ERROR == SQL->Connect(logs->mysql_handle, logs->db_id, logs->db_pw, logs->db_ip, logs->db_port, logs->db_name) )
+ exit(EXIT_FAILURE);
+ ShowStatus(""CL_WHITE"[SQL]"CL_RESET": Successfully '"CL_GREEN"connected"CL_RESET"' to Database '"CL_WHITE"%s"CL_RESET"'.\n", logs->db_name);
+
+ if( strlen(map->default_codepage) > 0 )
+ if ( SQL_ERROR == SQL->SetEncoding(logs->mysql_handle, map->default_codepage) )
+ Sql_ShowDebug(logs->mysql_handle);
+}
+void log_sql_final(void) {
+ ShowStatus("Close Log DB Connection....\n");
+ SQL->Free(logs->mysql_handle);
+ logs->mysql_handle = NULL;
+}
void log_set_defaults(void) {
memset(&logs->config, 0, sizeof(logs->config));
@@ -402,11 +401,11 @@ int log_config_read(const char* cfgName) {
return 1;
}
- while( fgets(line, sizeof(line), fp) ) {
- if( line[0] == '/' && line[1] == '/' )
+ while (fgets(line, sizeof(line), fp)) {
+ if (line[0] == '/' && line[1] == '/')
continue;
- if( sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 ) {
+ if (sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2) == 2) {
if( strcmpi(w1, "enable_logs") == 0 )
logs->config.enable_logs = (e_log_pick_type)config_switch(w2);
else if( strcmpi(w1, "sql_logs") == 0 )
@@ -504,6 +503,15 @@ void log_config_complete(void) {
void log_defaults(void) {
logs = &log_s;
+ sprintf(logs->db_ip,"127.0.0.1");
+ sprintf(logs->db_id,"ragnarok");
+ sprintf(logs->db_pw,"ragnarok");
+ sprintf(logs->db_name,"log");
+
+ logs->db_port = 3306;
+ logs->mysql_handle = NULL;
+ /* */
+
logs->pick_pc = log_pick_pc;
logs->pick_mob = log_pick_mob;
logs->zeny = log_zeny;
@@ -512,8 +520,6 @@ void log_defaults(void) {
logs->atcommand = log_atcommand;
logs->branch = log_branch;
logs->mvpdrop = log_mvpdrop;
- logs->config_read = log_config_read;
- logs->config_done = log_config_complete;
/* will be modified in a few seconds once loading is complete. */
logs->pick_sub = log_pick_sub_txt;
@@ -524,4 +530,12 @@ void log_defaults(void) {
logs->branch_sub = log_branch_sub_txt;
logs->mvpdrop_sub = log_mvpdrop_sub_txt;
+ logs->config_read = log_config_read;
+ logs->config_done = log_config_complete;
+ logs->sql_init = log_sql_init;
+ logs->sql_final = log_sql_final;
+
+ logs->picktype2char = log_picktype2char;
+ logs->chattype2char = log_chattype2char;
+ logs->should_log_item = should_log_item;
}
diff --git a/src/map/log.h b/src/map/log.h
index 462a12ff5..6ab142f87 100644
--- a/src/map/log.h
+++ b/src/map/log.h
@@ -2,16 +2,34 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _LOG_H_
-#define _LOG_H_
+#ifndef MAP_LOG_H
+#define MAP_LOG_H
-struct block_list;
-struct map_session_data;
-struct mob_data;
+#include "../common/cbasetypes.h"
+#include "../common/sql.h"
+
+/**
+ * Declarations
+ **/
struct item;
struct item_data;
+struct map_session_data;
+struct mob_data;
+/**
+ * Defines
+ **/
+#ifdef SQL_INNODB
+// database is using an InnoDB engine so do not use DELAYED
+ #define LOG_QUERY "INSERT"
+#else
+// database is using a MyISAM engine so use DELAYED
+ #define LOG_QUERY "INSERT DELAYED"
+#endif
+/**
+ * Enumerations
+ **/
typedef enum e_log_chat_type {
LOG_CHAT_GLOBAL = 0x01,
LOG_CHAT_WHISPER = 0x02,
@@ -22,7 +40,6 @@ typedef enum e_log_chat_type {
LOG_CHAT_ALL = 0xFF,
} e_log_chat_type;
-
typedef enum e_log_pick_type {
LOG_TYPE_NONE = 0,
LOG_TYPE_TRADE = 0x00001,
@@ -42,12 +59,31 @@ typedef enum e_log_pick_type {
LOG_TYPE_AUCTION = 0x04000,
LOG_TYPE_BUYING_STORE = 0x08000,
LOG_TYPE_OTHER = 0x10000,
+ LOG_TYPE_BANK = 0x20000,
// combinations
LOG_TYPE_LOOT = LOG_TYPE_PICKDROP_MONSTER|LOG_TYPE_CONSUME,
// all
LOG_TYPE_ALL = 0xFFFFF,
} e_log_pick_type;
+/// filters for item logging
+typedef enum e_log_filter {
+ LOG_FILTER_NONE = 0x000,
+ LOG_FILTER_ALL = 0x001,
+ // bits
+ LOG_FILTER_HEALING = 0x002, // Healing items (0)
+ LOG_FILTER_ETC_AMMO = 0x004, // Etc Items(3) + Arrows (10)
+ LOG_FILTER_USABLE = 0x008, // Usable Items(2) + Scrolls, Lures(11) + Usable Cash Items(18)
+ LOG_FILTER_WEAPON = 0x010, // Weapons(4)
+ LOG_FILTER_ARMOR = 0x020, // Shields, Armors, Headgears, Accessories, Garments and Shoes(5)
+ LOG_FILTER_CARD = 0x040, // Cards(6)
+ LOG_FILTER_PETITEM = 0x080, // Pet Accessories(8) + Eggs(7) (well, monsters don't drop 'em but we'll use the same system for ALL logs)
+ LOG_FILTER_PRICE = 0x100, // Log expensive items ( >= price_log )
+ LOG_FILTER_AMOUNT = 0x200, // Log large amount of items ( >= amount_log )
+ LOG_FILTER_REFINE = 0x400, // Log refined items ( refine >= refine_log ) [not implemented]
+ LOG_FILTER_CHANCE = 0x800, // Log rare items and Emperium ( drop chance <= rare_log )
+} e_log_filter;
+
struct log_interface {
struct {
e_log_pick_type enable_logs;
@@ -59,11 +95,18 @@ struct log_interface {
char log_branch[64], log_pick[64], log_zeny[64], log_mvpdrop[64], log_gm[64], log_npc[64], log_chat[64];
} config;
/* */
+ char db_ip[32];
+ int db_port;
+ char db_id[32];
+ char db_pw[32];
+ char db_name[32];
+ Sql* mysql_handle;
+ /* */
void (*pick_pc) (struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm, struct item_data *data);
void (*pick_mob) (struct mob_data* md, e_log_pick_type type, int amount, struct item* itm, struct item_data *data);
void (*zeny) (struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount);
void (*npc) (struct map_session_data* sd, const char *message);
- void (*chat) (e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message);
+ void (*chat) (e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char* dst_charname, const char* message);
void (*atcommand) (struct map_session_data* sd, const char* message);
void (*branch) (struct map_session_data* sd);
void (*mvpdrop) (struct map_session_data* sd, int monster_id, int* log_mvp);
@@ -71,17 +114,23 @@ struct log_interface {
void (*pick_sub) (int id, int16 m, e_log_pick_type type, int amount, struct item* itm, struct item_data *data);
void (*zeny_sub) (struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount);
void (*npc_sub) (struct map_session_data* sd, const char *message);
- void (*chat_sub) (e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message);
+ void (*chat_sub) (e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char* dst_charname, const char* message);
void (*atcommand_sub) (struct map_session_data* sd, const char* message);
void (*branch_sub) (struct map_session_data* sd);
void (*mvpdrop_sub) (struct map_session_data* sd, int monster_id, int* log_mvp);
int (*config_read) (const char* cfgName);
void (*config_done) (void);
-} log_s;
+ void (*sql_init) (void);
+ void (*sql_final) (void);
+
+ char (*picktype2char) (e_log_pick_type type);
+ char (*chattype2char) (e_log_chat_type type);
+ bool (*should_log_item) (int nameid, int amount, int refine, struct item_data *id);
+};
struct log_interface *logs;
void log_defaults(void);
-#endif /* _LOG_H_ */
+#endif /* MAP_LOG_H */
diff --git a/src/map/mail.c b/src/map/mail.c
index 9a8d4e521..7ba7d7470 100644
--- a/src/map/mail.c
+++ b/src/map/mail.c
@@ -2,18 +2,22 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/nullpo.h"
-#include "../common/showmsg.h"
+#define HERCULES_CORE
#include "mail.h"
+
+#include <time.h>
+#include <string.h>
+
#include "atcommand.h"
-#include "itemdb.h"
#include "clif.h"
-#include "pc.h"
+#include "itemdb.h"
#include "log.h"
+#include "pc.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
-#include <time.h>
-#include <string.h>
+struct mail_interface mail_s;
void mail_clear(struct map_session_data *sd)
{
@@ -62,7 +66,7 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
return 1;
if( idx == 0 ) { // Zeny Transfer
- if( amount < 0 || !pc->can_give_items(sd) )
+ if( amount < 0 || !pc_can_give_items(sd) )
return 1;
if( amount > sd->status.zeny )
@@ -79,8 +83,9 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
return 1;
if( amount < 0 || amount > sd->status.inventory[idx].amount )
return 1;
- if( !pc->can_give_items(sd) || sd->status.inventory[idx].expire_time ||
- !itemdb_canmail(&sd->status.inventory[idx],pc->get_group_level(sd)) )
+ if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time ||
+ !itemdb_canmail(&sd->status.inventory[idx],pc_get_group_level(sd)) ||
+ (sd->status.inventory[idx].bound && !pc_can_give_bound_items(sd)) )
return 1;
sd->mail.index = idx;
@@ -174,10 +179,8 @@ void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg)
}
// This function only check if the mail operations are valid
-bool mail_invalid_operation(struct map_session_data *sd)
-{
- if( !map[sd->bl.m].flag.town && !pc->can_use_command(sd, "@mail") )
- {
+bool mail_invalid_operation(struct map_session_data *sd) {
+ if( !map->list[sd->bl.m].flag.town && !pc->can_use_command(sd, "@mail") ) {
ShowWarning("clif->parse_Mail: char '%s' trying to do invalid mail operations.\n", sd->status.name);
return true;
}
@@ -198,4 +201,4 @@ void mail_defaults(void)
mail->openmail = mail_openmail;
mail->deliveryfail = mail_deliveryfail;
mail->invalid_operation = mail_invalid_operation;
-} \ No newline at end of file
+}
diff --git a/src/map/mail.h b/src/map/mail.h
index 99742c7bd..64b0f9779 100644
--- a/src/map/mail.h
+++ b/src/map/mail.h
@@ -2,10 +2,14 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _MAIL_H_
-#define _MAIL_H_
+#ifndef MAP_MAIL_H
+#define MAP_MAIL_H
-#include "../common/mmo.h"
+#include "../common/cbasetypes.h"
+
+struct item;
+struct mail_message;
+struct map_session_data;
struct mail_interface {
void (*clear) (struct map_session_data *sd);
@@ -17,10 +21,10 @@ struct mail_interface {
int (*openmail) (struct map_session_data *sd);
void (*deliveryfail) (struct map_session_data *sd, struct mail_message *msg);
bool (*invalid_operation) (struct map_session_data *sd);
-} mail_s;
+};
struct mail_interface *mail;
void mail_defaults(void);
-#endif /* _MAIL_H_ */
+#endif /* MAP_MAIL_H */
diff --git a/src/map/map.c b/src/map/map.c
index 5f86286e9..0c8c2d949 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -2,251 +2,203 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/core.h"
-#include "../common/timer.h"
-#include "../common/ers.h"
-#include "../common/grfio.h"
-#include "../common/malloc.h"
-#include "../common/socket.h" // WFIFO*()
-#include "../common/showmsg.h"
-#include "../common/nullpo.h"
-#include "../common/random.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
-#include "../common/conf.h"
-#include "../common/console.h"
-#include "../common/HPM.h"
+#define HERCULES_CORE
+#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, DBPATH, RENEWAL
#include "map.h"
-#include "path.h"
+
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "HPMmap.h"
+#include "atcommand.h"
+#include "battle.h"
+#include "battleground.h"
+#include "chat.h"
#include "chrif.h"
#include "clif.h"
#include "duel.h"
+#include "elemental.h"
+#include "guild.h"
+#include "homunculus.h"
+#include "instance.h"
#include "intif.h"
+#include "irc-bot.h"
+#include "itemdb.h"
+#include "log.h"
+#include "mail.h"
+#include "mapreg.h"
+#include "mercenary.h"
+#include "mob.h"
#include "npc.h"
+#include "npc.h" // npc_setcells(), npc_unsetcells()
+#include "party.h"
+#include "path.h"
#include "pc.h"
+#include "pet.h"
+#include "quest.h"
+#include "script.h"
+#include "skill.h"
#include "status.h"
-#include "mob.h"
-#include "npc.h" // npc_setcells(), npc_unsetcells()
-#include "chat.h"
-#include "itemdb.h"
#include "storage.h"
-#include "skill.h"
#include "trade.h"
-#include "party.h"
#include "unit.h"
-#include "battle.h"
-#include "battleground.h"
-#include "quest.h"
-#include "script.h"
-#include "mapreg.h"
-#include "guild.h"
-#include "pet.h"
-#include "homunculus.h"
-#include "instance.h"
-#include "mercenary.h"
-#include "elemental.h"
-#include "atcommand.h"
-#include "log.h"
-#include "mail.h"
-#include "irc-bot.h"
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/console.h"
+#include "../common/core.h"
+#include "../common/ers.h"
+#include "../common/grfio.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h" // WFIFO*()
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <math.h>
#ifndef _WIN32
#include <unistd.h>
#endif
-char default_codepage[32] = "";
-
-int map_server_port = 3306;
-char map_server_ip[32] = "127.0.0.1";
-char map_server_id[32] = "ragnarok";
-char map_server_pw[32] = "ragnarok";
-char map_server_db[32] = "ragnarok";
-Sql* mmysql_handle;
-
-int map_port=0;
-
-// log database
-char log_db_ip[32] = "127.0.0.1";
-int log_db_port = 3306;
-char log_db_id[32] = "ragnarok";
-char log_db_pw[32] = "ragnarok";
-char log_db_db[32] = "log";
-Sql* logmysql_handle;
-
-// DBMap declaartion
-static DBMap* id_db=NULL; // int id -> struct block_list*
-static DBMap* pc_db=NULL; // int id -> struct map_session_data*
-static DBMap* mobid_db=NULL; // int id -> struct mob_data*
-static DBMap* bossid_db=NULL; // int id -> struct mob_data* (MVP db)
-static DBMap* map_db=NULL; // unsigned int mapindex -> struct map_data_other_server*
-static DBMap* nick_db=NULL; // int char_id -> struct charid2nick* (requested names of offline characters)
-static DBMap* charid_db=NULL; // int char_id -> struct map_session_data*
-static DBMap* regen_db=NULL; // int id -> struct block_list* (status_natural_heal processing)
-
-static int map_users=0;
-
-#define BLOCK_SIZE 8
-#define block_free_max 1048576
-struct block_list *block_free[block_free_max];
-static int block_free_count = 0, block_free_lock = 0;
-
-#define BL_LIST_MAX 1048576
-static struct block_list *bl_list[BL_LIST_MAX];
-static int bl_list_count = 0;
-
-struct charid_request {
- struct charid_request* next;
- int charid;// who want to be notified of the nick
-};
-struct charid2nick {
- char nick[NAME_LENGTH];
- struct charid_request* requests;// requests of notification on this nick
-};
-
-// This is the main header found at the very beginning of the map cache
-struct map_cache_main_header {
- uint32 file_size;
- uint16 map_count;
-};
-
-// This is the header appended before every compressed map cells info in the map cache
-struct map_cache_map_info {
- char name[MAP_NAME_LENGTH];
- int16 xs;
- int16 ys;
- int32 len;
-};
-
-int16 index2mapid[MAX_MAPINDEX];
+struct map_interface map_s;
+struct mapit_interface mapit_s;
-int enable_grf = 0; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89]
+/*==========================================
+ * server player count (of all mapservers)
+ *------------------------------------------*/
+void map_setusers(int users) {
+ map->users = users;
+}
-/* [Ind/Hercules] */
-struct eri *map_iterator_ers;
-char *map_cache_buffer = NULL; // Has the uncompressed gat data of all maps, so just one allocation has to be made
+int map_getusers(void) {
+ return map->users;
+}
-/*==========================================
-* server player count (of all mapservers)
-*------------------------------------------*/
-void map_setusers(int users)
-{
- map_users = users;
+/**
+ * Expands map->bl_list on demand
+ **/
+static inline void map_bl_list_expand(void) {
+ map->bl_list_size += 250;
+ RECREATE(map->bl_list, struct block_list *, map->bl_list_size);
}
-int map_getusers(void)
-{
- return map_users;
+/**
+ * Expands map->block_free on demand
+ **/
+static inline void map_block_free_expand(void) {
+ map->block_free_list_size += 100;
+ RECREATE(map->block_free, struct block_list *, map->block_free_list_size);
}
/*==========================================
-* server player count (this mapserver only)
-*------------------------------------------*/
-int map_usercount(void)
-{
- return pc_db->size(pc_db);
+ * server player count (this mapserver only)
+ *------------------------------------------*/
+int map_usercount(void) {
+ return db_size(map->pc_db);
}
-
/*==========================================
-* Attempt to free a map blocklist
-*------------------------------------------*/
-int map_freeblock (struct block_list *bl)
-{
- nullpo_retr(block_free_lock, bl);
- if (block_free_lock == 0 || block_free_count >= block_free_max)
- {
- aFree(bl);
+ * Attempt to free a map blocklist
+ *------------------------------------------*/
+int map_freeblock (struct block_list *bl) {
+ nullpo_retr(map->block_free_lock, bl);
+
+ if (map->block_free_lock == 0) {
+ if( bl->type == BL_ITEM )
+ ers_free(map->flooritem_ers, bl);
+ else
+ aFree(bl);
bl = NULL;
- if (block_free_count >= block_free_max)
- ShowWarning("map_freeblock: too many free block! %d %d\n", block_free_count, block_free_lock);
- } else
- block_free[block_free_count++] = bl;
+ } else {
+
+ if( map->block_free_count >= map->block_free_list_size )
+ map_block_free_expand();
+
+ map->block_free[map->block_free_count++] = bl;
+ }
- return block_free_lock;
+ return map->block_free_lock;
}
/*==========================================
-* Lock blocklist, (prevent iMap->freeblock usage)
-*------------------------------------------*/
-int map_freeblock_lock (void)
-{
- return ++block_free_lock;
+ * Lock blocklist, (prevent map->freeblock usage)
+ *------------------------------------------*/
+int map_freeblock_lock (void) {
+ return ++map->block_free_lock;
}
/*==========================================
-* Remove the lock on map_bl
-*------------------------------------------*/
-int map_freeblock_unlock (void)
-{
- if ((--block_free_lock) == 0) {
+ * Remove the lock on map_bl
+ *------------------------------------------*/
+int map_freeblock_unlock (void) {
+
+ if ((--map->block_free_lock) == 0) {
int i;
- for (i = 0; i < block_free_count; i++)
- {
- aFree(block_free[i]);
- block_free[i] = NULL;
+ for (i = 0; i < map->block_free_count; i++) {
+ if( map->block_free[i]->type == BL_ITEM )
+ ers_free(map->flooritem_ers, map->block_free[i]);
+ else
+ aFree(map->block_free[i]);
+ map->block_free[i] = NULL;
}
- block_free_count = 0;
- } else if (block_free_lock < 0) {
+ map->block_free_count = 0;
+ } else if (map->block_free_lock < 0) {
ShowError("map_freeblock_unlock: lock count < 0 !\n");
- block_free_lock = 0;
+ map->block_free_lock = 0;
}
- return block_free_lock;
+ return map->block_free_lock;
}
// Timer function to check if there some remaining lock and remove them if so.
// Called each 1s
-int map_freeblock_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
- if (block_free_lock > 0) {
- ShowError("map_freeblock_timer: block_free_lock(%d) is invalid.\n", block_free_lock);
- block_free_lock = 1;
- iMap->freeblock_unlock();
+int map_freeblock_timer(int tid, int64 tick, int id, intptr_t data) {
+ if (map->block_free_lock > 0) {
+ ShowError("map_freeblock_timer: block_free_lock(%d) is invalid.\n", map->block_free_lock);
+ map->block_free_lock = 1;
+ map->freeblock_unlock();
}
return 0;
}
-//
-// blocklist
-//
-/*==========================================
-* Handling of map_bl[]
-* The adresse of bl_heal is set in bl->prev
-*------------------------------------------*/
-static struct block_list bl_head;
-
+/**
+ * Updates the counter (cell.cell_bl) of how many objects are on a tile.
+ * @param add Whether the counter should be increased or decreased
+ **/
+void map_update_cell_bl( struct block_list *bl, bool increase ) {
#ifdef CELL_NOSTACK
-/*==========================================
-* These pair of functions update the counter of how many objects
-* lie on a tile.
-*------------------------------------------*/
-static void map_addblcell(struct block_list *bl)
-{
- if( bl->m<0 || bl->x<0 || bl->x>=map[bl->m].xs || bl->y<0 || bl->y>=map[bl->m].ys || !(bl->type&BL_CHAR) )
- return;
- map[bl->m].cell[bl->x+bl->y*map[bl->m].xs].cell_bl++;
- return;
-}
+ int pos;
-static void map_delblcell(struct block_list *bl)
-{
- if( bl->m <0 || bl->x<0 || bl->x>=map[bl->m].xs || bl->y<0 || bl->y>=map[bl->m].ys || !(bl->type&BL_CHAR) )
+ if( bl->m < 0 || bl->x < 0 || bl->x >= map->list[bl->m].xs
+ || bl->y < 0 || bl->y >= map->list[bl->m].ys
+ || !(bl->type&BL_CHAR) )
return;
- map[bl->m].cell[bl->x+bl->y*map[bl->m].xs].cell_bl--;
-}
+
+ // When reading from mapcache the cell isn't initialized
+ // TODO: Maybe start initializing cells when they're loaded instead of
+ // having to get them here? [Panikon]
+ if( map->list[bl->m].cell == (struct mapcell *)0xdeadbeaf )
+ map->cellfromcache(&map->list[bl->m]);
+
+ pos = bl->x + bl->y*map->list[bl->m].xs;
+ if( increase )
+ map->list[bl->m].cell[pos].cell_bl++;
+ else
+ map->list[bl->m].cell[pos].cell_bl--;
#endif
+ return;
+}
/*==========================================
-* Adds a block to the map.
-* Returns 0 on success, 1 on failure (illegal coordinates).
-*------------------------------------------*/
+ * Adds a block to the map.
+ * Returns 0 on success, 1 on failure (illegal coordinates).
+ *------------------------------------------*/
int map_addblock(struct block_list* bl)
{
int16 m, x, y;
@@ -262,41 +214,39 @@ int map_addblock(struct block_list* bl)
m = bl->m;
x = bl->x;
y = bl->y;
- if( m < 0 || m >= iMap->map_num )
- {
- ShowError("map_addblock: invalid map id (%d), only %d are loaded.\n", m, iMap->map_num);
+ if( m < 0 || m >= map->count ) {
+ ShowError("map_addblock: invalid map id (%d), only %d are loaded.\n", m, map->count);
return 1;
}
- if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
- {
- ShowError("map_addblock: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d\n", map[m].name, x, y, map[m].xs, map[m].ys);
+ if( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) {
+ ShowError("map_addblock: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d\n", map->list[m].name, x, y, map->list[m].xs, map->list[m].ys);
return 1;
}
- pos = x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs;
+ pos = x/BLOCK_SIZE+(y/BLOCK_SIZE)*map->list[m].bxs;
if (bl->type == BL_MOB) {
- bl->next = map[m].block_mob[pos];
- bl->prev = &bl_head;
+ bl->next = map->list[m].block_mob[pos];
+ bl->prev = &map->bl_head;
if (bl->next) bl->next->prev = bl;
- map[m].block_mob[pos] = bl;
+ map->list[m].block_mob[pos] = bl;
} else {
- bl->next = map[m].block[pos];
- bl->prev = &bl_head;
+ bl->next = map->list[m].block[pos];
+ bl->prev = &map->bl_head;
if (bl->next) bl->next->prev = bl;
- map[m].block[pos] = bl;
+ map->list[m].block[pos] = bl;
}
#ifdef CELL_NOSTACK
- map_addblcell(bl);
+ map->update_cell_bl(bl, true);
#endif
return 0;
}
/*==========================================
-* Removes a block from the map.
-*------------------------------------------*/
+ * Removes a block from the map.
+ *------------------------------------------*/
int map_delblock(struct block_list* bl)
{
int pos;
@@ -305,26 +255,26 @@ int map_delblock(struct block_list* bl)
// blocklist (2ways chainlist)
if (bl->prev == NULL) {
if (bl->next != NULL) {
- // can't delete block (already at the begining of the chain)
+ // can't delete block (already at the beginning of the chain)
ShowError("map_delblock error : bl->next!=NULL\n");
}
return 0;
}
#ifdef CELL_NOSTACK
- map_delblcell(bl);
+ map->update_cell_bl(bl, false);
#endif
- pos = bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs;
+ pos = bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map->list[bl->m].bxs;
if (bl->next)
bl->next->prev = bl->prev;
- if (bl->prev == &bl_head) {
+ if (bl->prev == &map->bl_head) {
//Since the head of the list, update the block_list map of []
if (bl->type == BL_MOB) {
- map[bl->m].block_mob[pos] = bl->next;
+ map->list[bl->m].block_mob[pos] = bl->next;
} else {
- map[bl->m].block[pos] = bl->next;
+ map->list[bl->m].block[pos] = bl->next;
}
} else {
bl->prev->next = bl->next;
@@ -336,12 +286,11 @@ int map_delblock(struct block_list* bl)
}
/*==========================================
-* Moves a block a x/y target position. [Skotlex]
-* Pass flag as 1 to prevent doing skill->unit_move checks
-* (which are executed by default on BL_CHAR types)
-*------------------------------------------*/
-int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
-{
+ * Moves a block a x/y target position. [Skotlex]
+ * Pass flag as 1 to prevent doing skill->unit_move checks
+ * (which are executed by default on BL_CHAR types)
+ *------------------------------------------*/
+int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) {
int x0 = bl->x, y0 = bl->y;
struct status_change *sc = NULL;
int moveblock = ( x0/BLOCK_SIZE != x1/BLOCK_SIZE || y0/BLOCK_SIZE != y1/BLOCK_SIZE);
@@ -355,7 +304,7 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
//TODO: Perhaps some outs of bounds checking should be placed here?
if (bl->type&BL_CHAR) {
- sc = status_get_sc(bl);
+ sc = status->get_sc(bl);
skill->unit_move(bl,tick,2);
status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER);
@@ -363,21 +312,21 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
// status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); //Won't stop when you are knocked away, go figure...
status_change_end(bl, SC_NJ_TATAMIGAESHI, INVALID_TIMER);
status_change_end(bl, SC_MAGICROD, INVALID_TIMER);
- if (sc->data[SC_PROPERTYWALK] &&
+ if (sc && sc->data[SC_PROPERTYWALK] &&
sc->data[SC_PROPERTYWALK]->val3 >= skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) )
status_change_end(bl,SC_PROPERTYWALK,INVALID_TIMER);
} else if (bl->type == BL_NPC)
- npc_unsetcells((TBL_NPC*)bl);
+ npc->unsetcells((TBL_NPC*)bl);
- if (moveblock) iMap->delblock(bl);
+ if (moveblock) map->delblock(bl);
#ifdef CELL_NOSTACK
- else map_delblcell(bl);
+ else map->update_cell_bl(bl, false);
#endif
bl->x = x1;
bl->y = y1;
- if (moveblock) iMap->addblock(bl);
+ if (moveblock) map->addblock(bl);
#ifdef CELL_NOSTACK
- else map_addblcell(bl);
+ else map->update_cell_bl(bl, true);
#endif
if (bl->type&BL_CHAR) {
@@ -386,7 +335,7 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
if( bl->type == BL_PC && ((TBL_PC*)bl)->shadowform_id ) {//Shadow Form Target Moving
struct block_list *d_bl;
- if( (d_bl = iMap->id2bl(((TBL_PC*)bl)->shadowform_id)) == NULL || !check_distance_bl(bl,d_bl,10) ) {
+ if( (d_bl = map->id2bl(((TBL_PC*)bl)->shadowform_id)) == NULL || !check_distance_bl(bl,d_bl,10) ) {
if( d_bl )
status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER);
((TBL_PC*)bl)->shadowform_id = 0;
@@ -411,16 +360,17 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
if( sc->data[SC__SHADOWFORM] ) {//Shadow Form Caster Moving
struct block_list *d_bl;
- if( (d_bl = iMap->id2bl(sc->data[SC__SHADOWFORM]->val2)) == NULL || !check_distance_bl(bl,d_bl,10) )
+ if( (d_bl = map->id2bl(sc->data[SC__SHADOWFORM]->val2)) == NULL || !check_distance_bl(bl,d_bl,10) )
status_change_end(bl,SC__SHADOWFORM,INVALID_TIMER);
}
if (sc->data[SC_PROPERTYWALK]
- && sc->data[SC_PROPERTYWALK]->val3 < skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2)
- && iMap->find_skill_unit_oncell(bl,bl->x,bl->y,SO_ELECTRICWALK,NULL,0) == NULL
- && iMap->find_skill_unit_oncell(bl,bl->x,bl->y,SO_FIREWALK,NULL,0) == NULL
- && skill->unitsetting(bl,sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2,x0, y0,0)) {
- sc->data[SC_PROPERTYWALK]->val3++;
+ && sc->data[SC_PROPERTYWALK]->val3 < skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2)
+ && map->find_skill_unit_oncell(bl,bl->x,bl->y,SO_ELECTRICWALK,NULL,0) == NULL
+ && map->find_skill_unit_oncell(bl,bl->x,bl->y,SO_FIREWALK,NULL,0) == NULL
+ && skill->unitsetting(bl,sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2,x0, y0,0)
+ ) {
+ sc->data[SC_PROPERTYWALK]->val3++;
}
@@ -438,608 +388,848 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick)
}
}
} else if (bl->type == BL_NPC)
- npc_setcells((TBL_NPC*)bl);
+ npc->setcells((TBL_NPC*)bl);
return 0;
}
/*==========================================
-* Counts specified number of objects on given cell.
-*------------------------------------------*/
-int map_count_oncell(int16 m, int16 x, int16 y, int type)
-{
+ * Counts specified number of objects on given cell.
+ * TODO: merge with bl_getall_area
+ *------------------------------------------*/
+int map_count_oncell(int16 m, int16 x, int16 y, int type) {
int bx,by;
struct block_list *bl;
int count = 0;
- if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys))
+ if (x < 0 || y < 0 || (x >= map->list[m].xs) || (y >= map->list[m].ys))
return 0;
bx = x/BLOCK_SIZE;
by = y/BLOCK_SIZE;
if (type&~BL_MOB)
- for( bl = map[m].block[bx+by*map[m].bxs] ; bl != NULL ; bl = bl->next )
+ for( bl = map->list[m].block[bx+by*map->list[m].bxs] ; bl != NULL ; bl = bl->next )
if(bl->x == x && bl->y == y && bl->type&type)
count++;
if (type&BL_MOB)
- for( bl = map[m].block_mob[bx+by*map[m].bxs] ; bl != NULL ; bl = bl->next )
+ for( bl = map->list[m].block_mob[bx+by*map->list[m].bxs] ; bl != NULL ; bl = bl->next )
if(bl->x == x && bl->y == y)
count++;
return count;
}
/*
-* Looks for a skill unit on a given cell
-* flag&1: runs battle_check_target check based on unit->group->target_flag
-*/
+ * Looks for a skill unit on a given cell
+ * flag&1: runs battle_check_target check based on unit->group->target_flag
+ */
struct skill_unit* map_find_skill_unit_oncell(struct block_list* target,int16 x,int16 y,uint16 skill_id,struct skill_unit* out_unit, int flag) {
int16 m,bx,by;
struct block_list *bl;
- struct skill_unit *unit;
+ struct skill_unit *su;
m = target->m;
- if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys))
+ if (x < 0 || y < 0 || (x >= map->list[m].xs) || (y >= map->list[m].ys))
return NULL;
bx = x/BLOCK_SIZE;
by = y/BLOCK_SIZE;
- for( bl = map[m].block[bx+by*map[m].bxs] ; bl != NULL ; bl = bl->next )
- {
+ for( bl = map->list[m].block[bx+by*map->list[m].bxs] ; bl != NULL ; bl = bl->next ) {
if (bl->x != x || bl->y != y || bl->type != BL_SKILL)
continue;
- unit = (struct skill_unit *) bl;
- if( unit == out_unit || !unit->alive || !unit->group || unit->group->skill_id != skill_id )
+ su = (struct skill_unit *) bl;
+ if( su == out_unit || !su->alive || !su->group || su->group->skill_id != skill_id )
continue;
- if( !(flag&1) || battle->check_target(&unit->bl,target,unit->group->target_flag) > 0 )
- return unit;
+ if( !(flag&1) || battle->check_target(&su->bl,target,su->group->target_flag) > 0 )
+ return su;
}
return NULL;
}
-/*==========================================
-* Adapted from foreachinarea for an easier invocation. [Skotlex]
-*------------------------------------------*/
-int map_foreachinrange(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int type, ...)
-{
- int bx, by, m;
- int returnCount = 0; //total sum of returned values of func() [Skotlex]
- struct block_list *bl;
- int blockcount = bl_list_count, i;
- int x0, x1, y0, y1;
- va_list ap;
-
- m = center->m;
- x0 = max(center->x - range, 0);
- y0 = max(center->y - range, 0);
- x1 = min(center->x + range, map[ m ].xs - 1);
- y1 = min(center->y + range, map[ m ].ys - 1);
-
- if ( type&~BL_MOB )
- for ( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) {
- for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) {
- for( bl = map[m].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->type&type
- && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1
-#ifdef CIRCULAR_AREA
- && check_distance_bl(center, bl, range)
-#endif
- && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
- }
- }
- }
-
- if( type&BL_MOB )
- for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) {
- for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++) {
- for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1
-#ifdef CIRCULAR_AREA
- && check_distance_bl(center, bl, range)
-#endif
- && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
- }
- }
- }
-
- if( bl_list_count >= BL_LIST_MAX )
- ShowWarning("iMap->foreachinrange: block count too many!\n");
+/** @name Functions for block_list search and manipulation
+ */
- iMap->freeblock_lock();
+/* @{ */
+/**
+ * Applies func to every block_list in bl_list starting with bl_list[blockcount].
+ * Sets bl_list_count back to blockcount.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param blockcount Index of first relevant entry in bl_list
+ * @param max Maximum sum of values returned by func (usually max number of func calls)
+ * @param args Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+static int bl_vforeach(int (*func)(struct block_list*, va_list), int blockcount, int max, va_list args) {
+ int i;
+ int returnCount = 0;
- for( i = blockcount; i < bl_list_count; i++ )
- if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion.
- va_start(ap, type);
- returnCount += func(bl_list[ i ], ap);
- va_end(ap);
- }
+ map->freeblock_lock();
+ for (i = blockcount; i < map->bl_list_count && returnCount < max; i++) {
+ if (map->bl_list[i]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasn't queued for deletion.
+ va_list argscopy;
+ va_copy(argscopy, args);
+ returnCount += func(map->bl_list[i], argscopy);
+ va_end(argscopy);
+ }
+ }
+ map->freeblock_unlock();
- iMap->freeblock_unlock();
+ map->bl_list_count = blockcount;
- bl_list_count = blockcount;
- return returnCount; //[Skotlex]
+ return returnCount;
}
-/*==========================================
-* Same as foreachinrange, but there must be a shoot-able range between center and target to be counted in. [Skotlex]
-*------------------------------------------*/
-int map_foreachinshootrange(int (*func)(struct block_list*,va_list),struct block_list* center, int16 range, int type,...)
-{
- int bx, by, m;
- int returnCount = 0; //total sum of returned values of func() [Skotlex]
+/**
+ * Applies func to every block_list object of bl_type type on map m.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param m Map id
+ * @param type enum bl_type
+ * @param args Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+static int map_vforeachinmap(int (*func)(struct block_list*, va_list), int16 m, int type, va_list args) {
+ int i;
+ int returnCount = 0;
+ int bsize;
+ va_list argscopy;
struct block_list *bl;
- int blockcount = bl_list_count, i;
- int x0, x1, y0, y1;
- va_list ap;
+ int blockcount = map->bl_list_count;
- m = center->m;
- if ( m < 0 )
+ if (m < 0)
return 0;
- x0 = max(center->x-range, 0);
- y0 = max(center->y-range, 0);
- x1 = min(center->x+range, map[m].xs-1);
- y1 = min(center->y+range, map[m].ys-1);
-
- if ( type&~BL_MOB )
- for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) {
- for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) {
- for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->type&type
- && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1
-#ifdef CIRCULAR_AREA
- && check_distance_bl(center, bl, range)
-#endif
- && path_search_long(NULL, center->m, center->x, center->y, bl->x, bl->y, CELL_CHKWALL)
- && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
+ bsize = map->list[m].bxs * map->list[m].bys;
+ for (i = 0; i < bsize; i++) {
+ if (type&~BL_MOB) {
+ for (bl = map->list[m].block[i]; bl != NULL; bl = bl->next) {
+ if (bl->type&type) {
+ if( map->bl_list_count >= map->bl_list_size )
+ map_bl_list_expand();
+ map->bl_list[map->bl_list_count++] = bl;
}
}
}
- if( type&BL_MOB )
- for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) {
- for( bx=x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) {
- for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1
-#ifdef CIRCULAR_AREA
- && check_distance_bl(center, bl, range)
-#endif
- && path_search_long(NULL, center->m, center->x, center->y, bl->x, bl->y, CELL_CHKWALL)
- && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
- }
- }
+ if (type&BL_MOB) {
+ for (bl = map->list[m].block_mob[i]; bl != NULL; bl = bl->next) {
+ if( map->bl_list_count >= map->bl_list_size )
+ map_bl_list_expand();
+ map->bl_list[map->bl_list_count++] = bl;
}
+ }
+ }
- if( bl_list_count >= BL_LIST_MAX )
- ShowWarning("iMap->foreachinrange: block count too many!\n");
+ va_copy(argscopy, args);
+ returnCount = bl_vforeach(func, blockcount, INT_MAX, argscopy);
+ va_end(argscopy);
- iMap->freeblock_lock();
+ return returnCount;
+}
- for( i = blockcount; i < bl_list_count; i++ )
- if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion.
- va_start(ap, type);
- returnCount += func(bl_list[ i ], ap);
- va_end(ap);
- }
+/**
+ * Applies func to every block_list object of bl_type type on map m.
+ * Returns the sum of values returned by func.
+ * @see map_vforeachinmap
+ * @param func Function to be applied
+ * @param m Map id
+ * @param type enum bl_type
+ * @param ... Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_foreachinmap(int (*func)(struct block_list*, va_list), int16 m, int type, ...) {
+ int returnCount;
+ va_list ap;
- iMap->freeblock_unlock();
+ va_start(ap, type);
+ returnCount = map->vforeachinmap(func, m, type, ap);
+ va_end(ap);
- bl_list_count = blockcount;
- return returnCount; //[Skotlex]
+ return returnCount;
}
-/*==========================================
-* range = map m (x0,y0)-(x1,y1)
-* Apply *func with ... arguments for the range.
-* @type = BL_PC/BL_MOB etc..
-*------------------------------------------*/
-int map_foreachinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, ...)
-{
+/**
+ * Applies func to every block_list object of bl_type type on all maps
+ * of instance instance_id.
+ * Returns the sum of values returned by func.
+ * @see map_vforeachinmap.
+ * @param func Function to be applied
+ * @param m Map id
+ * @param type enum bl_type
+ * @param ap Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_vforeachininstance(int (*func)(struct block_list*, va_list), int16 instance_id, int type, va_list ap) {
+ int i;
+ int returnCount = 0;
+
+ for (i = 0; i < instance->list[instance_id].num_map; i++) {
+ int m = instance->list[instance_id].map[i];
+ va_list apcopy;
+ va_copy(apcopy, ap);
+ returnCount += map->vforeachinmap(func, m, type, apcopy);
+ va_end(apcopy);
+ }
+
+ return returnCount;
+}
+
+/**
+ * Applies func to every block_list object of bl_type type on all maps
+ * of instance instance_id.
+ * Returns the sum of values returned by func.
+ * @see map_vforeachininstance.
+ * @param func Function to be applied
+ * @param m Map id
+ * @param type enum bl_type
+ * @param ... Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_foreachininstance(int (*func)(struct block_list*, va_list), int16 instance_id, int type, ...) {
+ int returnCount;
+ va_list ap;
+
+ va_start(ap, type);
+ returnCount = map->vforeachininstance(func, instance_id, type, ap);
+ va_end(ap);
+
+ return returnCount;
+}
+
+/**
+ * Retrieves all map objects in area that are matched by the type
+ * and func. Appends them at the end of global bl_list array.
+ * @param type Matching enum bl_type
+ * @param m Map
+ * @param func Matching function
+ * @param ... Extra arguments for func
+ * @return Number of found objects
+ */
+static int bl_getall_area(int type, int m, int x0, int y0, int x1, int y1, int (*func)(struct block_list*, va_list), ...) {
+ va_list args;
int bx, by;
- int returnCount = 0; //total sum of returned values of func() [Skotlex]
struct block_list *bl;
- int blockcount = bl_list_count, i;
- va_list ap;
+ int found = 0;
- if ( m < 0 )
+ if (m < 0)
return 0;
- if ( x1 < x0 )
- swap(x0, x1);
- if ( y1 < y0 )
- swap(y0, y1);
+ if (x1 < x0) swap(x0, x1);
+ if (y1 < y0) swap(y0, y1);
+ // Limit search area to map size
x0 = max(x0, 0);
y0 = max(y0, 0);
- x1 = min(x1, map[ m ].xs - 1);
- y1 = min(y1, map[ m ].ys - 1);
- if ( type&~BL_MOB )
- for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ )
- for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ )
- for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next )
- if( bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
+ x1 = min(x1, map->list[m].xs - 1);
+ y1 = min(y1, map->list[m].ys - 1);
+
+ for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) {
+ for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) {
+ if (type&~BL_MOB) {
+ for (bl = map->list[m].block[bx + by * map->list[m].bxs]; bl != NULL; bl = bl->next) {
+ if (bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1) {
+ if( map->bl_list_count >= map->bl_list_size )
+ map_bl_list_expand();
+ if (func) {
+ va_start(args, func);
+ if (func(bl, args)) {
+ map->bl_list[map->bl_list_count++] = bl;
+ found++;
+ }
+ va_end(args);
+ } else {
+ map->bl_list[map->bl_list_count++] = bl;
+ found++;
+ }
+ }
+ }
+ }
+ if (type&BL_MOB) { // TODO: fix this code duplication
+ for (bl = map->list[m].block_mob[bx + by * map->list[m].bxs]; bl != NULL; bl = bl->next) {
+ if (bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1) {
+ if( map->bl_list_count >= map->bl_list_size )
+ map_bl_list_expand();
+ if (func) {
+ va_start(args, func);
+ if (func(bl, args)) {
+ map->bl_list[map->bl_list_count++] = bl;
+ found++;
+ }
+ va_end(args);
+ } else {
+ map->bl_list[map->bl_list_count++] = bl;
+ found++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return found;
+}
- if( type&BL_MOB )
- for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ )
- for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ )
- for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next )
- if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
+/**
+ * Checks if bl is within range cells from center.
+ * If CIRCULAR AREA is not used always returns 1, since
+ * preliminary range selection is already done in bl_getall_area.
+ * @return 1 if matches, 0 otherwise
+ */
+static int bl_vgetall_inrange(struct block_list *bl, va_list args)
+{
+#ifdef CIRCULAR_AREA
+ struct block_list *center = va_arg(args, struct block_list*);
+ int range = va_arg(args, int);
+ if (!check_distance_bl(center, bl, range))
+ return 0;
+#endif
+ return 1;
+}
- if( bl_list_count >= BL_LIST_MAX )
- ShowWarning("map_foreachinarea: block count too many!\n");
+/**
+ * Applies func to every block_list object of bl_type type within range cells from center.
+ * Area is rectangular, unless CIRCULAR_AREA is defined.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param center Center of the selection area
+ * @param range Range in cells from center
+ * @param type enum bl_type
+ * @param ap Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_vforeachinrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int type, va_list ap) {
+ int returnCount = 0;
+ int blockcount = map->bl_list_count;
+ va_list apcopy;
+
+ if (range < 0) range *= -1;
+
+ bl_getall_area(type, center->m, center->x - range, center->y - range, center->x + range, center->y + range, bl_vgetall_inrange, center, range);
+
+ va_copy(apcopy, ap);
+ returnCount = bl_vforeach(func, blockcount, INT_MAX, apcopy);
+ va_end(apcopy);
- iMap->freeblock_lock();
+ return returnCount;
+}
- for( i = blockcount; i < bl_list_count; i++ )
- if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion.
- va_start(ap, type);
- returnCount += func(bl_list[ i ], ap);
- va_end(ap);
- }
+/**
+ * Applies func to every block_list object of bl_type type within range cells from center.
+ * Area is rectangular, unless CIRCULAR_AREA is defined.
+ * Returns the sum of values returned by func.
+ * @see map_vforeachinrange
+ * @param func Function to be applied
+ * @param center Center of the selection area
+ * @param range Range in cells from center
+ * @param type enum bl_type
+ * @param ... Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_foreachinrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int type, ...) {
+ int returnCount;
+ va_list ap;
- iMap->freeblock_unlock();
+ va_start(ap, type);
+ returnCount = map->vforeachinrange(func, center, range, type, ap);
+ va_end(ap);
- bl_list_count = blockcount;
- return returnCount; //[Skotlex]
+ return returnCount;
}
-/*==========================================
-* Adapted from forcountinarea for an easier invocation. [pakpil]
-*------------------------------------------*/
-int map_forcountinrange(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int count, int type, ...)
-{
- int bx, by, m;
- int returnCount = 0; //total sum of returned values of func() [Skotlex]
- struct block_list *bl;
- int blockcount = bl_list_count, i;
- int x0, x1, y0, y1;
+
+/**
+ * Applies func to some block_list objects of bl_type type within range cells from center.
+ * Limit is set by count parameter.
+ * Area is rectangular, unless CIRCULAR_AREA is defined.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param center Center of the selection area
+ * @param range Range in cells from center
+ * @param count Maximum sum of values returned by func (usually max number of func calls)
+ * @param type enum bl_type
+ * @param ap Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_vforcountinrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int count, int type, va_list ap) {
+ int returnCount = 0;
+ int blockcount = map->bl_list_count;
+ va_list apcopy;
+
+ if (range < 0) range *= -1;
+
+ bl_getall_area(type, center->m, center->x - range, center->y - range, center->x + range, center->y + range, bl_vgetall_inrange, center, range);
+
+ va_copy(apcopy, ap);
+ returnCount = bl_vforeach(func, blockcount, count, apcopy);
+ va_end(apcopy);
+
+ return returnCount;
+}
+
+/**
+ * Applies func to some block_list objects of bl_type type within range cells from center.
+ * Limit is set by count parameter.
+ * Area is rectangular, unless CIRCULAR_AREA is defined.
+ * Returns the sum of values returned by func.
+ * @see map_vforcountinrange
+ * @param func Function to be applied
+ * @param center Center of the selection area
+ * @param range Range in cells from center
+ * @param count Maximum sum of values returned by func (usually max number of func calls)
+ * @param type enum bl_type
+ * @param ... Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_forcountinrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int count, int type, ...) {
+ int returnCount;
va_list ap;
- m = center->m;
- x0 = max(center->x - range, 0);
- y0 = max(center->y - range, 0);
- x1 = min(center->x + range, map[ m ].xs - 1);
- y1 = min(center->y + range, map[ m ].ys - 1);
-
- if ( type&~BL_MOB )
- for ( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) {
- for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) {
- for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->type&type
- && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1
-#ifdef CIRCULAR_AREA
- && check_distance_bl(center, bl, range)
-#endif
- && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
- }
- }
- }
- if( type&BL_MOB )
- for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) {
- for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ){
- for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1
+ va_start(ap, type);
+ returnCount = map->vforcountinrange(func, center, range, count, type, ap);
+ va_end(ap);
+
+ return returnCount;
+}
+
+/**
+ * Checks if bl is within shooting range from center.
+ * There must be a shootable path between bl and center.
+ * Does not check for range if CIRCULAR AREA is not defined, since
+ * preliminary range selection is already done in bl_getall_area.
+ * @return 1 if matches, 0 otherwise
+ */
+static int bl_vgetall_inshootrange(struct block_list *bl, va_list args)
+{
+ struct block_list *center = va_arg(args, struct block_list*);
#ifdef CIRCULAR_AREA
- && check_distance_bl(center, bl, range)
+ int range = va_arg(args, int);
+ if (!check_distance_bl(center, bl, range))
+ return 0;
#endif
- && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
- }
- }
- }
+ if (!path->search_long(NULL, center->m, center->x, center->y, bl->x, bl->y, CELL_CHKWALL))
+ return 0;
+ return 1;
+}
- if( bl_list_count >= BL_LIST_MAX )
- ShowWarning("map_forcountinrange: block count too many!\n");
+/**
+ * Applies func to every block_list object of bl_type type within shootable range from center.
+ * There must be a shootable path between bl and center.
+ * Area is rectangular, unless CIRCULAR_AREA is defined.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param center Center of the selection area
+ * @param range Range in cells from center
+ * @param type enum bl_type
+ * @param ap Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_vforeachinshootrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int type, va_list ap) {
+ int returnCount = 0;
+ int blockcount = map->bl_list_count;
+ va_list apcopy;
+
+ if (range < 0) range *= -1;
+
+ bl_getall_area(type, center->m, center->x - range, center->y - range, center->x + range, center->y + range, bl_vgetall_inshootrange, center, range);
+
+ va_copy(apcopy, ap);
+ returnCount = bl_vforeach(func, blockcount, INT_MAX, ap);
+ va_end(apcopy);
- iMap->freeblock_lock();
+ return returnCount;
+}
- for( i = blockcount; i < bl_list_count; i++ )
- if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion.
- va_start(ap, type);
- returnCount += func(bl_list[ i ], ap);
- va_end(ap);
- if( count && returnCount >= count )
- break;
- }
+/**
+ * Applies func to every block_list object of bl_type type within shootable range from center.
+ * There must be a shootable path between bl and center.
+ * Area is rectangular, unless CIRCULAR_AREA is defined.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param center Center of the selection area
+ * @param range Range in cells from center
+ * @param type enum bl_type
+ * @param ... Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_foreachinshootrange(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int type, ...) {
+ int returnCount;
+ va_list ap;
- iMap->freeblock_unlock();
+ va_start(ap, type);
+ returnCount = map->vforeachinshootrange(func, center, range, type, ap);
+ va_end(ap);
- bl_list_count = blockcount;
- return returnCount; //[Skotlex]
+ return returnCount;
}
-int map_forcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int count, int type, ...)
-{
- int bx, by;
- int returnCount = 0; //total sum of returned values of func() [Skotlex]
- struct block_list *bl;
- int blockcount = bl_list_count, i;
+
+/**
+ * Applies func to every block_list object of bl_type type in
+ * rectangular area (x0,y0)~(x1,y1) on map m.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param m Map id
+ * @param x0 Starting X-coordinate
+ * @param y0 Starting Y-coordinate
+ * @param x1 Ending X-coordinate
+ * @param y1 Ending Y-coordinate
+ * @param type enum bl_type
+ * @param ap Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_vforeachinarea(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, va_list ap) {
+ int returnCount = 0;
+ int blockcount = map->bl_list_count;
+ va_list apcopy;
+
+ bl_getall_area(type, m, x0, y0, x1, y1, NULL);
+
+ va_copy(apcopy, ap);
+ returnCount = bl_vforeach(func, blockcount, INT_MAX, apcopy);
+ va_end(apcopy);
+
+ return returnCount;
+}
+
+/**
+ * Applies func to every block_list object of bl_type type in
+ * rectangular area (x0,y0)~(x1,y1) on map m.
+ * Returns the sum of values returned by func.
+ * @see map_vforeachinarea
+ * @param func Function to be applied
+ * @param m Map id
+ * @param x0 Starting X-coordinate
+ * @param y0 Starting Y-coordinate
+ * @param x1 Ending X-coordinate
+ * @param y1 Ending Y-coordinate
+ * @param type enum bl_type
+ * @param ... Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_foreachinarea(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, ...) {
+ int returnCount;
va_list ap;
- if ( m < 0 )
- return 0;
+ va_start(ap, type);
+ returnCount = map->vforeachinarea(func, m, x0, y0, x1, y1, type, ap);
+ va_end(ap);
- if ( x1 < x0 )
- swap(x0, x1);
- if ( y1 < y0 )
- swap(y0, y1);
+ return returnCount;
+}
- x0 = max(x0, 0);
- y0 = max(y0, 0);
- x1 = min(x1, map[ m ].xs - 1);
- y1 = min(y1, map[ m ].ys - 1);
-
- if ( type&~BL_MOB )
- for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ )
- for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ )
- for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next )
- if( bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
-
- if( type&BL_MOB )
- for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ )
- for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ )
- for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next )
- if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
-
- if( bl_list_count >= BL_LIST_MAX )
- ShowWarning("map_foreachinarea: block count too many!\n");
-
- iMap->freeblock_lock();
-
- for( i = blockcount; i < bl_list_count; i++ )
- if(bl_list[ i ]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion.
- va_start(ap, type);
- returnCount += func(bl_list[ i ], ap);
- va_end(ap);
- if( count && returnCount >= count )
- break;
- }
+/**
+ * Applies func to some block_list objects of bl_type type in
+ * rectangular area (x0,y0)~(x1,y1) on map m.
+ * Limit is set by @count parameter.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param m Map id
+ * @param x0 Starting X-coordinate
+ * @param y0 Starting Y-coordinate
+ * @param x1 Ending X-coordinate
+ * @param y1 Ending Y-coordinate
+ * @param count Maximum sum of values returned by func (usually max number of func calls)
+ * @param type enum bl_type
+ * @param ap Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_vforcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int count, int type, va_list ap) {
+ int returnCount = 0;
+ int blockcount = map->bl_list_count;
+ va_list apcopy;
+
+ bl_getall_area(type, m, x0, y0, x1, y1, NULL);
+
+ va_copy(apcopy, ap);
+ returnCount = bl_vforeach(func, blockcount, count, apcopy);
+ va_end(apcopy);
+
+ return returnCount;
+}
+
+/**
+ * Applies func to some block_list objects of bl_type type in
+ * rectangular area (x0,y0)~(x1,y1) on map m.
+ * Limit is set by @count parameter.
+ * Returns the sum of values returned by func.
+ * @see map_vforcountinarea
+ * @param func Function to be applied
+ * @param m Map id
+ * @param x0 Starting X-coordinate
+ * @param y0 Starting Y-coordinate
+ * @param x1 Ending X-coordinate
+ * @param y1 Ending Y-coordinate
+ * @param count Maximum sum of values returned by func (usually max number of func calls)
+ * @param type enum bl_type
+ * @param ... Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_forcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int count, int type, ...) {
+ int returnCount;
+ va_list ap;
- iMap->freeblock_unlock();
+ va_start(ap, type);
+ returnCount = map->vforcountinarea(func, m, x0, y0, x1, y1, count, type, ap);
+ va_end(ap);
- bl_list_count = blockcount;
- return returnCount; //[Skotlex]
+ return returnCount;
}
-/*==========================================
-* For what I get
-* Move bl and do func* with va_list while moving.
-* Mouvement is set by dx dy wich are distance in x and y
-*------------------------------------------*/
-int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int16 dx, int16 dy, int type, ...)
+/**
+ * Checks if bl is inside area that was in range cells from the center
+ * before it was moved by (dx,dy) cells, but it is not in range cells
+ * from center after movement is completed.
+ * In other words, checks if bl is inside area that is no longer covered
+ * by center's range.
+ * Preliminary range selection is already done in bl_getall_area.
+ * @return 1 if matches, 0 otherwise
+ */
+static int bl_vgetall_inmovearea(struct block_list *bl, va_list args)
{
- int bx, by, m;
- int returnCount = 0; //total sum of returned values of func() [Skotlex]
- struct block_list *bl;
- int blockcount = bl_list_count, i;
- int x0, x1, y0, y1;
- va_list ap;
+ int dx = va_arg(args, int);
+ int dy = va_arg(args, int);
+ struct block_list *center = va_arg(args, struct block_list*);
+ int range = va_arg(args, int);
+
+ if ((dx > 0 && bl->x < center->x - range + dx) ||
+ (dx < 0 && bl->x > center->x + range + dx) ||
+ (dy > 0 && bl->y < center->y - range + dy) ||
+ (dy < 0 && bl->y > center->y + range + dy))
+ return 1;
+ return 0;
+}
- if ( !range ) return 0;
- if ( !dx && !dy ) return 0; //No movement.
+/**
+ * Applies func to every block_list object of bl_type type in
+ * area that was covered by range cells from center, but is no
+ * longer after center is moved by (dx,dy) cells (i.e. area that
+ * center has lost sight of).
+ * If used after center has reached its destination and with
+ * opposed movement vector (-dx,-dy), selection corresponds
+ * to new area in center's view).
+ * Uses rectangular area.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param center Center of the selection area
+ * @param range Range in cells from center
+ * @param dx Center's movement on X-axis
+ * @param dy Center's movement on Y-axis
+ * @param type enum bl_type
+ * @param ap Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_vforeachinmovearea(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int16 dx, int16 dy, int type, va_list ap) {
+ int returnCount = 0;
+ int blockcount = map->bl_list_count;
+ int m, x0, x1, y0, y1;
+ va_list apcopy;
+
+ if (!range) return 0;
+ if (!dx && !dy) return 0; // No movement.
+
+ if (range < 0) range *= -1;
m = center->m;
-
x0 = center->x - range;
x1 = center->x + range;
y0 = center->y - range;
y1 = center->y + range;
- if ( x1 < x0 )
- swap(x0, x1);
- if ( y1 < y0 )
- swap(y0, y1);
-
- if( dx == 0 || dy == 0 ) {
- //Movement along one axis only.
- if( dx == 0 ){
- if( dy < 0 ) //Moving south
- y0 = y1 + dy + 1;
- else //North
- y1 = y0 + dy - 1;
+ if (dx == 0 || dy == 0) { // Movement along one axis only.
+ if (dx == 0) {
+ if (dy < 0) { y0 = y1 + dy + 1; } // Moving south
+ else { y1 = y0 + dy - 1; } // North
} else { //dy == 0
- if( dx < 0 ) //West
- x0 = x1 + dx + 1;
- else //East
- x1 = x0 + dx - 1;
- }
-
- x0 = max(x0, 0);
- y0 = max(y0, 0);
- x1 = min(x1, map[ m ].xs - 1);
- y1 = min(y1, map[ m ].ys - 1);
-
- for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) {
- for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) {
- if ( type&~BL_MOB ) {
- for( bl = map[m].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->type&type &&
- bl->x >= x0 && bl->x <= x1 &&
- bl->y >= y0 && bl->y <= y1 &&
- bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
- }
- }
- if ( type&BL_MOB ) {
- for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->x >= x0 && bl->x <= x1 &&
- bl->y >= y0 && bl->y <= y1 &&
- bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
- }
- }
- }
- }
- } else { // Diagonal movement
-
- x0 = max(x0, 0);
- y0 = max(y0, 0);
- x1 = min(x1, map[ m ].xs - 1);
- y1 = min(y1, map[ m ].ys - 1);
-
- for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) {
- for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) {
- if ( type & ~BL_MOB ) {
- for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->type&type &&
- bl->x >= x0 && bl->x <= x1 &&
- bl->y >= y0 && bl->y <= y1 &&
- bl_list_count < BL_LIST_MAX )
- if( ( dx > 0 && bl->x < x0 + dx) ||
- ( dx < 0 && bl->x > x1 + dx) ||
- ( dy > 0 && bl->y < y0 + dy) ||
- ( dy < 0 && bl->y > y1 + dy) )
- bl_list[ bl_list_count++ ] = bl;
- }
- }
- if ( type&BL_MOB ) {
- for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->x >= x0 && bl->x <= x1 &&
- bl->y >= y0 && bl->y <= y1 &&
- bl_list_count < BL_LIST_MAX)
- if( ( dx > 0 && bl->x < x0 + dx) ||
- ( dx < 0 && bl->x > x1 + dx) ||
- ( dy > 0 && bl->y < y0 + dy) ||
- ( dy < 0 && bl->y > y1 + dy) )
- bl_list[ bl_list_count++ ] = bl;
- }
- }
- }
+ if (dx < 0) { x0 = x1 + dx + 1; } // West
+ else { x1 = x0 + dx - 1; } // East
}
-
+ bl_getall_area(type, m, x0, y0, x1, y1, NULL);
+ }
+ else { // Diagonal movement
+ bl_getall_area(type, m, x0, y0, x1, y1, bl_vgetall_inmovearea, dx, dy, center, range);
}
- if( bl_list_count >= BL_LIST_MAX )
- ShowWarning("map_foreachinmovearea: block count too many!\n");
+ va_copy(apcopy, ap);
+ returnCount = bl_vforeach(func, blockcount, INT_MAX, apcopy);
+ va_end(apcopy);
- iMap->freeblock_lock(); // Prohibit the release from memory
+ return returnCount;
+}
- for( i = blockcount; i < bl_list_count; i++ )
- if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion.
- va_start(ap, type);
- returnCount += func(bl_list[ i ], ap);
- va_end(ap);
- }
+/**
+ * Applies func to every block_list object of bl_type type in
+ * area that was covered by range cells from center, but is no
+ * longer after center is moved by (dx,dy) cells (i.e. area that
+ * center has lost sight of).
+ * If used after center has reached its destination and with
+ * opposed movement vector (-dx,-dy), selection corresponds
+ * to new area in center's view).
+ * Uses rectangular area.
+ * Returns the sum of values returned by func.
+ * @see map_vforeachinmovearea
+ * @param func Function to be applied
+ * @param center Center of the selection area
+ * @param range Range in cells from center
+ * @param dx Center's movement on X-axis
+ * @param dy Center's movement on Y-axis
+ * @param type enum bl_type
+ * @param ... Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_foreachinmovearea(int (*func)(struct block_list*, va_list), struct block_list* center, int16 range, int16 dx, int16 dy, int type, ...) {
+ int returnCount;
+ va_list ap;
- iMap->freeblock_unlock(); // Allow Free
+ va_start(ap, type);
+ returnCount = map->vforeachinmovearea(func, center, range, dx, dy, type, ap);
+ va_end(ap);
- bl_list_count = blockcount;
- return returnCount;
+ return returnCount;
}
-// -- moonsoul (added map_foreachincell which is a rework of map_foreachinarea but
-// which only checks the exact single x/y passed to it rather than an
-// area radius - may be more useful in some instances)
-//
-int map_foreachincell(int (*func)(struct block_list*,va_list), int16 m, int16 x, int16 y, int type, ...)
-{
- int bx, by;
- int returnCount = 0; //total sum of returned values of func() [Skotlex]
- struct block_list *bl;
- int blockcount = bl_list_count, i;
+/**
+ * Applies func to every block_list object of bl_type type in
+ * cell (x,y) on map m.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param m Map id
+ * @param x Target cell X-coordinate
+ * @param y Target cell Y-coordinate
+ * @param type enum bl_type
+ * @param ap Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_vforeachincell(int (*func)(struct block_list*, va_list), int16 m, int16 x, int16 y, int type, va_list ap) {
+ int returnCount = 0;
+ int blockcount = map->bl_list_count;
+ va_list apcopy;
+
+ bl_getall_area(type, m, x, y, x, y, NULL);
+
+ va_copy(apcopy, ap);
+ returnCount = bl_vforeach(func, blockcount, INT_MAX, apcopy);
+ va_end(apcopy);
+
+ return returnCount;
+}
+
+/**
+ * Applies func to every block_list object of bl_type type in
+ * cell (x,y) on map m.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param m Map id
+ * @param x Target cell X-coordinate
+ * @param y Target cell Y-coordinate
+ * @param type enum bl_type
+ * @param ... Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_foreachincell(int (*func)(struct block_list*, va_list), int16 m, int16 x, int16 y, int type, ...) {
+ int returnCount;
va_list ap;
- if ( x < 0 || y < 0 || x >= map[ m ].xs || y >= map[ m ].ys ) return 0;
+ va_start(ap, type);
+ returnCount = map->vforeachincell(func, m, x, y, type, ap);
+ va_end(ap);
- by = y / BLOCK_SIZE;
- bx = x / BLOCK_SIZE;
+ return returnCount;
+}
- if( type&~BL_MOB )
- for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next )
- if( bl->type&type && bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
- if( type&BL_MOB )
- for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs]; bl != NULL; bl = bl->next )
- if( bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX)
- bl_list[ bl_list_count++ ] = bl;
+/**
+ * Helper function for map_foreachinpath()
+ * Checks if shortest distance from bl to path
+ * between (x0,y0) and (x1,y1) is shorter than range.
+ * @see map_foreachinpath
+ */
+static int bl_vgetall_inpath(struct block_list *bl, va_list args)
+{
+ int m = va_arg(args, int);
+ int x0 = va_arg(args, int);
+ int y0 = va_arg(args, int);
+ int x1 = va_arg(args, int);
+ int y1 = va_arg(args, int);
+ int range = va_arg(args, int);
+ int len_limit = va_arg(args, int);
+ int magnitude2 = va_arg(args, int);
+
+ int xi = bl->x;
+ int yi = bl->y;
+ int xu, yu;
+
+ int k = ( xi - x0 ) * ( x1 - x0 ) + ( yi - y0 ) * ( y1 - y0 );
+
+ if ( k < 0 || k > len_limit ) //Since more skills use this, check for ending point as well.
+ return 0;
- if( bl_list_count >= BL_LIST_MAX )
- ShowWarning("map_foreachincell: block count too many!\n");
+ if ( k > magnitude2 && !path->search_long(NULL, m, x0, y0, xi, yi, CELL_CHKWALL) )
+ return 0; //Targets beyond the initial ending point need the wall check.
- iMap->freeblock_lock();
+ //All these shifts are to increase the precision of the intersection point and distance considering how it's
+ //int math.
+ k = ( k << 4 ) / magnitude2; //k will be between 1~16 instead of 0~1
+ xi <<= 4;
+ yi <<= 4;
+ xu = ( x0 << 4 ) + k * ( x1 - x0 );
+ yu = ( y0 << 4 ) + k * ( y1 - y0 );
- for( i = blockcount; i < bl_list_count; i++ )
- if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion.
- va_start(ap, type);
- returnCount += func(bl_list[ i ], ap);
- va_end(ap);
- }
+//Avoid needless calculations by not getting the sqrt right away.
+#define MAGNITUDE2(x0, y0, x1, y1) ( ( ( x1 ) - ( x0 ) ) * ( ( x1 ) - ( x0 ) ) + ( ( y1 ) - ( y0 ) ) * ( ( y1 ) - ( y0 ) ) )
- iMap->freeblock_unlock();
+ k = MAGNITUDE2(xi, yi, xu, yu);
- bl_list_count = blockcount;
- return returnCount;
+ //If all dot coordinates were <<4 the square of the magnitude is <<8
+ if ( k > range )
+ return 0;
+
+ return 1;
}
-/*============================================================
-* For checking a path between two points (x0, y0) and (x1, y1)
-*------------------------------------------------------------*/
-int map_foreachinpath(int (*func)(struct block_list*,va_list),int16 m,int16 x0,int16 y0,int16 x1,int16 y1,int16 range,int length, int type,...)
-{
- int returnCount = 0; //total sum of returned values of func() [Skotlex]
- //////////////////////////////////////////////////////////////
- //
- // sharp shooting 3 [Skotlex]
- //
- //////////////////////////////////////////////////////////////
- // problem:
- // Same as Sharp Shooting 1. Hits all targets within range of
- // the line.
- // (t1,t2 t3 and t4 get hit)
- //
- // target 1
- // x t4
- // t2
- // t3 x
- // x
- // S
- //////////////////////////////////////////////////////////////
- // Methodology:
- // My trigonometrics and math are a little rusty... so the approach I am writing
- // here is basicly do a double for to check for all targets in the square that
+/**
+ * Applies func to every block_list object of bl_type type in
+ * path on a line between (x0,y0) and (x1,y1) on map m.
+ * Path starts at (x0,y0) and is \a length cells long and \a range cells wide.
+ * Objects beyond the initial (x1,y1) ending point are checked
+ * for walls in the path.
+ * Returns the sum of values returned by func.
+ * @param func Function to be applied
+ * @param m Map id
+ * @param x Target cell X-coordinate
+ * @param y Target cell Y-coordinate
+ * @param type enum bl_type
+ * @param ap Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_vforeachinpath(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int16 range, int length, int type, va_list ap) {
+ // [Skotlex]
+ // check for all targets in the square that
// contains the initial and final positions (area range increased to match the
// radius given), then for each object to test, calculate the distance to the
// path and include it if the range fits and the target is in the line (0<k<1,
// as they call it).
// The implementation I took as reference is found at
- // http://astronomy.swin.edu.au/~pbourke/geometry/pointline/
- // (they have a link to a C implementation, too)
- // This approach is a lot like #2 commented on this function, which I have no
- // idea why it was commented. I won't use doubles/floats, but pure int math for
+ // http://web.archive.org/web/20050720125314/http://astronomy.swin.edu.au/~pbourke/geometry/pointline/
+ // http://paulbourke.net/geometry/pointlineplane/
+ // I won't use doubles/floats, but pure int math for
// speed purposes. The range considered is always the same no matter how
// close/far the target is because that's how SharpShooting works currently in
- // kRO.
+ // kRO
+
+ int returnCount = 0;
+ int blockcount = map->bl_list_count;
+ va_list apcopy;
- //Generic map_foreach* variables.
- int i, blockcount = bl_list_count;
- struct block_list *bl;
- int bx, by;
//method specific variables
int magnitude2, len_limit; //The square of the magnitude
- int k, xi, yi, xu, yu;
+ int k;
int mx0 = x0, mx1 = x1, my0 = y0, my1 = y1;
- va_list ap;
-
- //Avoid needless calculations by not getting the sqrt right away.
-#define MAGNITUDE2(x0, y0, x1, y1) ( ( ( x1 ) - ( x0 ) ) * ( ( x1 ) - ( x0 ) ) + ( ( y1 ) - ( y0 ) ) * ( ( y1 ) - ( y0 ) ) )
-
- if ( m < 0 )
- return 0;
len_limit = magnitude2 = MAGNITUDE2(x0, y0, x1, y1);
- if ( magnitude2 < 1 ) //Same begin and ending point, can't trace path.
+ if (magnitude2 < 1) //Same begin and ending point, can't trace path.
return 0;
- if ( length ) { //Adjust final position to fit in the given area.
+ if (length) { //Adjust final position to fit in the given area.
//TODO: Find an alternate method which does not requires a square root calculation.
k = (int)sqrt((float)magnitude2);
mx1 = x0 + (x1 - x0) * length / k;
@@ -1047,7 +1237,7 @@ int map_foreachinpath(int (*func)(struct block_list*,va_list),int16 m,int16 x0,i
len_limit = MAGNITUDE2(x0, y0, mx1, my1);
}
//Expand target area to cover range.
- if ( mx0 > mx1 ) {
+ if (mx0 > mx1) {
mx0 += range;
mx1 -= range;
} else {
@@ -1061,191 +1251,46 @@ int map_foreachinpath(int (*func)(struct block_list*,va_list),int16 m,int16 x0,i
my0 -= range;
my1 += range;
}
-
- //The two fors assume mx0 < mx1 && my0 < my1
- if ( mx0 > mx1 )
- swap(mx0, mx1);
- if ( my0 > my1 )
- swap(my0, my1);
-
- mx0 = max(mx0, 0);
- my0 = max(my0, 0);
- mx1 = min(mx1, map[ m ].xs - 1);
- my1 = min(my1, map[ m ].ys - 1);
-
range *= range << 8; //Values are shifted later on for higher precision using int math.
- if ( type&~BL_MOB )
- for ( by = my0 / BLOCK_SIZE; by <= my1 / BLOCK_SIZE; by++ ) {
- for( bx = mx0 / BLOCK_SIZE; bx <= mx1 / BLOCK_SIZE; bx++ ) {
- for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->prev && bl->type&type && bl_list_count < BL_LIST_MAX ) {
- xi = bl->x;
- yi = bl->y;
-
- k = ( xi - x0 ) * ( x1 - x0 ) + ( yi - y0 ) * ( y1 - y0 );
-
- if ( k < 0 || k > len_limit ) //Since more skills use this, check for ending point as well.
- continue;
+ bl_getall_area(type, m, mx0, my0, mx1, my1, bl_vgetall_inpath, m, x0, y0, x1, y1, range, len_limit, magnitude2);
- if ( k > magnitude2 && !path_search_long(NULL, m, x0, y0, xi, yi, CELL_CHKWALL) )
- continue; //Targets beyond the initial ending point need the wall check.
-
- //All these shifts are to increase the precision of the intersection point and distance considering how it's
- //int math.
- k = ( k << 4 ) / magnitude2; //k will be between 1~16 instead of 0~1
- xi <<= 4;
- yi <<= 4;
- xu = ( x0 << 4 ) + k * ( x1 - x0 );
- yu = ( y0 << 4 ) + k * ( y1 - y0 );
- k = MAGNITUDE2(xi, yi, xu, yu);
-
- //If all dot coordinates were <<4 the square of the magnitude is <<8
- if ( k > range )
- continue;
-
- bl_list[ bl_list_count++ ] = bl;
- }
- }
- }
- }
- if( type&BL_MOB )
- for( by = my0 / BLOCK_SIZE; by <= my1 / BLOCK_SIZE; by++ ) {
- for( bx = mx0 / BLOCK_SIZE; bx <= mx1 / BLOCK_SIZE; bx++ ) {
- for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) {
- if( bl->prev && bl_list_count < BL_LIST_MAX ) {
- xi = bl->x;
- yi = bl->y;
- k = ( xi - x0 ) * ( x1 - x0 ) + ( yi - y0 ) * ( y1 - y0 );
-
- if ( k < 0 || k > len_limit )
- continue;
-
- if ( k > magnitude2 && !path_search_long(NULL, m, x0, y0, xi, yi, CELL_CHKWALL) )
- continue; //Targets beyond the initial ending point need the wall check.
-
- k = ( k << 4 ) / magnitude2; //k will be between 1~16 instead of 0~1
- xi <<= 4;
- yi <<= 4;
- xu = ( x0 << 4 ) + k * ( x1 - x0 );
- yu = ( y0 << 4 ) + k * ( y1 - y0 );
- k = MAGNITUDE2(xi, yi, xu, yu);
-
- //If all dot coordinates were <<4 the square of the magnitude is <<8
- if ( k > range )
- continue;
-
- bl_list[ bl_list_count++ ] = bl;
- }
- }
- }
- }
-
- if( bl_list_count >= BL_LIST_MAX )
- ShowWarning("map_foreachinpath: block count too many!\n");
-
- iMap->freeblock_lock();
-
- for( i = blockcount; i < bl_list_count; i++ )
- if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion.
- va_start(ap, type);
- returnCount += func(bl_list[ i ], ap);
- va_end(ap);
- }
-
- iMap->freeblock_unlock();
-
- bl_list_count = blockcount;
- return returnCount; //[Skotlex]
+ va_copy(apcopy, ap);
+ returnCount = bl_vforeach(func, blockcount, INT_MAX, apcopy);
+ va_end(apcopy);
+ return returnCount;
}
+#undef MAGNITUDE2
-// Copy of map_foreachincell, but applied to the whole map. [Skotlex]
-int map_foreachinmap(int (*func)(struct block_list*,va_list), int16 m, int type,...) {
- int b, bsize;
- int returnCount = 0; //total sum of returned values of func() [Skotlex]
- struct block_list *bl;
- int blockcount = bl_list_count, i;
- va_list ap;
-
- bsize = map[ m ].bxs * map[ m ].bys;
-
- if( type&~BL_MOB )
- for( b = 0; b < bsize; b++ )
- for( bl = map[ m ].block[ b ]; bl != NULL; bl = bl->next )
- if( bl->type&type && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
-
- if( type&BL_MOB )
- for( b = 0; b < bsize; b++ )
- for( bl = map[ m ].block_mob[ b ]; bl != NULL; bl = bl->next )
- if( bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
-
- if( bl_list_count >= BL_LIST_MAX )
- ShowWarning("map_foreachinmap: block count too many!\n");
-
- iMap->freeblock_lock();
-
- for( i = blockcount; i < bl_list_count ; i++ )
- if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion.
- va_start(ap, type);
- returnCount += func(bl_list[ i ], ap);
- va_end(ap);
- }
-
- iMap->freeblock_unlock();
-
- bl_list_count = blockcount;
- return returnCount;
-}
-// Copy of map_foreachinmap, but applied to all maps in a instance id. [Ind/Hercules]
-int map_foreachininstance(int (*func)(struct block_list*,va_list), int16 instance_id, int type,...) {
- int b, bsize;
- int returnCount = 0; //total sum of returned values of func() [Skotlex]
- struct block_list *bl;
- int blockcount = bl_list_count, i, j;
- int16 m;
+/**
+ * Applies func to every block_list object of bl_type type in
+ * path on a line between (x0,y0) and (x1,y1) on map m.
+ * Path starts at (x0,y0) and is \a length cells long and \a range cells wide.
+ * Objects beyond the initial (x1,y1) ending point are checked
+ * for walls in the path.
+ * Returns the sum of values returned by func.
+ * @see map_vforeachinpath
+ * @param func Function to be applied
+ * @param m Map id
+ * @param x Target cell X-coordinate
+ * @param y Target cell Y-coordinate
+ * @param type enum bl_type
+ * @param ... Extra arguments for func
+ * @return Sum of the values returned by func
+ */
+int map_foreachinpath(int (*func)(struct block_list*, va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int16 range, int length, int type, ...) {
+ int returnCount;
va_list ap;
- for( j = 0; j < instances[instance_id].num_map; j++ ) {
-
- m = instances[instance_id].map[j];
-
- bsize = map[ m ].bxs * map[ m ].bys;
-
- if( type&~BL_MOB )
- for( b = 0; b < bsize; b++ )
- for( bl = map[ m ].block[ b ]; bl != NULL; bl = bl->next )
- if( bl->type&type && bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
-
- if( type&BL_MOB )
- for( b = 0; b < bsize; b++ )
- for( bl = map[ m ].block_mob[ b ]; bl != NULL; bl = bl->next )
- if( bl_list_count < BL_LIST_MAX )
- bl_list[ bl_list_count++ ] = bl;
-
- if( bl_list_count >= BL_LIST_MAX )
- ShowWarning("map_foreachininstance: block count too many!\n");
-
- iMap->freeblock_lock();
+ va_start(ap, type);
+ returnCount = map->vforeachinpath(func, m, x0, y0, x1, y1, range, length, type, ap);
+ va_end(ap);
- for( i = blockcount; i < bl_list_count ; i++ )
- if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion.
- va_start(ap, type);
- returnCount += func(bl_list[ i ], ap);
- va_end(ap);
- }
-
- iMap->freeblock_unlock();
-
- }
-
- bl_list_count = blockcount;
return returnCount;
}
+/** @} */
/// Generates a new flooritem object id from the interval [MIN_FLOORITEM, MAX_FLOORITEM).
/// Used for floor items, skill units and chatroom objects.
@@ -1261,7 +1306,7 @@ int map_get_new_object_id(void)
if( i == MAX_FLOORITEM )
i = MIN_FLOORITEM;
- if( !idb_exists(id_db, i) )
+ if( !idb_exists(map->id_db, i) )
break;
++i;
@@ -1279,12 +1324,11 @@ int map_get_new_object_id(void)
}
/*==========================================
-* Timered function to clear the floor (remove remaining item)
-* Called each flooritem_lifetime ms
-*------------------------------------------*/
-int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct flooritem_data* fitem = (struct flooritem_data*)idb_get(id_db, id);
+ * Timered function to clear the floor (remove remaining item)
+ * Called each flooritem_lifetime ms
+ *------------------------------------------*/
+int map_clearflooritem_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct flooritem_data* fitem = (struct flooritem_data*)idb_get(map->id_db, id);
if (fitem == NULL || fitem->bl.type != BL_ITEM || (fitem->cleartimer != tid)) {
ShowError("map_clearflooritem_timer : error\n");
@@ -1292,50 +1336,50 @@ int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data)
}
- if (search_petDB_index(fitem->item_data.nameid, PET_EGG) >= 0)
- intif_delete_petdata(MakeDWord(fitem->item_data.card[1], fitem->item_data.card[2]));
+ if (pet->search_petDB_index(fitem->item_data.nameid, PET_EGG) >= 0)
+ intif->delete_petdata(MakeDWord(fitem->item_data.card[1], fitem->item_data.card[2]));
clif->clearflooritem(fitem, 0);
- iMap->deliddb(&fitem->bl);
- iMap->delblock(&fitem->bl);
- iMap->freeblock(&fitem->bl);
+ map->deliddb(&fitem->bl);
+ map->delblock(&fitem->bl);
+ map->freeblock(&fitem->bl);
return 0;
}
/*
-* clears a single bl item out of the bazooonga.
-*/
+ * clears a single bl item out of the bazooonga.
+ */
void map_clearflooritem(struct block_list *bl) {
struct flooritem_data* fitem = (struct flooritem_data*)bl;
- if( fitem->cleartimer )
- iTimer->delete_timer(fitem->cleartimer,iMap->clearflooritem_timer);
+ if( fitem->cleartimer != INVALID_TIMER )
+ timer->delete(fitem->cleartimer,map->clearflooritem_timer);
clif->clearflooritem(fitem, 0);
- iMap->deliddb(&fitem->bl);
- iMap->delblock(&fitem->bl);
- iMap->freeblock(&fitem->bl);
+ map->deliddb(&fitem->bl);
+ map->delblock(&fitem->bl);
+ map->freeblock(&fitem->bl);
}
/*==========================================
-* (m,x,y) locates a random available free cell around the given coordinates
-* to place an BL_ITEM object. Scan area is 9x9, returns 1 on success.
-* x and y are modified with the target cell when successful.
-*------------------------------------------*/
+ * (m,x,y) locates a random available free cell around the given coordinates
+ * to place an BL_ITEM object. Scan area is 9x9, returns 1 on success.
+ * x and y are modified with the target cell when successful.
+ *------------------------------------------*/
int map_searchrandfreecell(int16 m,int16 *x,int16 *y,int stack) {
int free_cell,i,j;
int free_cells[9][2];
for(free_cell=0,i=-1;i<=1;i++){
- if(i+*y<0 || i+*y>=map[m].ys)
+ if(i+*y<0 || i+*y>=map->list[m].ys)
continue;
for(j=-1;j<=1;j++){
- if(j+*x<0 || j+*x>=map[m].xs)
+ if(j+*x<0 || j+*x>=map->list[m].xs)
continue;
- if(iMap->getcell(m,j+*x,i+*y,CELL_CHKNOPASS) && !iMap->getcell(m,j+*x,i+*y,CELL_CHKICEWALL))
+ if(map->getcell(m,j+*x,i+*y,CELL_CHKNOPASS) && !map->getcell(m,j+*x,i+*y,CELL_CHKICEWALL))
continue;
//Avoid item stacking to prevent against exploits. [Skotlex]
- if(stack && iMap->count_oncell(m,j+*x,i+*y, BL_ITEM) > stack)
+ if(stack && map->count_oncell(m,j+*x,i+*y, BL_ITEM) > stack)
continue;
free_cells[free_cell][0] = j+*x;
free_cells[free_cell++][1] = i+*y;
@@ -1350,23 +1394,22 @@ int map_searchrandfreecell(int16 m,int16 *x,int16 *y,int stack) {
}
-static int map_count_sub(struct block_list *bl,va_list ap)
-{
+int map_count_sub(struct block_list *bl,va_list ap) {
return 1;
}
/*==========================================
-* Locates a random spare cell around the object given, using range as max
-* distance from that spot. Used for warping functions. Use range < 0 for
-* whole map range.
-* Returns 1 on success. when it fails and src is available, x/y are set to src's
-* src can be null as long as flag&1
-* when ~flag&1, m is not needed.
-* Flag values:
-* &1 = random cell must be around given m,x,y, not around src
-* &2 = the target should be able to walk to the target tile.
-* &4 = there shouldn't be any players around the target tile (use the no_spawn_on_player setting)
-*------------------------------------------*/
+ * Locates a random spare cell around the object given, using range as max
+ * distance from that spot. Used for warping functions. Use range < 0 for
+ * whole map range.
+ * Returns 1 on success. when it fails and src is available, x/y are set to src's
+ * src can be null as long as flag&1
+ * when ~flag&1, m is not needed.
+ * Flag values:
+ * &1 = random cell must be around given m,x,y, not around src
+ * &2 = the target should be able to walk to the target tile.
+ * &4 = there shouldn't be any players around the target tile (use the no_spawn_on_player setting)
+ *------------------------------------------*/
int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int16 rx, int16 ry, int flag)
{
int tries, spawn=0;
@@ -1392,35 +1435,33 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
//No range? Return the target cell then....
*x = bx;
*y = by;
- return iMap->getcell(m,*x,*y,CELL_CHKREACH);
+ return map->getcell(m,*x,*y,CELL_CHKREACH);
}
if (rx >= 0 && ry >= 0) {
tries = rx2*ry2;
if (tries > 100) tries = 100;
} else {
- tries = map[m].xs*map[m].ys;
+ tries = map->list[m].xs*map->list[m].ys;
if (tries > 500) tries = 500;
}
while(tries--) {
- *x = (rx >= 0)?(rnd()%rx2-rx+bx):(rnd()%(map[m].xs-2)+1);
- *y = (ry >= 0)?(rnd()%ry2-ry+by):(rnd()%(map[m].ys-2)+1);
+ *x = (rx >= 0)?(rnd()%rx2-rx+bx):(rnd()%(map->list[m].xs-2)+1);
+ *y = (ry >= 0)?(rnd()%ry2-ry+by):(rnd()%(map->list[m].ys-2)+1);
if (*x == bx && *y == by)
continue; //Avoid picking the same target tile.
- if (iMap->getcell(m,*x,*y,CELL_CHKREACH))
- {
- if(flag&2 && !unit_can_reach_pos(src, *x, *y, 1))
+ if (map->getcell(m,*x,*y,CELL_CHKREACH)) {
+ if(flag&2 && !unit->can_reach_pos(src, *x, *y, 1))
continue;
if(flag&4) {
if (spawn >= 100) return 0; //Limit of retries reached.
- if (spawn++ < battle_config.no_spawn_on_player &&
- map_foreachinarea(map_count_sub, m,
- *x-AREA_SIZE, *y-AREA_SIZE,
- *x+AREA_SIZE, *y+AREA_SIZE, BL_PC)
- )
+ if (spawn++ < battle_config.no_spawn_on_player
+ && map->foreachinarea(map->count_sub, m, *x-AREA_SIZE, *y-AREA_SIZE,
+ *x+AREA_SIZE, *y+AREA_SIZE, BL_PC)
+ )
continue;
}
return 1;
@@ -1432,14 +1473,14 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
}
/*==========================================
-* Add an item to location (m,x,y)
-* Parameters
-* @item_data item attributes
-* @amount quantity
-* @m, @x, @y mapid,x,y
-* @first_charid, @second_charid, @third_charid, looting priority
-* @flag: &1 MVP item. &2 do stacking check.
-*------------------------------------------*/
+ * Add an item to location (m,x,y)
+ * Parameters
+ * @item_data item attributes
+ * @amount quantity
+ * @m, @x, @y mapid,x,y
+ * @first_charid, @second_charid, @third_charid, looting priority
+ * @flag: &1 MVP item. &2 do stacking check.
+ *------------------------------------------*/
int map_addflooritem(struct item *item_data,int amount,int16 m,int16 x,int16 y,int first_charid,int second_charid,int third_charid,int flags)
{
int r;
@@ -1447,24 +1488,25 @@ int map_addflooritem(struct item *item_data,int amount,int16 m,int16 x,int16 y,i
nullpo_ret(item_data);
- if(!map_searchrandfreecell(m,&x,&y,flags&2?1:0))
+ if(!map->searchrandfreecell(m,&x,&y,flags&2?1:0))
return 0;
r=rnd();
- CREATE(fitem, struct flooritem_data, 1);
- fitem->bl.type=BL_ITEM;
+ fitem = ers_alloc(map->flooritem_ers, struct flooritem_data);
+
+ fitem->bl.type = BL_ITEM;
fitem->bl.prev = fitem->bl.next = NULL;
- fitem->bl.m=m;
- fitem->bl.x=x;
- fitem->bl.y=y;
- fitem->bl.id = iMap->get_new_object_id();
+ fitem->bl.m = m;
+ fitem->bl.x = x;
+ fitem->bl.y = y;
+ fitem->bl.id = map->get_new_object_id();
if(fitem->bl.id==0){
- aFree(fitem);
+ ers_free(map->flooritem_ers, fitem);
return 0;
}
fitem->first_get_charid = first_charid;
- fitem->first_get_tick = iTimer->gettick() + (flags&1 ? battle_config.mvp_item_first_get_time : battle_config.item_first_get_time);
+ fitem->first_get_tick = timer->gettick() + (flags&1 ? battle_config.mvp_item_first_get_time : battle_config.item_first_get_time);
fitem->second_get_charid = second_charid;
fitem->second_get_tick = fitem->first_get_tick + (flags&1 ? battle_config.mvp_item_second_get_time : battle_config.item_second_get_time);
fitem->third_get_charid = third_charid;
@@ -1474,19 +1516,19 @@ int map_addflooritem(struct item *item_data,int amount,int16 m,int16 x,int16 y,i
fitem->item_data.amount=amount;
fitem->subx=(r&3)*3+3;
fitem->suby=((r>>2)&3)*3+3;
- fitem->cleartimer=iTimer->add_timer(iTimer->gettick()+battle_config.flooritem_lifetime,iMap->clearflooritem_timer,fitem->bl.id,0);
+ fitem->cleartimer=timer->add(timer->gettick()+battle_config.flooritem_lifetime,map->clearflooritem_timer,fitem->bl.id,0);
- iMap->addiddb(&fitem->bl);
- iMap->addblock(&fitem->bl);
+ map->addiddb(&fitem->bl);
+ map->addblock(&fitem->bl);
clif->dropflooritem(fitem);
return fitem->bl.id;
}
/**
-* @see DBCreateData
-*/
-static DBData create_charid2nick(DBKey key, va_list args)
+ * @see DBCreateData
+ */
+DBData create_charid2nick(DBKey key, va_list args)
{
struct charid2nick *p;
CREATE(p, struct charid2nick, 1);
@@ -1501,16 +1543,16 @@ void map_addnickdb(int charid, const char* nick)
struct charid_request* req;
struct map_session_data* sd;
- if( iMap->charid2sd(charid) )
+ if( map->charid2sd(charid) )
return;// already online
- p = idb_ensure(nick_db, charid, create_charid2nick);
+ p = idb_ensure(map->nick_db, charid, map->create_charid2nick);
safestrncpy(p->nick, nick, sizeof(p->nick));
while( p->requests ) {
req = p->requests;
p->requests = req->next;
- sd = iMap->charid2sd(req->charid);
+ sd = map->charid2sd(req->charid);
if( sd )
clif->solved_charname(sd->fd, charid, p->nick);
aFree(req);
@@ -1526,13 +1568,13 @@ void map_delnickdb(int charid, const char* name)
struct map_session_data* sd;
DBData data;
- if (!nick_db->remove(nick_db, DB->i2key(charid), &data) || (p = DB->data2ptr(&data)) == NULL)
+ if (!map->nick_db->remove(map->nick_db, DB->i2key(charid), &data) || (p = DB->data2ptr(&data)) == NULL)
return;
while( p->requests ) {
req = p->requests;
p->requests = req->next;
- sd = iMap->charid2sd(req->charid);
+ sd = map->charid2sd(req->charid);
if( sd )
clif->solved_charname(sd->fd, charid, name);
aFree(req);
@@ -1551,13 +1593,13 @@ void map_reqnickdb(struct map_session_data * sd, int charid)
nullpo_retv(sd);
- tsd = iMap->charid2sd(charid);
+ tsd = map->charid2sd(charid);
if( tsd ) {
clif->solved_charname(sd->fd, charid, tsd->status.name);
return;
}
- p = idb_ensure(nick_db, charid, create_charid2nick);
+ p = idb_ensure(map->nick_db, charid, map->create_charid2nick);
if( *p->nick ) {
clif->solved_charname(sd->fd, charid, p->nick);
return;
@@ -1566,12 +1608,12 @@ void map_reqnickdb(struct map_session_data * sd, int charid)
CREATE(req, struct charid_request, 1);
req->next = p->requests;
p->requests = req;
- chrif_searchcharid(charid);
+ chrif->searchcharid(charid);
}
/*==========================================
-* add bl to id_db
-*------------------------------------------*/
+ * add bl to id_db
+ *------------------------------------------*/
void map_addiddb(struct block_list *bl)
{
nullpo_retv(bl);
@@ -1579,27 +1621,27 @@ void map_addiddb(struct block_list *bl)
if( bl->type == BL_PC )
{
TBL_PC* sd = (TBL_PC*)bl;
- idb_put(pc_db,sd->bl.id,sd);
- idb_put(charid_db,sd->status.char_id,sd);
+ idb_put(map->pc_db,sd->bl.id,sd);
+ idb_put(map->charid_db,sd->status.char_id,sd);
}
else if( bl->type == BL_MOB )
{
TBL_MOB* md = (TBL_MOB*)bl;
- idb_put(mobid_db,bl->id,bl);
+ idb_put(map->mobid_db,bl->id,bl);
if( md->state.boss )
- idb_put(bossid_db, bl->id, bl);
+ idb_put(map->bossid_db, bl->id, bl);
}
if( bl->type & BL_REGEN )
- idb_put(regen_db, bl->id, bl);
+ idb_put(map->regen_db, bl->id, bl);
- idb_put(id_db,bl->id,bl);
+ idb_put(map->id_db,bl->id,bl);
}
/*==========================================
-* remove bl from id_db
-*------------------------------------------*/
+ * remove bl from id_db
+ *------------------------------------------*/
void map_deliddb(struct block_list *bl)
{
nullpo_retv(bl);
@@ -1607,68 +1649,76 @@ void map_deliddb(struct block_list *bl)
if( bl->type == BL_PC )
{
TBL_PC* sd = (TBL_PC*)bl;
- idb_remove(pc_db,sd->bl.id);
- idb_remove(charid_db,sd->status.char_id);
+ idb_remove(map->pc_db,sd->bl.id);
+ idb_remove(map->charid_db,sd->status.char_id);
}
else if( bl->type == BL_MOB )
{
- idb_remove(mobid_db,bl->id);
- idb_remove(bossid_db,bl->id);
+ idb_remove(map->mobid_db,bl->id);
+ idb_remove(map->bossid_db,bl->id);
}
if( bl->type & BL_REGEN )
- idb_remove(regen_db,bl->id);
+ idb_remove(map->regen_db,bl->id);
- idb_remove(id_db,bl->id);
+ idb_remove(map->id_db,bl->id);
}
/*==========================================
-* Standard call when a player connection is closed.
-*------------------------------------------*/
+ * Standard call when a player connection is closed.
+ *------------------------------------------*/
int map_quit(struct map_session_data *sd) {
int i;
if(!sd->state.active) { //Removing a player that is not active.
- struct auth_node *node = chrif_search(sd->status.account_id);
+ struct auth_node *node = chrif->search(sd->status.account_id);
if (node && node->char_id == sd->status.char_id &&
node->state != ST_LOGOUT)
//Except when logging out, clear the auth-connect data immediately.
- chrif_auth_delete(node->account_id, node->char_id, node->state);
+ chrif->auth_delete(node->account_id, node->char_id, node->state);
//Non-active players should not have loaded any data yet (or it was cleared already) so no additional cleanups are needed.
return 0;
}
+
+ if( sd->expiration_tid != INVALID_TIMER )
+ timer->delete(sd->expiration_tid,pc->expiration_timer);
if (sd->npc_timer_id != INVALID_TIMER) //Cancel the event timer.
- npc_timerevent_quit(sd);
+ npc->timerevent_quit(sd);
if (sd->npc_id)
- npc_event_dequeue(sd);
+ npc->event_dequeue(sd);
+
+ if( sd->bg_id && !sd->bg_queue.arena ) /* TODO: dump this chunk after bg_queue is fully enabled */
+ bg->team_leave(sd,BGTL_QUIT);
- if( sd->bg_id )
- bg_team_leave(sd,1);
+ if( sd->state.autotrade && runflag != MAPSERVER_ST_SHUTDOWN && !hChSys.closing )
+ pc->autotrade_update(sd,PAUC_REMOVE);
+ skill->cooldown_save(sd);
pc->itemcd_do(sd,false);
for( i = 0; i < sd->queues_count; i++ ) {
struct hQueue *queue;
if( (queue = script->queue(sd->queues[i])) && queue->onLogOut[0] != '\0' ) {
- npc_event(sd, queue->onLogOut, 0);
+ npc->event(sd, queue->onLogOut, 0);
}
}
/* two times, the npc event above may assign a new one or delete others */
for( i = 0; i < sd->queues_count; i++ ) {
- script->queue_remove(sd->queues[i],sd->status.account_id);
+ if( sd->queues[i] != -1 )
+ script->queue_remove(sd->queues[i],sd->status.account_id);
}
- npc_script_event(sd, NPCE_LOGOUT);
+ npc->script_event(sd, NPCE_LOGOUT);
//Unit_free handles clearing the player related data,
- //iMap->quit handles extra specific data which is related to quitting normally
- //(changing map-servers invokes unit_free but bypasses iMap->quit)
+ //map->quit handles extra specific data which is related to quitting normally
+ //(changing map-servers invokes unit_free but bypasses map->quit)
if( sd->sc.count ) {
//Status that are not saved...
for(i=0; i < SC_MAX; i++){
- if ( status_get_sc_type(i)&SC_NO_SAVE ){
+ if ( status->get_sc_type(i)&SC_NO_SAVE ) {
if ( !sd->sc.data[i] )
continue;
switch( i ){
@@ -1690,34 +1740,32 @@ int map_quit(struct map_session_data *sd) {
}
// Return loot to owner
- if( sd->pd ) pet_lootitem_drop(sd->pd, sd);
+ if( sd->pd ) pet->lootitem_drop(sd->pd, sd);
if( sd->state.storage_flag == 1 ) sd->state.storage_flag = 0; // No need to Double Save Storage on Quit.
- if (sd->state.permanent_speed == 1) sd->state.permanent_speed = 0; // Remove lock so speed is set back to normal at login.
-
if( sd->ed ) {
- elemental_clean_effect(sd->ed);
- unit_remove_map(&sd->ed->bl,CLR_TELEPORT);
+ elemental->clean_effect(sd->ed);
+ unit->remove_map(&sd->ed->bl,CLR_TELEPORT,ALC_MARK);
}
- if( hChSys.local && map[sd->bl.m].channel && idb_exists(map[sd->bl.m].channel->users, sd->status.char_id) ) {
- clif->chsys_left(map[sd->bl.m].channel,sd);
+ if( hChSys.local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id) ) {
+ clif->chsys_left(map->list[sd->bl.m].channel,sd);
}
clif->chsys_quit(sd);
- unit_remove_map_pc(sd,CLR_TELEPORT);
+ unit->remove_map_pc(sd,CLR_RESPAWN);
- if( map[sd->bl.m].instance_id >= 0 ) { // Avoid map conflicts and warnings on next login
+ if( map->list[sd->bl.m].instance_id >= 0 ) { // Avoid map conflicts and warnings on next login
int16 m;
struct point *pt;
- if( map[sd->bl.m].save.map )
- pt = &map[sd->bl.m].save;
+ if( map->list[sd->bl.m].save.map )
+ pt = &map->list[sd->bl.m].save;
else
pt = &sd->status.save_point;
- if( (m=iMap->mapindex2mapid(pt->map)) >= 0 ) {
+ if( (m=map->mapindex2mapid(pt->map)) >= 0 ) {
sd->bl.m = m;
sd->bl.x = pt->x;
sd->bl.y = pt->y;
@@ -1725,86 +1773,84 @@ int map_quit(struct map_session_data *sd) {
}
}
+ if( sd->state.vending ) {
+ idb_remove(vending->db, sd->status.char_id);
+ }
+
party->booking_delete(sd); // Party Booking [Spiria]
pc->makesavestatus(sd);
pc->clean_skilltree(sd);
- chrif_save(sd,1);
- unit_free_pc(sd);
+ chrif->save(sd,1);
+ unit->free_pc(sd);
return 0;
}
/*==========================================
-* Lookup, id to session (player,mob,npc,homon,merc..)
-*------------------------------------------*/
-struct map_session_data * map_id2sd(int id)
-{
+ * Lookup, id to session (player,mob,npc,homon,merc..)
+ *------------------------------------------*/
+struct map_session_data *map_id2sd(int id) {
if (id <= 0) return NULL;
- return (struct map_session_data*)idb_get(pc_db,id);
+ return (struct map_session_data*)idb_get(map->pc_db,id);
}
-struct mob_data * map_id2md(int id)
-{
+struct mob_data *map_id2md(int id) {
if (id <= 0) return NULL;
- return (struct mob_data*)idb_get(mobid_db,id);
+ return (struct mob_data*)idb_get(map->mobid_db,id);
}
-struct npc_data * map_id2nd(int id)
-{// just a id2bl lookup because there's no npc_db
- struct block_list* bl = iMap->id2bl(id);
+struct npc_data *map_id2nd(int id) {
+ // just a id2bl lookup because there's no npc_db
+ struct block_list* bl = map->id2bl(id);
return BL_CAST(BL_NPC, bl);
}
-struct homun_data* map_id2hd(int id)
-{
- struct block_list* bl = iMap->id2bl(id);
+struct homun_data *map_id2hd(int id) {
+ struct block_list* bl = map->id2bl(id);
return BL_CAST(BL_HOM, bl);
}
-struct mercenary_data* map_id2mc(int id)
-{
- struct block_list* bl = iMap->id2bl(id);
+struct mercenary_data *map_id2mc(int id) {
+ struct block_list* bl = map->id2bl(id);
return BL_CAST(BL_MER, bl);
}
-struct chat_data* map_id2cd(int id)
-{
- struct block_list* bl = iMap->id2bl(id);
+struct chat_data *map_id2cd(int id) {
+ struct block_list* bl = map->id2bl(id);
return BL_CAST(BL_CHAT, bl);
}
/// Returns the nick of the target charid or NULL if unknown (requests the nick to the char server).
-const char* map_charid2nick(int charid)
-{
+const char *map_charid2nick(int charid) {
struct charid2nick *p;
struct map_session_data* sd;
- sd = iMap->charid2sd(charid);
+ sd = map->charid2sd(charid);
if( sd )
return sd->status.name;// character is online, return it's name
- p = idb_ensure(nick_db, charid, create_charid2nick);
+ p = idb_ensure(map->nick_db, charid, map->create_charid2nick);
if( *p->nick )
return p->nick;// name in nick_db
- chrif_searchcharid(charid);// request the name
+ chrif->searchcharid(charid);// request the name
return NULL;
}
/// Returns the struct map_session_data of the charid or NULL if the char is not online.
struct map_session_data* map_charid2sd(int charid)
{
- return (struct map_session_data*)idb_get(charid_db, charid);
+ return (struct map_session_data*)idb_get(map->charid_db, charid);
}
/*==========================================
-* Search session data from a nick name
-* (without sensitive case if necessary)
-* return map_session_data pointer or NULL
-*------------------------------------------*/
+ * Search session data from a nick name
+ * (without sensitive case if necessary)
+ * return map_session_data pointer or NULL
+ *------------------------------------------*/
struct map_session_data * map_nick2sd(const char *nick)
{
struct map_session_data* sd;
@@ -1852,29 +1898,29 @@ struct map_session_data * map_nick2sd(const char *nick)
}
/*==========================================
-* Looksup id_db DBMap and returns BL pointer of 'id' or NULL if not found
-*------------------------------------------*/
+ * Looksup id_db DBMap and returns BL pointer of 'id' or NULL if not found
+ *------------------------------------------*/
struct block_list * map_id2bl(int id) {
- return (struct block_list*)idb_get(id_db,id);
+ return (struct block_list*)idb_get(map->id_db,id);
}
/**
-* Same as iMap->id2bl except it only checks for its existence
-**/
+ * Same as map->id2bl except it only checks for its existence
+ **/
bool map_blid_exists( int id ) {
- return (idb_exists(id_db,id));
+ return (idb_exists(map->id_db,id));
}
/*==========================================
-* Convext Mirror
-*------------------------------------------*/
+ * Convext Mirror
+ *------------------------------------------*/
struct mob_data * map_getmob_boss(int16 m)
{
DBIterator* iter;
struct mob_data *md = NULL;
bool found = false;
- iter = db_iterator(bossid_db);
+ iter = db_iterator(map->bossid_db);
for( md = (struct mob_data*)dbi_first(iter); dbi_exists(iter); md = (struct mob_data*)dbi_next(iter) )
{
if( md->bl.m == m )
@@ -1891,71 +1937,88 @@ struct mob_data * map_getmob_boss(int16 m)
struct mob_data * map_id2boss(int id)
{
if (id <= 0) return NULL;
- return (struct mob_data*)idb_get(bossid_db,id);
+ return (struct mob_data*)idb_get(map->bossid_db,id);
}
/// Applies func to all the players in the db.
/// Stops iterating if func returns -1.
-void map_map_foreachpc(int (*func)(struct map_session_data* sd, va_list args), ...) {
+void map_vforeachpc(int (*func)(struct map_session_data* sd, va_list args), va_list args) {
DBIterator* iter;
struct map_session_data* sd;
- iter = db_iterator(pc_db);
+ iter = db_iterator(map->pc_db);
for( sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter) )
{
- va_list args;
+ va_list argscopy;
int ret;
- va_start(args, func);
- ret = func(sd, args);
- va_end(args);
+ va_copy(argscopy, args);
+ ret = func(sd, argscopy);
+ va_end(argscopy);
if( ret == -1 )
break;// stop iterating
}
dbi_destroy(iter);
}
+/// Applies func to all the players in the db.
+/// Stops iterating if func returns -1.
+/// @see map_vforeachpc
+void map_foreachpc(int (*func)(struct map_session_data* sd, va_list args), ...) {
+ va_list args;
+
+ va_start(args, func);
+ map->vforeachpc(func, args);
+ va_end(args);
+}
+
/// Applies func to all the mobs in the db.
/// Stops iterating if func returns -1.
-void map_map_foreachmob(int (*func)(struct mob_data* md, va_list args), ...)
-{
+void map_vforeachmob(int (*func)(struct mob_data* md, va_list args), va_list args) {
DBIterator* iter;
struct mob_data* md;
- iter = db_iterator(mobid_db);
- for( md = (struct mob_data*)dbi_first(iter); dbi_exists(iter); md = (struct mob_data*)dbi_next(iter) )
- {
- va_list args;
+ iter = db_iterator(map->mobid_db);
+ for( md = (struct mob_data*)dbi_first(iter); dbi_exists(iter); md = (struct mob_data*)dbi_next(iter) ) {
+ va_list argscopy;
int ret;
- va_start(args, func);
- ret = func(md, args);
- va_end(args);
+ va_copy(argscopy, args);
+ ret = func(md, argscopy);
+ va_end(argscopy);
if( ret == -1 )
break;// stop iterating
}
dbi_destroy(iter);
}
+/// Applies func to all the mobs in the db.
+/// Stops iterating if func returns -1.
+/// @see map_vforeachmob
+void map_foreachmob(int (*func)(struct mob_data* md, va_list args), ...) {
+ va_list args;
+
+ va_start(args, func);
+ map->vforeachmob(func, args);
+ va_end(args);
+}
+
/// Applies func to all the npcs in the db.
/// Stops iterating if func returns -1.
-void map_map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...)
-{
+void map_vforeachnpc(int (*func)(struct npc_data* nd, va_list args), va_list args) {
DBIterator* iter;
struct block_list* bl;
- iter = db_iterator(id_db);
- for( bl = (struct block_list*)dbi_first(iter); dbi_exists(iter); bl = (struct block_list*)dbi_next(iter) )
- {
- if( bl->type == BL_NPC )
- {
+ iter = db_iterator(map->id_db);
+ for( bl = (struct block_list*)dbi_first(iter); dbi_exists(iter); bl = (struct block_list*)dbi_next(iter) ) {
+ if( bl->type == BL_NPC ) {
struct npc_data* nd = (struct npc_data*)bl;
- va_list args;
+ va_list argscopy;
int ret;
- va_start(args, func);
- ret = func(nd, args);
- va_end(args);
+ va_copy(argscopy, args);
+ ret = func(nd, argscopy);
+ va_end(argscopy);
if( ret == -1 )
break;// stop iterating
}
@@ -1963,22 +2026,31 @@ void map_map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...)
dbi_destroy(iter);
}
+/// Applies func to all the npcs in the db.
+/// Stops iterating if func returns -1.
+/// @see map_vforeachnpc
+void map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...) {
+ va_list args;
+
+ va_start(args, func);
+ map->vforeachnpc(func, args);
+ va_end(args);
+}
+
/// Applies func to everything in the db.
-/// Stops iteratin gif func returns -1.
-void map_map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...)
-{
+/// Stops iterating gif func returns -1.
+void map_vforeachregen(int (*func)(struct block_list* bl, va_list args), va_list args) {
DBIterator* iter;
struct block_list* bl;
- iter = db_iterator(regen_db);
- for( bl = (struct block_list*)dbi_first(iter); dbi_exists(iter); bl = (struct block_list*)dbi_next(iter) )
- {
- va_list args;
+ iter = db_iterator(map->regen_db);
+ for( bl = (struct block_list*)dbi_first(iter); dbi_exists(iter); bl = (struct block_list*)dbi_next(iter) ) {
+ va_list argscopy;
int ret;
- va_start(args, func);
- ret = func(bl, args);
- va_end(args);
+ va_copy(argscopy, args);
+ ret = func(bl, argscopy);
+ va_end(argscopy);
if( ret == -1 )
break;// stop iterating
}
@@ -1986,27 +2058,47 @@ void map_map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...)
}
/// Applies func to everything in the db.
+/// Stops iterating gif func returns -1.
+/// @see map_vforeachregen
+void map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...) {
+ va_list args;
+
+ va_start(args, func);
+ map->vforeachregen(func, args);
+ va_end(args);
+}
+
+/// Applies func to everything in the db.
/// Stops iterating if func returns -1.
-void map_map_foreachiddb(int (*func)(struct block_list* bl, va_list args), ...)
-{
+void map_vforeachiddb(int (*func)(struct block_list* bl, va_list args), va_list args) {
DBIterator* iter;
struct block_list* bl;
- iter = db_iterator(id_db);
- for( bl = (struct block_list*)dbi_first(iter); dbi_exists(iter); bl = (struct block_list*)dbi_next(iter) )
- {
- va_list args;
+ iter = db_iterator(map->id_db);
+ for( bl = (struct block_list*)dbi_first(iter); dbi_exists(iter); bl = (struct block_list*)dbi_next(iter) ) {
+ va_list argscopy;
int ret;
- va_start(args, func);
- ret = func(bl, args);
- va_end(args);
+ va_copy(argscopy, args);
+ ret = func(bl, argscopy);
+ va_end(argscopy);
if( ret == -1 )
break;// stop iterating
}
dbi_destroy(iter);
}
+/// Applies func to everything in the db.
+/// Stops iterating if func returns -1.
+/// @see map_vforeachiddb
+void map_foreachiddb(int (*func)(struct block_list* bl, va_list args), ...) {
+ va_list args;
+
+ va_start(args, func);
+ map->vforeachiddb(func, args);
+ va_end(args);
+}
+
/// Iterator.
/// Can filter by bl type.
struct s_mapiterator
@@ -2022,9 +2114,7 @@ struct s_mapiterator
/// @param _bl_ block_list
/// @return true if it matches
#define MAPIT_MATCHES(_mapit_,_bl_) \
- ( \
- ( (_bl_)->type & (_mapit_)->types /* type matches */ ) \
- )
+ ( (_bl_)->type & (_mapit_)->types /* type matches */ )
/// Allocates a new iterator.
/// Returns the new iterator.
@@ -2034,44 +2124,40 @@ struct s_mapiterator
/// @param flags Flags of the iterator
/// @param type Target types
/// @return Iterator
-struct s_mapiterator* mapit_alloc(enum e_mapitflags flags, enum bl_type types)
-{
- struct s_mapiterator* mapit;
+struct s_mapiterator* mapit_alloc(enum e_mapitflags flags, enum bl_type types) {
+ struct s_mapiterator* iter;
- mapit = ers_alloc(map_iterator_ers, struct s_mapiterator);
- mapit->flags = flags;
- mapit->types = types;
- if( types == BL_PC ) mapit->dbi = db_iterator(pc_db);
- else if( types == BL_MOB ) mapit->dbi = db_iterator(mobid_db);
- else mapit->dbi = db_iterator(id_db);
- return mapit;
+ iter = ers_alloc(map->iterator_ers, struct s_mapiterator);
+ iter->flags = flags;
+ iter->types = types;
+ if( types == BL_PC ) iter->dbi = db_iterator(map->pc_db);
+ else if( types == BL_MOB ) iter->dbi = db_iterator(map->mobid_db);
+ else iter->dbi = db_iterator(map->id_db);
+ return iter;
}
/// Frees the iterator.
///
-/// @param mapit Iterator
-void mapit_free(struct s_mapiterator* mapit)
-{
- nullpo_retv(mapit);
+/// @param iter Iterator
+void mapit_free(struct s_mapiterator* iter) {
+ nullpo_retv(iter);
- dbi_destroy(mapit->dbi);
- ers_free(map_iterator_ers, mapit);
+ dbi_destroy(iter->dbi);
+ ers_free(map->iterator_ers, iter);
}
/// Returns the first block_list that matches the description.
/// Returns NULL if not found.
///
-/// @param mapit Iterator
+/// @param iter Iterator
/// @return first block_list or NULL
-struct block_list* mapit_first(struct s_mapiterator* mapit)
-{
+struct block_list* mapit_first(struct s_mapiterator* iter) {
struct block_list* bl;
- nullpo_retr(NULL,mapit);
+ nullpo_retr(NULL,iter);
- for( bl = (struct block_list*)dbi_first(mapit->dbi); bl != NULL; bl = (struct block_list*)dbi_next(mapit->dbi) )
- {
- if( MAPIT_MATCHES(mapit,bl) )
+ for( bl = (struct block_list*)dbi_first(iter->dbi); bl != NULL; bl = (struct block_list*)dbi_next(iter->dbi) ) {
+ if( MAPIT_MATCHES(iter,bl) )
break;// found match
}
return bl;
@@ -2080,17 +2166,15 @@ struct block_list* mapit_first(struct s_mapiterator* mapit)
/// Returns the last block_list that matches the description.
/// Returns NULL if not found.
///
-/// @param mapit Iterator
+/// @param iter Iterator
/// @return last block_list or NULL
-struct block_list* mapit_last(struct s_mapiterator* mapit)
-{
+struct block_list* mapit_last(struct s_mapiterator* iter) {
struct block_list* bl;
- nullpo_retr(NULL,mapit);
+ nullpo_retr(NULL,iter);
- for( bl = (struct block_list*)dbi_last(mapit->dbi); bl != NULL; bl = (struct block_list*)dbi_prev(mapit->dbi) )
- {
- if( MAPIT_MATCHES(mapit,bl) )
+ for( bl = (struct block_list*)dbi_last(iter->dbi); bl != NULL; bl = (struct block_list*)dbi_prev(iter->dbi) ) {
+ if( MAPIT_MATCHES(iter,bl) )
break;// found match
}
return bl;
@@ -2099,20 +2183,18 @@ struct block_list* mapit_last(struct s_mapiterator* mapit)
/// Returns the next block_list that matches the description.
/// Returns NULL if not found.
///
-/// @param mapit Iterator
+/// @param iter Iterator
/// @return next block_list or NULL
-struct block_list* mapit_next(struct s_mapiterator* mapit)
-{
+struct block_list* mapit_next(struct s_mapiterator* iter) {
struct block_list* bl;
- nullpo_retr(NULL,mapit);
+ nullpo_retr(NULL,iter);
- for( ; ; )
- {
- bl = (struct block_list*)dbi_next(mapit->dbi);
+ for( ; ; ) {
+ bl = (struct block_list*)dbi_next(iter->dbi);
if( bl == NULL )
break;// end
- if( MAPIT_MATCHES(mapit,bl) )
+ if( MAPIT_MATCHES(iter,bl) )
break;// found a match
// try next
}
@@ -2122,20 +2204,18 @@ struct block_list* mapit_next(struct s_mapiterator* mapit)
/// Returns the previous block_list that matches the description.
/// Returns NULL if not found.
///
-/// @param mapit Iterator
+/// @param iter Iterator
/// @return previous block_list or NULL
-struct block_list* mapit_prev(struct s_mapiterator* mapit)
-{
+struct block_list* mapit_prev(struct s_mapiterator* iter) {
struct block_list* bl;
- nullpo_retr(NULL,mapit);
+ nullpo_retr(NULL,iter);
- for( ; ; )
- {
- bl = (struct block_list*)dbi_prev(mapit->dbi);
+ for( ; ; ) {
+ bl = (struct block_list*)dbi_prev(iter->dbi);
if( bl == NULL )
break;// end
- if( MAPIT_MATCHES(mapit,bl) )
+ if( MAPIT_MATCHES(iter,bl) )
break;// found a match
// try prev
}
@@ -2144,72 +2224,66 @@ struct block_list* mapit_prev(struct s_mapiterator* mapit)
/// Returns true if the current block_list exists in the database.
///
-/// @param mapit Iterator
+/// @param iter Iterator
/// @return true if it exists
-bool mapit_exists(struct s_mapiterator* mapit)
-{
- nullpo_retr(false,mapit);
+bool mapit_exists(struct s_mapiterator* iter) {
+ nullpo_retr(false,iter);
- return dbi_exists(mapit->dbi);
+ return dbi_exists(iter->dbi);
}
/*==========================================
-* Add npc-bl to id_db, basically register npc to map
-*------------------------------------------*/
+ * Add npc-bl to id_db, basically register npc to map
+ *------------------------------------------*/
bool map_addnpc(int16 m,struct npc_data *nd) {
nullpo_ret(nd);
- if( m < 0 || m >= iMap->map_num )
+ if( m < 0 || m >= map->count )
return false;
- if( map[m].npc_num == MAX_NPC_PER_MAP )
- {
- ShowWarning("too many NPCs in one map %s\n",map[m].name);
+ if( map->list[m].npc_num == MAX_NPC_PER_MAP ) {
+ ShowWarning("too many NPCs in one map %s\n",map->list[m].name);
return false;
}
- map[m].npc[map[m].npc_num]=nd;
- map[m].npc_num++;
- idb_put(id_db,nd->bl.id,nd);
+ map->list[m].npc[map->list[m].npc_num]=nd;
+ map->list[m].npc_num++;
+ idb_put(map->id_db,nd->bl.id,nd);
return true;
}
/*=========================================
-* Dynamic Mobs [Wizputer]
-*-----------------------------------------*/
+ * Dynamic Mobs [Wizputer]
+ *-----------------------------------------*/
// Stores the spawn data entry in the mob list.
// Returns the index of successful, or -1 if the list was full.
-int map_addmobtolist(unsigned short m, struct spawn_data *spawn)
-{
- size_t i;
- ARR_FIND( 0, MAX_MOB_LIST_PER_MAP, i, map[m].moblist[i] == NULL );
+int map_addmobtolist(unsigned short m, struct spawn_data *spawn) {
+ int i;
+ ARR_FIND( 0, MAX_MOB_LIST_PER_MAP, i, map->list[m].moblist[i] == NULL );
if( i < MAX_MOB_LIST_PER_MAP ) {
- map[m].moblist[i] = spawn;
+ map->list[m].moblist[i] = spawn;
return i;
}
return -1;
}
-void map_spawnmobs(int16 m)
-{
+void map_spawnmobs(int16 m) {
int i, k=0;
- if (map[m].mob_delete_timer != INVALID_TIMER)
- { //Mobs have not been removed yet [Skotlex]
- iTimer->delete_timer(map[m].mob_delete_timer, iMap->removemobs_timer);
- map[m].mob_delete_timer = INVALID_TIMER;
+ if (map->list[m].mob_delete_timer != INVALID_TIMER) {
+ //Mobs have not been removed yet [Skotlex]
+ timer->delete(map->list[m].mob_delete_timer, map->removemobs_timer);
+ map->list[m].mob_delete_timer = INVALID_TIMER;
return;
}
for(i=0; i<MAX_MOB_LIST_PER_MAP; i++)
- if(map[m].moblist[i]!=NULL)
- {
- k+=map[m].moblist[i]->num;
- npc_parse_mob2(map[m].moblist[i]);
+ if(map->list[m].moblist[i]!=NULL) {
+ k+=map->list[m].moblist[i]->num;
+ npc->parse_mob2(map->list[m].moblist[i]);
}
- if (battle_config.etc_log && k > 0)
- {
- ShowStatus("Map %s: Spawned '"CL_WHITE"%d"CL_RESET"' mobs.\n",map[m].name, k);
- }
+ if (battle_config.etc_log && k > 0) {
+ ShowStatus("Map %s: Spawned '"CL_WHITE"%d"CL_RESET"' mobs.\n",map->list[m].name, k);
+ }
}
int map_removemobs_sub(struct block_list *bl, va_list ap)
@@ -2234,73 +2308,71 @@ int map_removemobs_sub(struct block_list *bl, va_list ap)
if( md->db->mexp > 0 )
return 0;
- unit_free(&md->bl,CLR_OUTSIGHT);
+ unit->free(&md->bl,CLR_OUTSIGHT);
return 1;
}
-int map_removemobs_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+int map_removemobs_timer(int tid, int64 tick, int id, intptr_t data) {
int count;
const int16 m = id;
- if (m < 0 || m >= iMap->map_num) { //Incorrect map id!
+ if (m < 0 || m >= map->count) { //Incorrect map id!
ShowError("map_removemobs_timer error: timer %d points to invalid map %d\n",tid, m);
return 0;
}
- if (map[m].mob_delete_timer != tid) { //Incorrect timer call!
- ShowError("map_removemobs_timer mismatch: %d != %d (map %s)\n",map[m].mob_delete_timer, tid, map[m].name);
+ if (map->list[m].mob_delete_timer != tid) { //Incorrect timer call!
+ ShowError("map_removemobs_timer mismatch: %d != %d (map %s)\n",map->list[m].mob_delete_timer, tid, map->list[m].name);
return 0;
}
- map[m].mob_delete_timer = INVALID_TIMER;
- if (map[m].users > 0) //Map not empty!
+ map->list[m].mob_delete_timer = INVALID_TIMER;
+ if (map->list[m].users > 0) //Map not empty!
return 1;
- count = map_foreachinmap(map_removemobs_sub, m, BL_MOB);
+ count = map->foreachinmap(map->removemobs_sub, m, BL_MOB);
if (battle_config.etc_log && count > 0)
- ShowStatus("Map %s: Removed '"CL_WHITE"%d"CL_RESET"' mobs.\n",map[m].name, count);
+ ShowStatus("Map %s: Removed '"CL_WHITE"%d"CL_RESET"' mobs.\n",map->list[m].name, count);
return 1;
}
-void map_removemobs(int16 m)
-{
- if (map[m].mob_delete_timer != INVALID_TIMER) // should never happen
+void map_removemobs(int16 m) {
+ if (map->list[m].mob_delete_timer != INVALID_TIMER) // should never happen
return; //Mobs are already scheduled for removal
- map[m].mob_delete_timer = iTimer->add_timer(iTimer->gettick()+battle_config.mob_remove_delay, iMap->removemobs_timer, m, 0);
+ map->list[m].mob_delete_timer = timer->add(timer->gettick()+battle_config.mob_remove_delay, map->removemobs_timer, m, 0);
}
/*==========================================
-* Hookup, get map_id from map_name
-*------------------------------------------*/
+ * Hookup, get map_id from map_name
+ *------------------------------------------*/
int16 map_mapname2mapid(const char* name) {
unsigned short map_index;
- map_index = mapindex_name2id(name);
+ map_index = mapindex->name2id(name);
if (!map_index)
return -1;
- return iMap->mapindex2mapid(map_index);
+ return map->mapindex2mapid(map_index);
}
/*==========================================
-* Returns the map of the given mapindex. [Skotlex]
-*------------------------------------------*/
-int16 map_mapindex2mapid(unsigned short mapindex) {
+ * Returns the map of the given mapindex. [Skotlex]
+ *------------------------------------------*/
+int16 map_mapindex2mapid(unsigned short map_index) {
- if (!mapindex || mapindex > MAX_MAPINDEX)
+ if (!map_index || map_index > MAX_MAPINDEX)
return -1;
- return index2mapid[mapindex];
+ return map->index2mapid[map_index];
}
/*==========================================
-* Switching Ip, port ? (like changing map_server) get ip/port from map_name
-*------------------------------------------*/
+ * Switching Ip, port ? (like changing map_server) get ip/port from map_name
+ *------------------------------------------*/
int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port) {
struct map_data_other_server *mdos;
- mdos = (struct map_data_other_server*)uidb_get(map_db,(unsigned int)name);
+ mdos = (struct map_data_other_server*)uidb_get(map->map_db,(unsigned int)name);
if(mdos==NULL || mdos->cell) //If gat isn't null, this is a local map.
return -1;
*ip=mdos->ip;
@@ -2316,21 +2388,21 @@ int map_check_dir(int s_dir,int t_dir)
if(s_dir == t_dir)
return 0;
switch(s_dir) {
- case 0: if(t_dir == 7 || t_dir == 1 || t_dir == 0) return 0; break;
- case 1: if(t_dir == 0 || t_dir == 2 || t_dir == 1) return 0; break;
- case 2: if(t_dir == 1 || t_dir == 3 || t_dir == 2) return 0; break;
- case 3: if(t_dir == 2 || t_dir == 4 || t_dir == 3) return 0; break;
- case 4: if(t_dir == 3 || t_dir == 5 || t_dir == 4) return 0; break;
- case 5: if(t_dir == 4 || t_dir == 6 || t_dir == 5) return 0; break;
- case 6: if(t_dir == 5 || t_dir == 7 || t_dir == 6) return 0; break;
- case 7: if(t_dir == 6 || t_dir == 0 || t_dir == 7) return 0; break;
+ case 0: if(t_dir == 7 || t_dir == 1 || t_dir == 0) return 0; break;
+ case 1: if(t_dir == 0 || t_dir == 2 || t_dir == 1) return 0; break;
+ case 2: if(t_dir == 1 || t_dir == 3 || t_dir == 2) return 0; break;
+ case 3: if(t_dir == 2 || t_dir == 4 || t_dir == 3) return 0; break;
+ case 4: if(t_dir == 3 || t_dir == 5 || t_dir == 4) return 0; break;
+ case 5: if(t_dir == 4 || t_dir == 6 || t_dir == 5) return 0; break;
+ case 6: if(t_dir == 5 || t_dir == 7 || t_dir == 6) return 0; break;
+ case 7: if(t_dir == 6 || t_dir == 0 || t_dir == 7) return 0; break;
}
return 1;
}
/*==========================================
-* Returns the direction of the given cell, relative to 'src'
-*------------------------------------------*/
+ * Returns the direction of the given cell, relative to 'src'
+ *------------------------------------------*/
uint8 map_calc_dir(struct block_list* src, int16 x, int16 y)
{
uint8 dir = 0;
@@ -2341,9 +2413,10 @@ uint8 map_calc_dir(struct block_list* src, int16 x, int16 y)
dx = x-src->x;
dy = y-src->y;
if( dx == 0 && dy == 0 )
- { // both are standing on the same spot
- //dir = 6; // aegis-style, makes knockback default to the left
- dir = unit_getdir(src); // athena-style, makes knockback default to behind 'src'
+ { // both are standing on the same spot.
+ // aegis-style, makes knockback default to the left.
+ // athena-style, makes knockback default to behind 'src'.
+ dir = (battle_config.knockback_left ? 6 : unit->getdir(src));
}
else if( dx >= 0 && dy >=0 )
{ // upper-right
@@ -2374,9 +2447,9 @@ uint8 map_calc_dir(struct block_list* src, int16 x, int16 y)
}
/*==========================================
-* Randomizes target cell x,y to a random walkable cell that
-* has the same distance from object as given coordinates do. [Skotlex]
-*------------------------------------------*/
+ * Randomizes target cell x,y to a random walkable cell that
+ * has the same distance from object as given coordinates do. [Skotlex]
+ *------------------------------------------*/
int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
{
short xi = *x-bl->x;
@@ -2394,9 +2467,8 @@ int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
xi = bl->x + segment*dirx[j];
segment = (short)sqrt((float)(dist2 - segment*segment)); //The complement of the previously picked segment
yi = bl->y + segment*diry[j];
- } while (
- (iMap->getcell(bl->m,xi,yi,CELL_CHKNOPASS) || !path_search(NULL,bl->m,bl->x,bl->y,xi,yi,1,CELL_CHKNOREACH))
- && (++i)<100 );
+ } while ( (map->getcell(bl->m,xi,yi,CELL_CHKNOPASS) || !path->search(NULL,bl->m,bl->x,bl->y,xi,yi,1,CELL_CHKNOREACH))
+ && (++i)<100 );
if (i < 100) {
*x = xi;
@@ -2413,13 +2485,13 @@ inline static struct mapcell map_gat2cell(int gat) {
memset(&cell,0,sizeof(struct mapcell));
switch( gat ) {
- case 0: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // walkable ground
- case 1: cell.walkable = 0; cell.shootable = 0; cell.water = 0; break; // non-walkable ground
- case 2: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // ???
- case 3: cell.walkable = 1; cell.shootable = 1; cell.water = 1; break; // walkable water
- case 4: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // ???
- case 5: cell.walkable = 0; cell.shootable = 1; cell.water = 0; break; // gap (snipable)
- case 6: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // ???
+ case 0: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // walkable ground
+ case 1: cell.walkable = 0; cell.shootable = 0; cell.water = 0; break; // non-walkable ground
+ case 2: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // ???
+ case 3: cell.walkable = 1; cell.shootable = 1; cell.water = 1; break; // walkable water
+ case 4: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // ???
+ case 5: cell.walkable = 0; cell.shootable = 1; cell.water = 0; break; // gap (snipable)
+ case 6: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // ???
default:
ShowWarning("map_gat2cell: unrecognized gat type '%d'\n", gat);
break;
@@ -2428,7 +2500,7 @@ inline static struct mapcell map_gat2cell(int gat) {
return cell;
}
-static int map_cell2gat(struct mapcell cell) {
+int map_cell2gat(struct mapcell cell) {
if( cell.walkable == 1 && cell.shootable == 1 && cell.water == 0 ) return 0;
if( cell.walkable == 0 && cell.shootable == 0 && cell.water == 0 ) return 1;
if( cell.walkable == 1 && cell.shootable == 1 && cell.water == 1 ) return 3;
@@ -2437,8 +2509,6 @@ static int map_cell2gat(struct mapcell cell) {
ShowWarning("map_cell2gat: cell has no matching gat type\n");
return 1; // default to 'wall'
}
-int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk);
-void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag);
void map_cellfromcache(struct map_data *m) {
char decode_buffer[MAX_MAP_SIZE];
struct map_cache_map_info *info = NULL;
@@ -2453,23 +2523,28 @@ void map_cellfromcache(struct map_data *m) {
decode_zip(decode_buffer, &size, m->cellPos+sizeof(struct map_cache_map_info), info->len);
CREATE(m->cell, struct mapcell, size);
- for( xy = 0; xy < size; ++xy )
- m->cell[xy] = map_gat2cell(decode_buffer[xy]);
+ // Set cell properties
+ for( xy = 0; xy < size; ++xy ) {
+ m->cell[xy] = map->gat2cell(decode_buffer[xy]);
+#ifdef CELL_NOSTACK
+ m->cell[xy].cell_bl = 0;
+#endif
+ }
- m->getcellp = map_getcellp;
- m->setcell = map_setcell;
+ m->getcellp = map->getcellp;
+ m->setcell = map->setcell;
for(i = 0; i < m->npc_num; i++) {
- npc_setcells(m->npc[i]);
+ npc->setcells(m->npc[i]);
}
}
}
/*==========================================
-* Confirm if celltype in (m,x,y) match the one given in cellchk
-*------------------------------------------*/
+ * Confirm if celltype in (m,x,y) match the one given in cellchk
+ *------------------------------------------*/
int map_getcell(int16 m,int16 x,int16 y,cell_chk cellchk) {
- return (m < 0 || m >= iMap->map_num) ? 0 : map[m].getcellp(&map[m],x,y,cellchk);
+ return (m < 0 || m >= map->count) ? 0 : map->list[m].getcellp(&map->list[m],x,y,cellchk);
}
int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) {
@@ -2486,7 +2561,7 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) {
switch(cellchk) {
// gat type retrieval
case CELL_GETTYPE:
- return map_cell2gat(cell);
+ return map->cell2gat(cell);
// base gat type checks
case CELL_CHKWALL:
@@ -2510,8 +2585,6 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) {
return (cell.novending);
case CELL_CHKNOCHAT:
return (cell.nochat);
- case CELL_CHKMAELSTROM:
- return (cell.maelstrom);
case CELL_CHKICEWALL:
return (cell.icewall);
@@ -2544,72 +2617,67 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) {
/* [Ind/Hercules] */
int map_sub_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) {
- iMap->cellfromcache(m);
- m->getcellp = map_getcellp;
- m->setcell = map_setcell;
+ map->cellfromcache(m);
+ m->getcellp = map->getcellp;
+ m->setcell = map->setcell;
return m->getcellp(m,x,y,cellchk);
}
/*==========================================
-* Change the type/flags of a map cell
-* 'cell' - which flag to modify
-* 'flag' - true = on, false = off
-*------------------------------------------*/
+ * Change the type/flags of a map cell
+ * 'cell' - which flag to modify
+ * 'flag' - true = on, false = off
+ *------------------------------------------*/
void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) {
int j;
- if( m < 0 || m >= iMap->map_num || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
+ if( m < 0 || m >= map->count || x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys )
return;
- j = x + y*map[m].xs;
+ j = x + y*map->list[m].xs;
switch( cell ) {
- case CELL_WALKABLE: map[m].cell[j].walkable = flag; break;
- case CELL_SHOOTABLE: map[m].cell[j].shootable = flag; break;
- case CELL_WATER: map[m].cell[j].water = flag; break;
-
- case CELL_NPC: map[m].cell[j].npc = flag; break;
- case CELL_BASILICA: map[m].cell[j].basilica = flag; break;
- case CELL_LANDPROTECTOR: map[m].cell[j].landprotector = flag; break;
- case CELL_NOVENDING: map[m].cell[j].novending = flag; break;
- case CELL_NOCHAT: map[m].cell[j].nochat = flag; break;
- case CELL_MAELSTROM: map[m].cell[j].maelstrom = flag; break;
- case CELL_ICEWALL: map[m].cell[j].icewall = flag; break;
+ case CELL_WALKABLE: map->list[m].cell[j].walkable = flag; break;
+ case CELL_SHOOTABLE: map->list[m].cell[j].shootable = flag; break;
+ case CELL_WATER: map->list[m].cell[j].water = flag; break;
+
+ case CELL_NPC: map->list[m].cell[j].npc = flag; break;
+ case CELL_BASILICA: map->list[m].cell[j].basilica = flag; break;
+ case CELL_LANDPROTECTOR: map->list[m].cell[j].landprotector = flag; break;
+ case CELL_NOVENDING: map->list[m].cell[j].novending = flag; break;
+ case CELL_NOCHAT: map->list[m].cell[j].nochat = flag; break;
+ case CELL_ICEWALL: map->list[m].cell[j].icewall = flag; break;
default:
ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell);
break;
}
}
void map_sub_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) {
-
- if( m < 0 || m >= iMap->map_num || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
+ if( m < 0 || m >= map->count || x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys )
return;
- iMap->cellfromcache(&map[m]);
- map[m].setcell = map_setcell;
- map[m].getcellp = map_getcellp;
- map[m].setcell(m,x,y,cell,flag);
+ map->cellfromcache(&map->list[m]);
+ map->list[m].setcell = map->setcell;
+ map->list[m].getcellp = map->getcellp;
+ map->list[m].setcell(m,x,y,cell,flag);
}
-void map_setgatcell(int16 m, int16 x, int16 y, int gat)
-{
+void map_setgatcell(int16 m, int16 x, int16 y, int gat) {
int j;
struct mapcell cell;
- if( m < 0 || m >= iMap->map_num || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys )
+ if( m < 0 || m >= map->count || x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys )
return;
- j = x + y*map[m].xs;
+ j = x + y*map->list[m].xs;
- cell = map_gat2cell(gat);
- map[m].cell[j].walkable = cell.walkable;
- map[m].cell[j].shootable = cell.shootable;
- map[m].cell[j].water = cell.water;
+ cell = map->gat2cell(gat);
+ map->list[m].cell[j].walkable = cell.walkable;
+ map->list[m].cell[j].shootable = cell.shootable;
+ map->list[m].cell[j].water = cell.water;
}
/*==========================================
* Invisible Walls
*------------------------------------------*/
-static DBMap* iwall_db;
-
void map_iwall_nextxy(int16 x, int16 y, int8 dir, int pos, int16 *x1, int16 *y1)
{
if( dir == 0 || dir == 4 )
@@ -2636,10 +2704,10 @@ bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable
if( size < 1 || !wall_name )
return false;
- if( (iwall = (struct iwall_data *)strdb_get(iwall_db, wall_name)) != NULL )
+ if( (iwall = (struct iwall_data *)strdb_get(map->iwall_db, wall_name)) != NULL )
return false; // Already Exists
- if( iMap->getcell(m, x, y, CELL_CHKNOREACH) )
+ if( map->getcell(m, x, y, CELL_CHKNOREACH) )
return false; // Starting cell problem
CREATE(iwall, struct iwall_data, 1);
@@ -2651,23 +2719,22 @@ bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable
iwall->shootable = shootable;
safestrncpy(iwall->wall_name, wall_name, sizeof(iwall->wall_name));
- for( i = 0; i < size; i++ )
- {
- map_iwall_nextxy(x, y, dir, i, &x1, &y1);
+ for( i = 0; i < size; i++ ) {
+ map->iwall_nextxy(x, y, dir, i, &x1, &y1);
- if( iMap->getcell(m, x1, y1, CELL_CHKNOREACH) )
+ if( map->getcell(m, x1, y1, CELL_CHKNOREACH) )
break; // Collision
- map[m].setcell(m, x1, y1, CELL_WALKABLE, false);
- map[m].setcell(m, x1, y1, CELL_SHOOTABLE, shootable);
+ map->list[m].setcell(m, x1, y1, CELL_WALKABLE, false);
+ map->list[m].setcell(m, x1, y1, CELL_SHOOTABLE, shootable);
- clif->changemapcell(0, m, x1, y1, iMap->getcell(m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP);
+ clif->changemapcell(0, m, x1, y1, map->getcell(m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP);
}
iwall->size = i;
- strdb_put(iwall_db, iwall->wall_name, iwall);
- map[m].iwall_num++;
+ strdb_put(map->iwall_db, iwall->wall_name, iwall);
+ map->list[m].iwall_num++;
return true;
}
@@ -2678,17 +2745,17 @@ void map_iwall_get(struct map_session_data *sd) {
int16 x1, y1;
int i;
- if( map[sd->bl.m].iwall_num < 1 )
+ if( map->list[sd->bl.m].iwall_num < 1 )
return;
- iter = db_iterator(iwall_db);
+ iter = db_iterator(map->iwall_db);
for( iwall = dbi_first(iter); dbi_exists(iter); iwall = dbi_next(iter) ) {
if( iwall->m != sd->bl.m )
continue;
for( i = 0; i < iwall->size; i++ ) {
- map_iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1);
- clif->changemapcell(sd->fd, iwall->m, x1, y1, iMap->getcell(iwall->m, x1, y1, CELL_GETTYPE), SELF);
+ map->iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1);
+ clif->changemapcell(sd->fd, iwall->m, x1, y1, map->getcell(iwall->m, x1, y1, CELL_GETTYPE), SELF);
}
}
dbi_destroy(iter);
@@ -2699,49 +2766,49 @@ void map_iwall_remove(const char *wall_name)
struct iwall_data *iwall;
int16 i, x1, y1;
- if( (iwall = (struct iwall_data *)strdb_get(iwall_db, wall_name)) == NULL )
+ if( (iwall = (struct iwall_data *)strdb_get(map->iwall_db, wall_name)) == NULL )
return; // Nothing to do
for( i = 0; i < iwall->size; i++ ) {
- map_iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1);
+ map->iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1);
- map[iwall->m].setcell(iwall->m, x1, y1, CELL_SHOOTABLE, true);
- map[iwall->m].setcell(iwall->m, x1, y1, CELL_WALKABLE, true);
+ map->list[iwall->m].setcell(iwall->m, x1, y1, CELL_SHOOTABLE, true);
+ map->list[iwall->m].setcell(iwall->m, x1, y1, CELL_WALKABLE, true);
- clif->changemapcell(0, iwall->m, x1, y1, iMap->getcell(iwall->m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP);
+ clif->changemapcell(0, iwall->m, x1, y1, map->getcell(iwall->m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP);
}
- map[iwall->m].iwall_num--;
- strdb_remove(iwall_db, iwall->wall_name);
+ map->list[iwall->m].iwall_num--;
+ strdb_remove(map->iwall_db, iwall->wall_name);
}
/**
-* @see DBCreateData
-*/
-static DBData create_map_data_other_server(DBKey key, va_list args)
+ * @see DBCreateData
+ */
+DBData create_map_data_other_server(DBKey key, va_list args)
{
struct map_data_other_server *mdos;
- unsigned short mapindex = (unsigned short)key.ui;
+ unsigned short map_index = (unsigned short)key.ui;
mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server));
- mdos->index = mapindex;
- memcpy(mdos->name, mapindex_id2name(mapindex), MAP_NAME_LENGTH);
+ mdos->index = map_index;
+ memcpy(mdos->name, mapindex_id2name(map_index), MAP_NAME_LENGTH);
return DB->ptr2data(mdos);
}
/*==========================================
-* Add mapindex to db of another map server
-*------------------------------------------*/
-int map_setipport(unsigned short mapindex, uint32 ip, uint16 port)
+ * Add mapindex to db of another map server
+ *------------------------------------------*/
+int map_setipport(unsigned short map_index, uint32 ip, uint16 port)
{
struct map_data_other_server *mdos;
- mdos= uidb_ensure(map_db,(unsigned int)mapindex, create_map_data_other_server);
+ mdos= uidb_ensure(map->map_db,(unsigned int)map_index, map->create_map_data_other_server);
if(mdos->cell) //Local map,Do nothing. Give priority to our own local maps over ones from another server. [Skotlex]
return 0;
if(ip == clif->map_ip && port == clif->map_port) {
//That's odd, we received info that we are the ones with this map, but... we don't have it.
- ShowFatalError("map_setipport : received info that this map-server SHOULD have map '%s', but it is not loaded.\n",mapindex_id2name(mapindex));
+ ShowFatalError("map_setipport : received info that this map-server SHOULD have map '%s', but it is not loaded.\n",mapindex_id2name(map_index));
exit(EXIT_FAILURE);
}
mdos->ip = ip;
@@ -2750,36 +2817,36 @@ int map_setipport(unsigned short mapindex, uint32 ip, uint16 port)
}
/**
-* Delete all the other maps server management
-* @see DBApply
-*/
+ * Delete all the other maps server management
+ * @see DBApply
+ */
int map_eraseallipport_sub(DBKey key, DBData *data, va_list va)
{
struct map_data_other_server *mdos = DB->data2ptr(data);
if(mdos->cell == NULL) {
- db_remove(map_db,key);
+ db_remove(map->map_db,key);
aFree(mdos);
}
return 0;
}
int map_eraseallipport(void) {
- map_db->foreach(map_db,map_eraseallipport_sub);
+ map->map_db->foreach(map->map_db,map->eraseallipport_sub);
return 1;
}
/*==========================================
-* Delete mapindex from db of another map server
-*------------------------------------------*/
-int map_eraseipport(unsigned short mapindex, uint32 ip, uint16 port) {
+ * Delete mapindex from db of another map server
+ *------------------------------------------*/
+int map_eraseipport(unsigned short map_index, uint32 ip, uint16 port) {
struct map_data_other_server *mdos;
- mdos = (struct map_data_other_server*)uidb_get(map_db,(unsigned int)mapindex);
+ mdos = (struct map_data_other_server*)uidb_get(map->map_db,(unsigned int)map_index);
if(!mdos || mdos->cell) //Map either does not exists or is a local map.
return 0;
if(mdos->ip==ip && mdos->port == port) {
- uidb_remove(map_db,(unsigned int)mapindex);
+ uidb_remove(map->map_db,(unsigned int)map_index);
aFree(mdos);
return 1;
}
@@ -2787,10 +2854,10 @@ int map_eraseipport(unsigned short mapindex, uint32 ip, uint16 port) {
}
/*==========================================
-* [Shinryo]: Init the mapcache
-*------------------------------------------*/
-static char *map_init_mapcache(FILE *fp)
-{
+ * [Shinryo]: Init the mapcache
+ *------------------------------------------*/
+char *map_init_mapcache(FILE *fp) {
+ struct map_cache_main_header header;
size_t size = 0;
char *buffer;
@@ -2811,6 +2878,21 @@ static char *map_init_mapcache(FILE *fp)
// Read file into buffer..
if(fread(buffer, sizeof(char), size, fp) != size) {
ShowError("map_init_mapcache: Could not read entire mapcache file\n");
+ aFree(buffer);
+ return NULL;
+ }
+
+ rewind(fp);
+
+ // Get main header to verify if data is corrupted
+ if( fread(&header, sizeof(header), 1, fp) != 1 ) {
+ ShowError("map_init_mapcache: Error obtaining main header!\n");
+ aFree(buffer);
+ return NULL;
+ }
+ if( GetULong((unsigned char *)&(header.file_size)) != size ) {
+ ShowError("map_init_mapcache: Map cache is corrupted!\n");
+ aFree(buffer);
return NULL;
}
@@ -2818,9 +2900,9 @@ static char *map_init_mapcache(FILE *fp)
}
/*==========================================
-* Map cache reading
-* [Shinryo]: Optimized some behaviour to speed this up
-*==========================================*/
+ * Map cache reading
+ * [Shinryo]: Optimized some behaviour to speed this up
+ *==========================================*/
int map_readfromcache(struct map_data *m, char *buffer) {
int i;
struct map_cache_main_header *header = (struct map_cache_main_header *)buffer;
@@ -2862,16 +2944,16 @@ int map_readfromcache(struct map_data *m, char *buffer) {
}
-int map_addmap(char* mapname) {
- map[iMap->map_num].instance_id = -1;
- mapindex_getmapname(mapname, map[iMap->map_num++].name);
+int map_addmap(const char* mapname) {
+ map->list[map->count].instance_id = -1;
+ mapindex->getmapname(mapname, map->list[map->count++].name);
return 0;
}
-static void map_delmapid(int id) {
- ShowNotice("Removing map [ %s ] from maplist"CL_CLL"\n",map[id].name);
- memmove(map+id, map+id+1, sizeof(map[0])*(iMap->map_num-id-1));
- iMap->map_num--;
+void map_delmapid(int id) {
+ ShowNotice("Removing map [ %s ] from maplist"CL_CLL"\n",map->list[id].name);
+ memmove(map->list+id, map->list+id+1, sizeof(map->list[0])*(map->count-id-1));
+ map->count--;
}
int map_delmap(char* mapname) {
@@ -2879,14 +2961,14 @@ int map_delmap(char* mapname) {
char map_name[MAP_NAME_LENGTH];
if (strcmpi(mapname, "all") == 0) {
- iMap->map_num = 0;
+ map->count = 0;
return 0;
}
- mapindex_getmapname(mapname, map_name);
- for(i = 0; i < iMap->map_num; i++) {
- if (strcmp(map[i].name, map_name) == 0) {
- map_delmapid(i);
+ mapindex->getmapname(mapname, map_name);
+ for(i = 0; i < map->count; i++) {
+ if (strcmp(map->list[i].name, map_name) == 0) {
+ map->delmapid(i);
return 1;
}
}
@@ -2896,7 +2978,7 @@ void map_zone_db_clear(void) {
struct map_zone_data *zone;
int i;
- DBIterator *iter = db_iterator(zone_db);
+ DBIterator *iter = db_iterator(map->zone_db);
for(zone = dbi_first(iter); dbi_exists(iter); zone = dbi_next(iter)) {
for(i = 0; i < zone->disabled_skills_count; i++) {
aFree(zone->disabled_skills[i]);
@@ -2918,229 +3000,247 @@ void map_zone_db_clear(void) {
}
dbi_destroy(iter);
- db_destroy(zone_db);/* will aFree(zone) */
+ db_destroy(map->zone_db);/* will aFree(zone) */
/* clear the pk zone stuff */
- for(i = 0; i < map_zone_pk.disabled_skills_count; i++) {
- aFree(map_zone_pk.disabled_skills[i]);
+ for(i = 0; i < map->zone_pk.disabled_skills_count; i++) {
+ aFree(map->zone_pk.disabled_skills[i]);
}
- aFree(map_zone_pk.disabled_skills);
- aFree(map_zone_pk.disabled_items);
- for(i = 0; i < map_zone_pk.mapflags_count; i++) {
- aFree(map_zone_pk.mapflags[i]);
+ aFree(map->zone_pk.disabled_skills);
+ aFree(map->zone_pk.disabled_items);
+ for(i = 0; i < map->zone_pk.mapflags_count; i++) {
+ aFree(map->zone_pk.mapflags[i]);
}
- aFree(map_zone_pk.mapflags);
- for(i = 0; i < map_zone_pk.disabled_commands_count; i++) {
- aFree(map_zone_pk.disabled_commands[i]);
+ aFree(map->zone_pk.mapflags);
+ for(i = 0; i < map->zone_pk.disabled_commands_count; i++) {
+ aFree(map->zone_pk.disabled_commands[i]);
}
- aFree(map_zone_pk.disabled_commands);
- for(i = 0; i < map_zone_pk.capped_skills_count; i++) {
- aFree(map_zone_pk.capped_skills[i]);
+ aFree(map->zone_pk.disabled_commands);
+ for(i = 0; i < map->zone_pk.capped_skills_count; i++) {
+ aFree(map->zone_pk.capped_skills[i]);
}
- aFree(map_zone_pk.capped_skills);
+ aFree(map->zone_pk.capped_skills);
/* clear the main zone stuff */
- for(i = 0; i < map_zone_all.disabled_skills_count; i++) {
- aFree(map_zone_all.disabled_skills[i]);
+ for(i = 0; i < map->zone_all.disabled_skills_count; i++) {
+ aFree(map->zone_all.disabled_skills[i]);
}
- aFree(map_zone_all.disabled_skills);
- aFree(map_zone_all.disabled_items);
- for(i = 0; i < map_zone_all.mapflags_count; i++) {
- aFree(map_zone_all.mapflags[i]);
+ aFree(map->zone_all.disabled_skills);
+ aFree(map->zone_all.disabled_items);
+ for(i = 0; i < map->zone_all.mapflags_count; i++) {
+ aFree(map->zone_all.mapflags[i]);
}
- aFree(map_zone_all.mapflags);
- for(i = 0; i < map_zone_all.disabled_commands_count; i++) {
- aFree(map_zone_all.disabled_commands[i]);
+ aFree(map->zone_all.mapflags);
+ for(i = 0; i < map->zone_all.disabled_commands_count; i++) {
+ aFree(map->zone_all.disabled_commands[i]);
}
- aFree(map_zone_all.disabled_commands);
- for(i = 0; i < map_zone_all.capped_skills_count; i++) {
- aFree(map_zone_all.capped_skills[i]);
+ aFree(map->zone_all.disabled_commands);
+ for(i = 0; i < map->zone_all.capped_skills_count; i++) {
+ aFree(map->zone_all.capped_skills[i]);
}
- aFree(map_zone_all.capped_skills);
+ aFree(map->zone_all.capped_skills);
}
void map_clean(int i) {
int v;
- if(map[i].cell && map[i].cell != (struct mapcell *)0xdeadbeaf) aFree(map[i].cell);
- if(map[i].block) aFree(map[i].block);
- if(map[i].block_mob) aFree(map[i].block_mob);
+ if(map->list[i].cell && map->list[i].cell != (struct mapcell *)0xdeadbeaf) aFree(map->list[i].cell);
+ if(map->list[i].block) aFree(map->list[i].block);
+ if(map->list[i].block_mob) aFree(map->list[i].block_mob);
if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random]
int j;
- if(map[i].mob_delete_timer != INVALID_TIMER)
- iTimer->delete_timer(map[i].mob_delete_timer, iMap->removemobs_timer);
+ if(map->list[i].mob_delete_timer != INVALID_TIMER)
+ timer->delete(map->list[i].mob_delete_timer, map->removemobs_timer);
for (j=0; j<MAX_MOB_LIST_PER_MAP; j++)
- if (map[i].moblist[j]) aFree(map[i].moblist[j]);
+ if (map->list[i].moblist[j]) aFree(map->list[i].moblist[j]);
}
- if( map[i].unit_count ) {
- for(v = 0; v < map[i].unit_count; v++) {
- aFree(map[i].units[v]);
+ if( map->list[i].unit_count ) {
+ for(v = 0; v < map->list[i].unit_count; v++) {
+ aFree(map->list[i].units[v]);
}
- if( map[i].units ) {
- aFree(map[i].units);
- map[i].units = NULL;
+ if( map->list[i].units ) {
+ aFree(map->list[i].units);
+ map->list[i].units = NULL;
}
- map[i].unit_count = 0;
+ map->list[i].unit_count = 0;
}
- if( map[i].skill_count ) {
- for(v = 0; v < map[i].skill_count; v++) {
- aFree(map[i].skills[v]);
+ if( map->list[i].skill_count ) {
+ for(v = 0; v < map->list[i].skill_count; v++) {
+ aFree(map->list[i].skills[v]);
}
- if( map[i].skills ) {
- aFree(map[i].skills);
- map[i].skills = NULL;
+ if( map->list[i].skills ) {
+ aFree(map->list[i].skills);
+ map->list[i].skills = NULL;
}
- map[i].skill_count = 0;
+ map->list[i].skill_count = 0;
}
- if( map[i].zone_mf_count ) {
- for(v = 0; v < map[i].zone_mf_count; v++) {
- aFree(map[i].zone_mf[v]);
+ if( map->list[i].zone_mf_count ) {
+ for(v = 0; v < map->list[i].zone_mf_count; v++) {
+ aFree(map->list[i].zone_mf[v]);
}
- if( map[i].zone_mf ) {
- aFree(map[i].zone_mf);
- map[i].zone_mf = NULL;
+ if( map->list[i].zone_mf ) {
+ aFree(map->list[i].zone_mf);
+ map->list[i].zone_mf = NULL;
}
- map[i].zone_mf_count = 0;
+ map->list[i].zone_mf_count = 0;
}
- if( map[i].channel )
- clif->chsys_delete(map[i].channel);
+ if( map->list[i].channel )
+ clif->chsys_delete(map->list[i].channel);
}
void do_final_maps(void) {
int i, v = 0;
- for( i = 0; i < iMap->map_num; i++ ) {
+ for( i = 0; i < map->count; i++ ) {
- if(map[i].cell && map[i].cell != (struct mapcell *)0xdeadbeaf ) aFree(map[i].cell);
- if(map[i].block) aFree(map[i].block);
- if(map[i].block_mob) aFree(map[i].block_mob);
+ if(map->list[i].cell && map->list[i].cell != (struct mapcell *)0xdeadbeaf ) aFree(map->list[i].cell);
+ if(map->list[i].block) aFree(map->list[i].block);
+ if(map->list[i].block_mob) aFree(map->list[i].block_mob);
if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random]
int j;
- if(map[i].mob_delete_timer != INVALID_TIMER)
- iTimer->delete_timer(map[i].mob_delete_timer, iMap->removemobs_timer);
+ if(map->list[i].mob_delete_timer != INVALID_TIMER)
+ timer->delete(map->list[i].mob_delete_timer, map->removemobs_timer);
for (j=0; j<MAX_MOB_LIST_PER_MAP; j++)
- if (map[i].moblist[j]) aFree(map[i].moblist[j]);
+ if (map->list[i].moblist[j]) aFree(map->list[i].moblist[j]);
}
- if( map[i].unit_count ) {
- for(v = 0; v < map[i].unit_count; v++) {
- aFree(map[i].units[v]);
+ if( map->list[i].unit_count ) {
+ for(v = 0; v < map->list[i].unit_count; v++) {
+ aFree(map->list[i].units[v]);
}
- if( map[i].units ) {
- aFree(map[i].units);
- map[i].units = NULL;
+ if( map->list[i].units ) {
+ aFree(map->list[i].units);
+ map->list[i].units = NULL;
}
- map[i].unit_count = 0;
+ map->list[i].unit_count = 0;
}
- if( map[i].skill_count ) {
- for(v = 0; v < map[i].skill_count; v++) {
- aFree(map[i].skills[v]);
+ if( map->list[i].skill_count ) {
+ for(v = 0; v < map->list[i].skill_count; v++) {
+ aFree(map->list[i].skills[v]);
}
- if( map[i].skills ) {
- aFree(map[i].skills);
- map[i].skills = NULL;
+ if( map->list[i].skills ) {
+ aFree(map->list[i].skills);
+ map->list[i].skills = NULL;
}
- map[i].skill_count = 0;
+ map->list[i].skill_count = 0;
}
- if( map[i].zone_mf_count ) {
- for(v = 0; v < map[i].zone_mf_count; v++) {
- aFree(map[i].zone_mf[v]);
+ if( map->list[i].zone_mf_count ) {
+ for(v = 0; v < map->list[i].zone_mf_count; v++) {
+ aFree(map->list[i].zone_mf[v]);
}
- if( map[i].zone_mf ) {
- aFree(map[i].zone_mf);
- map[i].zone_mf = NULL;
+ if( map->list[i].zone_mf ) {
+ aFree(map->list[i].zone_mf);
+ map->list[i].zone_mf = NULL;
}
- map[i].zone_mf_count = 0;
+ map->list[i].zone_mf_count = 0;
}
- if( map[i].drop_list_count ) {
- map[i].drop_list_count = 0;
+ if( map->list[i].drop_list_count ) {
+ map->list[i].drop_list_count = 0;
}
- if( map[i].drop_list != NULL )
- aFree(map[i].drop_list);
+ if( map->list[i].drop_list != NULL )
+ aFree(map->list[i].drop_list);
- if( map[i].channel )
- clif->chsys_delete(map[i].channel);
+ if( map->list[i].channel )
+ clif->chsys_delete(map->list[i].channel);
+
+ if( map->list[i].qi_data )
+ aFree(map->list[i].qi_data);
+
+ for( v = 0; v < map->list[i].hdatac; v++ ) {
+ if( map->list[i].hdata[v]->flag.free ) {
+ aFree(map->list[i].hdata[v]->data);
+ }
+ aFree(map->list[i].hdata[v]);
+ }
+ if( map->list[i].hdata )
+ aFree(map->list[i].hdata);
}
- map_zone_db_clear();
+ map->zone_db_clear();
}
/// Initializes map flags and adjusts them depending on configuration.
void map_flags_init(void) {
int i, v = 0;
- for( i = 0; i < iMap->map_num; i++ ) {
+ for( i = 0; i < map->count; i++ ) {
// mapflags
- memset(&map[i].flag, 0, sizeof(map[i].flag));
+ memset(&map->list[i].flag, 0, sizeof(map->list[i].flag));
// additional mapflag data
- map[i].nocommand = 0; // nocommand mapflag level
- map[i].bexp = 100; // per map base exp multiplicator
- map[i].jexp = 100; // per map job exp multiplicator
- if( map[i].drop_list != NULL )
- aFree(map[i].drop_list);
- map[i].drop_list = NULL;
- map[i].drop_list_count = 0;
-
- if( map[i].unit_count ) {
- for(v = 0; v < map[i].unit_count; v++) {
- aFree(map[i].units[v]);
+ map->list[i].nocommand = 0; // nocommand mapflag level
+ map->list[i].bexp = 100; // per map base exp multiplicator
+ map->list[i].jexp = 100; // per map job exp multiplicator
+ if( map->list[i].drop_list != NULL )
+ aFree(map->list[i].drop_list);
+ map->list[i].drop_list = NULL;
+ map->list[i].drop_list_count = 0;
+
+ if( map->list[i].unit_count ) {
+ for(v = 0; v < map->list[i].unit_count; v++) {
+ aFree(map->list[i].units[v]);
}
- aFree(map[i].units);
+ aFree(map->list[i].units);
}
- map[i].units = NULL;
- map[i].unit_count = 0;
+ map->list[i].units = NULL;
+ map->list[i].unit_count = 0;
- if( map[i].skill_count ) {
- for(v = 0; v < map[i].skill_count; v++) {
- aFree(map[i].skills[v]);
+ if( map->list[i].skill_count ) {
+ for(v = 0; v < map->list[i].skill_count; v++) {
+ aFree(map->list[i].skills[v]);
}
- aFree(map[i].skills);
+ aFree(map->list[i].skills);
}
- map[i].skills = NULL;
- map[i].skill_count = 0;
+ map->list[i].skills = NULL;
+ map->list[i].skill_count = 0;
// adjustments
if( battle_config.pk_mode ) {
- map[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
- map[i].zone = &map_zone_pk;
+ map->list[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
+ map->list[i].zone = &map->zone_pk;
} else /* align with 'All' zone */
- map[i].zone = &map_zone_all;
+ map->list[i].zone = &map->zone_all;
- if( map[i].zone_mf_count ) {
- for(v = 0; v < map[i].zone_mf_count; v++) {
- aFree(map[i].zone_mf[v]);
+ if( map->list[i].zone_mf_count ) {
+ for(v = 0; v < map->list[i].zone_mf_count; v++) {
+ aFree(map->list[i].zone_mf[v]);
}
- aFree(map[i].zone_mf);
+ aFree(map->list[i].zone_mf);
}
- map[i].zone_mf = NULL;
- map[i].zone_mf_count = 0;
- map[i].prev_zone = map[i].zone;
+ map->list[i].zone_mf = NULL;
+ map->list[i].zone_mf_count = 0;
+ map->list[i].prev_zone = map->list[i].zone;
- map[i].invincible_time_inc = 0;
+ map->list[i].invincible_time_inc = 0;
- map[i].weapon_damage_rate = 100;
- map[i].magic_damage_rate = 100;
- map[i].misc_damage_rate = 100;
- map[i].short_damage_rate = 100;
- map[i].long_damage_rate = 100;
+ map->list[i].weapon_damage_rate = 100;
+ map->list[i].magic_damage_rate = 100;
+ map->list[i].misc_damage_rate = 100;
+ map->list[i].short_damage_rate = 100;
+ map->list[i].long_damage_rate = 100;
+
+ if( map->list[i].qi_data )
+ aFree(map->list[i].qi_data);
+
+ map->list[i].qi_data = NULL;
+ map->list[i].qi_count = 0;
}
}
#define NO_WATER 1000000
/*
-* Reads from the .rsw for each map
-* Returns water height (or NO_WATER if file doesn't exist) or other error is encountered.
-* Assumed path for file is data/mapname.rsw
-* Credits to LittleWolf
-*/
+ * Reads from the .rsw for each map
+ * Returns water height (or NO_WATER if file doesn't exist) or other error is encountered.
+ * Assumed path for file is data/mapname.rsw
+ * Credits to LittleWolf
+ */
int map_waterheight(char* mapname)
{
char fn[256];
@@ -3154,19 +3254,19 @@ int map_waterheight(char* mapname)
// read & convert fn
rsw = (char *) grfio_read (fn);
- if (rsw)
- { //Load water height from file
+ if (rsw) {
+ //Load water height from file
int wh = (int) *(float*)(rsw+166);
aFree(rsw);
return wh;
}
- ShowWarning("Failed to find water level for (%s)\n", mapname, fn);
+ ShowWarning("Failed to find water level for %s (%s)\n", mapname, fn);
return NO_WATER;
}
/*==================================
-* .GAT format
-*----------------------------------*/
+ * .GAT format
+ *----------------------------------*/
int map_readgat (struct map_data* m)
{
char filename[256];
@@ -3185,7 +3285,7 @@ int map_readgat (struct map_data* m)
num_cells = m->xs * m->ys;
CREATE(m->cell, struct mapcell, num_cells);
- water_height = map_waterheight(m->name);
+ water_height = map->waterheight(m->name);
// Set cell properties
off = 14;
@@ -3199,7 +3299,10 @@ int map_readgat (struct map_data* m)
if( type == 0 && water_height != NO_WATER && height > water_height )
type = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water)
- m->cell[xy] = map_gat2cell(type);
+ m->cell[xy] = map->gat2cell(type);
+#ifdef CELL_NOSTACK
+ m->cell[xy].cell_bl = 0;
+#endif
}
aFree(gat);
@@ -3208,29 +3311,29 @@ int map_readgat (struct map_data* m)
}
/*======================================
-* Add/Remove map to the map_db
-*--------------------------------------*/
+ * Add/Remove map to the map_db
+ *--------------------------------------*/
void map_addmap2db(struct map_data *m) {
- index2mapid[m->index] = m->m;
+ map->index2mapid[m->index] = m->m;
}
void map_removemapdb(struct map_data *m) {
- index2mapid[m->index] = -1;
+ map->index2mapid[m->index] = -1;
}
/*======================================
-* Initiate maps loading stage
-*--------------------------------------*/
+ * Initiate maps loading stage
+ *--------------------------------------*/
int map_readallmaps (void) {
int i;
FILE* fp=NULL;
int maps_removed = 0;
- if( enable_grf )
+ if( map->enable_grf )
ShowStatus("Loading maps (using GRF files)...\n");
else {
char mapcachefilepath[254];
- sprintf(mapcachefilepath,"%s/%s%s",iMap->db_path,DBPATH,"map_cache.dat");
+ sprintf(mapcachefilepath,"%s/%s%s",map->db_path,DBPATH,"map_cache.dat");
ShowStatus("Loading maps (using %s as map cache)...\n", mapcachefilepath);
if( (fp = fopen(mapcachefilepath, "rb")) == NULL ) {
ShowFatalError("Unable to open map cache file "CL_WHITE"%s"CL_RESET"\n", mapcachefilepath);
@@ -3238,73 +3341,73 @@ int map_readallmaps (void) {
}
// Init mapcache data.. [Shinryo]
- map_cache_buffer = map_init_mapcache(fp);
- if(!map_cache_buffer) {
+ map->cache_buffer = map->init_mapcache(fp);
+ if(!map->cache_buffer) {
ShowFatalError("Failed to initialize mapcache data (%s)..\n", mapcachefilepath);
exit(EXIT_FAILURE);
}
}
- for(i = 0; i < iMap->map_num; i++) {
+ for(i = 0; i < map->count; i++) {
size_t size;
// show progress
- if(enable_grf)
- ShowStatus("Loading maps [%i/%i]: %s"CL_CLL"\r", i, iMap->map_num, map[i].name);
+ if(map->enable_grf)
+ ShowStatus("Loading maps [%i/%i]: %s"CL_CLL"\r", i, map->count, map->list[i].name);
// try to load the map
if( !
- (enable_grf?
- map_readgat(&map[i])
- :map_readfromcache(&map[i], map_cache_buffer))
+ (map->enable_grf?
+ map->readgat(&map->list[i])
+ :map->readfromcache(&map->list[i], map->cache_buffer))
) {
- map_delmapid(i);
+ map->delmapid(i);
maps_removed++;
i--;
continue;
}
- map[i].index = mapindex_name2id(map[i].name);
+ map->list[i].index = mapindex->name2id(map->list[i].name);
- if ( index2mapid[map[i].index] != -1 ) {
- ShowWarning("Map %s already loaded!"CL_CLL"\n", map[i].name);
- if (map[i].cell && map[i].cell != (struct mapcell *)0xdeadbeaf) {
- aFree(map[i].cell);
- map[i].cell = NULL;
+ if ( map->index2mapid[map_id2index(i)] != -1 ) {
+ ShowWarning("Map %s already loaded!"CL_CLL"\n", map->list[i].name);
+ if (map->list[i].cell && map->list[i].cell != (struct mapcell *)0xdeadbeaf) {
+ aFree(map->list[i].cell);
+ map->list[i].cell = NULL;
}
- map_delmapid(i);
+ map->delmapid(i);
maps_removed++;
i--;
continue;
}
- map[i].m = i;
- iMap->addmap2db(&map[i]);
+ map->list[i].m = i;
+ map->addmap2db(&map->list[i]);
- memset(map[i].moblist, 0, sizeof(map[i].moblist)); //Initialize moblist [Skotlex]
- map[i].mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex]
+ memset(map->list[i].moblist, 0, sizeof(map->list[i].moblist)); //Initialize moblist [Skotlex]
+ map->list[i].mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex]
- map[i].bxs = (map[i].xs + BLOCK_SIZE - 1) / BLOCK_SIZE;
- map[i].bys = (map[i].ys + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ map->list[i].bxs = (map->list[i].xs + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ map->list[i].bys = (map->list[i].ys + BLOCK_SIZE - 1) / BLOCK_SIZE;
- size = map[i].bxs * map[i].bys * sizeof(struct block_list*);
- map[i].block = (struct block_list**)aCalloc(size, 1);
- map[i].block_mob = (struct block_list**)aCalloc(size, 1);
+ size = map->list[i].bxs * map->list[i].bys * sizeof(struct block_list*);
+ map->list[i].block = (struct block_list**)aCalloc(size, 1);
+ map->list[i].block_mob = (struct block_list**)aCalloc(size, 1);
- map[i].getcellp = map_sub_getcellp;
- map[i].setcell = map_sub_setcell;
+ map->list[i].getcellp = map->sub_getcellp;
+ map->list[i].setcell = map->sub_setcell;
}
// intialization and configuration-dependent adjustments of mapflags
- iMap->flags_init();
+ map->flags_init();
- if( !enable_grf ) {
+ if( !map->enable_grf ) {
fclose(fp);
}
// finished map loading
- ShowInfo("Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps."CL_CLL"\n",iMap->map_num);
- instance->start_id = iMap->map_num; // Next Map Index will be instances
+ ShowInfo("Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps."CL_CLL"\n",map->count);
+ instance->start_id = map->count; // Next Map Index will be instances
if (maps_removed)
ShowNotice("Maps removed: '"CL_WHITE"%d"CL_RESET"'\n",maps_removed);
@@ -3312,13 +3415,9 @@ int map_readallmaps (void) {
return 0;
}
-////////////////////////////////////////////////////////////////////////
-static int map_ip_set = 0;
-static int char_ip_set = 0;
-
/*==========================================
-* Read map server configuration files (conf/map_server.conf...)
-*------------------------------------------*/
+ * Read map server configuration files (conf/map_server.conf...)
+ *------------------------------------------*/
int map_config_read(char *cfgName) {
char line[1024], w1[1024], w2[1024];
FILE *fp;
@@ -3329,14 +3428,14 @@ int map_config_read(char *cfgName) {
return 1;
}
- while( fgets(line, sizeof(line), fp) ) {
+ while (fgets(line, sizeof(line), fp)) {
char* ptr;
- if( line[0] == '/' && line[1] == '/' )
+ if (line[0] == '/' && line[1] == '/')
continue;
- if( (ptr = strstr(line, "//")) != NULL )
+ if ((ptr = strstr(line, "//")) != NULL)
*ptr = '\n'; //Strip comments
- if( sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2 )
+ if (sscanf(line, "%1023[^:]: %1023[^\t\r\n]", w1, w2) < 2)
continue;
//Strip trailing spaces
@@ -3354,56 +3453,56 @@ int map_config_read(char *cfgName) {
if( msg_silent ) // only bother if its actually enabled
ShowInfo("Console Silent Setting: %d\n", atoi(w2));
} else if (strcmpi(w1, "userid")==0)
- chrif_setuserid(w2);
+ chrif->setuserid(w2);
else if (strcmpi(w1, "passwd") == 0)
- chrif_setpasswd(w2);
+ chrif->setpasswd(w2);
else if (strcmpi(w1, "char_ip") == 0)
- char_ip_set = chrif_setip(w2);
+ map->char_ip_set = chrif->setip(w2);
else if (strcmpi(w1, "char_port") == 0)
- chrif_setport(atoi(w2));
+ chrif->setport(atoi(w2));
else if (strcmpi(w1, "map_ip") == 0)
- map_ip_set = clif->setip(w2);
+ map->ip_set = clif->setip(w2);
else if (strcmpi(w1, "bind_ip") == 0)
clif->setbindip(w2);
else if (strcmpi(w1, "map_port") == 0) {
clif->setport(atoi(w2));
- map_port = (atoi(w2));
+ map->port = (atoi(w2));
} else if (strcmpi(w1, "map") == 0)
- iMap->map_num++;
+ map->count++;
else if (strcmpi(w1, "delmap") == 0)
- iMap->map_num--;
+ map->count--;
else if (strcmpi(w1, "npc") == 0)
- npc_addsrcfile(w2);
+ npc->addsrcfile(w2);
else if (strcmpi(w1, "delnpc") == 0)
- npc_delsrcfile(w2);
+ npc->delsrcfile(w2);
else if (strcmpi(w1, "autosave_time") == 0) {
- iMap->autosave_interval = atoi(w2);
- if (iMap->autosave_interval < 1) //Revert to default saving.
- iMap->autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
+ map->autosave_interval = atoi(w2);
+ if (map->autosave_interval < 1) //Revert to default saving.
+ map->autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
else
- iMap->autosave_interval *= 1000; //Pass from sec to ms
+ map->autosave_interval *= 1000; //Pass from sec to ms
} else if (strcmpi(w1, "minsave_time") == 0) {
- iMap->minsave_interval= atoi(w2);
- if (iMap->minsave_interval < 1)
- iMap->minsave_interval = 1;
+ map->minsave_interval= atoi(w2);
+ if (map->minsave_interval < 1)
+ map->minsave_interval = 1;
} else if (strcmpi(w1, "save_settings") == 0)
- iMap->save_settings = atoi(w2);
+ map->save_settings = atoi(w2);
else if (strcmpi(w1, "help_txt") == 0)
- strcpy(iMap->help_txt, w2);
+ strcpy(map->help_txt, w2);
else if (strcmpi(w1, "help2_txt") == 0)
- strcpy(iMap->help2_txt, w2);
+ strcpy(map->help2_txt, w2);
else if (strcmpi(w1, "charhelp_txt") == 0)
- strcpy(iMap->charhelp_txt, w2);
+ strcpy(map->charhelp_txt, w2);
else if(strcmpi(w1,"db_path") == 0)
- safestrncpy(iMap->db_path,w2,255);
+ safestrncpy(map->db_path,w2,255);
else if (strcmpi(w1, "enable_spy") == 0)
- iMap->enable_spy = config_switch(w2);
+ map->enable_spy = config_switch(w2);
else if (strcmpi(w1, "use_grf") == 0)
- enable_grf = config_switch(w2);
+ map->enable_grf = config_switch(w2);
else if (strcmpi(w1, "console_msg_log") == 0)
console_msg_log = atoi(w2);//[Ind]
else if (strcmpi(w1, "import") == 0)
- map_config_read(w2);
+ map->config_read(w2);
else
ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
}
@@ -3416,19 +3515,19 @@ int map_config_read_sub(char *cfgName) {
FILE *fp;
fp = fopen(cfgName,"r");
- if( fp == NULL ) {
+ if (fp == NULL) {
ShowError("Map configuration file not found at: %s\n", cfgName);
return 1;
}
- while( fgets(line, sizeof(line), fp) ) {
+ while (fgets(line, sizeof(line), fp)) {
char* ptr;
- if( line[0] == '/' && line[1] == '/' )
+ if (line[0] == '/' && line[1] == '/')
continue;
- if( (ptr = strstr(line, "//")) != NULL )
+ if ((ptr = strstr(line, "//")) != NULL)
*ptr = '\n'; //Strip comments
- if( sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2 )
+ if (sscanf(line, "%1023[^:]: %1023[^\t\r\n]", w1, w2) < 2)
continue;
//Strip trailing spaces
@@ -3438,37 +3537,34 @@ int map_config_read_sub(char *cfgName) {
*ptr = '\0';
if (strcmpi(w1, "map") == 0)
- map_addmap(w2);
+ map->addmap(w2);
else if (strcmpi(w1, "delmap") == 0)
- iMap->delmap(w2);
+ map->delmap(w2);
else if (strcmpi(w1, "import") == 0)
- map_config_read_sub(w2);
+ map->config_read_sub(w2);
}
fclose(fp);
return 0;
}
-void map_reloadnpc_sub(char *cfgName)
-{
+void map_reloadnpc_sub(char *cfgName) {
char line[1024], w1[1024], w2[1024];
FILE *fp;
fp = fopen(cfgName,"r");
- if( fp == NULL )
- {
+ if (fp == NULL) {
ShowError("Map configuration file not found at: %s\n", cfgName);
return;
}
- while( fgets(line, sizeof(line), fp) )
- {
+ while (fgets(line, sizeof(line), fp)) {
char* ptr;
- if( line[0] == '/' && line[1] == '/' )
+ if (line[0] == '/' && line[1] == '/')
continue;
- if( (ptr = strstr(line, "//")) != NULL )
+ if ((ptr = strstr(line, "//")) != NULL)
*ptr = '\n'; //Strip comments
- if( sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2 )
+ if (sscanf(line, "%1023[^:]: %1023[^\t\r\n]", w1, w2) < 2)
continue;
//Strip trailing spaces
@@ -3478,9 +3574,11 @@ void map_reloadnpc_sub(char *cfgName)
*ptr = '\0';
if (strcmpi(w1, "npc") == 0)
- npc_addsrcfile(w2);
+ npc->addsrcfile(w2);
else if (strcmpi(w1, "import") == 0)
- map_reloadnpc_sub(w2);
+ map->reloadnpc_sub(w2);
+ else if (strcmpi(w1, "delnpc") == 0)
+ npc->delsrcfile(w2);
else
ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
}
@@ -3488,83 +3586,102 @@ void map_reloadnpc_sub(char *cfgName)
fclose(fp);
}
-void map_reloadnpc(bool clear)
-{
+void map_reloadnpc(bool clear, const char * const *extra_scripts, int extra_scripts_count) {
+ int i;
if (clear)
- npc_addsrcfile("clear"); // this will clear the current script list
+ npc->addsrcfile("clear"); // this will clear the current script list
#ifdef RENEWAL
- map_reloadnpc_sub("npc/re/scripts_main.conf");
+ map->reloadnpc_sub("npc/re/scripts_main.conf");
#else
- map_reloadnpc_sub("npc/pre-re/scripts_main.conf");
+ map->reloadnpc_sub("npc/pre-re/scripts_main.conf");
#endif
+
+ // Append extra scripts
+ for( i = 0; i < extra_scripts_count; i++ ) {
+ npc->addsrcfile(extra_scripts[i]);
+ }
}
int inter_config_read(char *cfgName) {
char line[1024],w1[1024],w2[1024];
FILE *fp;
- if( !( fp = fopen(cfgName,"r") ) ){
+ if (!(fp = fopen(cfgName,"r"))) {
ShowError("File not found: %s\n",cfgName);
return 1;
}
- while(fgets(line, sizeof(line), fp)) {
- if(line[0] == '/' && line[1] == '/')
+ while (fgets(line, sizeof(line), fp)) {
+ if (line[0] == '/' && line[1] == '/')
continue;
- if( sscanf(line,"%[^:]: %[^\r\n]",w1,w2) < 2 )
+ if (sscanf(line,"%1023[^:]: %1023[^\r\n]", w1, w2) < 2)
continue;
/* table names */
if(strcmpi(w1,"item_db_db")==0)
- strcpy(iMap->item_db_db,w2);
+ strcpy(map->item_db_db,w2);
else if(strcmpi(w1,"mob_db_db")==0)
- strcpy(iMap->mob_db_db,w2);
+ strcpy(map->mob_db_db,w2);
else if(strcmpi(w1,"item_db2_db")==0)
- strcpy(iMap->item_db2_db,w2);
+ strcpy(map->item_db2_db,w2);
else if(strcmpi(w1,"item_db_re_db")==0)
- strcpy(iMap->item_db_re_db,w2);
+ strcpy(map->item_db_re_db,w2);
else if(strcmpi(w1,"mob_db2_db")==0)
- strcpy(iMap->mob_db2_db,w2);
+ strcpy(map->mob_db2_db,w2);
else if(strcmpi(w1,"mob_skill_db_db")==0)
- strcpy(iMap->mob_skill_db_db,w2);
+ strcpy(map->mob_skill_db_db,w2);
else if(strcmpi(w1,"mob_skill_db2_db")==0)
- strcpy(iMap->mob_skill_db2_db,w2);
+ strcpy(map->mob_skill_db2_db,w2);
else if(strcmpi(w1,"interreg_db")==0)
- strcpy(iMap->interreg_db,w2);
+ strcpy(map->interreg_db,w2);
/* map sql stuff */
else if(strcmpi(w1,"map_server_ip")==0)
- strcpy(map_server_ip, w2);
+ strcpy(map->server_ip, w2);
else if(strcmpi(w1,"map_server_port")==0)
- map_server_port=atoi(w2);
+ map->server_port=atoi(w2);
else if(strcmpi(w1,"map_server_id")==0)
- strcpy(map_server_id, w2);
+ strcpy(map->server_id, w2);
else if(strcmpi(w1,"map_server_pw")==0)
- strcpy(map_server_pw, w2);
+ strcpy(map->server_pw, w2);
else if(strcmpi(w1,"map_server_db")==0)
- strcpy(map_server_db, w2);
+ strcpy(map->server_db, w2);
else if(strcmpi(w1,"default_codepage")==0)
- strcpy(default_codepage, w2);
- else if(strcmpi(w1,"use_sql_db")==0) {
- iMap->db_use_sqldbs = config_switch(w2);
- ShowStatus ("Using SQL dbs: %s\n",w2);
- }
+ strcpy(map->default_codepage, w2);
+ else if(strcmpi(w1,"use_sql_item_db")==0) {
+ map->db_use_sql_item_db = config_switch(w2);
+ ShowStatus ("Using item database as SQL: '%s'\n", w2);
+ }
+ else if(strcmpi(w1,"use_sql_mob_db")==0) {
+ map->db_use_sql_mob_db = config_switch(w2);
+ ShowStatus ("Using monster database as SQL: '%s'\n", w2);
+ }
+ else if(strcmpi(w1,"use_sql_mob_skill_db")==0) {
+ map->db_use_sql_mob_skill_db = config_switch(w2);
+ ShowStatus ("Using monster skill database as SQL: '%s'\n", w2);
+ }
+ else if(strcmpi(w1,"autotrade_merchants_db")==0)
+ strcpy(map->autotrade_merchants_db, w2);
+ else if(strcmpi(w1,"autotrade_data_db")==0)
+ strcpy(map->autotrade_data_db, w2);
+ else if(strcmpi(w1,"npc_market_data_db")==0)
+ strcpy(map->npc_market_data_db, w2);
/* sql log db */
else if(strcmpi(w1,"log_db_ip")==0)
- strcpy(log_db_ip, w2);
+ strcpy(logs->db_ip, w2);
else if(strcmpi(w1,"log_db_id")==0)
- strcpy(log_db_id, w2);
+ strcpy(logs->db_id, w2);
else if(strcmpi(w1,"log_db_pw")==0)
- strcpy(log_db_pw, w2);
+ strcpy(logs->db_pw, w2);
else if(strcmpi(w1,"log_db_port")==0)
- log_db_port = atoi(w2);
+ logs->db_port = atoi(w2);
else if(strcmpi(w1,"log_db_db")==0)
- strcpy(log_db_db, w2);
+ strcpy(logs->db_name, w2);
/* mapreg */
- else if( mapreg_config_read(w1,w2) )
+ else if( mapreg->config_read(w1,w2) )
continue;
/* import */
else if(strcmpi(w1,"import")==0)
- inter_config_read(w2);
+ map->inter_config_read(w2);
}
fclose(fp);
@@ -3572,21 +3689,21 @@ int inter_config_read(char *cfgName) {
}
/*=======================================
-* MySQL Init
-*---------------------------------------*/
+ * MySQL Init
+ *---------------------------------------*/
int map_sql_init(void)
{
// main db connection
- mmysql_handle = SQL->Malloc();
+ map->mysql_handle = SQL->Malloc();
ShowInfo("Connecting to the Map DB Server....\n");
- if( SQL_ERROR == SQL->Connect(mmysql_handle, map_server_id, map_server_pw, map_server_ip, map_server_port, map_server_db) )
+ if( SQL_ERROR == SQL->Connect(map->mysql_handle, map->server_id, map->server_pw, map->server_ip, map->server_port, map->server_db) )
exit(EXIT_FAILURE);
ShowStatus("connect success! (Map Server Connection)\n");
- if( strlen(default_codepage) > 0 )
- if ( SQL_ERROR == SQL->SetEncoding(mmysql_handle, default_codepage) )
- Sql_ShowDebug(mmysql_handle);
+ if( strlen(map->default_codepage) > 0 )
+ if ( SQL_ERROR == SQL->SetEncoding(map->mysql_handle, map->default_codepage) )
+ Sql_ShowDebug(map->mysql_handle);
return 0;
}
@@ -3594,58 +3711,141 @@ int map_sql_init(void)
int map_sql_close(void)
{
ShowStatus("Close Map DB Connection....\n");
- SQL->Free(mmysql_handle);
- mmysql_handle = NULL;
+ SQL->Free(map->mysql_handle);
+ map->mysql_handle = NULL;
if (logs->config.sql_logs) {
- ShowStatus("Close Log DB Connection....\n");
- SQL->Free(logmysql_handle);
- logmysql_handle = NULL;
+ logs->sql_final();
}
return 0;
}
-int log_sql_init(void)
-{
- // log db connection
- logmysql_handle = SQL->Malloc();
-
- ShowInfo(""CL_WHITE"[SQL]"CL_RESET": Connecting to the Log Database "CL_WHITE"%s"CL_RESET" At "CL_WHITE"%s"CL_RESET"...\n",log_db_db,log_db_ip);
- if ( SQL_ERROR == SQL->Connect(logmysql_handle, log_db_id, log_db_pw, log_db_ip, log_db_port, log_db_db) )
- exit(EXIT_FAILURE);
- ShowStatus(""CL_WHITE"[SQL]"CL_RESET": Successfully '"CL_GREEN"connected"CL_RESET"' to Database '"CL_WHITE"%s"CL_RESET"'.\n", log_db_db);
-
- if( strlen(default_codepage) > 0 )
- if ( SQL_ERROR == SQL->SetEncoding(logmysql_handle, default_codepage) )
- Sql_ShowDebug(logmysql_handle);
- return 0;
+/**
+ * Merges two zones into a new one
+ * @param main the zone whose data must override the others upon conflict,
+ * e.g. enabling pvp on a town means that main is the pvp zone, while "other" is the towns previous zone
+ *
+ * @return the newly created zone from merging main and other
+ **/
+struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone_data *other) {
+ char newzone[MAP_ZONE_NAME_LENGTH];
+ struct map_zone_data *zone = NULL;
+ int cursor, i;
+
+ sprintf(newzone, "%s+%s",main->name,other->name);
+
+ if( (zone = strdb_get(map->zone_db, newzone)) )
+ return zone;/* this zone has already been merged */
+
+ CREATE(zone, struct map_zone_data, 1);
+
+ safestrncpy(zone->name, newzone, MAP_ZONE_NAME_LENGTH);
+
+ zone->disabled_skills_count = main->disabled_skills_count + other->disabled_skills_count;
+ zone->disabled_items_count = main->disabled_items_count + other->disabled_items_count;
+ zone->mapflags_count = main->mapflags_count + other->mapflags_count;
+ zone->disabled_commands_count = main->disabled_commands_count + other->disabled_commands_count;
+ zone->capped_skills_count = main->capped_skills_count + other->capped_skills_count;
+
+ CREATE(zone->disabled_skills, struct map_zone_disabled_skill_entry *, zone->disabled_skills_count );
+
+ for(i = 0, cursor = 0; i < main->disabled_skills_count; i++, cursor++ ) {
+ CREATE(zone->disabled_skills[cursor], struct map_zone_disabled_skill_entry, 1 );
+ memcpy(zone->disabled_skills[cursor], main->disabled_skills[i], sizeof(struct map_zone_disabled_skill_entry));
+ }
+
+ for(i = 0; i < other->disabled_skills_count; i++, cursor++ ) {
+ CREATE(zone->disabled_skills[cursor], struct map_zone_disabled_skill_entry, 1 );
+ memcpy(zone->disabled_skills[cursor], other->disabled_skills[i], sizeof(struct map_zone_disabled_skill_entry));
+ }
+
+ CREATE(zone->disabled_items, int, zone->disabled_items_count );
+
+ for(i = 0, cursor = 0; i < main->disabled_items_count; i++, cursor++ ) {
+ zone->disabled_items[cursor] = main->disabled_items[i];
+ }
+
+ for(i = 0; i < other->disabled_items_count; i++, cursor++ ) {
+ zone->disabled_items[cursor] = other->disabled_items[i];
+ }
+
+ CREATE(zone->mapflags, char *, zone->mapflags_count );
+
+ for(i = 0, cursor = 0; i < main->mapflags_count; i++, cursor++ ) {
+ CREATE(zone->mapflags[cursor], char, MAP_ZONE_MAPFLAG_LENGTH );
+ safestrncpy(zone->mapflags[cursor], main->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH);
+ }
+
+ for(i = 0; i < other->mapflags_count; i++, cursor++ ) {
+ CREATE(zone->mapflags[cursor], char, MAP_ZONE_MAPFLAG_LENGTH );
+ safestrncpy(zone->mapflags[cursor], other->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH);
+ }
+
+ CREATE(zone->disabled_commands, struct map_zone_disabled_command_entry *, zone->disabled_commands_count);
+
+ for(i = 0, cursor = 0; i < main->disabled_commands_count; i++, cursor++ ) {
+ CREATE(zone->disabled_commands[cursor], struct map_zone_disabled_command_entry, 1);
+ memcpy(zone->disabled_commands[cursor], main->disabled_commands[i], sizeof(struct map_zone_disabled_command_entry));
+ }
+
+ for(i = 0; i < other->disabled_commands_count; i++, cursor++ ) {
+ CREATE(zone->disabled_commands[cursor], struct map_zone_disabled_command_entry, 1);
+ memcpy(zone->disabled_commands[cursor], other->disabled_commands[i], sizeof(struct map_zone_disabled_command_entry));
+ }
+
+ CREATE(zone->capped_skills, struct map_zone_skill_damage_cap_entry *, zone->capped_skills_count);
+
+ for(i = 0, cursor = 0; i < main->capped_skills_count; i++, cursor++ ) {
+ CREATE(zone->capped_skills[cursor], struct map_zone_skill_damage_cap_entry, 1);
+ memcpy(zone->capped_skills[cursor], main->capped_skills[i], sizeof(struct map_zone_skill_damage_cap_entry));
+ }
+
+ for(i = 0; i < other->capped_skills_count; i++, cursor++ ) {
+ CREATE(zone->capped_skills[cursor], struct map_zone_skill_damage_cap_entry, 1);
+ memcpy(zone->capped_skills[cursor], other->capped_skills[i], sizeof(struct map_zone_skill_damage_cap_entry));
+ }
+
+ zone->info.special = 2;
+
+ strdb_put(map->zone_db, newzone, zone);
+
+ return zone;
}
+
void map_zone_change2(int m, struct map_zone_data *zone) {
char empty[1] = "\0";
- map[m].prev_zone = map[m].zone;
-
- if( map[m].zone_mf_count )
- iMap->zone_remove(m);
+ if( map->list[m].zone == zone )
+ return;
+
+ if( map->list[m].zone->info.special != 2 ) /* we don't update it for merged zones! */
+ map->list[m].prev_zone = map->list[m].zone;
+
+ if( map->list[m].zone_mf_count )
+ map->zone_remove(m);
- iMap->zone_apply(m,zone,empty,empty,empty);
+ if( zone->info.special ) {
+ zone = map->merge_zone(zone,map->list[m].prev_zone);
+ }
+
+ map->zone_apply(m,zone,empty,empty,empty);
}
/* when changing from a mapflag to another during runtime */
void map_zone_change(int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath) {
- map[m].prev_zone = map[m].zone;
+ map->list[m].prev_zone = map->list[m].zone;
- if( map[m].zone_mf_count )
- iMap->zone_remove(m);
- iMap->zone_apply(m,zone,start,buffer,filepath);
+ if( map->list[m].zone_mf_count )
+ map->zone_remove(m);
+ map->zone_apply(m,zone,start,buffer,filepath);
}
/* removes previous mapflags from this map */
void map_zone_remove(int m) {
char flag[MAP_ZONE_MAPFLAG_LENGTH], params[MAP_ZONE_MAPFLAG_LENGTH];
unsigned short k;
char empty[1] = "\0";
- for(k = 0; k < map[m].zone_mf_count; k++) {
- int len = strlen(map[m].zone_mf[k]),j;
+ for(k = 0; k < map->list[m].zone_mf_count; k++) {
+ size_t len = strlen(map->list[m].zone_mf[k]),j;
params[0] = '\0';
- memcpy(flag, map[m].zone_mf[k], MAP_ZONE_MAPFLAG_LENGTH);
+ memcpy(flag, map->list[m].zone_mf[k], MAP_ZONE_MAPFLAG_LENGTH);
for(j = 0; j < len; j++) {
if( flag[j] == '\t' ) {
memcpy(params, &flag[j+1], len - j);
@@ -3654,19 +3854,19 @@ void map_zone_remove(int m) {
}
}
- npc_parse_mapflag(map[m].name,empty,flag,params,empty,empty,empty);
- aFree(map[m].zone_mf[k]);
- map[m].zone_mf[k] = NULL;
+ npc->parse_mapflag(map->list[m].name,empty,flag,params,empty,empty,empty, NULL);
+ aFree(map->list[m].zone_mf[k]);
+ map->list[m].zone_mf[k] = NULL;
}
- aFree(map[m].zone_mf);
- map[m].zone_mf = NULL;
- map[m].zone_mf_count = 0;
+ aFree(map->list[m].zone_mf);
+ map->list[m].zone_mf = NULL;
+ map->list[m].zone_mf_count = 0;
}
static inline void map_zone_mf_cache_add(int m, char *rflag) {
- RECREATE(map[m].zone_mf, char *, ++map[m].zone_mf_count);
- CREATE(map[m].zone_mf[map[m].zone_mf_count - 1], char, MAP_ZONE_MAPFLAG_LENGTH);
- safestrncpy(map[m].zone_mf[map[m].zone_mf_count - 1], rflag, MAP_ZONE_MAPFLAG_LENGTH);
+ RECREATE(map->list[m].zone_mf, char *, ++map->list[m].zone_mf_count);
+ CREATE(map->list[m].zone_mf[map->list[m].zone_mf_count - 1], char, MAP_ZONE_MAPFLAG_LENGTH);
+ safestrncpy(map->list[m].zone_mf[map->list[m].zone_mf_count - 1], rflag, MAP_ZONE_MAPFLAG_LENGTH);
}
/* TODO: introduce enumerations to each mapflag so instead of reading the string a number of times we read it only once and use its value wherever we need */
/* cache previous values to revert */
@@ -3678,524 +3878,524 @@ bool map_zone_mf_cache(int m, char *flag, char *params) {
state = 0;
if (!strcmpi(flag, "nosave")) {
- ;/* not yet supported to be reversed */
- /*
+#if 0 /* not yet supported to be reversed */
char savemap[32];
int savex, savey;
if (state == 0) {
- if( map[m].flag.nosave ) {
- sprintf(rflag, "nosave SavePoint");
- map_zone_mf_cache_add(m,nosave);
- }
+ if( map->list[m].flag.nosave ) {
+ sprintf(rflag, "nosave\tSavePoint");
+ map_zone_mf_cache_add(m,nosave);
+ }
} else if (!strcmpi(params, "SavePoint")) {
- if( map[m].save.map ) {
- sprintf(rflag, "nosave %s,%d,%d",mapindex_id2name(map[m].save.map),map[m].save.x,map[m].save.y);
- } else
- sprintf(rflag, "nosave %s,%d,%d",mapindex_id2name(map[m].save.map),map[m].save.x,map[m].save.y);
- map_zone_mf_cache_add(m,nosave);
+ if( map->list[m].save.map ) {
+ sprintf(rflag, "nosave\t%s,%d,%d",mapindex_id2name(map->list[m].save.map),map->list[m].save.x,map->list[m].save.y);
+ } else
+ sprintf(rflag, "nosave\t%s,%d,%d",mapindex_id2name(map->list[m].save.map),map->list[m].save.x,map->list[m].save.y);
+ map_zone_mf_cache_add(m,nosave);
} else if (sscanf(params, "%31[^,],%d,%d", savemap, &savex, &savey) == 3) {
- if( map[m].save.map ) {
- sprintf(rflag, "nosave %s,%d,%d",mapindex_id2name(map[m].save.map),map[m].save.x,map[m].save.y);
- map_zone_mf_cache_add(m,nosave);
+ if( map->list[m].save.map ) {
+ sprintf(rflag, "nosave\t%s,%d,%d",mapindex_id2name(map->list[m].save.map),map->list[m].save.x,map->list[m].save.y);
+ map_zone_mf_cache_add(m,nosave);
+ }
}
- }*/
+#endif // 0
} else if (!strcmpi(flag,"autotrade")) {
- if( state && map[m].flag.autotrade )
+ if( state && map->list[m].flag.autotrade )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"autotrade off");
- else if( !map[m].flag.autotrade )
+ map_zone_mf_cache_add(m,"autotrade\toff");
+ else if( !map->list[m].flag.autotrade )
map_zone_mf_cache_add(m,"autotrade");
}
} else if (!strcmpi(flag,"allowks")) {
- if( state && map[m].flag.allowks )
+ if( state && map->list[m].flag.allowks )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"allowks off");
- else if( !map[m].flag.allowks )
+ map_zone_mf_cache_add(m,"allowks\toff");
+ else if( !map->list[m].flag.allowks )
map_zone_mf_cache_add(m,"allowks");
}
} else if (!strcmpi(flag,"town")) {
- if( state && map[m].flag.town )
+ if( state && map->list[m].flag.town )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"town off");
- else if( !map[m].flag.town )
+ map_zone_mf_cache_add(m,"town\toff");
+ else if( !map->list[m].flag.town )
map_zone_mf_cache_add(m,"town");
}
} else if (!strcmpi(flag,"nomemo")) {
- if( state && map[m].flag.nomemo )
+ if( state && map->list[m].flag.nomemo )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nomemo off");
- else if( !map[m].flag.nomemo )
+ map_zone_mf_cache_add(m,"nomemo\toff");
+ else if( !map->list[m].flag.nomemo )
map_zone_mf_cache_add(m,"nomemo");
}
} else if (!strcmpi(flag,"noteleport")) {
- if( state && map[m].flag.noteleport )
+ if( state && map->list[m].flag.noteleport )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"noteleport off");
- else if( !map[m].flag.noteleport )
+ map_zone_mf_cache_add(m,"noteleport\toff");
+ else if( !map->list[m].flag.noteleport )
map_zone_mf_cache_add(m,"noteleport");
}
} else if (!strcmpi(flag,"nowarp")) {
- if( state && map[m].flag.nowarp )
+ if( state && map->list[m].flag.nowarp )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nowarp off");
- else if( !map[m].flag.nowarp )
+ map_zone_mf_cache_add(m,"nowarp\toff");
+ else if( !map->list[m].flag.nowarp )
map_zone_mf_cache_add(m,"nowarp");
}
} else if (!strcmpi(flag,"nowarpto")) {
- if( state && map[m].flag.nowarpto )
+ if( state && map->list[m].flag.nowarpto )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nowarpto off");
- else if( !map[m].flag.nowarpto )
+ map_zone_mf_cache_add(m,"nowarpto\toff");
+ else if( !map->list[m].flag.nowarpto )
map_zone_mf_cache_add(m,"nowarpto");
}
} else if (!strcmpi(flag,"noreturn")) {
- if( state && map[m].flag.noreturn )
+ if( state && map->list[m].flag.noreturn )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"noreturn off");
- else if( map[m].flag.noreturn )
+ map_zone_mf_cache_add(m,"noreturn\toff");
+ else if( map->list[m].flag.noreturn )
map_zone_mf_cache_add(m,"noreturn");
}
} else if (!strcmpi(flag,"monster_noteleport")) {
- if( state && map[m].flag.monster_noteleport )
+ if( state && map->list[m].flag.monster_noteleport )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"monster_noteleport off");
- else if( map[m].flag.monster_noteleport )
+ map_zone_mf_cache_add(m,"monster_noteleport\toff");
+ else if( map->list[m].flag.monster_noteleport )
map_zone_mf_cache_add(m,"monster_noteleport");
}
} else if (!strcmpi(flag,"nobranch")) {
- if( state && map[m].flag.nobranch )
+ if( state && map->list[m].flag.nobranch )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nobranch off");
- else if( map[m].flag.nobranch )
+ map_zone_mf_cache_add(m,"nobranch\toff");
+ else if( map->list[m].flag.nobranch )
map_zone_mf_cache_add(m,"nobranch");
}
} else if (!strcmpi(flag,"nopenalty")) {
- if( state && map[m].flag.noexppenalty ) /* they are applied together, no need to check both */
+ if( state && map->list[m].flag.noexppenalty ) /* they are applied together, no need to check both */
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nopenalty off");
- else if( map[m].flag.noexppenalty )
+ map_zone_mf_cache_add(m,"nopenalty\toff");
+ else if( map->list[m].flag.noexppenalty )
map_zone_mf_cache_add(m,"nopenalty");
}
} else if (!strcmpi(flag,"pvp")) {
- if( state && map[m].flag.pvp )
+ if( state && map->list[m].flag.pvp )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"pvp off");
- else if( map[m].flag.pvp )
+ map_zone_mf_cache_add(m,"pvp\toff");
+ else if( map->list[m].flag.pvp )
map_zone_mf_cache_add(m,"pvp");
}
}
else if (!strcmpi(flag,"pvp_noparty")) {
- if( state && map[m].flag.pvp_noparty )
+ if( state && map->list[m].flag.pvp_noparty )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"pvp_noparty off");
- else if( map[m].flag.pvp_noparty )
+ map_zone_mf_cache_add(m,"pvp_noparty\toff");
+ else if( map->list[m].flag.pvp_noparty )
map_zone_mf_cache_add(m,"pvp_noparty");
}
} else if (!strcmpi(flag,"pvp_noguild")) {
- if( state && map[m].flag.pvp_noguild )
+ if( state && map->list[m].flag.pvp_noguild )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"pvp_noguild off");
- else if( map[m].flag.pvp_noguild )
+ map_zone_mf_cache_add(m,"pvp_noguild\toff");
+ else if( map->list[m].flag.pvp_noguild )
map_zone_mf_cache_add(m,"pvp_noguild");
}
} else if (!strcmpi(flag, "pvp_nightmaredrop")) {
- if( state && map[m].flag.pvp_nightmaredrop )
+ if( state && map->list[m].flag.pvp_nightmaredrop )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"pvp_nightmaredrop off");
- else if( map[m].flag.pvp_nightmaredrop )
+ map_zone_mf_cache_add(m,"pvp_nightmaredrop\toff");
+ else if( map->list[m].flag.pvp_nightmaredrop )
map_zone_mf_cache_add(m,"pvp_nightmaredrop");
}
- /* not yet fully supported */
- /*char drop_arg1[16], drop_arg2[16];
+#if 0 /* not yet fully supported */
+ char drop_arg1[16], drop_arg2[16];
int drop_per = 0;
- if (sscanf(w4, "%[^,],%[^,],%d", drop_arg1, drop_arg2, &drop_per) == 3) {
- int drop_id = 0, drop_type = 0;
- if (!strcmpi(drop_arg1, "random"))
- drop_id = -1;
- else if (itemdb_exists((drop_id = atoi(drop_arg1))) == NULL)
- drop_id = 0;
- if (!strcmpi(drop_arg2, "inventory"))
- drop_type = 1;
- else if (!strcmpi(drop_arg2,"equip"))
- drop_type = 2;
- else if (!strcmpi(drop_arg2,"all"))
- drop_type = 3;
-
- if (drop_id != 0){
- int i;
- for (i = 0; i < MAX_DROP_PER_MAP; i++) {
- if (map[m].drop_list[i].drop_id == 0){
- map[m].drop_list[i].drop_id = drop_id;
- map[m].drop_list[i].drop_type = drop_type;
- map[m].drop_list[i].drop_per = drop_per;
- break;
- }
- }
- map[m].flag.pvp_nightmaredrop = 1;
- }
+ if (sscanf(w4, "%15[^,],%15[^,],%d", drop_arg1, drop_arg2, &drop_per) == 3) {
+ int drop_id = 0, drop_type = 0;
+ if (!strcmpi(drop_arg1, "random"))
+ drop_id = -1;
+ else if (itemdb->exists((drop_id = atoi(drop_arg1))) == NULL)
+ drop_id = 0;
+ if (!strcmpi(drop_arg2, "inventory"))
+ drop_type = 1;
+ else if (!strcmpi(drop_arg2,"equip"))
+ drop_type = 2;
+ else if (!strcmpi(drop_arg2,"all"))
+ drop_type = 3;
+
+ if (drop_id != 0) {
+ int i;
+ for (i = 0; i < MAX_DROP_PER_MAP; i++) {
+ if (map->list[m].drop_list[i].drop_id == 0){
+ map->list[m].drop_list[i].drop_id = drop_id;
+ map->list[m].drop_list[i].drop_type = drop_type;
+ map->list[m].drop_list[i].drop_per = drop_per;
+ break;
+ }
+ }
+ map->list[m].flag.pvp_nightmaredrop = 1;
+ }
} else if (!state) //Disable
- map[m].flag.pvp_nightmaredrop = 0;
- */
+ map->list[m].flag.pvp_nightmaredrop = 0;
+#endif // 0
} else if (!strcmpi(flag,"pvp_nocalcrank")) {
- if( state && map[m].flag.pvp_nocalcrank )
+ if( state && map->list[m].flag.pvp_nocalcrank )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"pvp_nocalcrank off");
- else if( map[m].flag.pvp_nocalcrank )
+ map_zone_mf_cache_add(m,"pvp_nocalcrank\toff");
+ else if( map->list[m].flag.pvp_nocalcrank )
map_zone_mf_cache_add(m,"pvp_nocalcrank");
}
} else if (!strcmpi(flag,"gvg")) {
- if( state && map[m].flag.gvg )
+ if( state && map->list[m].flag.gvg )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"gvg off");
- else if( map[m].flag.gvg )
+ map_zone_mf_cache_add(m,"gvg\toff");
+ else if( map->list[m].flag.gvg )
map_zone_mf_cache_add(m,"gvg");
}
} else if (!strcmpi(flag,"gvg_noparty")) {
- if( state && map[m].flag.gvg_noparty )
+ if( state && map->list[m].flag.gvg_noparty )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"gvg_noparty off");
- else if( map[m].flag.gvg_noparty )
+ map_zone_mf_cache_add(m,"gvg_noparty\toff");
+ else if( map->list[m].flag.gvg_noparty )
map_zone_mf_cache_add(m,"gvg_noparty");
}
} else if (!strcmpi(flag,"gvg_dungeon")) {
- if( state && map[m].flag.gvg_dungeon )
+ if( state && map->list[m].flag.gvg_dungeon )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"gvg_dungeon off");
- else if( map[m].flag.gvg_dungeon )
+ map_zone_mf_cache_add(m,"gvg_dungeon\toff");
+ else if( map->list[m].flag.gvg_dungeon )
map_zone_mf_cache_add(m,"gvg_dungeon");
}
}
else if (!strcmpi(flag,"gvg_castle")) {
- if( state && map[m].flag.gvg_castle )
+ if( state && map->list[m].flag.gvg_castle )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"gvg_castle off");
- else if( map[m].flag.gvg_castle )
+ map_zone_mf_cache_add(m,"gvg_castle\toff");
+ else if( map->list[m].flag.gvg_castle )
map_zone_mf_cache_add(m,"gvg_castle");
}
}
else if (!strcmpi(flag,"battleground")) {
- if( state && map[m].flag.battleground )
+ if( state && map->list[m].flag.battleground )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"battleground off");
- else if( map[m].flag.battleground )
+ map_zone_mf_cache_add(m,"battleground\toff");
+ else if( map->list[m].flag.battleground )
map_zone_mf_cache_add(m,"battleground");
}
} else if (!strcmpi(flag,"noexppenalty")) {
- if( state && map[m].flag.noexppenalty )
+ if( state && map->list[m].flag.noexppenalty )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"noexppenalty off");
- else if( map[m].flag.noexppenalty )
+ map_zone_mf_cache_add(m,"noexppenalty\toff");
+ else if( map->list[m].flag.noexppenalty )
map_zone_mf_cache_add(m,"noexppenalty");
}
} else if (!strcmpi(flag,"nozenypenalty")) {
- if( state && map[m].flag.nozenypenalty )
+ if( state && map->list[m].flag.nozenypenalty )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nozenypenalty off");
- else if( map[m].flag.nozenypenalty )
+ map_zone_mf_cache_add(m,"nozenypenalty\toff");
+ else if( map->list[m].flag.nozenypenalty )
map_zone_mf_cache_add(m,"nozenypenalty");
}
} else if (!strcmpi(flag,"notrade")) {
- if( state && map[m].flag.notrade )
+ if( state && map->list[m].flag.notrade )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"notrade off");
- else if( map[m].flag.notrade )
+ map_zone_mf_cache_add(m,"notrade\toff");
+ else if( map->list[m].flag.notrade )
map_zone_mf_cache_add(m,"notrade");
}
} else if (!strcmpi(flag,"novending")) {
- if( state && map[m].flag.novending )
+ if( state && map->list[m].flag.novending )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"novending off");
- else if( map[m].flag.novending )
+ map_zone_mf_cache_add(m,"novending\toff");
+ else if( map->list[m].flag.novending )
map_zone_mf_cache_add(m,"novending");
}
} else if (!strcmpi(flag,"nodrop")) {
- if( state && map[m].flag.nodrop )
+ if( state && map->list[m].flag.nodrop )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nodrop off");
- else if( map[m].flag.nodrop )
+ map_zone_mf_cache_add(m,"nodrop\toff");
+ else if( map->list[m].flag.nodrop )
map_zone_mf_cache_add(m,"nodrop");
}
} else if (!strcmpi(flag,"noskill")) {
- if( state && map[m].flag.noskill )
+ if( state && map->list[m].flag.noskill )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"noskill off");
- else if( map[m].flag.noskill )
+ map_zone_mf_cache_add(m,"noskill\toff");
+ else if( map->list[m].flag.noskill )
map_zone_mf_cache_add(m,"noskill");
}
} else if (!strcmpi(flag,"noicewall")) {
- if( state && map[m].flag.noicewall )
+ if( state && map->list[m].flag.noicewall )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"noicewall off");
- else if( map[m].flag.noicewall )
+ map_zone_mf_cache_add(m,"noicewall\toff");
+ else if( map->list[m].flag.noicewall )
map_zone_mf_cache_add(m,"noicewall");
}
} else if (!strcmpi(flag,"snow")) {
- if( state && map[m].flag.snow )
+ if( state && map->list[m].flag.snow )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"snow off");
- else if( map[m].flag.snow )
+ map_zone_mf_cache_add(m,"snow\toff");
+ else if( map->list[m].flag.snow )
map_zone_mf_cache_add(m,"snow");
}
} else if (!strcmpi(flag,"clouds")) {
- if( state && map[m].flag.clouds )
+ if( state && map->list[m].flag.clouds )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"clouds off");
- else if( map[m].flag.clouds )
+ map_zone_mf_cache_add(m,"clouds\toff");
+ else if( map->list[m].flag.clouds )
map_zone_mf_cache_add(m,"clouds");
}
} else if (!strcmpi(flag,"clouds2")) {
- if( state && map[m].flag.clouds2 )
+ if( state && map->list[m].flag.clouds2 )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"clouds2 off");
- else if( map[m].flag.clouds2 )
+ map_zone_mf_cache_add(m,"clouds2\toff");
+ else if( map->list[m].flag.clouds2 )
map_zone_mf_cache_add(m,"clouds2");
}
} else if (!strcmpi(flag,"fog")) {
- if( state && map[m].flag.fog )
+ if( state && map->list[m].flag.fog )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"fog off");
- else if( map[m].flag.fog )
+ map_zone_mf_cache_add(m,"fog\toff");
+ else if( map->list[m].flag.fog )
map_zone_mf_cache_add(m,"fog");
}
} else if (!strcmpi(flag,"fireworks")) {
- if( state && map[m].flag.fireworks )
+ if( state && map->list[m].flag.fireworks )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"fireworks off");
- else if( map[m].flag.fireworks )
+ map_zone_mf_cache_add(m,"fireworks\toff");
+ else if( map->list[m].flag.fireworks )
map_zone_mf_cache_add(m,"fireworks");
}
} else if (!strcmpi(flag,"sakura")) {
- if( state && map[m].flag.sakura )
+ if( state && map->list[m].flag.sakura )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"sakura off");
- else if( map[m].flag.sakura )
+ map_zone_mf_cache_add(m,"sakura\toff");
+ else if( map->list[m].flag.sakura )
map_zone_mf_cache_add(m,"sakura");
}
} else if (!strcmpi(flag,"leaves")) {
- if( state && map[m].flag.leaves )
+ if( state && map->list[m].flag.leaves )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"leaves off");
- else if( map[m].flag.leaves )
+ map_zone_mf_cache_add(m,"leaves\toff");
+ else if( map->list[m].flag.leaves )
map_zone_mf_cache_add(m,"leaves");
}
} else if (!strcmpi(flag,"nightenabled")) {
- if( state && map[m].flag.nightenabled )
+ if( state && map->list[m].flag.nightenabled )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nightenabled off");
- else if( map[m].flag.nightenabled )
+ map_zone_mf_cache_add(m,"nightenabled\toff");
+ else if( map->list[m].flag.nightenabled )
map_zone_mf_cache_add(m,"nightenabled");
}
} else if (!strcmpi(flag,"noexp")) {
- if( state && map[m].flag.nobaseexp )
+ if( state && map->list[m].flag.nobaseexp )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"noexp off");
- else if( map[m].flag.nobaseexp )
+ map_zone_mf_cache_add(m,"noexp\toff");
+ else if( map->list[m].flag.nobaseexp )
map_zone_mf_cache_add(m,"noexp");
}
}
else if (!strcmpi(flag,"nobaseexp")) {
- if( state && map[m].flag.nobaseexp )
+ if( state && map->list[m].flag.nobaseexp )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nobaseexp off");
- else if( map[m].flag.nobaseexp )
+ map_zone_mf_cache_add(m,"nobaseexp\toff");
+ else if( map->list[m].flag.nobaseexp )
map_zone_mf_cache_add(m,"nobaseexp");
}
} else if (!strcmpi(flag,"nojobexp")) {
- if( state && map[m].flag.nojobexp )
+ if( state && map->list[m].flag.nojobexp )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nojobexp off");
- else if( map[m].flag.nojobexp )
+ map_zone_mf_cache_add(m,"nojobexp\toff");
+ else if( map->list[m].flag.nojobexp )
map_zone_mf_cache_add(m,"nojobexp");
}
} else if (!strcmpi(flag,"noloot")) {
- if( state && map[m].flag.nomobloot )
+ if( state && map->list[m].flag.nomobloot )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"noloot off");
- else if( map[m].flag.nomobloot )
+ map_zone_mf_cache_add(m,"noloot\toff");
+ else if( map->list[m].flag.nomobloot )
map_zone_mf_cache_add(m,"noloot");
}
} else if (!strcmpi(flag,"nomobloot")) {
- if( state && map[m].flag.nomobloot )
+ if( state && map->list[m].flag.nomobloot )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nomobloot off");
- else if( map[m].flag.nomobloot )
+ map_zone_mf_cache_add(m,"nomobloot\toff");
+ else if( map->list[m].flag.nomobloot )
map_zone_mf_cache_add(m,"nomobloot");
}
} else if (!strcmpi(flag,"nomvploot")) {
- if( state && map[m].flag.nomvploot )
+ if( state && map->list[m].flag.nomvploot )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nomvploot off");
- else if( map[m].flag.nomvploot )
+ map_zone_mf_cache_add(m,"nomvploot\toff");
+ else if( map->list[m].flag.nomvploot )
map_zone_mf_cache_add(m,"nomvploot");
}
} else if (!strcmpi(flag,"nocommand")) {
/* implementation may be incomplete */
if( state && sscanf(params, "%d", &state) == 1 ) {
- sprintf(rflag, "nocommand %s",params);
+ sprintf(rflag, "nocommand\t%s",params);
map_zone_mf_cache_add(m,rflag);
- } else if( !state && map[m].nocommand ) {
- sprintf(rflag, "nocommand %d",map[m].nocommand);
+ } else if( !state && map->list[m].nocommand ) {
+ sprintf(rflag, "nocommand\t%d",map->list[m].nocommand);
map_zone_mf_cache_add(m,rflag);
- } else if( map[m].nocommand ) {
- map_zone_mf_cache_add(m,"nocommand off");
+ } else if( map->list[m].nocommand ) {
+ map_zone_mf_cache_add(m,"nocommand\toff");
}
} else if (!strcmpi(flag,"jexp")) {
if( !state ) {
- if( map[m].jexp != 100 ) {
- sprintf(rflag,"jexp %d",map[m].jexp);
+ if( map->list[m].jexp != 100 ) {
+ sprintf(rflag,"jexp\t%d",map->list[m].jexp);
map_zone_mf_cache_add(m,rflag);
}
} if( sscanf(params, "%d", &state) == 1 ) {
- if( state != map[m].jexp ) {
- sprintf(rflag,"jexp %s",params);
+ if( state != map->list[m].jexp ) {
+ sprintf(rflag,"jexp\t%s",params);
map_zone_mf_cache_add(m,rflag);
}
}
} else if (!strcmpi(flag,"bexp")) {
if( !state ) {
- if( map[m].bexp != 100 ) {
- sprintf(rflag,"bexp %d",map[m].jexp);
+ if( map->list[m].bexp != 100 ) {
+ sprintf(rflag,"bexp\t%d",map->list[m].jexp);
map_zone_mf_cache_add(m,rflag);
}
} if( sscanf(params, "%d", &state) == 1 ) {
- if( state != map[m].bexp ) {
- sprintf(rflag,"bexp %s",params);
+ if( state != map->list[m].bexp ) {
+ sprintf(rflag,"bexp\t%s",params);
map_zone_mf_cache_add(m,rflag);
}
}
} else if (!strcmpi(flag,"loadevent")) {
- if( state && map[m].flag.loadevent )
+ if( state && map->list[m].flag.loadevent )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"loadevent off");
- else if( map[m].flag.loadevent )
+ map_zone_mf_cache_add(m,"loadevent\toff");
+ else if( map->list[m].flag.loadevent )
map_zone_mf_cache_add(m,"loadevent");
}
} else if (!strcmpi(flag,"nochat")) {
- if( state && map[m].flag.nochat )
+ if( state && map->list[m].flag.nochat )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nochat off");
- else if( map[m].flag.nochat )
+ map_zone_mf_cache_add(m,"nochat\toff");
+ else if( map->list[m].flag.nochat )
map_zone_mf_cache_add(m,"nochat");
}
} else if (!strcmpi(flag,"partylock")) {
- if( state && map[m].flag.partylock )
+ if( state && map->list[m].flag.partylock )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"partylock off");
- else if( map[m].flag.partylock )
+ map_zone_mf_cache_add(m,"partylock\toff");
+ else if( map->list[m].flag.partylock )
map_zone_mf_cache_add(m,"partylock");
}
} else if (!strcmpi(flag,"guildlock")) {
- if( state && map[m].flag.guildlock )
+ if( state && map->list[m].flag.guildlock )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"guildlock off");
- else if( map[m].flag.guildlock )
+ map_zone_mf_cache_add(m,"guildlock\toff");
+ else if( map->list[m].flag.guildlock )
map_zone_mf_cache_add(m,"guildlock");
}
} else if (!strcmpi(flag,"reset")) {
- if( state && map[m].flag.reset )
+ if( state && map->list[m].flag.reset )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"reset off");
- else if( map[m].flag.reset )
+ map_zone_mf_cache_add(m,"reset\toff");
+ else if( map->list[m].flag.reset )
map_zone_mf_cache_add(m,"reset");
}
} else if (!strcmpi(flag,"adjust_unit_duration")) {
int skill_id, k;
char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH];
- int len = strlen(params);
+ size_t len = strlen(params);
modifier[0] = '\0';
memcpy(skill_name, params, MAP_ZONE_MAPFLAG_LENGTH);
@@ -4209,27 +4409,26 @@ bool map_zone_mf_cache(int m, char *flag, char *params) {
}
if( modifier[0] == '\0' || !( skill_id = skill->name2id(skill_name) ) || !skill->get_unit_id( skill->name2id(skill_name), 0) || atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) {
- ;/* we dont mind it, the server will take care of it next. */
+ ;/* we don't mind it, the server will take care of it next. */
} else {
- int idx = map[m].unit_count;
+ int idx = map->list[m].unit_count;
- k = 0;
- ARR_FIND(0, idx, k, map[m].units[k]->skill_id == skill_id);
+ ARR_FIND(0, idx, k, map->list[m].units[k]->skill_id == skill_id);
if( k < idx ) {
- if( atoi(modifier) != map[m].units[k]->modifier ) {
- sprintf(rflag,"adjust_unit_duration %s %d",skill_name,map[m].units[k]->modifier);
+ if( atoi(modifier) != map->list[m].units[k]->modifier ) {
+ sprintf(rflag,"adjust_unit_duration\t%s\t%d",skill_name,map->list[m].units[k]->modifier);
map_zone_mf_cache_add(m,rflag);
}
} else {
- sprintf(rflag,"adjust_unit_duration %s 100",skill_name);
+ sprintf(rflag,"adjust_unit_duration\t%s\t100",skill_name);
map_zone_mf_cache_add(m,rflag);
- }
+ }
}
} else if (!strcmpi(flag,"adjust_skill_damage")) {
int skill_id, k;
char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH];
- int len = strlen(params);
+ size_t len = strlen(params);
modifier[0] = '\0';
memcpy(skill_name, params, MAP_ZONE_MAPFLAG_LENGTH);
@@ -4243,127 +4442,136 @@ bool map_zone_mf_cache(int m, char *flag, char *params) {
}
if( modifier[0] == '\0' || !( skill_id = skill->name2id(skill_name) ) || atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) {
- ;/* we dont mind it, the server will take care of it next. */
+ ;/* we don't mind it, the server will take care of it next. */
} else {
- int idx = map[m].skill_count;
+ int idx = map->list[m].skill_count;
- k = 0;
- ARR_FIND(0, idx, k, map[m].skills[k]->skill_id == skill_id);
+ ARR_FIND(0, idx, k, map->list[m].skills[k]->skill_id == skill_id);
if( k < idx ) {
- if( atoi(modifier) != map[m].skills[k]->modifier ) {
- sprintf(rflag,"adjust_skill_damage %s %d",skill_name,map[m].skills[k]->modifier);
+ if( atoi(modifier) != map->list[m].skills[k]->modifier ) {
+ sprintf(rflag,"adjust_skill_damage\t%s\t%d",skill_name,map->list[m].skills[k]->modifier);
map_zone_mf_cache_add(m,rflag);
}
} else {
- sprintf(rflag,"adjust_skill_damage %s 100",skill_name);
+ sprintf(rflag,"adjust_skill_damage\t%s\t100",skill_name);
map_zone_mf_cache_add(m,rflag);
}
}
} else if (!strcmpi(flag,"zone")) {
- ShowWarning("You can't add a zone through a zone! ERROR, skipping for '%s'...\n",map[m].name);
+ ShowWarning("You can't add a zone through a zone! ERROR, skipping for '%s'...\n",map->list[m].name);
return true;
} else if ( !strcmpi(flag,"nomapchannelautojoin") ) {
- if( state && map[m].flag.chsysnolocalaj )
+ if( state && map->list[m].flag.chsysnolocalaj )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"nomapchannelautojoin off");
- else if( map[m].flag.chsysnolocalaj )
+ map_zone_mf_cache_add(m,"nomapchannelautojoin\toff");
+ else if( map->list[m].flag.chsysnolocalaj )
map_zone_mf_cache_add(m,"nomapchannelautojoin");
}
} else if ( !strcmpi(flag,"invincible_time_inc") ) {
if( !state ) {
- if( map[m].invincible_time_inc != 0 ) {
- sprintf(rflag,"invincible_time_inc %d",map[m].invincible_time_inc);
+ if( map->list[m].invincible_time_inc != 0 ) {
+ sprintf(rflag,"invincible_time_inc\t%d",map->list[m].invincible_time_inc);
map_zone_mf_cache_add(m,rflag);
}
} if( sscanf(params, "%d", &state) == 1 ) {
- if( state != map[m].invincible_time_inc ) {
- sprintf(rflag,"invincible_time_inc %s",params);
+ if( state != map->list[m].invincible_time_inc ) {
+ sprintf(rflag,"invincible_time_inc\t%s",params);
map_zone_mf_cache_add(m,rflag);
}
}
} else if ( !strcmpi(flag,"noknockback") ) {
- if( state && map[m].flag.noknockback )
+ if( state && map->list[m].flag.noknockback )
;/* nothing to do */
else {
if( state )
- map_zone_mf_cache_add(m,"noknockback off");
- else if( map[m].flag.noknockback )
+ map_zone_mf_cache_add(m,"noknockback\toff");
+ else if( map->list[m].flag.noknockback )
map_zone_mf_cache_add(m,"noknockback");
}
} else if ( !strcmpi(flag,"weapon_damage_rate") ) {
if( !state ) {
- if( map[m].weapon_damage_rate != 100 ) {
- sprintf(rflag,"weapon_damage_rate %d",map[m].weapon_damage_rate);
+ if( map->list[m].weapon_damage_rate != 100 ) {
+ sprintf(rflag,"weapon_damage_rate\t%d",map->list[m].weapon_damage_rate);
map_zone_mf_cache_add(m,rflag);
}
} if( sscanf(params, "%d", &state) == 1 ) {
- if( state != map[m].weapon_damage_rate ) {
- sprintf(rflag,"weapon_damage_rate %s",params);
+ if( state != map->list[m].weapon_damage_rate ) {
+ sprintf(rflag,"weapon_damage_rate\t%s",params);
map_zone_mf_cache_add(m,rflag);
}
}
} else if ( !strcmpi(flag,"magic_damage_rate") ) {
if( !state ) {
- if( map[m].magic_damage_rate != 100 ) {
- sprintf(rflag,"magic_damage_rate %d",map[m].magic_damage_rate);
+ if( map->list[m].magic_damage_rate != 100 ) {
+ sprintf(rflag,"magic_damage_rate\t%d",map->list[m].magic_damage_rate);
map_zone_mf_cache_add(m,rflag);
}
} if( sscanf(params, "%d", &state) == 1 ) {
- if( state != map[m].magic_damage_rate ) {
- sprintf(rflag,"magic_damage_rate %s",params);
+ if( state != map->list[m].magic_damage_rate ) {
+ sprintf(rflag,"magic_damage_rate\t%s",params);
map_zone_mf_cache_add(m,rflag);
}
}
} else if ( !strcmpi(flag,"misc_damage_rate") ) {
if( !state ) {
- if( map[m].misc_damage_rate != 100 ) {
- sprintf(rflag,"misc_damage_rate %d",map[m].misc_damage_rate);
+ if( map->list[m].misc_damage_rate != 100 ) {
+ sprintf(rflag,"misc_damage_rate\t%d",map->list[m].misc_damage_rate);
map_zone_mf_cache_add(m,rflag);
}
} if( sscanf(params, "%d", &state) == 1 ) {
- if( state != map[m].misc_damage_rate ) {
- sprintf(rflag,"misc_damage_rate %s",params);
+ if( state != map->list[m].misc_damage_rate ) {
+ sprintf(rflag,"misc_damage_rate\t%s",params);
map_zone_mf_cache_add(m,rflag);
}
}
} else if ( !strcmpi(flag,"short_damage_rate") ) {
if( !state ) {
- if( map[m].short_damage_rate != 100 ) {
- sprintf(rflag,"short_damage_rate %d",map[m].short_damage_rate);
+ if( map->list[m].short_damage_rate != 100 ) {
+ sprintf(rflag,"short_damage_rate\t%d",map->list[m].short_damage_rate);
map_zone_mf_cache_add(m,rflag);
}
} if( sscanf(params, "%d", &state) == 1 ) {
- if( state != map[m].short_damage_rate ) {
- sprintf(rflag,"short_damage_rate %s",params);
+ if( state != map->list[m].short_damage_rate ) {
+ sprintf(rflag,"short_damage_rate\t%s",params);
map_zone_mf_cache_add(m,rflag);
}
}
} else if ( !strcmpi(flag,"long_damage_rate") ) {
if( !state ) {
- if( map[m].long_damage_rate != 100 ) {
- sprintf(rflag,"long_damage_rate %d",map[m].long_damage_rate);
+ if( map->list[m].long_damage_rate != 100 ) {
+ sprintf(rflag,"long_damage_rate\t%d",map->list[m].long_damage_rate);
map_zone_mf_cache_add(m,rflag);
}
} if( sscanf(params, "%d", &state) == 1 ) {
- if( state != map[m].long_damage_rate ) {
- sprintf(rflag,"long_damage_rate %s",params);
+ if( state != map->list[m].long_damage_rate ) {
+ sprintf(rflag,"long_damage_rate\t%s",params);
map_zone_mf_cache_add(m,rflag);
}
}
+ } else if (!strcmpi(flag,"nocashshop")) {
+ if( state && map->list[m].flag.nocashshop )
+ ;/* nothing to do */
+ else {
+ if( state )
+ map_zone_mf_cache_add(m,"nocashshop\toff");
+ else if( map->list[m].flag.nocashshop )
+ map_zone_mf_cache_add(m,"nocashshop");
+ }
}
+
return false;
}
void map_zone_apply(int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath) {
int i;
char empty[1] = "\0";
char flag[MAP_ZONE_MAPFLAG_LENGTH], params[MAP_ZONE_MAPFLAG_LENGTH];
- map[m].zone = zone;
+ map->list[m].zone = zone;
for(i = 0; i < zone->mapflags_count; i++) {
- int len = strlen(zone->mapflags[i]);
+ size_t len = strlen(zone->mapflags[i]);
int k;
params[0] = '\0';
memcpy(flag, zone->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH);
@@ -4375,10 +4583,10 @@ void map_zone_apply(int m, struct map_zone_data *zone, const char* start, const
}
}
- if( map_zone_mf_cache(m,flag,params) )
+ if( map->zone_mf_cache(m,flag,params) )
continue;
- npc_parse_mapflag(map[m].name,empty,flag,params,start,buffer,filepath);
+ npc->parse_mapflag(map->list[m].name, empty, flag, params, start, buffer, filepath, NULL);
}
}
/* used on npc load and reload to apply all "Normal" and "PK Mode" zones */
@@ -4388,10 +4596,10 @@ void map_zone_init(void) {
char empty[1] = "\0";
int i,k,j;
- zone = &map_zone_all;
+ zone = &map->zone_all;
for(i = 0; i < zone->mapflags_count; i++) {
- int len = strlen(zone->mapflags[i]);
+ size_t len = strlen(zone->mapflags[i]);
params[0] = '\0';
memcpy(flag, zone->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH);
for(k = 0; k < len; k++) {
@@ -4402,19 +4610,19 @@ void map_zone_init(void) {
}
}
- for(j = 0; j < iMap->map_num; j++) {
- if( map[j].zone == zone ) {
- if( map_zone_mf_cache(j,flag,params) )
+ for(j = 0; j < map->count; j++) {
+ if( map->list[j].zone == zone ) {
+ if( map->zone_mf_cache(j,flag,params) )
break;
- npc_parse_mapflag(map[j].name,empty,flag,params,empty,empty,empty);
+ npc->parse_mapflag(map->list[j].name, empty, flag, params, empty, empty, empty, NULL);
}
}
}
if( battle_config.pk_mode ) {
- zone = &map_zone_pk;
+ zone = &map->zone_pk;
for(i = 0; i < zone->mapflags_count; i++) {
- int len = strlen(zone->mapflags[i]);
+ size_t len = strlen(zone->mapflags[i]);
params[0] = '\0';
memcpy(flag, zone->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH);
for(k = 0; k < len; k++) {
@@ -4424,11 +4632,11 @@ void map_zone_init(void) {
break;
}
}
- for(j = 0; j < iMap->map_num; j++) {
- if( map[j].zone == zone ) {
- if( map_zone_mf_cache(j,flag,params) )
+ for(j = 0; j < map->count; j++) {
+ if( map->list[j].zone == zone ) {
+ if( map->zone_mf_cache(j,flag,params) )
break;
- npc_parse_mapflag(map[j].name,empty,flag,params,empty,empty,empty);
+ npc->parse_mapflag(map->list[j].name, empty, flag, params, empty, empty, empty, NULL);
}
}
}
@@ -4440,12 +4648,12 @@ unsigned short map_zone_str2itemid(const char *name) {
if( !name )
return 0;
- if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) {
- if( !( data = itemdb_exists(atoi(name+2))) ) {
+ if( name[0] == 'I' && name[1] == 'D' && strlen(name) < 8 ) {
+ if( !( data = itemdb->exists(atoi(name+2))) ) {
return 0;
}
} else {
- if( !( data = itemdb_searchname(name) ) ) {
+ if( !( data = itemdb->search_name(name) ) ) {
return 0;
}
}
@@ -4457,11 +4665,11 @@ unsigned short map_zone_str2skillid(const char *name) {
if( !name )
return 0;
- if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) {
+ if( name[0] == 'I' && name[1] == 'D' && strlen(name) < 8 ) {
if( !skill->get_index((nameid = atoi(name+2))) )
return 0;
} else {
- if( !( nameid = strdb_iget(skilldb_name2id, name) ) ) {
+ if( !( nameid = strdb_iget(skill->name2id_db, name) ) ) {
return 0;
}
}
@@ -4521,10 +4729,10 @@ void read_map_zone_db(void) {
#else
const char *config_filename = "db/pre-re/map_zone_db.conf"; // FIXME hardcoded name
#endif
- if (conf_read_file(&map_zone_db, config_filename))
+ if (libconfig->read_file(&map_zone_db, config_filename))
return;
- zones = config_lookup(&map_zone_db, "zones");
+ zones = libconfig->lookup(&map_zone_db, "zones");
if (zones != NULL) {
struct map_zone_data *zone;
@@ -4541,24 +4749,24 @@ void read_map_zone_db(void) {
disabled_commands_count = 0, capped_skills_count = 0;
enum map_zone_skill_subtype subtype;
- zone_count = config_setting_length(zones);
+ zone_count = libconfig->setting_length(zones);
for (i = 0; i < zone_count; ++i) {
bool is_all = false;
- zone_e = config_setting_get_elem(zones, i);
+ zone_e = libconfig->setting_get_elem(zones, i);
- if (!config_setting_lookup_string(zone_e, "name", &zonename)) {
+ if (!libconfig->setting_lookup_string(zone_e, "name", &zonename)) {
ShowError("map_zone_db: missing zone name, skipping... (%s:%d)\n",
config_setting_source_file(zone_e), config_setting_source_line(zone_e));
- config_setting_remove_elem(zones,i);/* remove from the tree */
+ libconfig->setting_remove_elem(zones,i);/* remove from the tree */
--zone_count;
--i;
continue;
}
- if( strdb_exists(zone_db, zonename) ) {
+ if( strdb_exists(map->zone_db, zonename) ) {
ShowError("map_zone_db: duplicate zone name '%s', skipping...\n",zonename);
- config_setting_remove_elem(zones,i);/* remove from the tree */
+ libconfig->setting_remove_elem(zones,i);/* remove from the tree */
--zone_count;
--i;
continue;
@@ -4566,46 +4774,46 @@ void read_map_zone_db(void) {
/* is this the global template? */
if( strncmpi(zonename,MAP_ZONE_NORMAL_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) {
- zone = &map_zone_all;
+ zone = &map->zone_all;
is_all = true;
} else if( strncmpi(zonename,MAP_ZONE_PK_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) {
- zone = &map_zone_pk;
+ zone = &map->zone_pk;
is_all = true;
} else {
CREATE( zone, struct map_zone_data, 1 );
zone->disabled_skills_count = 0;
zone->disabled_items_count = 0;
}
- safestrncpy(zone->name, zonename, MAP_ZONE_NAME_LENGTH);
+ safestrncpy(zone->name, zonename, MAP_ZONE_NAME_LENGTH/2);
- if( (skills = config_setting_get_member(zone_e, "disabled_skills")) != NULL ) {
- disabled_skills_count = config_setting_length(skills);
+ if( (skills = libconfig->setting_get_member(zone_e, "disabled_skills")) != NULL ) {
+ disabled_skills_count = libconfig->setting_length(skills);
/* validate */
- for(h = 0; h < config_setting_length(skills); h++) {
- config_setting_t *skill = config_setting_get_elem(skills, h);
- name = config_setting_name(skill);
- if( !map_zone_str2skillid(name) ) {
+ for(h = 0; h < libconfig->setting_length(skills); h++) {
+ config_setting_t *skillinfo = libconfig->setting_get_elem(skills, h);
+ name = config_setting_name(skillinfo);
+ if( !map->zone_str2skillid(name) ) {
ShowError("map_zone_db: unknown skill (%s) in disabled_skills for zone '%s', skipping skill...\n",name,zone->name);
- config_setting_remove_elem(skills,h);
+ libconfig->setting_remove_elem(skills,h);
--disabled_skills_count;
--h;
continue;
}
- if( !map_zone_bl_type(config_setting_get_string_elem(skills,h),&subtype) )/* we dont remove it from the three due to inheritance */
+ if( !map->zone_bl_type(libconfig->setting_get_string_elem(skills,h),&subtype) )/* we don't remove it from the three due to inheritance */
--disabled_skills_count;
}
/* all ok, process */
CREATE( zone->disabled_skills, struct map_zone_disabled_skill_entry *, disabled_skills_count );
- for(h = 0, v = 0; h < config_setting_length(skills); h++) {
- config_setting_t *skill = config_setting_get_elem(skills, h);
+ for(h = 0, v = 0; h < libconfig->setting_length(skills); h++) {
+ config_setting_t *skillinfo = libconfig->setting_get_elem(skills, h);
struct map_zone_disabled_skill_entry * entry;
enum bl_type type;
- name = config_setting_name(skill);
+ name = config_setting_name(skillinfo);
- if( (type = map_zone_bl_type(config_setting_get_string_elem(skills,h),&subtype)) ) { /* only add if enabled */
+ if( (type = map->zone_bl_type(libconfig->setting_get_string_elem(skills,h),&subtype)) ) { /* only add if enabled */
CREATE( entry, struct map_zone_disabled_skill_entry, 1 );
- entry->nameid = map_zone_str2skillid(name);
+ entry->nameid = map->zone_str2skillid(name);
entry->type = type;
entry->subtype = subtype;
@@ -4616,44 +4824,44 @@ void read_map_zone_db(void) {
zone->disabled_skills_count = disabled_skills_count;
}
- if( (items = config_setting_get_member(zone_e, "disabled_items")) != NULL ) {
- disabled_items_count = config_setting_length(items);
+ if( (items = libconfig->setting_get_member(zone_e, "disabled_items")) != NULL ) {
+ disabled_items_count = libconfig->setting_length(items);
/* validate */
- for(h = 0; h < config_setting_length(items); h++) {
- config_setting_t *item = config_setting_get_elem(items, h);
+ for(h = 0; h < libconfig->setting_length(items); h++) {
+ config_setting_t *item = libconfig->setting_get_elem(items, h);
name = config_setting_name(item);
- if( !map_zone_str2itemid(name) ) {
+ if( !map->zone_str2itemid(name) ) {
ShowError("map_zone_db: unknown item (%s) in disabled_items for zone '%s', skipping item...\n",name,zone->name);
- config_setting_remove_elem(items,h);
+ libconfig->setting_remove_elem(items,h);
--disabled_items_count;
--h;
continue;
}
- if( !config_setting_get_bool(item) )/* we dont remove it from the three due to inheritance */
+ if( !libconfig->setting_get_bool(item) )/* we don't remove it from the three due to inheritance */
--disabled_items_count;
}
/* all ok, process */
CREATE( zone->disabled_items, int, disabled_items_count );
- for(h = 0, v = 0; h < config_setting_length(items); h++) {
- config_setting_t *item = config_setting_get_elem(items, h);
+ for(h = 0, v = 0; h < libconfig->setting_length(items); h++) {
+ config_setting_t *item = libconfig->setting_get_elem(items, h);
- if( config_setting_get_bool(item) ) { /* only add if enabled */
+ if( libconfig->setting_get_bool(item) ) { /* only add if enabled */
name = config_setting_name(item);
- zone->disabled_items[v++] = map_zone_str2itemid(name);
+ zone->disabled_items[v++] = map->zone_str2itemid(name);
}
}
zone->disabled_items_count = disabled_items_count;
}
- if( (mapflags = config_setting_get_member(zone_e, "mapflags")) != NULL ) {
- mapflags_count = config_setting_length(mapflags);
+ if( (mapflags = libconfig->setting_get_member(zone_e, "mapflags")) != NULL ) {
+ mapflags_count = libconfig->setting_length(mapflags);
/* mapflags are not validated here, so we save all anyway */
CREATE( zone->mapflags, char *, mapflags_count );
for(h = 0; h < mapflags_count; h++) {
CREATE( zone->mapflags[h], char, MAP_ZONE_MAPFLAG_LENGTH );
- name = config_setting_get_string_elem(mapflags, h);
+ name = libconfig->setting_get_string_elem(mapflags, h);
safestrncpy(zone->mapflags[h], name, MAP_ZONE_MAPFLAG_LENGTH);
@@ -4661,81 +4869,81 @@ void read_map_zone_db(void) {
zone->mapflags_count = mapflags_count;
}
- if( (commands = config_setting_get_member(zone_e, "disabled_commands")) != NULL ) {
- disabled_commands_count = config_setting_length(commands);
+ if( (commands = libconfig->setting_get_member(zone_e, "disabled_commands")) != NULL ) {
+ disabled_commands_count = libconfig->setting_length(commands);
/* validate */
- for(h = 0; h < config_setting_length(commands); h++) {
- config_setting_t *command = config_setting_get_elem(commands, h);
+ for(h = 0; h < libconfig->setting_length(commands); h++) {
+ config_setting_t *command = libconfig->setting_get_elem(commands, h);
name = config_setting_name(command);
if( !atcommand->exists(name) ) {
ShowError("map_zone_db: unknown command '%s' in disabled_commands for zone '%s', skipping entry...\n",name,zone->name);
- config_setting_remove_elem(commands,h);
+ libconfig->setting_remove_elem(commands,h);
--disabled_commands_count;
--h;
continue;
}
- if( !config_setting_get_int(command) )/* we dont remove it from the three due to inheritance */
+ if( !libconfig->setting_get_int(command) )/* we don't remove it from the three due to inheritance */
--disabled_commands_count;
}
/* all ok, process */
CREATE( zone->disabled_commands, struct map_zone_disabled_command_entry *, disabled_commands_count );
- for(h = 0, v = 0; h < config_setting_length(commands); h++) {
- config_setting_t *command = config_setting_get_elem(commands, h);
+ for(h = 0, v = 0; h < libconfig->setting_length(commands); h++) {
+ config_setting_t *command = libconfig->setting_get_elem(commands, h);
struct map_zone_disabled_command_entry * entry;
int group_lv;
name = config_setting_name(command);
- if( (group_lv = config_setting_get_int(command)) ) { /* only add if enabled */
+ if( (group_lv = libconfig->setting_get_int(command)) ) { /* only add if enabled */
CREATE( entry, struct map_zone_disabled_command_entry, 1 );
entry->cmd = atcommand->exists(name)->func;
entry->group_lv = group_lv;
zone->disabled_commands[v++] = entry;
- }
+ }
}
zone->disabled_commands_count = disabled_commands_count;
}
- if( (caps = config_setting_get_member(zone_e, "skill_damage_cap")) != NULL ) {
- capped_skills_count = config_setting_length(caps);
+ if( (caps = libconfig->setting_get_member(zone_e, "skill_damage_cap")) != NULL ) {
+ capped_skills_count = libconfig->setting_length(caps);
/* validate */
- for(h = 0; h < config_setting_length(caps); h++) {
- config_setting_t *cap = config_setting_get_elem(caps, h);
+ for(h = 0; h < libconfig->setting_length(caps); h++) {
+ config_setting_t *cap = libconfig->setting_get_elem(caps, h);
name = config_setting_name(cap);
- if( !map_zone_str2skillid(name) ) {
+ if( !map->zone_str2skillid(name) ) {
ShowError("map_zone_db: unknown skill (%s) in skill_damage_cap for zone '%s', skipping skill...\n",name,zone->name);
- config_setting_remove_elem(caps,h);
+ libconfig->setting_remove_elem(caps,h);
--capped_skills_count;
--h;
continue;
}
- if( !map_zone_bl_type(config_setting_get_string_elem(cap,1),&subtype) )/* we dont remove it from the three due to inheritance */
+ if( !map->zone_bl_type(libconfig->setting_get_string_elem(cap,1),&subtype) )/* we don't remove it from the three due to inheritance */
--capped_skills_count;
}
/* all ok, process */
CREATE( zone->capped_skills, struct map_zone_skill_damage_cap_entry *, capped_skills_count );
- for(h = 0, v = 0; h < config_setting_length(caps); h++) {
- config_setting_t *cap = config_setting_get_elem(caps, h);
+ for(h = 0, v = 0; h < libconfig->setting_length(caps); h++) {
+ config_setting_t *cap = libconfig->setting_get_elem(caps, h);
struct map_zone_skill_damage_cap_entry * entry;
enum bl_type type;
name = config_setting_name(cap);
- if( (type = map_zone_bl_type(config_setting_get_string_elem(cap,1),&subtype)) ) { /* only add if enabled */
+ if( (type = map->zone_bl_type(libconfig->setting_get_string_elem(cap,1),&subtype)) ) { /* only add if enabled */
CREATE( entry, struct map_zone_skill_damage_cap_entry, 1 );
- entry->nameid = map_zone_str2skillid(name);
- entry->cap = config_setting_get_int_elem(cap,0);
+ entry->nameid = map->zone_str2skillid(name);
+ entry->cap = libconfig->setting_get_int_elem(cap,0);
entry->type = type;
entry->subtype = subtype;
zone->capped_skills[v++] = entry;
}
}
zone->capped_skills_count = capped_skills_count;
- }
+ }
if( !is_all ) /* global template doesn't go into db -- since it isn't a alloc'd piece of data */
- strdb_put(zone_db, zonename, zone);
+ strdb_put(map->zone_db, zonename, zone);
}
@@ -4745,24 +4953,24 @@ void read_map_zone_db(void) {
config_setting_t *new_entry = NULL;
int inherit_count;
- zone_e = config_setting_get_elem(zones, i);
- config_setting_lookup_string(zone_e, "name", &zonename);
+ zone_e = libconfig->setting_get_elem(zones, i);
+ libconfig->setting_lookup_string(zone_e, "name", &zonename);
if( strncmpi(zonename,MAP_ZONE_ALL_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) {
continue;/* all zone doesn't inherit anything (if it did, everything would link to each other and boom endless loop) */
}
- if( (inherit_tree = config_setting_get_member(zone_e, "inherit")) != NULL ) {
+ if( (inherit_tree = libconfig->setting_get_member(zone_e, "inherit")) != NULL ) {
/* append global zone to this */
- new_entry = config_setting_add(inherit_tree,MAP_ZONE_ALL_NAME,CONFIG_TYPE_STRING);
- config_setting_set_string(new_entry,MAP_ZONE_ALL_NAME);
+ new_entry = libconfig->setting_add(inherit_tree,MAP_ZONE_ALL_NAME,CONFIG_TYPE_STRING);
+ libconfig->setting_set_string(new_entry,MAP_ZONE_ALL_NAME);
} else {
/* create inherit member and add global zone to it */
- inherit_tree = config_setting_add(zone_e, "inherit",CONFIG_TYPE_ARRAY);
- new_entry = config_setting_add(inherit_tree,MAP_ZONE_ALL_NAME,CONFIG_TYPE_STRING);
- config_setting_set_string(new_entry,MAP_ZONE_ALL_NAME);
+ inherit_tree = libconfig->setting_add(zone_e, "inherit",CONFIG_TYPE_ARRAY);
+ new_entry = libconfig->setting_add(inherit_tree,MAP_ZONE_ALL_NAME,CONFIG_TYPE_STRING);
+ libconfig->setting_set_string(new_entry,MAP_ZONE_ALL_NAME);
}
- inherit_count = config_setting_length(inherit_tree);
+ inherit_count = libconfig->setting_length(inherit_tree);
for(h = 0; h < inherit_count; h++) {
struct map_zone_data *izone; /* inherit zone */
int disabled_skills_count_i = 0; /* disabled skill count from inherit zone */
@@ -4772,20 +4980,20 @@ void read_map_zone_db(void) {
int capped_skills_count_i = 0; /* skill capped count from inherit zone */
int j;
- name = config_setting_get_string_elem(inherit_tree, h);
- config_setting_lookup_string(zone_e, "name", &zonename);/* will succeed for we validated it earlier */
+ name = libconfig->setting_get_string_elem(inherit_tree, h);
+ libconfig->setting_lookup_string(zone_e, "name", &zonename);/* will succeed for we validated it earlier */
- if( !(izone = strdb_get(zone_db, name)) ) {
+ if( !(izone = strdb_get(map->zone_db, name)) ) {
ShowError("map_zone_db: Unknown zone '%s' being inherit by zone '%s', skipping...\n",name,zonename);
continue;
}
if( strncmpi(zonename,MAP_ZONE_NORMAL_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) {
- zone = &map_zone_all;
+ zone = &map->zone_all;
} else if( strncmpi(zonename,MAP_ZONE_PK_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) {
- zone = &map_zone_pk;
+ zone = &map->zone_pk;
} else
- zone = strdb_get(zone_db, zonename);/* will succeed for we just put it in here */
+ zone = strdb_get(map->zone_db, zonename);/* will succeed for we just put it in here */
disabled_skills_count_i = izone->disabled_skills_count;
disabled_items_count_i = izone->disabled_items_count;
@@ -4795,14 +5003,14 @@ void read_map_zone_db(void) {
/* process everything to override, paying attention to config_setting_get_bool */
if( disabled_skills_count_i ) {
- if( (skills = config_setting_get_member(zone_e, "disabled_skills")) == NULL )
- skills = config_setting_add(zone_e, "disabled_skills",CONFIG_TYPE_GROUP);
- disabled_skills_count = config_setting_length(skills);
+ if( (skills = libconfig->setting_get_member(zone_e, "disabled_skills")) == NULL )
+ skills = libconfig->setting_add(zone_e, "disabled_skills",CONFIG_TYPE_GROUP);
+ disabled_skills_count = libconfig->setting_length(skills);
for(j = 0; j < disabled_skills_count_i; j++) {
int k;
for(k = 0; k < disabled_skills_count; k++) {
- config_setting_t *skill = config_setting_get_elem(skills, k);
- if( map_zone_str2skillid(config_setting_name(skill)) == izone->disabled_skills[j]->nameid ) {
+ config_setting_t *skillinfo = libconfig->setting_get_elem(skills, k);
+ if( map->zone_str2skillid(config_setting_name(skillinfo)) == izone->disabled_skills[j]->nameid ) {
break;
}
}
@@ -4818,18 +5026,18 @@ void read_map_zone_db(void) {
}
if( disabled_items_count_i ) {
- if( (items = config_setting_get_member(zone_e, "disabled_items")) == NULL )
- items = config_setting_add(zone_e, "disabled_items",CONFIG_TYPE_GROUP);
- disabled_items_count = config_setting_length(items);
+ if( (items = libconfig->setting_get_member(zone_e, "disabled_items")) == NULL )
+ items = libconfig->setting_add(zone_e, "disabled_items",CONFIG_TYPE_GROUP);
+ disabled_items_count = libconfig->setting_length(items);
for(j = 0; j < disabled_items_count_i; j++) {
int k;
for(k = 0; k < disabled_items_count; k++) {
- config_setting_t *item = config_setting_get_elem(items, k);
+ config_setting_t *item = libconfig->setting_get_elem(items, k);
name = config_setting_name(item);
- if( map_zone_str2itemid(name) == izone->disabled_items[j] ) {
- if( config_setting_get_bool(item) )
+ if( map->zone_str2itemid(name) == izone->disabled_items[j] ) {
+ if( libconfig->setting_get_bool(item) )
continue;
break;
}
@@ -4842,13 +5050,13 @@ void read_map_zone_db(void) {
}
if( mapflags_count_i ) {
- if( (mapflags = config_setting_get_member(zone_e, "mapflags")) == NULL )
- mapflags = config_setting_add(zone_e, "mapflags",CONFIG_TYPE_ARRAY);
- mapflags_count = config_setting_length(mapflags);
+ if( (mapflags = libconfig->setting_get_member(zone_e, "mapflags")) == NULL )
+ mapflags = libconfig->setting_add(zone_e, "mapflags",CONFIG_TYPE_ARRAY);
+ mapflags_count = libconfig->setting_length(mapflags);
for(j = 0; j < mapflags_count_i; j++) {
int k;
for(k = 0; k < mapflags_count; k++) {
- name = config_setting_get_string_elem(mapflags, k);
+ name = libconfig->setting_get_string_elem(mapflags, k);
if( strcmpi(name,izone->mapflags[j]) == 0 ) {
break;
@@ -4863,14 +5071,14 @@ void read_map_zone_db(void) {
}
if( disabled_commands_count_i ) {
- if( (commands = config_setting_get_member(zone_e, "disabled_commands")) == NULL )
- commands = config_setting_add(zone_e, "disabled_commands",CONFIG_TYPE_GROUP);
+ if( (commands = libconfig->setting_get_member(zone_e, "disabled_commands")) == NULL )
+ commands = libconfig->setting_add(zone_e, "disabled_commands",CONFIG_TYPE_GROUP);
- disabled_commands_count = config_setting_length(commands);
+ disabled_commands_count = libconfig->setting_length(commands);
for(j = 0; j < disabled_commands_count_i; j++) {
int k;
for(k = 0; k < disabled_commands_count; k++) {
- config_setting_t *command = config_setting_get_elem(commands, k);
+ config_setting_t *command = libconfig->setting_get_elem(commands, k);
if( atcommand->exists(config_setting_name(command))->func == izone->disabled_commands[j]->cmd ) {
break;
}
@@ -4887,15 +5095,15 @@ void read_map_zone_db(void) {
}
if( capped_skills_count_i ) {
- if( (caps = config_setting_get_member(zone_e, "skill_damage_cap")) == NULL )
- caps = config_setting_add(zone_e, "skill_damage_cap",CONFIG_TYPE_GROUP);
+ if( (caps = libconfig->setting_get_member(zone_e, "skill_damage_cap")) == NULL )
+ caps = libconfig->setting_add(zone_e, "skill_damage_cap",CONFIG_TYPE_GROUP);
- capped_skills_count = config_setting_length(caps);
+ capped_skills_count = libconfig->setting_length(caps);
for(j = 0; j < capped_skills_count_i; j++) {
int k;
for(k = 0; k < capped_skills_count; k++) {
- config_setting_t *cap = config_setting_get_elem(caps, k);
- if( map_zone_str2skillid(config_setting_name(cap)) == izone->capped_skills[j]->nameid ) {
+ config_setting_t *cap = libconfig->setting_get_elem(caps, k);
+ if( map->zone_str2skillid(config_setting_name(cap)) == izone->capped_skills[j]->nameid ) {
break;
}
}
@@ -4916,13 +5124,57 @@ void read_map_zone_db(void) {
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' zones in '"CL_WHITE"%s"CL_RESET"'.\n", zone_count, config_filename);
/* not supposed to go in here but in skill_final whatever */
- config_destroy(&map_zone_db);
+ libconfig->destroy(&map_zone_db);
+
+ /* post-load processing */
+ if( (zone = strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)) )
+ zone->info.special = 1;
+ if( (zone = strdb_get(map->zone_db, MAP_ZONE_GVG_NAME)) )
+ zone->info.special = 1;
+ if( (zone = strdb_get(map->zone_db, MAP_ZONE_BG_NAME)) )
+ zone->info.special = 1;
+ }
+}
+
+int map_get_new_bonus_id (void) {
+ return map->bonus_id++;
+}
+
+void map_add_questinfo(int m, struct questinfo *qi) {
+ unsigned short i;
+
+ /* duplicate, override */
+ for(i = 0; i < map->list[m].qi_count; i++) {
+ if( map->list[m].qi_data[i].nd == qi->nd )
+ break;
+ }
+
+ if( i == map->list[m].qi_count )
+ RECREATE(map->list[m].qi_data, struct questinfo, ++map->list[m].qi_count);
+
+ memcpy(&map->list[m].qi_data[i], qi, sizeof(struct questinfo));
+}
+
+bool map_remove_questinfo(int m, struct npc_data *nd) {
+ unsigned short i;
+
+ for(i = 0; i < map->list[m].qi_count; i++) {
+ struct questinfo *qi = &map->list[m].qi_data[i];
+ if( qi->nd == nd ) {
+ memset(&map->list[m].qi_data[i], 0, sizeof(struct questinfo));
+ if( i != --map->list[m].qi_count ) {
+ memmove(&map->list[m].qi_data[i],&map->list[m].qi_data[i+1],sizeof(struct questinfo)*(map->list[m].qi_count-i));
+ }
+ return true;
+ }
}
+
+ return false;
}
/**
-* @see DBApply
-*/
+ * @see DBApply
+ */
int map_db_final(DBKey key, DBData *data, va_list ap) {
struct map_data_other_server *mdos = DB->data2ptr(data);
@@ -4933,8 +5185,8 @@ int map_db_final(DBKey key, DBData *data, va_list ap) {
}
/**
-* @see DBApply
-*/
+ * @see DBApply
+ */
int nick_db_final(DBKey key, DBData *data, va_list args)
{
struct charid2nick* p = DB->data2ptr(data);
@@ -4956,127 +5208,139 @@ int cleanup_sub(struct block_list *bl, va_list ap) {
nullpo_ret(bl);
switch(bl->type) {
- case BL_PC:
- iMap->quit((struct map_session_data *) bl);
- break;
- case BL_NPC:
- npc_unload((struct npc_data *)bl,false);
- break;
- case BL_MOB:
- unit_free(bl,CLR_OUTSIGHT);
- break;
- case BL_PET:
- //There is no need for this, the pet is removed together with the player. [Skotlex]
- break;
- case BL_ITEM:
- iMap->clearflooritem(bl);
- break;
- case BL_SKILL:
- skill->delunit((struct skill_unit *) bl);
- break;
+ case BL_PC:
+ map->quit((struct map_session_data *) bl);
+ break;
+ case BL_NPC:
+ npc->unload((struct npc_data *)bl,false);
+ break;
+ case BL_MOB:
+ unit->free(bl,CLR_OUTSIGHT);
+ break;
+ case BL_PET:
+ //There is no need for this, the pet is removed together with the player. [Skotlex]
+ break;
+ case BL_ITEM:
+ map->clearflooritem(bl);
+ break;
+ case BL_SKILL:
+ skill->delunit((struct skill_unit *) bl);
+ break;
}
return 1;
}
/**
-* @see DBApply
-*/
-static int cleanup_db_sub(DBKey key, DBData *data, va_list va)
-{
- return iMap->cleanup_sub(DB->data2ptr(data), va);
+ * @see DBApply
+ */
+int cleanup_db_sub(DBKey key, DBData *data, va_list va) {
+ return map->cleanup_sub(DB->data2ptr(data), va);
}
/*==========================================
-* map destructor
-*------------------------------------------*/
-void do_final(void)
-{
+ * map destructor
+ *------------------------------------------*/
+int do_final(void) {
int i;
struct map_session_data* sd;
struct s_mapiterator* iter;
ShowStatus("Terminating...\n");
+
hChSys.closing = true;
HPM->event(HPET_FINAL);
+
+ if (map->cpsd) aFree(map->cpsd);
//Ladies and babies first.
iter = mapit_getallusers();
for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) )
- iMap->quit(sd);
+ map->quit(sd);
mapit->free(iter);
- instance->final();
-
/* prepares npcs for a faster shutdown process */
- do_clear_npc();
+ npc->do_clear_npc();
// remove all objects on maps
- for (i = 0; i < iMap->map_num; i++) {
- ShowStatus("Cleaning up maps [%d/%d]: %s..."CL_CLL"\r", i+1, iMap->map_num, map[i].name);
- if (map[i].m >= 0)
- map_foreachinmap(iMap->cleanup_sub, i, BL_ALL);
+ for (i = 0; i < map->count; i++) {
+ ShowStatus("Cleaning up maps [%d/%d]: %s..."CL_CLL"\r", i+1, map->count, map->list[i].name);
+ if (map->list[i].m >= 0)
+ map->foreachinmap(map->cleanup_sub, i, BL_ALL);
}
- ShowStatus("Cleaned up %d maps."CL_CLL"\n", iMap->map_num);
+ ShowStatus("Cleaned up %d maps."CL_CLL"\n", map->count);
- id_db->foreach(id_db,cleanup_db_sub);
- chrif_char_reset_offline();
- chrif_flush_fifo();
+ map->id_db->foreach(map->id_db,map->cleanup_db_sub);
+ chrif->char_reset_offline();
+ chrif->flush();
atcommand->final();
battle->final();
- do_final_chrif();
+ chrif->final();
ircbot->final();/* before clif. */
clif->final();
- do_final_npc();
+ npc->final();
+ quest->final();
script->final();
- do_final_itemdb();
- do_final_storage();
+ itemdb->final();
+ instance->final();
+ gstorage->final();
guild->final();
- party->do_final_party();
- pc->do_final_pc();
- do_final_pet();
- do_final_mob();
+ party->final();
+ pc->final();
+ pet->final();
+ mob->final();
homun->final();
atcommand->final_msg();
skill->final();
- do_final_status();
- do_final_unit();
- do_final_battleground();
- do_final_duel();
- do_final_elemental();
- do_final_maps();
+ status->final();
+ unit->final();
+ bg->final();
+ duel->final();
+ elemental->final();
+ map->list_final();
vending->final();
- map_db->destroy(map_db, map_db_final);
+ HPM_map_do_final();
+
+ map->map_db->destroy(map->map_db, map->db_final);
- mapindex_final();
- if(enable_grf)
+ mapindex->final();
+ if(map->enable_grf)
grfio_final();
- id_db->destroy(id_db, NULL);
- pc_db->destroy(pc_db, NULL);
- mobid_db->destroy(mobid_db, NULL);
- bossid_db->destroy(bossid_db, NULL);
- nick_db->destroy(nick_db, nick_db_final);
- charid_db->destroy(charid_db, NULL);
- iwall_db->destroy(iwall_db, NULL);
- regen_db->destroy(regen_db, NULL);
-
- map_sql_close();
- ers_destroy(map_iterator_ers);
-
- aFree(map);
-
- if( !enable_grf )
- aFree(map_cache_buffer);
-
+ db_destroy(map->id_db);
+ db_destroy(map->pc_db);
+ db_destroy(map->mobid_db);
+ db_destroy(map->bossid_db);
+ map->nick_db->destroy(map->nick_db, map->nick_db_final);
+ db_destroy(map->charid_db);
+ db_destroy(map->iwall_db);
+ db_destroy(map->regen_db);
+
+ map->sql_close();
+ ers_destroy(map->iterator_ers);
+ ers_destroy(map->flooritem_ers);
+
+ aFree(map->list);
+
+ if( map->block_free )
+ aFree(map->block_free);
+ if( map->bl_list )
+ aFree(map->bl_list);
+
+
+ if( !map->enable_grf )
+ aFree(map->cache_buffer);
+
+ HPM->event(HPET_POST_FINAL);
+
ShowStatus("Finished.\n");
+ return map->retval;
}
-static int map_abort_sub(struct map_session_data* sd, va_list ap)
-{
- chrif_save(sd,1);
+int map_abort_sub(struct map_session_data* sd, va_list ap) {
+ chrif->save(sd,1);
return 1;
}
@@ -5094,47 +5358,49 @@ void do_abort(void)
return;
}
run = 1;
- if (!chrif_isconnected())
+ if (!chrif->isconnected())
{
- if (pc_db->size(pc_db))
- ShowFatalError("Server has crashed without a connection to the char-server, %u characters can't be saved!\n", pc_db->size(pc_db));
+ if (db_size(map->pc_db))
+ ShowFatalError("Server has crashed without a connection to the char-server, %u characters can't be saved!\n", db_size(map->pc_db));
return;
}
ShowError("Server received crash signal! Attempting to save all online characters!\n");
- iMap->map_foreachpc(map_abort_sub);
- chrif_flush_fifo();
+ map->foreachpc(map->abort_sub);
+ chrif->flush();
}
/*======================================================
* Map-Server Version Screen [MC Cameri]
*------------------------------------------------------*/
-static void map_helpscreen(bool do_exit)
+void map_helpscreen(bool do_exit)
{
ShowInfo("Usage: %s [options]\n", SERVER_NAME);
ShowInfo("\n");
ShowInfo("Options:\n");
- ShowInfo(" -?, -h [--help]\t\tDisplays this help screen.\n");
- ShowInfo(" -v [--version]\t\tDisplays the server's version.\n");
- ShowInfo(" --run-once\t\t\tCloses server after loading (testing).\n");
- ShowInfo(" --map-config <file>\t\tAlternative map-server configuration.\n");
- ShowInfo(" --battle-config <file>\tAlternative battle configuration.\n");
- ShowInfo(" --atcommand-config <file>\tAlternative atcommand configuration.\n");
- ShowInfo(" --script-config <file>\tAlternative script configuration.\n");
- ShowInfo(" --msg-config <file>\t\tAlternative message configuration.\n");
- ShowInfo(" --grf-path <file>\t\tAlternative GRF path configuration.\n");
- ShowInfo(" --inter-config <file>\t\tAlternative inter-server configuration.\n");
- ShowInfo(" --log-config <file>\t\tAlternative logging configuration.\n");
+ ShowInfo(" -?, -h [--help] Displays this help screen.\n");
+ ShowInfo(" -v [--version] Displays the server's version.\n");
+ ShowInfo(" --run-once Closes server after loading (testing).\n");
+ ShowInfo(" --map-config <file> Alternative map-server configuration.\n");
+ ShowInfo(" --battle-config <file> Alternative battle configuration.\n");
+ ShowInfo(" --atcommand-config <file> Alternative atcommand configuration.\n");
+ ShowInfo(" --script-config <file> Alternative script configuration.\n");
+ ShowInfo(" --msg-config <file> Alternative message configuration.\n");
+ ShowInfo(" --grf-path <file> Alternative GRF path configuration.\n");
+ ShowInfo(" --inter-config <file> Alternative inter-server configuration.\n");
+ ShowInfo(" --log-config <file> Alternative logging configuration.\n");
+ ShowInfo(" --script-check Doesn't run the server, only tests the\n");
+ ShowInfo(" scripts passed through --load-script.\n");
+ ShowInfo(" --load-script <file> Loads an additional script (can be repeated).\n");
+ ShowInfo(" --load-plugin <name> Loads an additional plugin (can be repeated).\n");
+ HPM->arg_help();/* display help for commands implemented thru HPM */
if( do_exit )
exit(EXIT_SUCCESS);
}
/*======================================================
-* Map-Server Version Screen [MC Cameri]
-*------------------------------------------------------*/
-static void map_versionscreen(bool do_exit) {
- const char *svn = get_svn_revision();
- const char *git = get_git_hash();
- ShowInfo(CL_WHITE"Hercules version: %s" CL_RESET"\n", git[0] != HERC_UNKNOWN_VER ? git : svn[0] != HERC_UNKNOWN_VER ? svn : "Unknown");
+ * Map-Server Version Screen [MC Cameri]
+ *------------------------------------------------------*/
+void map_versionscreen(bool do_exit) {
ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://hercules.ws/\n");
ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rizon.net/#Hercules\n");
ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n");
@@ -5162,20 +5428,21 @@ void do_shutdown(void)
mapit->free(iter);
flush_fifos();
}
- chrif_check_shutdown();
+ chrif->check_shutdown();
}
}
-static bool map_arg_next_value(const char* option, int i, int argc)
+bool map_arg_next_value(const char* option, int i, int argc, bool must)
{
if( i >= argc-1 ) {
- ShowWarning("Missing value for option '%s'.\n", option);
+ if( must )
+ ShowWarning("Missing value for option '%s'.\n", option);
return false;
}
return true;
}
-struct map_session_data cpsd;
+
CPCMD(gm_position) {
int x = 0, y = 0, m = 0;
char map_name[25];
@@ -5185,20 +5452,20 @@ CPCMD(gm_position) {
return;
}
- if ( (m = iMap->mapname2mapid(map_name) <= 0 ) ) {
+ if ( (m = map->mapname2mapid(map_name) <= 0 ) ) {
ShowError("gm:info '"CL_WHITE"%s"CL_RESET"' is not a known map\n",map_name);
return;
}
- if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) {
+ if( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) {
ShowError("gm:info '"CL_WHITE"%d %d"CL_RESET"' is out of '"CL_WHITE"%s"CL_RESET"' map bounds!\n",x,y,map_name);
return;
}
ShowInfo("HCP: updated console's game position to '"CL_WHITE"%d %d %s"CL_RESET"'\n",x,y,map_name);
- cpsd.bl.x = x;
- cpsd.bl.y = y;
- cpsd.bl.m = m;
+ map->cpsd->bl.x = x;
+ map->cpsd->bl.y = y;
+ map->cpsd->bl.m = m;
}
CPCMD(gm_use) {
@@ -5206,25 +5473,29 @@ CPCMD(gm_use) {
ShowError("gm:use invalid syntax. use '"CL_WHITE"gm:use @command <optional params>"CL_RESET"'\n");
return;
}
- cpsd.fd = -2;
- if( !atcommand->parse(cpsd.fd, &cpsd, line, 0) )
+
+ map->cpsd_active = true;
+
+ if( !atcommand->exec(map->cpsd->fd, map->cpsd, line, false) )
ShowInfo("HCP: '"CL_WHITE"%s"CL_RESET"' failed\n",line);
else
ShowInfo("HCP: '"CL_WHITE"%s"CL_RESET"' was used\n",line);
- cpsd.fd = 0;
-
+
+ map->cpsd_active = false;
}
/* Hercules Console Parser */
void map_cp_defaults(void) {
+#ifdef CONSOLE_INPUT
/* default HCP data */
- memset(&cpsd, 0, sizeof(struct map_session_data));
- strcpy(cpsd.status.name, "Hercules Console");
- cpsd.bl.x = 150;
- cpsd.bl.y = 150;
- cpsd.bl.m = iMap->mapname2mapid("prontera");
-
- console->addCommand("gm:info",CPCMD_A(gm_position));
- console->addCommand("gm:use",CPCMD_A(gm_use));
+ map->cpsd = pc->get_dummy_sd();
+ strcpy(map->cpsd->status.name, "Hercules Console");
+ map->cpsd->bl.x = MAP_DEFAULT_X;
+ map->cpsd->bl.y = MAP_DEFAULT_Y;
+ map->cpsd->bl.m = map->mapname2mapid(MAP_DEFAULT);
+
+ console->input->addCommand("gm:info",CPCMD_A(gm_position));
+ console->input->addCommand("gm:use",CPCMD_A(gm_use));
+#endif
}
/* Hercules Plugin Mananger */
void map_hp_symbols(void) {
@@ -5234,38 +5505,64 @@ void map_hp_symbols(void) {
HPM->share(bg,"battlegrounds");
HPM->share(buyingstore,"buyingstore");
HPM->share(clif,"clif");
+ HPM->share(chrif,"chrif");
HPM->share(guild,"guild");
+ HPM->share(gstorage,"gstorage");
HPM->share(homun,"homun");
+ HPM->share(map,"map");
HPM->share(ircbot,"ircbot");
HPM->share(itemdb,"itemdb");
HPM->share(logs,"logs");
HPM->share(mail,"mail");
+ HPM->share(instance,"instance");
HPM->share(script,"script");
HPM->share(searchstore,"searchstore");
HPM->share(skill,"skill");
HPM->share(vending,"vending");
HPM->share(pc,"pc");
+ HPM->share(pcg,"pc_groups");
HPM->share(party,"party");
+ HPM->share(storage,"storage");
HPM->share(trade,"trade");
- HPM->share(iMap,"iMap");
- /* partial */
+ HPM->share(status,"status");
+ HPM->share(chat, "chat");
+ HPM->share(duel,"duel");
+ HPM->share(elemental,"elemental");
+ HPM->share(intif,"intif");
+ HPM->share(mercenary,"mercenary");
+ HPM->share(mob,"mob");
+ HPM->share(unit,"unit");
+ HPM->share(npc,"npc");
+ HPM->share(mapreg,"mapreg");
+ HPM->share(pet,"pet");
+ HPM->share(path,"path");
+ HPM->share(quest,"quest");
+#ifdef PCRE_SUPPORT
+ HPM->share(npc_chat,"npc_chat");
+ HPM->share(libpcre,"libpcre");
+#endif
HPM->share(mapit,"mapit");
+ HPM->share(mapindex,"mapindex");
/* sql link */
- HPM->share(mmysql_handle,"sql_handle");
+ HPM->share(map->mysql_handle,"sql_handle");
/* specific */
HPM->share(atcommand->create,"addCommand");
HPM->share(script->addScript,"addScript");
- /* vars */
- HPM->share(map,"map");
+ HPM->share(HPM_map_add_group_permission,"addGroupPermission");
}
-void load_defaults(void) {
+void map_load_defaults(void) {
+ mapindex_defaults();
+ map_defaults();
+ /* */
atcommand_defaults();
battle_defaults();
battleground_defaults();
buyingstore_defaults();
clif_defaults();
+ chrif_defaults();
guild_defaults();
+ gstorage_defaults();
homunculus_defaults();
instance_defaults();
ircbot_defaults();
@@ -5278,221 +5575,288 @@ void load_defaults(void) {
skill_defaults();
vending_defaults();
pc_defaults();
+ pc_groups_defaults();
party_defaults();
+ storage_defaults();
trade_defaults();
+ status_defaults();
+ chat_defaults();
+ duel_defaults();
+ elemental_defaults();
+ intif_defaults();
+ mercenary_defaults();
+ mob_defaults();
+ unit_defaults();
+ mapreg_defaults();
+ pet_defaults();
+ path_defaults();
+ quest_defaults();
+#ifdef PCRE_SUPPORT
+ npc_chat_defaults();
+#endif
}
int do_init(int argc, char *argv[])
{
- int i;
+ bool minimal = false;
+ bool scriptcheck = false;
+ int i, load_extras_count = 0;
+ char **load_extras = NULL;
#ifdef GCOLLECT
GC_enable_incremental();
#endif
+
+ map_load_defaults();
- map_defaults();
-
- iMap->map_num = 0;
-
- sprintf(iMap->db_path ,"db");
- sprintf(iMap->help_txt ,"conf/help.txt");
- sprintf(iMap->help2_txt ,"conf/help2.txt");
- sprintf(iMap->charhelp_txt ,"conf/charhelp.txt");
-
- sprintf(iMap->wisp_server_name ,"Server"); // can be modified in char-server configuration file
-
- iMap->autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
- iMap->minsave_interval = 100;
- iMap->save_settings = 0xFFFF;
- iMap->agit_flag = 0;
- iMap->agit2_flag = 0;
- iMap->night_flag = 0; // 0=day, 1=night [Yor]
- iMap->enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex]
-
- iMap->db_use_sqldbs = 0;
-
- sprintf(iMap->item_db_db, "item_db");
- sprintf(iMap->item_db2_db, "item_db2");
- sprintf(iMap->item_db_re_db, "item_db_re");
- sprintf(iMap->mob_db_db, "mob_db");
- sprintf(iMap->mob_db2_db, "mob_db2");
- sprintf(iMap->mob_skill_db_db, "mob_skill_db");
- sprintf(iMap->mob_skill_db2_db, "mob_skill_db2");
- sprintf(iMap->interreg_db, "interreg");
-
- iMap->INTER_CONF_NAME="conf/inter-server.conf";
- iMap->LOG_CONF_NAME="conf/logs.conf";
- iMap->MAP_CONF_NAME = "conf/map-server.conf";
- iMap->BATTLE_CONF_FILENAME = "conf/battle.conf";
- iMap->ATCOMMAND_CONF_FILENAME = "conf/atcommand.conf";
- iMap->SCRIPT_CONF_NAME = "conf/script.conf";
- iMap->MSG_CONF_NAME = "conf/messages.conf";
- iMap->GRF_PATH_FILENAME = "conf/grf-files.txt";
- rnd_init();
-
+ HPM_map_do_init();
+ HPM->DataCheck = HPM_map_DataCheck;
+ HPM->load_sub = HPM_map_plugin_load_sub;
+ HPM->symbol_defaults_sub = map_hp_symbols;
+ HPM->grabHPDataSub = HPM_map_grabHPData;
+ for( i = 1; i < argc; i++ ) {
+ const char* arg = argv[i];
+ if( strcmp(arg, "--load-plugin") == 0 ) {
+ if( map->arg_next_value(arg, i, argc, true) ) {
+ RECREATE(load_extras, char *, ++load_extras_count);
+ load_extras[load_extras_count-1] = argv[++i];
+ }
+ }
+ }
+ HPM->config_read((const char * const *)load_extras, load_extras_count);
+ if (load_extras) {
+ aFree(load_extras);
+ load_extras = NULL;
+ load_extras_count = 0;
+ }
+
+ HPM->event(HPET_PRE_INIT);
+
for( i = 1; i < argc ; i++ ) {
const char* arg = argv[i];
if( arg[0] != '-' && ( arg[0] != '/' || arg[1] == '-' ) ) {// -, -- and /
ShowError("Unknown option '%s'.\n", argv[i]);
exit(EXIT_FAILURE);
+ } else if ( HPM->parse_arg(arg,&i,argv,map->arg_next_value(arg, i, argc, false)) ) {
+ continue; /* HPM Triggered */
} else if( (++arg)[0] == '-' ) {// long option
arg++;
if( strcmp(arg, "help") == 0 ) {
- map_helpscreen(true);
+ map->helpscreen(true);
} else if( strcmp(arg, "version") == 0 ) {
- map_versionscreen(true);
+ map->versionscreen(true);
} else if( strcmp(arg, "map-config") == 0 ) {
- if( map_arg_next_value(arg, i, argc) )
- iMap->MAP_CONF_NAME = argv[++i];
+ if( map->arg_next_value(arg, i, argc, true) )
+ map->MAP_CONF_NAME = argv[++i];
} else if( strcmp(arg, "battle-config") == 0 ) {
- if( map_arg_next_value(arg, i, argc) )
- iMap->BATTLE_CONF_FILENAME = argv[++i];
+ if( map->arg_next_value(arg, i, argc, true) )
+ map->BATTLE_CONF_FILENAME = argv[++i];
} else if( strcmp(arg, "atcommand-config") == 0 ) {
- if( map_arg_next_value(arg, i, argc) )
- iMap->ATCOMMAND_CONF_FILENAME = argv[++i];
+ if( map->arg_next_value(arg, i, argc, true) )
+ map->ATCOMMAND_CONF_FILENAME = argv[++i];
} else if( strcmp(arg, "script-config") == 0 ) {
- if( map_arg_next_value(arg, i, argc) )
- iMap->SCRIPT_CONF_NAME = argv[++i];
+ if( map->arg_next_value(arg, i, argc, true) )
+ map->SCRIPT_CONF_NAME = argv[++i];
} else if( strcmp(arg, "msg-config") == 0 ) {
- if( map_arg_next_value(arg, i, argc) )
- iMap->MSG_CONF_NAME = argv[++i];
+ if( map->arg_next_value(arg, i, argc, true) )
+ map->MSG_CONF_NAME = argv[++i];
} else if( strcmp(arg, "grf-path-file") == 0 ) {
- if( map_arg_next_value(arg, i, argc) )
- iMap->GRF_PATH_FILENAME = argv[++i];
+ if( map->arg_next_value(arg, i, argc, true) )
+ map->GRF_PATH_FILENAME = argv[++i];
} else if( strcmp(arg, "inter-config") == 0 ) {
- if( map_arg_next_value(arg, i, argc) )
- iMap->INTER_CONF_NAME = argv[++i];
+ if( map->arg_next_value(arg, i, argc, true) )
+ map->INTER_CONF_NAME = argv[++i];
} else if( strcmp(arg, "log-config") == 0 ) {
- if( map_arg_next_value(arg, i, argc) )
- iMap->LOG_CONF_NAME = argv[++i];
+ if( map->arg_next_value(arg, i, argc, true) )
+ map->LOG_CONF_NAME = argv[++i];
} else if( strcmp(arg, "run-once") == 0 ) { // close the map-server as soon as its done.. for testing [Celest]
runflag = CORE_ST_STOP;
+ } else if( strcmp(arg, "script-check") == 0 ) {
+ map->minimal = true;
+ runflag = CORE_ST_STOP;
+ scriptcheck = true;
+ } else if( strcmp(arg, "load-plugin") == 0 ) {
+ if( map->arg_next_value(arg, i, argc, true) )
+ i++;
+ } else if( strcmp(arg, "load-script") == 0 ) {
+ if( map->arg_next_value(arg, i, argc, true) ) {
+ RECREATE(load_extras, char *, ++load_extras_count);
+ load_extras[load_extras_count-1] = argv[++i];
+ }
} else {
ShowError("Unknown option '%s'.\n", argv[i]);
exit(EXIT_FAILURE);
}
- } else switch( arg[0] ) {// short option
- case '?':
- case 'h':
- map_helpscreen(true);
- break;
- case 'v':
- map_versionscreen(true);
- break;
- default:
- ShowError("Unknown option '%s'.\n", argv[i]);
- exit(EXIT_FAILURE);
+ } else {
+ switch( arg[0] ) {// short option
+ case '?':
+ case 'h':
+ map->helpscreen(true);
+ break;
+ case 'v':
+ map->versionscreen(true);
+ break;
+ default:
+ ShowError("Unknown option '%s'.\n", argv[i]);
+ exit(EXIT_FAILURE);
+ }
}
}
- memset(&index2mapid, -1, sizeof(index2mapid));
+ minimal = map->minimal;/* temp (perhaps make minimal a mask with options of what to load? e.g. plugin 1 does minimal |= mob_db; */
+ if (!minimal) {
+ map->config_read(map->MAP_CONF_NAME);
+ CREATE(map->list,struct map_data,map->count);
+ map->count = 0;
+ map->config_read_sub(map->MAP_CONF_NAME);
- load_defaults();
- map_config_read(iMap->MAP_CONF_NAME);
- CREATE(map,struct map_data,iMap->map_num);
- iMap->map_num = 0;
- map_config_read_sub(iMap->MAP_CONF_NAME);
- // loads npcs
- iMap->reloadnpc(false);
+ // loads npcs
+ map->reloadnpc(false, (const char * const *)load_extras, load_extras_count);
- chrif_checkdefaultlogin();
+ chrif->checkdefaultlogin();
- if (!map_ip_set || !char_ip_set) {
- char ip_str[16];
- ip2str(addr_[0], ip_str);
+ if (!map->ip_set || !map->char_ip_set) {
+ char ip_str[16];
+ ip2str(sockt->addr_[0], ip_str);
- ShowWarning("Not all IP addresses in /conf/map-server.conf configured, autodetecting...\n");
+ ShowWarning("Not all IP addresses in /conf/map-server.conf configured, auto-detecting...\n");
- if (naddr_ == 0)
- ShowError("Unable to determine your IP address...\n");
- else if (naddr_ > 1)
- ShowNotice("Multiple interfaces detected...\n");
+ if (sockt->naddr_ == 0)
+ ShowError("Unable to determine your IP address...\n");
+ else if (sockt->naddr_ > 1)
+ ShowNotice("Multiple interfaces detected...\n");
- ShowInfo("Defaulting to %s as our IP address\n", ip_str);
+ ShowInfo("Defaulting to %s as our IP address\n", ip_str);
- if (!map_ip_set)
- clif->setip(ip_str);
- if (!char_ip_set)
- chrif_setip(ip_str);
- }
+ if (!map->ip_set)
+ clif->setip(ip_str);
+ if (!map->char_ip_set)
+ chrif->setip(ip_str);
+ }
- battle->config_read(iMap->BATTLE_CONF_FILENAME);
- atcommand->msg_read(iMap->MSG_CONF_NAME);
- script_config_read(iMap->SCRIPT_CONF_NAME);
- inter_config_read(iMap->INTER_CONF_NAME);
- logs->config_read(iMap->LOG_CONF_NAME);
+ battle->config_read(map->BATTLE_CONF_FILENAME);
+ atcommand->msg_read(map->MSG_CONF_NAME, false);
+ map->inter_config_read(map->INTER_CONF_NAME);
+ logs->config_read(map->LOG_CONF_NAME);
+ }
+ script->config_read(map->SCRIPT_CONF_NAME);
- id_db = idb_alloc(DB_OPT_BASE);
- pc_db = idb_alloc(DB_OPT_BASE); //Added for reliable iMap->id2sd() use. [Skotlex]
- mobid_db = idb_alloc(DB_OPT_BASE); //Added to lower the load of the lazy mob ai. [Skotlex]
- bossid_db = idb_alloc(DB_OPT_BASE); // Used for Convex Mirror quick MVP search
- map_db = uidb_alloc(DB_OPT_BASE);
- nick_db = idb_alloc(DB_OPT_BASE);
- charid_db = idb_alloc(DB_OPT_BASE);
- regen_db = idb_alloc(DB_OPT_BASE); // efficient status_natural_heal processing
+ map->id_db = idb_alloc(DB_OPT_BASE);
+ map->pc_db = idb_alloc(DB_OPT_BASE); //Added for reliable map->id2sd() use. [Skotlex]
+ map->mobid_db = idb_alloc(DB_OPT_BASE); //Added to lower the load of the lazy mob AI. [Skotlex]
+ map->bossid_db = idb_alloc(DB_OPT_BASE); // Used for Convex Mirror quick MVP search
+ map->map_db = uidb_alloc(DB_OPT_BASE);
+ map->nick_db = idb_alloc(DB_OPT_BASE);
+ map->charid_db = idb_alloc(DB_OPT_BASE);
+ map->regen_db = idb_alloc(DB_OPT_BASE); // efficient status_natural_heal processing
+ map->iwall_db = strdb_alloc(DB_OPT_RELEASE_DATA,2*NAME_LENGTH+2+1); // [Zephyrus] Invisible Walls
+ map->zone_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, MAP_ZONE_NAME_LENGTH);
- iwall_db = strdb_alloc(DB_OPT_RELEASE_DATA,2*NAME_LENGTH+2+1); // [Zephyrus] Invisible Walls
- zone_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, MAP_ZONE_NAME_LENGTH);
+ map->iterator_ers = ers_new(sizeof(struct s_mapiterator),"map.c::map_iterator_ers",ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
+ ers_chunk_size(map->iterator_ers, 25);
- map_iterator_ers = ers_new(sizeof(struct s_mapiterator),"map.c::map_iterator_ers",ERS_OPT_NONE);
+ map->flooritem_ers = ers_new(sizeof(struct flooritem_data),"map.c::map_flooritem_ers",ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
+ ers_chunk_size(map->flooritem_ers, 100);
- map_sql_init();
- if (logs->config.sql_logs)
- log_sql_init();
+ if (!minimal) {
+ map->sql_init();
+ if (logs->config.sql_logs)
+ logs->sql_init();
+ }
- mapindex_init();
- if(enable_grf)
- grfio_init(iMap->GRF_PATH_FILENAME);
+ i = mapindex->init();
- map_readallmaps();
+ if (minimal) {
+ // Pretend all maps from the mapindex are on this mapserver
+ CREATE(map->list,struct map_data,i);
- iTimer->add_timer_func_list(map_freeblock_timer, "map_freeblock_timer");
- iTimer->add_timer_func_list(map_clearflooritem_timer, "map_clearflooritem_timer");
- iTimer->add_timer_func_list(map_removemobs_timer, "map_removemobs_timer");
- iTimer->add_timer_interval(iTimer->gettick()+1000, map_freeblock_timer, 0, 0, 60*1000);
+ for( i = 0; i < MAX_MAPINDEX; i++ ) {
+ if (mapindex_exists(i)) {
+ map->addmap(mapindex_id2name(i));
+ }
+ }
+ }
- HPM->symbol_defaults_sub = map_hp_symbols;
- HPM->config_read();
- HPM->event(HPET_INIT);
-
- atcommand->init();
- battle->init();
- instance->init();
- do_init_chrif();
- clif->init();
- ircbot->init();
- script->init();
- do_init_itemdb();
- skill->init();
- read_map_zone_db();/* read after item and skill initalization */
- do_init_mob();
- pc->do_init_pc();
- do_init_status();
- party->do_init_party();
- guild->init();
- do_init_storage();
- do_init_pet();
- homun->init();
- do_init_mercenary();
- do_init_elemental();
- do_init_quest();
- do_init_npc();
- do_init_unit();
- do_init_battleground();
- do_init_duel();
- vending->init();
-
- npc_event_do_oninit(); // Init npcs (OnInit)
+ if(map->enable_grf)
+ grfio_init(map->GRF_PATH_FILENAME);
+
+ map->readallmaps();
+
+
+ if (!minimal) {
+ timer->add_func_list(map->freeblock_timer, "map_freeblock_timer");
+ timer->add_func_list(map->clearflooritem_timer, "map_clearflooritem_timer");
+ timer->add_func_list(map->removemobs_timer, "map_removemobs_timer");
+ timer->add_interval(timer->gettick()+1000, map->freeblock_timer, 0, 0, 60*1000);
+
+ HPM->event(HPET_INIT);
+ }
+
+ atcommand->init(minimal);
+ battle->init(minimal);
+ instance->init(minimal);
+ chrif->init(minimal);
+ clif->init(minimal);
+ ircbot->init(minimal);
+ script->init(minimal);
+ itemdb->init(minimal);
+ skill->init(minimal);
+ if (!minimal)
+ map->read_zone_db();/* read after item and skill initialization */
+ mob->init(minimal);
+ pc->init(minimal);
+ status->init(minimal);
+ party->init(minimal);
+ guild->init(minimal);
+ gstorage->init(minimal);
+ pet->init(minimal);
+ homun->init(minimal);
+ mercenary->init(minimal);
+ elemental->init(minimal);
+ quest->init(minimal);
+ npc->init(minimal);
+ unit->init(minimal);
+ bg->init(minimal);
+ duel->init(minimal);
+ vending->init(minimal);
+
+ if (scriptcheck) {
+ bool failed = load_extras_count > 0 ? false : true;
+ for (i = 0; i < load_extras_count; i++) {
+ if (npc->parsesrcfile(load_extras[i], false) != EXIT_SUCCESS)
+ failed = true;
+ }
+ if (failed)
+ exit(EXIT_FAILURE);
+ exit(EXIT_SUCCESS);
+ }
+ if (load_extras) {
+ aFree(load_extras);
+ load_extras = NULL;
+ //load_extras_count = 0; // Dead store. Uncomment if needed again.
+ }
+ if( minimal ) {
+ HPM->event(HPET_READY);
+ exit(EXIT_SUCCESS);
+ }
+
+ npc->event_do_oninit( false ); // Init npcs (OnInit)
+ npc->market_fromsql(); /* after OnInit */
+
if (battle_config.pk_mode)
ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n");
- Sql_HerculesUpdateCheck(mmysql_handle);
-
- ShowStatus("Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map_port);
+ Sql_HerculesUpdateCheck(map->mysql_handle);
+
+#ifdef CONSOLE_INPUT
+ console->input->setSQL(map->mysql_handle);
+#endif
+
+ ShowStatus("Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map->port);
if( runflag != CORE_ST_STOP ) {
- shutdown_callback = iMap->do_shutdown;
+ shutdown_callback = map->do_shutdown;
runflag = MAPSERVER_ST_RUNNING;
}
@@ -5504,121 +5868,284 @@ int do_init(int argc, char *argv[])
}
/*=====================================
-* Default Functions : map.h
+* Default Functions : map.h
* Generated by HerculesInterfaceMaker
* created by Susu
*-------------------------------------*/
void map_defaults(void) {
- iMap = &iMap_s;
+ map = &map_s;
+ /* */
+ map->minimal = false;
+ map->count = 0;
+ map->retval = EXIT_SUCCESS;
+
+ sprintf(map->db_path ,"db");
+ sprintf(map->help_txt ,"conf/help.txt");
+ sprintf(map->help2_txt ,"conf/help2.txt");
+ sprintf(map->charhelp_txt ,"conf/charhelp.txt");
+
+ sprintf(map->wisp_server_name ,"Server"); // can be modified in char-server configuration file
+
+ map->autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
+ map->minsave_interval = 100;
+ map->save_settings = 0xFFFF;
+ map->agit_flag = 0;
+ map->agit2_flag = 0;
+ map->night_flag = 0; // 0=day, 1=night [Yor]
+ map->enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex]
+
+ map->db_use_sql_item_db = 0;
+ map->db_use_sql_mob_db = 0;
+ map->db_use_sql_mob_skill_db = 0;
+
+ sprintf(map->item_db_db, "item_db");
+ sprintf(map->item_db2_db, "item_db2");
+ sprintf(map->item_db_re_db, "item_db_re");
+ sprintf(map->mob_db_db, "mob_db");
+ sprintf(map->mob_db2_db, "mob_db2");
+ sprintf(map->mob_skill_db_db, "mob_skill_db");
+ sprintf(map->mob_skill_db2_db, "mob_skill_db2");
+ sprintf(map->interreg_db, "interreg");
+
+ map->INTER_CONF_NAME="conf/inter-server.conf";
+ map->LOG_CONF_NAME="conf/logs.conf";
+ map->MAP_CONF_NAME = "conf/map-server.conf";
+ map->BATTLE_CONF_FILENAME = "conf/battle.conf";
+ map->ATCOMMAND_CONF_FILENAME = "conf/atcommand.conf";
+ map->SCRIPT_CONF_NAME = "conf/script.conf";
+ map->MSG_CONF_NAME = "conf/messages.conf";
+ map->GRF_PATH_FILENAME = "conf/grf-files.txt";
+
+ map->default_codepage[0] = '\0';
+ map->server_port = 3306;
+ sprintf(map->server_ip,"127.0.0.1");
+ sprintf(map->server_id,"ragnarok");
+ sprintf(map->server_pw,"ragnarok");
+ sprintf(map->server_db,"ragnarok");
+ map->mysql_handle = NULL;
+
+ map->cpsd_active = false;
+
+ map->port = 0;
+ map->users = 0;
+ map->ip_set = 0;
+ map->char_ip_set = 0;
+ map->enable_grf = 0;
+
+ memset(&map->index2mapid, -1, sizeof(map->index2mapid));
+
+ map->id_db = NULL;
+ map->pc_db = NULL;
+ map->mobid_db = NULL;
+ map->bossid_db = NULL;
+ map->map_db = NULL;
+ map->nick_db = NULL;
+ map->charid_db = NULL;
+ map->regen_db = NULL;
+ map->zone_db = NULL;
+ map->iwall_db = NULL;
+
+ map->block_free = NULL;
+ map->block_free_count = 0;
+ map->block_free_lock = 0;
+ map->block_free_list_size = 0;
+ map->bl_list = NULL;
+ map->bl_list_count = 0;
+ map->bl_list_size = 0;
+
+ //all in a big chunk, respects order
+ memset(&map->bl_head,0,sizeof(map->bl_head)
+ + sizeof(map->zone_all)
+ + sizeof(map->zone_pk)
+ );
+
+ map->cpsd = NULL;
+ map->list = NULL;
+
+ map->iterator_ers = NULL;
+ map->cache_buffer = NULL;
+
+ map->flooritem_ers = NULL;
+ /* */
+ map->bonus_id = SP_LAST_KNOWN;
/* funcs */
- iMap->zone_init = map_zone_init;
- iMap->zone_remove = map_zone_remove;
- iMap->zone_apply = map_zone_apply;
- iMap->zone_change = map_zone_change;
- iMap->zone_change2 = map_zone_change2;
+ map->zone_init = map_zone_init;
+ map->zone_remove = map_zone_remove;
+ map->zone_apply = map_zone_apply;
+ map->zone_change = map_zone_change;
+ map->zone_change2 = map_zone_change2;
- iMap->getcell = map_getcell;
- iMap->setgatcell = map_setgatcell;
+ map->getcell = map_getcell;
+ map->setgatcell = map_setgatcell;
- iMap->cellfromcache = map_cellfromcache;
+ map->cellfromcache = map_cellfromcache;
// users
- iMap->setusers = map_setusers;
- iMap->getusers = map_getusers;
- iMap->usercount = map_usercount;
+ map->setusers = map_setusers;
+ map->getusers = map_getusers;
+ map->usercount = map_usercount;
// blocklist lock
- iMap->freeblock = map_freeblock;
- iMap->freeblock_lock = map_freeblock_lock;
- iMap->freeblock_unlock = map_freeblock_unlock;
+ map->freeblock = map_freeblock;
+ map->freeblock_lock = map_freeblock_lock;
+ map->freeblock_unlock = map_freeblock_unlock;
// blocklist manipulation
- iMap->addblock = map_addblock;
- iMap->delblock = map_delblock;
- iMap->moveblock = map_moveblock;
+ map->addblock = map_addblock;
+ map->delblock = map_delblock;
+ map->moveblock = map_moveblock;
//blocklist nb in one cell
- iMap->count_oncell = map_count_oncell;
- iMap->find_skill_unit_oncell = map_find_skill_unit_oncell;
+ map->count_oncell = map_count_oncell;
+ map->find_skill_unit_oncell = map_find_skill_unit_oncell;
// search and creation
- iMap->get_new_object_id = map_get_new_object_id;
- iMap->search_freecell = map_search_freecell;
+ map->get_new_object_id = map_get_new_object_id;
+ map->search_freecell = map_search_freecell;
//
- iMap->quit = map_quit;
+ map->quit = map_quit;
// npc
- iMap->addnpc = map_addnpc;
+ map->addnpc = map_addnpc;
// map item
- iMap->clearflooritem_timer = map_clearflooritem_timer;
- iMap->removemobs_timer = map_removemobs_timer;
- iMap->clearflooritem = map_clearflooritem;
- iMap->addflooritem = map_addflooritem;
+ map->clearflooritem_timer = map_clearflooritem_timer;
+ map->removemobs_timer = map_removemobs_timer;
+ map->clearflooritem = map_clearflooritem;
+ map->addflooritem = map_addflooritem;
// player to map session
- iMap->addnickdb = map_addnickdb;
- iMap->delnickdb = map_delnickdb;
- iMap->reqnickdb = map_reqnickdb;
- iMap->charid2nick = map_charid2nick;
- iMap->charid2sd = map_charid2sd;
-
- iMap->id2sd = map_id2sd;
- iMap->id2md = map_id2md;
- iMap->id2nd = map_id2nd;
- iMap->id2hd = map_id2hd;
- iMap->id2mc = map_id2mc;
- iMap->id2cd = map_id2cd;
- iMap->id2bl = map_id2bl;
- iMap->blid_exists = map_blid_exists;
- iMap->mapindex2mapid = map_mapindex2mapid;
- iMap->mapname2mapid = map_mapname2mapid;
- iMap->mapname2ipport = map_mapname2ipport;
- iMap->setipport = map_setipport;
- iMap->eraseipport = map_eraseipport;
- iMap->eraseallipport = map_eraseallipport;
- iMap->addiddb = map_addiddb;
- iMap->deliddb = map_deliddb;
+ map->addnickdb = map_addnickdb;
+ map->delnickdb = map_delnickdb;
+ map->reqnickdb = map_reqnickdb;
+ map->charid2nick = map_charid2nick;
+ map->charid2sd = map_charid2sd;
+
+ map->vforeachpc = map_vforeachpc;
+ map->foreachpc = map_foreachpc;
+ map->vforeachmob = map_vforeachmob;
+ map->foreachmob = map_foreachmob;
+ map->vforeachnpc = map_vforeachnpc;
+ map->foreachnpc = map_foreachnpc;
+ map->vforeachregen = map_vforeachregen;
+ map->foreachregen = map_foreachregen;
+ map->vforeachiddb = map_vforeachiddb;
+ map->foreachiddb = map_foreachiddb;
+
+ map->vforeachinrange = map_vforeachinrange;
+ map->foreachinrange = map_foreachinrange;
+ map->vforeachinshootrange = map_vforeachinshootrange;
+ map->foreachinshootrange = map_foreachinshootrange;
+ map->vforeachinarea = map_vforeachinarea;
+ map->foreachinarea = map_foreachinarea;
+ map->vforcountinrange = map_vforcountinrange;
+ map->forcountinrange = map_forcountinrange;
+ map->vforcountinarea = map_vforcountinarea;
+ map->forcountinarea = map_forcountinarea;
+ map->vforeachinmovearea = map_vforeachinmovearea;
+ map->foreachinmovearea = map_foreachinmovearea;
+ map->vforeachincell = map_vforeachincell;
+ map->foreachincell = map_foreachincell;
+ map->vforeachinpath = map_vforeachinpath;
+ map->foreachinpath = map_foreachinpath;
+ map->vforeachinmap = map_vforeachinmap;
+ map->foreachinmap = map_foreachinmap;
+ map->vforeachininstance = map_vforeachininstance;
+ map->foreachininstance = map_foreachininstance;
+
+ map->id2sd = map_id2sd;
+ map->id2md = map_id2md;
+ map->id2nd = map_id2nd;
+ map->id2hd = map_id2hd;
+ map->id2mc = map_id2mc;
+ map->id2cd = map_id2cd;
+ map->id2bl = map_id2bl;
+ map->blid_exists = map_blid_exists;
+ map->mapindex2mapid = map_mapindex2mapid;
+ map->mapname2mapid = map_mapname2mapid;
+ map->mapname2ipport = map_mapname2ipport;
+ map->setipport = map_setipport;
+ map->eraseipport = map_eraseipport;
+ map->eraseallipport = map_eraseallipport;
+ map->addiddb = map_addiddb;
+ map->deliddb = map_deliddb;
/* */
- iMap->nick2sd = map_nick2sd;
- iMap->getmob_boss = map_getmob_boss;
- iMap->id2boss = map_id2boss;
+ map->nick2sd = map_nick2sd;
+ map->getmob_boss = map_getmob_boss;
+ map->id2boss = map_id2boss;
// reload config file looking only for npcs
- iMap->reloadnpc = map_reloadnpc;
-
- iMap->check_dir = map_check_dir;
- iMap->calc_dir = map_calc_dir;
- iMap->random_dir = map_random_dir; // [Skotlex]
-
- iMap->cleanup_sub = cleanup_sub;
-
- iMap->delmap = map_delmap;
- iMap->flags_init = map_flags_init;
-
- iMap->iwall_set = map_iwall_set;
- iMap->iwall_get = map_iwall_get;
- iMap->iwall_remove = map_iwall_remove;
-
- iMap->addmobtolist = map_addmobtolist; // [Wizputer]
- iMap->spawnmobs = map_spawnmobs; // [Wizputer]
- iMap->removemobs = map_removemobs; // [Wizputer]
- iMap->addmap2db = map_addmap2db;
- iMap->removemapdb = map_removemapdb;
- iMap->clean = map_clean;
-
- iMap->do_shutdown = do_shutdown;
-
- iMap->map_foreachpc = map_map_foreachpc;
- iMap->map_foreachmob = map_map_foreachmob;
- iMap->map_foreachnpc = map_map_foreachnpc;
- iMap->map_foreachregen = map_map_foreachregen;
- iMap->map_foreachiddb = map_map_foreachiddb;
-
- iMap->foreachinrange = map_foreachinrange;
- iMap->foreachinshootrange = map_foreachinshootrange;
- iMap->foreachinarea=map_foreachinarea;
- iMap->forcountinrange=map_forcountinrange;
- iMap->forcountinarea=map_forcountinarea;
- iMap->foreachinmovearea = map_foreachinmovearea;
- iMap->foreachincell=map_foreachincell;
- iMap->foreachinpath=map_foreachinpath;
- iMap->foreachinmap=map_foreachinmap;
- iMap->foreachininstance=map_foreachininstance;
-
- /* temporary until the map.c "Hercules Renewal Phase One" design is complete. [Ind] */
+ map->reloadnpc = map_reloadnpc;
+
+ map->check_dir = map_check_dir;
+ map->calc_dir = map_calc_dir;
+ map->random_dir = map_random_dir; // [Skotlex]
+
+ map->cleanup_sub = cleanup_sub;
+
+ map->delmap = map_delmap;
+ map->flags_init = map_flags_init;
+
+ map->iwall_set = map_iwall_set;
+ map->iwall_get = map_iwall_get;
+ map->iwall_remove = map_iwall_remove;
+
+ map->addmobtolist = map_addmobtolist; // [Wizputer]
+ map->spawnmobs = map_spawnmobs; // [Wizputer]
+ map->removemobs = map_removemobs; // [Wizputer]
+ map->addmap2db = map_addmap2db;
+ map->removemapdb = map_removemapdb;
+ map->clean = map_clean;
+
+ map->do_shutdown = do_shutdown;
+
+ map->freeblock_timer = map_freeblock_timer;
+ map->searchrandfreecell = map_searchrandfreecell;
+ map->count_sub = map_count_sub;
+ map->create_charid2nick = create_charid2nick;
+ map->removemobs_sub = map_removemobs_sub;
+ map->gat2cell = map_gat2cell;
+ map->cell2gat = map_cell2gat;
+ map->getcellp = map_getcellp;
+ map->setcell = map_setcell;
+ map->sub_getcellp = map_sub_getcellp;
+ map->sub_setcell = map_sub_setcell;
+ map->iwall_nextxy = map_iwall_nextxy;
+ map->create_map_data_other_server = create_map_data_other_server;
+ map->eraseallipport_sub = map_eraseallipport_sub;
+ map->init_mapcache = map_init_mapcache;
+ map->readfromcache = map_readfromcache;
+ map->addmap = map_addmap;
+ map->delmapid = map_delmapid;
+ map->zone_db_clear = map_zone_db_clear;
+ map->list_final = do_final_maps;
+ map->waterheight = map_waterheight;
+ map->readgat = map_readgat;
+ map->readallmaps = map_readallmaps;
+ map->config_read = map_config_read;
+ map->config_read_sub = map_config_read_sub;
+ map->reloadnpc_sub = map_reloadnpc_sub;
+ map->inter_config_read = inter_config_read;
+ map->sql_init = map_sql_init;
+ map->sql_close = map_sql_close;
+ map->zone_mf_cache = map_zone_mf_cache;
+ map->zone_str2itemid = map_zone_str2itemid;
+ map->zone_str2skillid = map_zone_str2skillid;
+ map->zone_bl_type = map_zone_bl_type;
+ map->read_zone_db = read_map_zone_db;
+ map->db_final = map_db_final;
+ map->nick_db_final = nick_db_final;
+ map->cleanup_db_sub = cleanup_db_sub;
+ map->abort_sub = map_abort_sub;
+ map->helpscreen = map_helpscreen;
+ map->versionscreen = map_versionscreen;
+ map->arg_next_value = map_arg_next_value;
+
+ map->update_cell_bl = map_update_cell_bl;
+
+ map->get_new_bonus_id = map_get_new_bonus_id;
+
+ map->add_questinfo = map_add_questinfo;
+ map->remove_questinfo = map_remove_questinfo;
+
+ map->merge_zone = map_merge_zone;
+
+ /**
+ * mapit interface
+ **/
+
mapit = &mapit_s;
mapit->alloc = mapit_alloc;
@@ -5628,4 +6155,5 @@ void map_defaults(void) {
mapit->next = mapit_next;
mapit->prev = mapit_prev;
mapit->exists = mapit_exists;
+
}
diff --git a/src/map/map.h b/src/map/map.h
index 3e7c45bc3..dba565cc0 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -1,26 +1,32 @@
// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _MAP_H_
-#define _MAP_H_
+
+#ifndef MAP_MAP_H
+#define MAP_MAP_H
+
+#include <stdarg.h>
+
+#include "atcommand.h"
#include "../common/cbasetypes.h"
#include "../common/core.h" // CORE_ST_LAST
-#include "../common/mmo.h"
-#include "../common/mapindex.h"
#include "../common/db.h"
-#include "../config/core.h"
-#include "atcommand.h"
-#include <stdarg.h>
+#include "../common/mapindex.h"
+#include "../common/mmo.h"
+#include "../common/sql.h"
+
+struct mob_data;
struct npc_data;
-struct item_data;
struct hChSysCh;
+
enum E_MAPSERVER_ST {
MAPSERVER_ST_RUNNING = CORE_ST_LAST,
MAPSERVER_ST_SHUTDOWN,
MAPSERVER_ST_LAST
};
+
#define MAX_NPC_PER_MAP 512
-#define AREA_SIZE battle_config.area_size
+#define AREA_SIZE (battle->bc->area_size)
#define DAMAGELOG_SIZE 30
#define LOOTITEM_SIZE 10
#define MAX_MOBSKILL 50
@@ -30,10 +36,15 @@ enum E_MAPSERVER_ST {
#define NATURAL_HEAL_INTERVAL 500
#define MIN_FLOORITEM 2
#define MAX_FLOORITEM START_ACCOUNT_NUM
-#define MAX_LEVEL 150
#define MAX_IGNORE_LIST 20 // official is 14
#define MAX_VENDING 12
-#define MAX_MAP_SIZE 512*512 // Wasn't there something like this already? Can't find it.. [Shinryo]
+#define MAX_MAP_SIZE (512*512) // Wasn't there something like this already? Can't find it.. [Shinryo]
+
+#define BLOCK_SIZE 8
+#define block_free_max 1048576
+#define BL_LIST_MAX 1048576
+
+
// Added definitions for WoESE objects. [L0ne_W0lf]
enum MOBID {
MOBID_EMPERIUM = 1288,
@@ -51,6 +62,7 @@ enum MOBID {
MOBID_SILVERSNIPER = 2042,
MOBID_MAGICDECOY_WIND = 2046,
};
+
// The following system marks a different job ID system used by the map server,
// which makes a lot more sense than the normal one. [Skotlex]
// These marks the "level" of the job.
@@ -60,10 +72,12 @@ enum MOBID {
#define JOBL_UPPER 0x1000 //4096
#define JOBL_BABY 0x2000 //8192
#define JOBL_THIRD 0x4000 //16384
+
// For filtering and quick checking.
#define MAPID_BASEMASK 0x00ff
#define MAPID_UPPERMASK 0x0fff
#define MAPID_THIRDMASK (JOBL_THIRD|MAPID_UPPERMASK)
+
//First Jobs
//Note the oddity of the novice:
//Super Novices are considered the 2-1 version of the novice! Novices are considered a first class type.
@@ -92,6 +106,7 @@ enum {
MAPID_BLACKSMITH,
MAPID_ASSASSIN,
MAPID_STAR_GLADIATOR,
+ MAPID_REBELLION = JOBL_2_1|0x09,
MAPID_KAGEROUOBORO = JOBL_2_1|0x0A,
MAPID_DEATH_KNIGHT = JOBL_2_1|0x0E,
//2-2 Jobs
@@ -102,7 +117,7 @@ enum {
MAPID_ALCHEMIST,
MAPID_ROGUE,
MAPID_SOUL_LINKER,
- MAPID_DARK_COLLECTOR = JOBL_2_2|0x0D,
+ MAPID_DARK_COLLECTOR = JOBL_2_2|0x0E,
//Trans Novice And Trans 1-1 Jobs
MAPID_NOVICE_HIGH = JOBL_UPPER|0x0,
MAPID_SWORDMAN_HIGH,
@@ -193,6 +208,7 @@ enum {
MAPID_BABY_GENETIC,
MAPID_BABY_CHASER,
};
+
// Max size for inputs to Graffiti, Talkie Box and Vending text prompts
#define MESSAGE_SIZE (79 + 1)
// String length you can write in the 'talking box'
@@ -204,15 +220,15 @@ enum {
#define CHAT_SIZE_MAX (255 + 1)
// 24 for npc name + 24 for label + 2 for a "::" and 1 for EOS
#define EVENT_NAME_LENGTH ( NAME_LENGTH * 2 + 3 )
-#define DEFAULT_AUTOSAVE_INTERVAL 5*60*1000
+#define DEFAULT_AUTOSAVE_INTERVAL (5*60*1000)
// Specifies maps where players may hit each other
-#define map_flag_vs(m) (map[m].flag.pvp || map[m].flag.gvg_dungeon || map[m].flag.gvg || ((iMap->agit_flag || iMap->agit2_flag) && map[m].flag.gvg_castle) || map[m].flag.battleground)
+#define map_flag_vs(m) (map->list[m].flag.pvp || map->list[m].flag.gvg_dungeon || map->list[m].flag.gvg || ((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle) || map->list[m].flag.battleground)
// Specifies maps that have special GvG/WoE restrictions
-#define map_flag_gvg(m) (map[m].flag.gvg || ((iMap->agit_flag || iMap->agit2_flag) && map[m].flag.gvg_castle))
-// Specifies if the map is tagged as GvG/WoE (regardless of iMap->agit_flag status)
-#define map_flag_gvg2(m) (map[m].flag.gvg || map[m].flag.gvg_castle)
+#define map_flag_gvg(m) (map->list[m].flag.gvg || ((map->agit_flag || map->agit2_flag) && map->list[m].flag.gvg_castle))
+// Specifies if the map is tagged as GvG/WoE (regardless of map->agit_flag status)
+#define map_flag_gvg2(m) (map->list[m].flag.gvg || map->list[m].flag.gvg_castle)
// No Kill Steal Protection
-#define map_flag_ks(m) (map[m].flag.town || map[m].flag.pvp || map[m].flag.gvg || map[m].flag.battleground)
+#define map_flag_ks(m) (map->list[m].flag.town || map->list[m].flag.pvp || map->list[m].flag.gvg || map->list[m].flag.battleground)
//This stackable implementation does not means a BL can be more than one type at a time, but it's
// meant to make it easier to check for multiple types at a time on invocations such as map_foreach* calls [Skotlex]
@@ -296,7 +312,6 @@ struct block_list {
enum bl_type type;
};
-
// Mob List Held in memory for Dynamic Mobs [Wizputer]
// Expanded to specify all mob-related spawn data by [Skotlex]
struct spawn_data {
@@ -309,7 +324,7 @@ struct spawn_data {
unsigned int level;
struct {
unsigned int size : 2; //Holds if mob has to be tiny/large
- unsigned int ai : 4; //Special ai for summoned monsters.
+ unsigned int ai : 4; //Special AI for summoned monsters.
//0: Normal mob | 1: Standard summon, attacks mobs
//2: Alchemist Marine Sphere | 3: Alchemist Summon Flora | 4: Summon Zanzou
unsigned int dynamic : 1; //Whether this data is indexed by a map's dynamic mob list
@@ -323,11 +338,11 @@ struct flooritem_data {
unsigned char subx,suby;
int cleartimer;
int first_get_charid,second_get_charid,third_get_charid;
- unsigned int first_get_tick,second_get_tick,third_get_tick;
+ int64 first_get_tick,second_get_tick,third_get_tick;
struct item item_data;
};
-enum _sp {
+enum status_point_types {
SP_SPEED,SP_BASEEXP,SP_JOBEXP,SP_KARMA,SP_MANNER,SP_HP,SP_MAXHP,SP_SP, // 0-7
SP_MAXSP,SP_STATUSPOINT,SP_0a,SP_BASELEVEL,SP_SKILLPOINT,SP_STR,SP_AGI,SP_VIT, // 8-15
SP_INT,SP_DEX,SP_LUK,SP_CLASS,SP_ZENY,SP_SEX,SP_NEXTBASEEXP,SP_NEXTJOBEXP, // 16-23
@@ -344,6 +359,9 @@ enum _sp {
SP_KILLEDRID=122,
SP_SLOTCHANGE=123,
SP_CHARRENAME=124,
+ SP_MOD_EXP=125,
+ SP_MOD_DROP=126,
+ SP_MOD_DEATH=127,
// Mercenaries
SP_MERCFLEE=165, SP_MERCKILLS=189, SP_MERCFAITH=190,
@@ -386,14 +404,19 @@ enum _sp {
SP_SUBSIZE, SP_HP_DRAIN_VALUE_RACE, SP_ADD_ITEM_HEAL_RATE, SP_SP_DRAIN_VALUE_RACE, SP_EXP_ADDRACE, // 2026-2030
SP_SP_GAIN_RACE, SP_SUBRACE2, SP_UNBREAKABLE_SHOES, // 2031-2033
SP_UNSTRIPABLE_WEAPON,SP_UNSTRIPABLE_ARMOR,SP_UNSTRIPABLE_HELM,SP_UNSTRIPABLE_SHIELD, // 2034-2037
- SP_INTRAVISION, SP_ADD_MONSTER_DROP_ITEMGROUP, SP_SP_LOSS_RATE, // 2038-2040
+ SP_INTRAVISION, SP_ADD_MONSTER_DROP_CHAINITEM, SP_SP_LOSS_RATE, // 2038-2040
SP_ADD_SKILL_BLOW, SP_SP_VANISH_RATE, SP_MAGIC_SP_GAIN_VALUE, SP_MAGIC_HP_GAIN_VALUE, SP_ADD_CLASS_DROP_ITEM, //2041-2045
SP_EMATK, SP_SP_GAIN_RACE_ATTACK, SP_HP_GAIN_RACE_ATTACK, SP_SKILL_USE_SP_RATE, //2046-2049
SP_SKILL_COOLDOWN,SP_SKILL_FIXEDCAST, SP_SKILL_VARIABLECAST, SP_FIXCASTRATE, SP_VARCASTRATE, //2050-2054
- SP_SKILL_USE_SP,SP_MAGIC_ATK_ELE, SP_ADD_FIXEDCAST, SP_ADD_VARIABLECAST //2055-2058
+ SP_SKILL_USE_SP,SP_MAGIC_ATK_ELE, SP_ADD_FIXEDCAST, SP_ADD_VARIABLECAST, //2055-2058
+ SP_SET_DEF_RACE,SP_SET_MDEF_RACE, //2059-2060
+
+
+ /* must be the last, plugins add bonuses from this value onwards */
+ SP_LAST_KNOWN,
};
-enum _look {
+enum look {
LOOK_BASE,
LOOK_HAIR,
LOOK_WEAPON,
@@ -420,12 +443,11 @@ typedef enum {
CELL_LANDPROTECTOR,
CELL_NOVENDING,
CELL_NOCHAT,
- CELL_MAELSTROM,
CELL_ICEWALL,
} cell_t;
-// used by iMap->getcell()
+// used by map->getcell()
typedef enum {
CELL_GETTYPE, // retrieves a cell's 'gat' type
@@ -444,31 +466,28 @@ typedef enum {
CELL_CHKLANDPROTECTOR,
CELL_CHKNOVENDING,
CELL_CHKNOCHAT,
- CELL_CHKMAELSTROM,
CELL_CHKICEWALL,
} cell_chk;
-struct mapcell
-{
+struct mapcell {
// terrain flags
unsigned char
-walkable : 1,
-shootable : 1,
-water : 1;
+ walkable : 1,
+ shootable : 1,
+ water : 1;
// dynamic flags
unsigned char
-npc : 1,
-basilica : 1,
-landprotector : 1,
-novending : 1,
-nochat : 1,
-maelstrom : 1,
-icewall : 1;
+ npc : 1,
+ basilica : 1,
+ landprotector : 1,
+ novending : 1,
+ nochat : 1,
+ icewall : 1;
#ifdef CELL_NOSTACK
- unsigned char cell_bl; //Holds amount of bls in this cell.
+ int cell_bl; //Holds amount of bls in this cell.
#endif
};
@@ -509,7 +528,7 @@ struct map_zone_skill_damage_cap_entry {
enum map_zone_skill_subtype subtype;
};
-#define MAP_ZONE_NAME_LENGTH 30
+#define MAP_ZONE_NAME_LENGTH 60
#define MAP_ZONE_ALL_NAME "All"
#define MAP_ZONE_NORMAL_NAME "Normal"
#define MAP_ZONE_PVP_NAME "PvP"
@@ -517,7 +536,7 @@ struct map_zone_skill_damage_cap_entry {
#define MAP_ZONE_BG_NAME "Battlegrounds"
#define MAP_ZONE_PK_NAME "PK Mode"
#define MAP_ZONE_MAPFLAG_LENGTH 50
-DBMap *zone_db;/* string => struct map_zone_data */
+
struct map_zone_data {
char name[MAP_ZONE_NAME_LENGTH];/* 20'd */
struct map_zone_disabled_skill_entry **disabled_skills;
@@ -530,11 +549,11 @@ struct map_zone_data {
int disabled_commands_count;
struct map_zone_skill_damage_cap_entry **capped_skills;
int capped_skills_count;
+ struct {
+ unsigned int special : 2;/* 1: whether this is a mergeable zone; 2: whether it is a merged zone */
+ } info;
};
-struct map_zone_data map_zone_all;/* used as a base on all maps */
-struct map_zone_data map_zone_pk;/* used for (pk_mode) */
-
struct map_drop_list {
int drop_id;
int drop_type;
@@ -542,12 +561,33 @@ struct map_drop_list {
};
+struct questinfo {
+ struct npc_data *nd;
+ unsigned short icon;
+ unsigned char color;
+ int quest_id;
+ bool hasJob;
+ unsigned short job;/* perhaps a mapid mask would be most flexible? */
+};
+
+
struct map_data {
char name[MAP_NAME_LENGTH];
uint16 index; // The map index used by the mapindex* functions.
struct mapcell* cell; // Holds the information of each map cell (NULL if the map is not on this map-server).
- struct block_list **block;
- struct block_list **block_mob;
+
+ /* 2D Orthogonal Range Search: Grid Implementation
+ "Algorithms in Java, Parts 1-4" 3.18, Robert Sedgewick
+ Map is divided into squares, called blocks (side length = BLOCK_SIZE).
+ For each block there is a linked list of objects in that block (block_list).
+ Array provides capability to access immediately the set of objects close
+ to a given object.
+ The linked lists provide the flexibility to store the objects without
+ knowing ahead how many objects fall into each block.
+ */
+ struct block_list **block; // Grid array of block_lists containing only non-BL_MOB objects
+ struct block_list **block_mob; // Grid array of block_lists containing only BL_MOB objects
+
int16 m;
int16 xs,ys; // map dimensions (in cells)
int16 bxs,bys; // map dimensions (in blocks)
@@ -605,6 +645,8 @@ struct map_data {
unsigned reset :1; // [Daegaladh]
unsigned chsysnolocalaj : 1;
unsigned noknockback : 1;
+ unsigned notomb : 1;
+ unsigned nocashshop : 1;
} flag;
struct point save;
struct npc_data *npc[MAX_NPC_PER_MAP];
@@ -618,8 +660,8 @@ struct map_data {
int nocommand; //Blocks @/# commands for non-gms. [Skotlex]
/**
* Ice wall reference counter for bugreport:3574
- * - since there are a thounsand mobs out there in a lot of maps checking on,
- * - every targetting for icewall on attack path would just be a waste, so,
+ * - since there are a thousand mobs out there in a lot of maps checking on,
+ * - every targeting for icewall on attack path would just be a waste, so,
* - this counter allows icewall checking be only run when there is a actual ice wall on the map
**/
int icewall_num;
@@ -657,13 +699,23 @@ struct map_data {
/* long_damage_rate mapflag */
unsigned short long_damage_rate;
- /* instance unique name */
- char *cName;
+ bool custom_name; ///< Whether the instanced map is using a custom name
/* */
int (*getcellp)(struct map_data* m,int16 x,int16 y,cell_chk cellchk);
void (*setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag);
char *cellPos;
+
+ /* ShowEvent Data Cache */
+ struct questinfo *qi_data;
+ unsigned short qi_count;
+
+ /* speeds up clif_updatestatus processing by causing hpmeter to run only when someone with the permission can view it */
+ unsigned short hpmeter_visible;
+
+ /* HPM Custom Struct */
+ struct HPluginData **hdata;
+ unsigned int hdatac;
};
/// Stores information about a remote map (for multi-mapserver setups).
@@ -676,59 +728,34 @@ struct map_data_other_server {
uint16 port;
};
-
-struct map_data *map;
-
-
-
-
-
-
-//int map_foreachinrange(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int type, ...);
-//int map_foreachinshootrange(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int type, ...);
-//int map_foreachinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, ...);
-//int map_forcountinrange(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int count, int type, ...);
-//int map_forcountinarea(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int count, int type, ...);
-//int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int16 dx, int16 dy, int type, ...);
-//int map_foreachincell(int (*func)(struct block_list*,va_list), int16 m, int16 x, int16 y, int type, ...);
-//int map_foreachinpath(int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int16 range, int length, int type, ...);
-//int map_foreachinmap(int (*func)(struct block_list*,va_list), int16 m, int type, ...);
-//int map_foreachininstance(int (*func)(struct block_list*,va_list), int16 instance_id, int type,...);
-//
-
-
-
-
-#define map_id2index(id) map[(id)].index
+#define map_id2index(id) (map->list[(id)].index)
/// Bitfield of flags for the iterator.
enum e_mapitflags {
MAPIT_NORMAL = 0,
- // MAPIT_PCISPLAYING = 1,// Unneeded as pc_db/id_db will only hold auth'ed, active players.
+ // MAPIT_PCISPLAYING = 1,// Unneeded as pc_db/id_db will only hold authed, active players.
};
+
struct s_mapiterator;
+
/* temporary until the map.c "Hercules Renewal Phase One" design is complete. */
struct mapit_interface {
struct s_mapiterator* (*alloc) (enum e_mapitflags flags, enum bl_type types);
- void (*free) (struct s_mapiterator* mapit);
- struct block_list* (*first) (struct s_mapiterator* mapit);
- struct block_list* (*last) (struct s_mapiterator* mapit);
- struct block_list* (*next) (struct s_mapiterator* mapit);
- struct block_list* (*prev) (struct s_mapiterator* mapit);
- bool (*exists) (struct s_mapiterator* mapit);
-} mapit_s;
-struct mapit_interface *mapit;
-#define mapit_getallusers() mapit->alloc(MAPIT_NORMAL,BL_PC)
-#define mapit_geteachpc() mapit->alloc(MAPIT_NORMAL,BL_PC)
-#define mapit_geteachmob() mapit->alloc(MAPIT_NORMAL,BL_MOB)
-#define mapit_geteachnpc() mapit->alloc(MAPIT_NORMAL,BL_NPC)
-#define mapit_geteachiddb() mapit->alloc(MAPIT_NORMAL,BL_ALL)
-
-
-
-
+ void (*free) (struct s_mapiterator* iter);
+ struct block_list* (*first) (struct s_mapiterator* iter);
+ struct block_list* (*last) (struct s_mapiterator* iter);
+ struct block_list* (*next) (struct s_mapiterator* iter);
+ struct block_list* (*prev) (struct s_mapiterator* iter);
+ bool (*exists) (struct s_mapiterator* iter);
+};
+struct mapit_interface *mapit;
+#define mapit_getallusers() (mapit->alloc(MAPIT_NORMAL,BL_PC))
+#define mapit_geteachpc() (mapit->alloc(MAPIT_NORMAL,BL_PC))
+#define mapit_geteachmob() (mapit->alloc(MAPIT_NORMAL,BL_MOB))
+#define mapit_geteachnpc() (mapit->alloc(MAPIT_NORMAL,BL_NPC))
+#define mapit_geteachiddb() (mapit->alloc(MAPIT_NORMAL,BL_ALL))
//Useful typedefs from jA [Skotlex]
typedef struct map_session_data TBL_PC;
@@ -745,23 +772,41 @@ typedef struct elemental_data TBL_ELEM;
#define BL_CAST(type_, bl) \
( ((bl) == (struct block_list*)NULL || (bl)->type != (type_)) ? (T ## type_ *)NULL : (T ## type_ *)(bl) )
-#include "../common/sql.h"
-
+struct charid_request {
+ struct charid_request* next;
+ int charid;// who want to be notified of the nick
+};
+struct charid2nick {
+ char nick[NAME_LENGTH];
+ struct charid_request* requests;// requests of notification on this nick
+};
-extern Sql* mmysql_handle;
-extern Sql* logmysql_handle;
+// This is the main header found at the very beginning of the map cache
+struct map_cache_main_header {
+ uint32 file_size;
+ uint16 map_count;
+};
+// This is the header appended before every compressed map cells info in the map cache
+struct map_cache_map_info {
+ char name[MAP_NAME_LENGTH];
+ int16 xs;
+ int16 ys;
+ int32 len;
+};
/*=====================================
-* Interface : map.h
+* Interface : map.h
* Generated by HerculesInterfaceMaker
* created by Susu
*-------------------------------------*/
struct map_interface {
/* vars */
- int map_num;
+ bool minimal;
+ int retval;
+ int count;
int autosave_interval;
int minsave_interval;
@@ -787,7 +832,9 @@ struct map_interface {
char *MSG_CONF_NAME;
char *GRF_PATH_FILENAME;
- int db_use_sqldbs;
+ int db_use_sql_item_db;
+ int db_use_sql_mob_db;
+ int db_use_sql_mob_skill_db;
char item_db_db[32];
char item_db2_db[32];
@@ -797,7 +844,58 @@ struct map_interface {
char mob_skill_db_db[32];
char mob_skill_db2_db[32];
char interreg_db[32];
+ char autotrade_merchants_db[32];
+ char autotrade_data_db[32];
+ char npc_market_data_db[32];
+
+ char default_codepage[32];
+
+ int server_port;
+ char server_ip[32];
+ char server_id[32];
+ char server_pw[32];
+ char server_db[32];
+ Sql* mysql_handle;
+
+ int port;
+ int users;
+ int enable_grf; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89]
+ bool ip_set;
+ bool char_ip_set;
+ int16 index2mapid[MAX_MAPINDEX];
+ /* */
+ DBMap* id_db; // int id -> struct block_list*
+ DBMap* pc_db; // int id -> struct map_session_data*
+ DBMap* mobid_db; // int id -> struct mob_data*
+ DBMap* bossid_db; // int id -> struct mob_data* (MVP db)
+ DBMap* map_db; // unsigned int mapindex -> struct map_data_other_server*
+ DBMap* nick_db; // int char_id -> struct charid2nick* (requested names of offline characters)
+ DBMap* charid_db; // int char_id -> struct map_session_data*
+ DBMap* regen_db; // int id -> struct block_list* (status_natural_heal processing)
+ DBMap* zone_db; // string => struct map_zone_data
+ DBMap* iwall_db;
+ /* order respected by map_defaults() in order to zero */
+ /* from block_free until zone_pk */
+ struct block_list **block_free;
+ int block_free_count, block_free_lock, block_free_list_size;
+ struct block_list **bl_list;
+ int bl_list_count, bl_list_size;
+ struct block_list bl_head;
+ struct map_zone_data zone_all;/* used as a base on all maps */
+ struct map_zone_data zone_pk;/* used for (pk_mode) */
+ /* */
+ struct map_session_data *cpsd;
+ struct map_data *list;
+ /* [Ind/Hercules] */
+ struct eri *iterator_ers;
+ char *cache_buffer; // Has the uncompressed gat data of all maps, so just one allocation has to be made
+ /* */
+ struct eri *flooritem_ers;
+ /* */
+ int bonus_id;
+ /* */
+ bool cpsd_active;
/* funcs */
void (*zone_init) (void);
void (*zone_remove) (int m);
@@ -820,20 +918,20 @@ struct map_interface {
// blocklist manipulation
int (*addblock) (struct block_list* bl);
int (*delblock) (struct block_list* bl);
- int (*moveblock) (struct block_list *, int, int, unsigned int);
+ int (*moveblock) (struct block_list *bl, int x1, int y1, int64 tick);
//blocklist nb in one cell
int (*count_oncell) (int16 m,int16 x,int16 y,int type);
- struct skill_unit * (*find_skill_unit_oncell) (struct block_list *,int16 x,int16 y,uint16 skill_id,struct skill_unit *, int flag);
+ struct skill_unit * (*find_skill_unit_oncell) (struct block_list* target,int16 x,int16 y,uint16 skill_id,struct skill_unit* out_unit, int flag);
// search and creation
int (*get_new_object_id) (void);
int (*search_freecell) (struct block_list *src, int16 m, int16 *x, int16 *y, int16 rx, int16 ry, int flag);
//
- int (*quit) (struct map_session_data *);
+ int (*quit) (struct map_session_data *sd);
// npc
- bool (*addnpc) (int16 m,struct npc_data *);
+ bool (*addnpc) (int16 m,struct npc_data *nd);
// map item
- int (*clearflooritem_timer) (int tid, unsigned int tick, int id, intptr_t data);
- int (*removemobs_timer) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*clearflooritem_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*removemobs_timer) (int tid, int64 tick, int id, intptr_t data);
void (*clearflooritem) (struct block_list* bl);
int (*addflooritem) (struct item *item_data,int amount,int16 m,int16 x,int16 y,int first_charid,int second_charid,int third_charid,int flags);
// player to map session
@@ -843,21 +941,36 @@ struct map_interface {
const char* (*charid2nick) (int charid);
struct map_session_data* (*charid2sd) (int charid);
- void (*map_foreachpc) (int (*func)(struct map_session_data* sd, va_list args), ...);
- void (*map_foreachmob) (int (*func)(struct mob_data* md, va_list args), ...);
- void (*map_foreachnpc) (int (*func)(struct npc_data* nd, va_list args), ...);
- void (*map_foreachregen) (int (*func)(struct block_list* bl, va_list args), ...);
- void (*map_foreachiddb) (int (*func)(struct block_list* bl, va_list args), ...);
-
+ void (*vforeachpc) (int (*func)(struct map_session_data* sd, va_list args), va_list args);
+ void (*foreachpc) (int (*func)(struct map_session_data* sd, va_list args), ...);
+ void (*vforeachmob) (int (*func)(struct mob_data* md, va_list args), va_list args);
+ void (*foreachmob) (int (*func)(struct mob_data* md, va_list args), ...);
+ void (*vforeachnpc) (int (*func)(struct npc_data* nd, va_list args), va_list args);
+ void (*foreachnpc) (int (*func)(struct npc_data* nd, va_list args), ...);
+ void (*vforeachregen) (int (*func)(struct block_list* bl, va_list args), va_list args);
+ void (*foreachregen) (int (*func)(struct block_list* bl, va_list args), ...);
+ void (*vforeachiddb) (int (*func)(struct block_list* bl, va_list args), va_list args);
+ void (*foreachiddb) (int (*func)(struct block_list* bl, va_list args), ...);
+
+ int (*vforeachinrange) (int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int type, va_list ap);
int (*foreachinrange) (int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int type, ...);
+ int (*vforeachinshootrange) (int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int type, va_list ap);
int (*foreachinshootrange) (int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int type, ...);
+ int (*vforeachinarea) (int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, va_list ap);
int (*foreachinarea) (int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int type, ...);
+ int (*vforcountinrange) (int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int count, int type, va_list ap);
int (*forcountinrange) (int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int count, int type, ...);
+ int (*vforcountinarea) (int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int count, int type, va_list ap);
int (*forcountinarea) (int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int count, int type, ...);
+ int (*vforeachinmovearea) (int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int16 dx, int16 dy, int type, va_list ap);
int (*foreachinmovearea) (int (*func)(struct block_list*,va_list), struct block_list* center, int16 range, int16 dx, int16 dy, int type, ...);
+ int (*vforeachincell) (int (*func)(struct block_list*,va_list), int16 m, int16 x, int16 y, int type, va_list ap);
int (*foreachincell) (int (*func)(struct block_list*,va_list), int16 m, int16 x, int16 y, int type, ...);
+ int (*vforeachinpath) (int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int16 range, int length, int type, va_list ap);
int (*foreachinpath) (int (*func)(struct block_list*,va_list), int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int16 range, int length, int type, ...);
+ int (*vforeachinmap) (int (*func)(struct block_list*,va_list), int16 m, int type, va_list args);
int (*foreachinmap) (int (*func)(struct block_list*,va_list), int16 m, int type, ...);
+ int (*vforeachininstance)(int (*func)(struct block_list*,va_list), int16 instance_id, int type, va_list ap);
int (*foreachininstance)(int (*func)(struct block_list*,va_list), int16 instance_id, int type,...);
struct map_session_data * (*id2sd) (int id);
@@ -868,20 +981,20 @@ struct map_interface {
struct chat_data* (*id2cd) (int id);
struct block_list * (*id2bl) (int id);
bool (*blid_exists) (int id);
- int16 (*mapindex2mapid) (unsigned short mapindex);
+ int16 (*mapindex2mapid) (unsigned short map_index);
int16 (*mapname2mapid) (const char* name);
int (*mapname2ipport) (unsigned short name, uint32* ip, uint16* port);
- int (*setipport) (unsigned short map, uint32 ip, uint16 port);
- int (*eraseipport) (unsigned short map, uint32 ip, uint16 port);
+ int (*setipport) (unsigned short map_index, uint32 ip, uint16 port);
+ int (*eraseipport) (unsigned short map_index, uint32 ip, uint16 port);
int (*eraseallipport) (void);
- void (*addiddb) (struct block_list *);
+ void (*addiddb) (struct block_list *bl);
void (*deliddb) (struct block_list *bl);
/* */
- struct map_session_data * (*nick2sd) (const char*);
+ struct map_session_data * (*nick2sd) (const char *nick);
struct mob_data * (*getmob_boss) (int16 m);
struct mob_data * (*id2boss) (int id);
// reload config file looking only for npcs
- void (*reloadnpc) (bool clear);
+ void (*reloadnpc) (bool clear, const char * const *extra_scripts, int extra_scripts_count);
int (*check_dir) (int s_dir,int t_dir);
uint8 (*calc_dir) (struct block_list *src,int16 x,int16 y);
@@ -899,16 +1012,63 @@ struct map_interface {
int (*addmobtolist) (unsigned short m, struct spawn_data *spawn); // [Wizputer]
void (*spawnmobs) (int16 m); // [Wizputer]
void (*removemobs) (int16 m); // [Wizputer]
- void (*do_reconnect_map) (void); //Invoked on map-char reconnection [Skotlex] Note used but still keeping it, just in case
+ //void (*do_reconnect_map) (void); //Invoked on map-char reconnection [Skotlex] Note used but still keeping it, just in case
void (*addmap2db) (struct map_data *m);
void (*removemapdb) (struct map_data *m);
void (*clean) (int i);
void (*do_shutdown) (void);
-} iMap_s;
+
+ int (*freeblock_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*searchrandfreecell) (int16 m, int16 *x, int16 *y, int stack);
+ int (*count_sub) (struct block_list *bl, va_list ap);
+ DBData (*create_charid2nick) (DBKey key, va_list args);
+ int (*removemobs_sub) (struct block_list *bl, va_list ap);
+ struct mapcell (*gat2cell) (int gat);
+ int (*cell2gat) (struct mapcell cell);
+ int (*getcellp) (struct map_data *m, int16 x, int16 y, cell_chk cellchk);
+ void (*setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag);
+ int (*sub_getcellp) (struct map_data *m, int16 x, int16 y, cell_chk cellchk);
+ void (*sub_setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag);
+ void (*iwall_nextxy) (int16 x, int16 y, int8 dir, int pos, int16 *x1, int16 *y1);
+ DBData (*create_map_data_other_server) (DBKey key, va_list args);
+ int (*eraseallipport_sub) (DBKey key, DBData *data, va_list va);
+ char* (*init_mapcache) (FILE *fp);
+ int (*readfromcache) (struct map_data *m, char *buffer);
+ int (*addmap) (const char *mapname);
+ void (*delmapid) (int id);
+ void (*zone_db_clear) (void);
+ void (*list_final) (void);
+ int (*waterheight) (char *mapname);
+ int (*readgat) (struct map_data *m);
+ int (*readallmaps) (void);
+ int (*config_read) (char *cfgName);
+ int (*config_read_sub) (char *cfgName);
+ void (*reloadnpc_sub) (char *cfgName);
+ int (*inter_config_read) (char *cfgName);
+ int (*sql_init) (void);
+ int (*sql_close) (void);
+ bool (*zone_mf_cache) (int m, char *flag, char *params);
+ unsigned short (*zone_str2itemid) (const char *name);
+ unsigned short (*zone_str2skillid) (const char *name);
+ enum bl_type (*zone_bl_type) (const char *entry, enum map_zone_skill_subtype *subtype);
+ void (*read_zone_db) (void);
+ int (*db_final) (DBKey key, DBData *data, va_list ap);
+ int (*nick_db_final) (DBKey key, DBData *data, va_list args);
+ int (*cleanup_db_sub) (DBKey key, DBData *data, va_list va);
+ int (*abort_sub) (struct map_session_data *sd, va_list ap);
+ void (*helpscreen) (bool do_exit);
+ void (*versionscreen) (bool do_exit);
+ bool (*arg_next_value) (const char *option, int i, int argc, bool must);
+ void (*update_cell_bl) (struct block_list *bl, bool increase);
+ int (*get_new_bonus_id) (void);
+ void (*add_questinfo) (int m, struct questinfo *qi);
+ bool (*remove_questinfo) (int m, struct npc_data *nd);
+ struct map_zone_data *(*merge_zone) (struct map_zone_data *main, struct map_zone_data *other);
+};
-struct map_interface *iMap;
+struct map_interface *map;
void map_defaults(void);
-#endif /* _MAP_H_ */
+#endif /* MAP_MAP_H */
diff --git a/src/map/mapreg.h b/src/map/mapreg.h
index e83f9e053..59d226cda 100644
--- a/src/map/mapreg.h
+++ b/src/map/mapreg.h
@@ -2,26 +2,52 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _MAPREG_H_
-#define _MAPREG_H_
+#ifndef MAP_MAPREG_H
+#define MAP_MAPREG_H
+#include "script.h" // struct reg_db
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+
+/** Container for a mapreg value */
struct mapreg_save {
- int uid;
+ int64 uid; ///< Unique ID
union {
- int i;
- char *str;
+ int i; ///< Numeric value
+ char *str; ///< String value
} u;
- bool save;
+ bool is_string; ///< true if it's a string, false if it's a number
+ bool save; ///< Whether a save operation is pending
+};
+
+struct mapreg_interface {
+ struct reg_db regs;
+ /* */
+ bool skip_insert;
+ /* */
+ struct eri *ers; //[Ind/Hercules]
+ /* */
+ char table[32];
+ /* */
+ bool dirty; ///< Whether there are modified regs to be saved
+ /* */
+ void (*init) (void);
+ void (*final) (void);
+ /* */
+ int (*readreg) (int64 uid);
+ char* (*readregstr) (int64 uid);
+ bool (*setreg) (int64 uid, int val);
+ bool (*setregstr) (int64 uid, const char *str);
+ void (*load) (void);
+ void (*save) (void);
+ int (*save_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*destroyreg) (DBKey key, DBData *data, va_list ap);
+ void (*reload) (void);
+ bool (*config_read) (const char *w1, const char *w2);
};
-void mapreg_reload(void);
-void mapreg_final(void);
-void mapreg_init(void);
-bool mapreg_config_read(const char* w1, const char* w2);
+struct mapreg_interface *mapreg;
-int mapreg_readreg(int uid);
-char* mapreg_readregstr(int uid);
-bool mapreg_setreg(int uid, int val);
-bool mapreg_setregstr(int uid, const char* str);
+void mapreg_defaults(void);
-#endif /* _MAPREG_H_ */
+#endif /* MAP_MAPREG_H */
diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c
index b6865c8fd..f026fde00 100644
--- a/src/map/mapreg_sql.c
+++ b/src/map/mapreg_sql.c
@@ -2,6 +2,15 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
+#define HERCULES_CORE
+
+#include "mapreg.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "map.h" // map->mysql_handle
+#include "script.h"
#include "../common/cbasetypes.h"
#include "../common/db.h"
#include "../common/ers.h"
@@ -10,143 +19,167 @@
#include "../common/sql.h"
#include "../common/strlib.h"
#include "../common/timer.h"
-#include "map.h" // mmysql_handle
-#include "script.h"
-#include "mapreg.h"
-#include <stdlib.h>
-#include <string.h>
-
-static DBMap* mapreg_db = NULL; // int var_id -> int value
-static DBMap* mapregstr_db = NULL; // int var_id -> char* value
-static struct eri *mapreg_ers; //[Ind/Hercules]
-static char mapreg_table[32] = "mapreg";
-static bool mapreg_i_dirty = false;
-static bool mapreg_str_dirty = false;
+struct mapreg_interface mapreg_s;
#define MAPREG_AUTOSAVE_INTERVAL (300*1000)
-
-/// Looks up the value of an integer variable using its uid.
-int mapreg_readreg(int uid) {
- struct mapreg_save *m = idb_get(mapreg_db, uid);
+/**
+ * Looks up the value of an integer variable using its uid.
+ *
+ * @param uid variable's unique identifier.
+ * @return variable's integer value
+ */
+int mapreg_readreg(int64 uid) {
+ struct mapreg_save *m = i64db_get(mapreg->regs.vars, uid);
return m?m->u.i:0;
}
-/// Looks up the value of a string variable using its uid.
-char* mapreg_readregstr(int uid) {
- struct mapreg_save *m = idb_get(mapregstr_db, uid);
+/**
+ * Looks up the value of a string variable using its uid.
+ *
+ * @param uid variable's unique identifier
+ * @return variable's string value
+ */
+char* mapreg_readregstr(int64 uid) {
+ struct mapreg_save *m = i64db_get(mapreg->regs.vars, uid);
return m?m->u.str:NULL;
}
-/// Modifies the value of an integer variable.
-bool mapreg_setreg(int uid, int val) {
+/**
+ * Modifies the value of an integer variable.
+ *
+ * @param uid variable's unique identifier
+ * @param val new value
+ * @retval true value was successfully set
+ */
+bool mapreg_setreg(int64 uid, int val) {
struct mapreg_save *m;
- int num = (uid & 0x00ffffff);
- int i = (uid & 0xff000000) >> 24;
- const char* name = get_str(num);
+ int num = script_getvarid(uid);
+ unsigned int i = script_getvaridx(uid);
+ const char* name = script->get_str(num);
if( val != 0 ) {
- if( (m = idb_get(mapreg_db,uid)) ) {
+ if( (m = i64db_get(mapreg->regs.vars, uid)) ) {
m->u.i = val;
if(name[1] != '@') {
m->save = true;
- mapreg_i_dirty = true;
+ mapreg->dirty = true;
}
} else {
- m = ers_alloc(mapreg_ers, struct mapreg_save);
+ if( i )
+ script->array_update(&mapreg->regs, uid, false);
+
+ m = ers_alloc(mapreg->ers, struct mapreg_save);
m->u.i = val;
m->uid = uid;
m->save = false;
+ m->is_string = false;
- if(name[1] != '@') {// write new variable to database
+ if(name[1] != '@' && !mapreg->skip_insert) {// write new variable to database
char tmp_str[32*2+1];
- SQL->EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32));
- if( SQL_ERROR == SQL->Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%d')", mapreg_table, tmp_str, i, val) )
- Sql_ShowDebug(mmysql_handle);
+ SQL->EscapeStringLen(map->mysql_handle, tmp_str, name, strnlen(name, 32));
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%d')", mapreg->table, tmp_str, i, val) )
+ Sql_ShowDebug(map->mysql_handle);
}
- idb_put(mapreg_db, uid, m);
+ i64db_put(mapreg->regs.vars, uid, m);
}
} else { // val == 0
- if( (m = idb_get(mapreg_db,uid)) ) {
- ers_free(mapreg_ers, m);
+ if( i )
+ script->array_update(&mapreg->regs, uid, true);
+ if( (m = i64db_get(mapreg->regs.vars, uid)) ) {
+ ers_free(mapreg->ers, m);
}
- idb_remove(mapreg_db,uid);
+ i64db_remove(mapreg->regs.vars, uid);
if( name[1] != '@' ) {// Remove from database because it is unused.
- if( SQL_ERROR == SQL->Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) )
- Sql_ShowDebug(mmysql_handle);
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg->table, name, i) )
+ Sql_ShowDebug(map->mysql_handle);
}
}
return true;
}
-/// Modifies the value of a string variable.
-bool mapreg_setregstr(int uid, const char* str) {
+/**
+ * Modifies the value of a string variable.
+ *
+ * @param uid variable's unique identifier
+ * @param str new value
+ * @retval true value was successfully set
+ */
+bool mapreg_setregstr(int64 uid, const char* str) {
struct mapreg_save *m;
- int num = (uid & 0x00ffffff);
- int i = (uid & 0xff000000) >> 24;
- const char* name = get_str(num);
-
+ int num = script_getvarid(uid);
+ unsigned int i = script_getvaridx(uid);
+ const char* name = script->get_str(num);
+
if( str == NULL || *str == 0 ) {
+ if( i )
+ script->array_update(&mapreg->regs, uid, true);
if(name[1] != '@') {
- if( SQL_ERROR == SQL->Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) )
- Sql_ShowDebug(mmysql_handle);
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg->table, name, i) )
+ Sql_ShowDebug(map->mysql_handle);
}
- if( (m = idb_get(mapregstr_db,uid)) ) {
+ if( (m = i64db_get(mapreg->regs.vars, uid)) ) {
if( m->u.str != NULL )
aFree(m->u.str);
- ers_free(mapreg_ers, m);
+ ers_free(mapreg->ers, m);
}
- idb_remove(mapregstr_db,uid);
+ i64db_remove(mapreg->regs.vars, uid);
} else {
- if( (m = idb_get(mapregstr_db,uid)) ) {
+ if( (m = i64db_get(mapreg->regs.vars, uid)) ) {
if( m->u.str != NULL )
aFree(m->u.str);
m->u.str = aStrdup(str);
if(name[1] != '@') {
- mapreg_str_dirty = true;
+ mapreg->dirty = true;
m->save = true;
}
} else {
- m = ers_alloc(mapreg_ers, struct mapreg_save);
+ if( i )
+ script->array_update(&mapreg->regs, uid, false);
+
+ m = ers_alloc(mapreg->ers, struct mapreg_save);
m->uid = uid;
m->u.str = aStrdup(str);
m->save = false;
-
- if(name[1] != '@') { //put returned null, so we must insert.
+ m->is_string = true;
+
+ if(name[1] != '@' && !mapreg->skip_insert) { //put returned null, so we must insert.
char tmp_str[32*2+1];
char tmp_str2[255*2+1];
- SQL->EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32));
- SQL->EscapeStringLen(mmysql_handle, tmp_str2, str, strnlen(str, 255));
- if( SQL_ERROR == SQL->Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%s')", mapreg_table, tmp_str, i, tmp_str2) )
- Sql_ShowDebug(mmysql_handle);
+ SQL->EscapeStringLen(map->mysql_handle, tmp_str, name, strnlen(name, 32));
+ SQL->EscapeStringLen(map->mysql_handle, tmp_str2, str, strnlen(str, 255));
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%s')", mapreg->table, tmp_str, i, tmp_str2) )
+ Sql_ShowDebug(map->mysql_handle);
}
- idb_put(mapregstr_db, uid, m);
+ i64db_put(mapreg->regs.vars, uid, m);
}
}
return true;
}
-/// Loads permanent variables from database
-static void script_load_mapreg(void) {
+/**
+ * Loads permanent variables from database.
+ */
+void script_load_mapreg(void) {
/*
0 1 2
+-------------------------+
| varname | index | value |
+-------------------------+
*/
- SqlStmt* stmt = SQL->StmtMalloc(mmysql_handle);
+ SqlStmt* stmt = SQL->StmtMalloc(map->mysql_handle);
char varname[32+1];
int index;
char value[255+1];
uint32 length;
- if ( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `varname`, `index`, `value` FROM `%s`", mapreg_table)
+ if ( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `varname`, `index`, `value` FROM `%s`", mapreg->table)
|| SQL_ERROR == SQL->StmtExecute(stmt)
) {
SqlStmt_ShowDebug(stmt);
@@ -154,163 +187,187 @@ static void script_load_mapreg(void) {
return;
}
+ mapreg->skip_insert = true;
+
SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &varname[0], sizeof(varname), &length, NULL);
SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &index, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 2, SQLDT_STRING, &value[0], sizeof(value), NULL, NULL);
-
+
while ( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) {
- struct mapreg_save *m = NULL;
- int s = add_str(varname);
+ int s = script->add_str(varname);
int i = index;
- if( varname[length-1] == '$' ) {
- if( idb_exists(mapregstr_db, (i<<24)|s) ) {
- ShowWarning("load_mapreg: duplicate! '%s' => '%s' skipping...\n",varname,value);
- continue;
- }
- } else {
- if( idb_exists(mapreg_db, (i<<24)|s) ) {
- ShowWarning("load_mapreg: duplicate! '%s' => '%s' skipping...\n",varname,value);
- continue;
- }
+
+ if( i64db_exists(mapreg->regs.vars, reference_uid(s, i)) ) {
+ ShowWarning("load_mapreg: duplicate! '%s' => '%s' skipping...\n",varname,value);
+ continue;
}
-
- m = ers_alloc(mapreg_ers, struct mapreg_save);
- m->uid = (i<<24)|s;
- m->save = false;
if( varname[length-1] == '$' ) {
- m->u.str = aStrdup(value);
- idb_put(mapregstr_db, m->uid, m);
+ mapreg->setregstr(reference_uid(s, i),value);
} else {
- m->u.i = atoi(value);
- idb_put(mapreg_db, m->uid, m);
+ mapreg->setreg(reference_uid(s, i),atoi(value));
}
}
-
+
SQL->StmtFree(stmt);
- mapreg_i_dirty = false;
- mapreg_str_dirty = false;
+ mapreg->skip_insert = false;
+
+ mapreg->dirty = false;
}
-/// Saves permanent variables to database
-static void script_save_mapreg(void) {
+/**
+ * Saves permanent variables to database.
+ */
+void script_save_mapreg(void) {
DBIterator* iter;
struct mapreg_save *m = NULL;
- if( mapreg_i_dirty ) {
- iter = db_iterator(mapreg_db);
- for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
- if( m->save ) {
- int num = (m->uid & 0x00ffffff);
- int i = (m->uid & 0xff000000) >> 24;
- const char* name = get_str(num);
-
- if( SQL_ERROR == SQL->Query(mmysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg_table, m->u.i, name, i) )
- Sql_ShowDebug(mmysql_handle);
- m->save = false;
- }
- }
- dbi_destroy(iter);
- mapreg_i_dirty = false;
- }
-
- if( mapreg_str_dirty ) {
- iter = db_iterator(mapregstr_db);
+ if( mapreg->dirty ) {
+ iter = db_iterator(mapreg->regs.vars);
for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
if( m->save ) {
- int num = (m->uid & 0x00ffffff);
- int i = (m->uid & 0xff000000) >> 24;
- const char* name = get_str(num);
- char tmp_str2[2*255+1];
-
- SQL->EscapeStringLen(mmysql_handle, tmp_str2, m->u.str, safestrnlen(m->u.str, 255));
- if( SQL_ERROR == SQL->Query(mmysql_handle, "UPDATE `%s` SET `value`='%s' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg_table, tmp_str2, name, i) )
- Sql_ShowDebug(mmysql_handle);
+ int num = script_getvarid(m->uid);
+ int i = script_getvaridx(m->uid);
+ const char* name = script->get_str(num);
+ if (!m->is_string) {
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg->table, m->u.i, name, i) )
+ Sql_ShowDebug(map->mysql_handle);
+ } else {
+ char tmp_str2[2*255+1];
+ SQL->EscapeStringLen(map->mysql_handle, tmp_str2, m->u.str, safestrnlen(m->u.str, 255));
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE `%s` SET `value`='%s' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg->table, tmp_str2, name, i) )
+ Sql_ShowDebug(map->mysql_handle);
+ }
m->save = false;
}
}
dbi_destroy(iter);
- mapreg_str_dirty = false;
+ mapreg->dirty = false;
}
}
-static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr_t data) {
- script_save_mapreg();
+/**
+ * Timer event to auto-save permanent variables.
+ *
+ * @see timer->do_timer
+ */
+int script_autosave_mapreg(int tid, int64 tick, int id, intptr_t data) {
+ mapreg->save();
return 0;
}
-
-void mapreg_reload(void) {
- DBIterator* iter;
+/**
+ * Destroys a mapreg_save structure, freeing the contained string, if any.
+ *
+ * @see DBApply
+ */
+int mapreg_destroyreg(DBKey key, DBData *data, va_list ap) {
struct mapreg_save *m = NULL;
- script_save_mapreg();
+ if (data->type != DB_DATA_PTR) // Sanity check
+ return 0;
- iter = db_iterator(mapreg_db);
- for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
- ers_free(mapreg_ers, m);
- }
- dbi_destroy(iter);
-
- iter = db_iterator(mapregstr_db);
- for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
- if( m->u.str != NULL ) {
+ m = DB->data2ptr(data);
+
+ if (m->is_string) {
+ if (m->u.str)
aFree(m->u.str);
- }
- ers_free(mapreg_ers, m);
}
- dbi_destroy(iter);
-
- db_clear(mapreg_db);
- db_clear(mapregstr_db);
+ ers_free(mapreg->ers, m);
- script_load_mapreg();
+ return 0;
}
-void mapreg_final(void) {
- DBIterator* iter;
- struct mapreg_save *m = NULL;
-
- script_save_mapreg();
+/**
+ * Reloads mapregs, saving to database beforehand.
+ *
+ * This has the effect of clearing the temporary variables, and
+ * reloading the permanent ones.
+ */
+void mapreg_reload(void) {
+ mapreg->save();
- iter = db_iterator(mapreg_db);
- for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
- ers_free(mapreg_ers, m);
- }
- dbi_destroy(iter);
-
- iter = db_iterator(mapregstr_db);
- for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) {
- if( m->u.str != NULL ) {
- aFree(m->u.str);
- }
- ers_free(mapreg_ers, m);
+ mapreg->regs.vars->clear(mapreg->regs.vars, mapreg->destroyreg);
+
+ if( mapreg->regs.arrays ) {
+ mapreg->regs.arrays->destroy(mapreg->regs.arrays, script->array_free_db);
+ mapreg->regs.arrays = NULL;
}
- dbi_destroy(iter);
-
- db_destroy(mapreg_db);
- db_destroy(mapregstr_db);
-
- ers_destroy(mapreg_ers);
+
+ mapreg->load();
}
+/**
+ * Finalizer.
+ */
+void mapreg_final(void) {
+ mapreg->save();
+
+ mapreg->regs.vars->destroy(mapreg->regs.vars, mapreg->destroyreg);
+
+ ers_destroy(mapreg->ers);
+
+ if( mapreg->regs.arrays )
+ mapreg->regs.arrays->destroy(mapreg->regs.arrays, script->array_free_db);
+}
+
+/**
+ * Initializer.
+ */
void mapreg_init(void) {
- mapreg_db = idb_alloc(DB_OPT_BASE);
- mapregstr_db = idb_alloc(DB_OPT_BASE);
- mapreg_ers = ers_new(sizeof(struct mapreg_save), "mapreg_sql.c::mapreg_ers", ERS_OPT_NONE);
+ mapreg->regs.vars = i64db_alloc(DB_OPT_BASE);
+ mapreg->ers = ers_new(sizeof(struct mapreg_save), "mapreg_sql.c::mapreg_ers", ERS_OPT_CLEAN);
- script_load_mapreg();
+ mapreg->load();
- iTimer->add_timer_func_list(script_autosave_mapreg, "script_autosave_mapreg");
- iTimer->add_timer_interval(iTimer->gettick() + MAPREG_AUTOSAVE_INTERVAL, script_autosave_mapreg, 0, 0, MAPREG_AUTOSAVE_INTERVAL);
+ timer->add_func_list(mapreg->save_timer, "mapreg_script_autosave_mapreg");
+ timer->add_interval(timer->gettick() + MAPREG_AUTOSAVE_INTERVAL, mapreg->save_timer, 0, 0, MAPREG_AUTOSAVE_INTERVAL);
}
+/**
+ * Loads the mapreg configuration file.
+ */
bool mapreg_config_read(const char* w1, const char* w2) {
if(!strcmpi(w1, "mapreg_db"))
- safestrncpy(mapreg_table, w2, sizeof(mapreg_table));
+ safestrncpy(mapreg->table, w2, sizeof(mapreg->table));
else
return false;
return true;
}
+
+/**
+ * Interface defaults initializer.
+ */
+void mapreg_defaults(void) {
+ mapreg = &mapreg_s;
+
+ /* */
+ mapreg->regs.vars = NULL;
+ mapreg->ers = NULL;
+ mapreg->skip_insert = false;
+
+ safestrncpy(mapreg->table, "mapreg", sizeof(mapreg->table));
+ mapreg->dirty = false;
+
+ /* */
+ mapreg->regs.arrays = NULL;
+
+ /* */
+ mapreg->init = mapreg_init;
+ mapreg->final = mapreg_final;
+
+ /* */
+ mapreg->readreg = mapreg_readreg;
+ mapreg->readregstr = mapreg_readregstr;
+ mapreg->setreg = mapreg_setreg;
+ mapreg->setregstr = mapreg_setregstr;
+ mapreg->load = script_load_mapreg;
+ mapreg->save = script_save_mapreg;
+ mapreg->save_timer = script_autosave_mapreg;
+ mapreg->destroyreg = mapreg_destroyreg;
+ mapreg->reload = mapreg_reload;
+ mapreg->config_read = mapreg_config_read;
+
+}
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index 566f68409..80bcfdf05 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -2,64 +2,66 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/malloc.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/mmo.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
+#define HERCULES_CORE
-#include "log.h"
-#include "clif.h"
+#include "mercenary.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "atcommand.h"
+#include "battle.h"
#include "chrif.h"
+#include "clif.h"
+#include "guild.h"
#include "intif.h"
#include "itemdb.h"
+#include "log.h"
#include "map.h"
-#include "pc.h"
-#include "status.h"
-#include "skill.h"
#include "mob.h"
-#include "pet.h"
-#include "battle.h"
+#include "npc.h"
#include "party.h"
-#include "guild.h"
-#include "atcommand.h"
+#include "pc.h"
+#include "pet.h"
#include "script.h"
-#include "npc.h"
+#include "skill.h"
+#include "status.h"
#include "trade.h"
#include "unit.h"
-#include "mercenary.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
+#include "../common/cbasetypes.h"
+#include "../common/malloc.h"
+#include "../common/mmo.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS]; // Mercenary Database
+struct mercenary_interface mercenary_s;
int merc_search_index(int class_)
{
int i;
- ARR_FIND(0, MAX_MERCENARY_CLASS, i, mercenary_db[i].class_ == class_);
+ ARR_FIND(0, MAX_MERCENARY_CLASS, i, mercenary->db[i].class_ == class_);
return (i == MAX_MERCENARY_CLASS)?-1:i;
}
bool merc_class(int class_)
{
- return (bool)(merc_search_index(class_) > -1);
+ return (bool)(mercenary->search_index(class_) > -1);
}
struct view_data * merc_get_viewdata(int class_)
{
- int i = merc_search_index(class_);
+ int i = mercenary->search_index(class_);
if( i < 0 )
return 0;
- return &mercenary_db[i].vd;
+ return &mercenary->db[i].vd;
}
int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime)
@@ -69,10 +71,10 @@ int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime)
int i;
nullpo_retr(0,sd);
- if( (i = merc_search_index(class_)) < 0 )
+ if( (i = mercenary->search_index(class_)) < 0 )
return 0;
- db = &mercenary_db[i];
+ db = &mercenary->db[i];
memset(&merc,0,sizeof(struct s_mercenary));
merc.char_id = sd->status.char_id;
@@ -82,7 +84,7 @@ int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime)
merc.life_time = lifetime;
// Request Char Server to create this mercenary
- intif_mercenary_create(&merc);
+ intif->mercenary_create(&merc);
return 1;
}
@@ -93,8 +95,8 @@ int mercenary_get_lifetime(struct mercenary_data *md)
if( md == NULL || md->contract_timer == INVALID_TIMER )
return 0;
- td = iTimer->get_timer(md->contract_timer);
- return (td != NULL) ? DIFF_TICK(td->tick, iTimer->gettick()) : 0;
+ td = timer->get(md->contract_timer);
+ return (td != NULL) ? DIFF_TICK32(td->tick, timer->gettick()) : 0;
}
int mercenary_get_guild(struct mercenary_data *md)
@@ -211,30 +213,29 @@ int mercenary_save(struct mercenary_data *md)
{
md->mercenary.hp = md->battle_status.hp;
md->mercenary.sp = md->battle_status.sp;
- md->mercenary.life_time = mercenary_get_lifetime(md);
+ md->mercenary.life_time = mercenary->get_lifetime(md);
- intif_mercenary_save(&md->mercenary);
+ intif->mercenary_save(&md->mercenary);
return 1;
}
-static int merc_contract_end(int tid, unsigned int tick, int id, intptr_t data)
-{
+int merc_contract_end_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
struct mercenary_data *md;
- if( (sd = iMap->id2sd(id)) == NULL )
+ if( (sd = map->id2sd(id)) == NULL )
return 1;
if( (md = sd->md) == NULL )
return 1;
if( md->contract_timer != tid )
{
- ShowError("merc_contract_end %d != %d.\n", md->contract_timer, tid);
+ ShowError("merc_contract_end_timer %d != %d.\n", md->contract_timer, tid);
return 0;
}
md->contract_timer = INVALID_TIMER;
- merc_delete(md, 0); // Mercenary soldier's duty hour is over.
+ mercenary->delete(md, 0); // Mercenary soldier's duty hour is over.
return 0;
}
@@ -244,10 +245,10 @@ int merc_delete(struct mercenary_data *md, int reply)
struct map_session_data *sd = md->master;
md->mercenary.life_time = 0;
- merc_contract_stop(md);
+ mercenary->contract_stop(md);
if( !sd )
- return unit_free(&md->bl, CLR_OUTSIGHT);
+ return unit->free(&md->bl, CLR_OUTSIGHT);
if( md->devotion_flag )
{
@@ -257,38 +258,37 @@ int merc_delete(struct mercenary_data *md, int reply)
switch( reply )
{
- case 0: mercenary_set_faith(md, 1); break; // +1 Loyalty on Contract ends.
- case 1: mercenary_set_faith(md, -1); break; // -1 Loyalty on Mercenary killed
+ case 0: mercenary->set_faith(md, 1); break; // +1 Loyalty on Contract ends.
+ case 1: mercenary->set_faith(md, -1); break; // -1 Loyalty on Mercenary killed
}
clif->mercenary_message(sd, reply);
- return unit_remove_map(&md->bl, CLR_OUTSIGHT);
+ return unit->remove_map(&md->bl, CLR_OUTSIGHT, ALC_MARK);
}
void merc_contract_stop(struct mercenary_data *md)
{
nullpo_retv(md);
if( md->contract_timer != INVALID_TIMER )
- iTimer->delete_timer(md->contract_timer, merc_contract_end);
+ timer->delete(md->contract_timer, mercenary->contract_end_timer);
md->contract_timer = INVALID_TIMER;
}
void merc_contract_init(struct mercenary_data *md)
{
if( md->contract_timer == INVALID_TIMER )
- md->contract_timer = iTimer->add_timer(iTimer->gettick() + md->mercenary.life_time, merc_contract_end, md->master->bl.id, 0);
+ md->contract_timer = timer->add(timer->gettick() + md->mercenary.life_time, mercenary->contract_end_timer, md->master->bl.id, 0);
md->regen.state.block = 0;
}
-int merc_data_received(struct s_mercenary *merc, bool flag)
-{
+int merc_data_received(struct s_mercenary *merc, bool flag) {
struct map_session_data *sd;
struct mercenary_data *md;
struct s_mercenary_db *db;
- int i = merc_search_index(merc->class_);
+ int i = mercenary->search_index(merc->class_);
- if( (sd = iMap->charid2sd(merc->char_id)) == NULL )
+ if( (sd = map->charid2sd(merc->char_id)) == NULL )
return 0;
if( !flag || i < 0 )
{ // Not created - loaded - DB info
@@ -296,31 +296,30 @@ int merc_data_received(struct s_mercenary *merc, bool flag)
return 0;
}
- db = &mercenary_db[i];
- if( !sd->md )
- {
+ db = &mercenary->db[i];
+ if( !sd->md ) {
sd->md = md = (struct mercenary_data*)aCalloc(1,sizeof(struct mercenary_data));
md->bl.type = BL_MER;
- md->bl.id = npc_get_new_npc_id();
+ md->bl.id = npc->get_new_npc_id();
md->devotion_flag = 0;
md->master = sd;
md->db = db;
memcpy(&md->mercenary, merc, sizeof(struct s_mercenary));
- status_set_viewdata(&md->bl, md->mercenary.class_);
- status_change_init(&md->bl);
- unit_dataset(&md->bl);
+ status->set_viewdata(&md->bl, md->mercenary.class_);
+ status->change_init(&md->bl);
+ unit->dataset(&md->bl);
md->ud.dir = sd->ud.dir;
md->bl.m = sd->bl.m;
md->bl.x = sd->bl.x;
md->bl.y = sd->bl.y;
- unit_calc_pos(&md->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
+ unit->calc_pos(&md->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
md->bl.x = md->ud.to_x;
md->bl.y = md->ud.to_y;
- iMap->addiddb(&md->bl);
- status_calc_mercenary(md,1);
+ map->addiddb(&md->bl);
+ status_calc_mercenary(md,SCO_FIRST);
md->contract_timer = INVALID_TIMER;
merc_contract_init(md);
}
@@ -331,12 +330,11 @@ int merc_data_received(struct s_mercenary *merc, bool flag)
}
if( sd->status.mer_id == 0 )
- mercenary_set_calls(md, 1);
+ mercenary->set_calls(md, 1);
sd->status.mer_id = merc->mercenary_id;
- if( md && md->bl.prev == NULL && sd->bl.prev != NULL )
- {
- iMap->addblock(&md->bl);
+ if( md && md->bl.prev == NULL && sd->bl.prev != NULL ) {
+ map->addblock(&md->bl);
clif->spawn(&md->bl);
clif->mercenary_info(sd);
clif->mercenary_skillblock(sd);
@@ -355,7 +353,7 @@ void mercenary_heal(struct mercenary_data *md, int hp, int sp)
int mercenary_dead(struct mercenary_data *md)
{
- merc_delete(md, 1);
+ mercenary->delete(md, 1);
return 0;
}
@@ -364,7 +362,7 @@ int mercenary_killbonus(struct mercenary_data *md)
const enum sc_type scs[] = { SC_MER_FLEE, SC_MER_ATK, SC_MER_HP, SC_MER_SP, SC_MER_HIT };
int index = rnd() % ARRAYLENGTH(scs);
- sc_start(&md->bl, scs[index], 100, rnd() % 5, 600000);
+ sc_start(NULL,&md->bl, scs[index], 100, rnd() % 5, 600000);
return 0;
}
@@ -375,8 +373,8 @@ int mercenary_kills(struct mercenary_data *md)
if( (md->mercenary.kill_count % 50) == 0 )
{
- mercenary_set_faith(md, 1);
- mercenary_killbonus(md);
+ mercenary->set_faith(md, 1);
+ mercenary->killbonus(md);
}
if( md->master )
@@ -397,78 +395,74 @@ int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id)
return 0;
}
-static bool read_mercenarydb_sub(char* str[], int columns, int current)
-{
+bool read_mercenarydb_sub(char* str[], int columns, int current) {
int ele;
struct s_mercenary_db *db;
- struct status_data *status;
+ struct status_data *mstatus;
- db = &mercenary_db[current];
+ db = &mercenary->db[current];
db->class_ = atoi(str[0]);
safestrncpy(db->sprite, str[1], NAME_LENGTH);
safestrncpy(db->name, str[2], NAME_LENGTH);
db->lv = atoi(str[3]);
- status = &db->status;
+ mstatus = &db->status;
db->vd.class_ = db->class_;
- status->max_hp = atoi(str[4]);
- status->max_sp = atoi(str[5]);
- status->rhw.range = atoi(str[6]);
- status->rhw.atk = atoi(str[7]);
- status->rhw.atk2 = status->rhw.atk + atoi(str[8]);
- status->def = atoi(str[9]);
- status->mdef = atoi(str[10]);
- status->str = atoi(str[11]);
- status->agi = atoi(str[12]);
- status->vit = atoi(str[13]);
- status->int_ = atoi(str[14]);
- status->dex = atoi(str[15]);
- status->luk = atoi(str[16]);
+ mstatus->max_hp = atoi(str[4]);
+ mstatus->max_sp = atoi(str[5]);
+ mstatus->rhw.range = atoi(str[6]);
+ mstatus->rhw.atk = atoi(str[7]);
+ mstatus->rhw.atk2 = mstatus->rhw.atk + atoi(str[8]);
+ mstatus->def = atoi(str[9]);
+ mstatus->mdef = atoi(str[10]);
+ mstatus->str = atoi(str[11]);
+ mstatus->agi = atoi(str[12]);
+ mstatus->vit = atoi(str[13]);
+ mstatus->int_ = atoi(str[14]);
+ mstatus->dex = atoi(str[15]);
+ mstatus->luk = atoi(str[16]);
db->range2 = atoi(str[17]);
db->range3 = atoi(str[18]);
- status->size = atoi(str[19]);
- status->race = atoi(str[20]);
+ mstatus->size = atoi(str[19]);
+ mstatus->race = atoi(str[20]);
ele = atoi(str[21]);
- status->def_ele = ele%10;
- status->ele_lv = ele/20;
- if( status->def_ele >= ELE_MAX )
- {
- ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1);
- status->def_ele = ELE_NEUTRAL;
+ mstatus->def_ele = ele%10;
+ mstatus->ele_lv = ele/20;
+ if( mstatus->def_ele >= ELE_MAX ) {
+ ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, mstatus->def_ele, ELE_MAX - 1);
+ mstatus->def_ele = ELE_NEUTRAL;
}
- if( status->ele_lv < 1 || status->ele_lv > 4 )
- {
- ShowWarning("Mercenary %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv);
- status->ele_lv = 1;
+ if( mstatus->ele_lv < 1 || mstatus->ele_lv > 4 ) {
+ ShowWarning("Mercenary %d has invalid element level %d (max is 4)\n", db->class_, mstatus->ele_lv);
+ mstatus->ele_lv = 1;
}
- status->aspd_rate = 1000;
- status->speed = atoi(str[22]);
- status->adelay = atoi(str[23]);
- status->amotion = atoi(str[24]);
- status->dmotion = atoi(str[25]);
+ mstatus->aspd_rate = 1000;
+ mstatus->speed = atoi(str[22]);
+ mstatus->adelay = atoi(str[23]);
+ mstatus->amotion = atoi(str[24]);
+ mstatus->dmotion = atoi(str[25]);
return true;
}
-int read_mercenarydb(void)
-{
- memset(mercenary_db,0,sizeof(mercenary_db));
- sv->readdb(iMap->db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, &read_mercenarydb_sub);
+int read_mercenarydb(void) {
+ memset(mercenary->db,0,sizeof(mercenary->db));
+ sv->readdb(map->db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, mercenary->read_db_sub);
return 0;
}
-static bool read_mercenary_skilldb_sub(char* str[], int columns, int current)
+bool read_mercenary_skilldb_sub(char* str[], int columns, int current)
{// <merc id>,<skill id>,<skill level>
struct s_mercenary_db *db;
int i, class_;
uint16 skill_id, skill_lv;
class_ = atoi(str[0]);
- ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary_db[i].class_);
+ ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary->db[i].class_);
if( i == MAX_MERCENARY_CLASS )
{
ShowError("read_mercenary_skilldb : Class %d not found in mercenary_db for skill entry.\n", class_);
@@ -482,7 +476,7 @@ static bool read_mercenary_skilldb_sub(char* str[], int columns, int current)
return false;
}
- db = &mercenary_db[i];
+ db = &mercenary->db[i];
skill_lv = atoi(str[2]);
i = skill_id - MC_SKILLBASE;
@@ -492,20 +486,66 @@ static bool read_mercenary_skilldb_sub(char* str[], int columns, int current)
return true;
}
-int read_mercenary_skilldb(void)
-{
- sv->readdb(iMap->db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, &read_mercenary_skilldb_sub);
+int read_mercenary_skilldb(void) {
+ sv->readdb(map->db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, mercenary->read_skill_db_sub);
return 0;
}
-int do_init_mercenary(void)
-{
- read_mercenarydb();
- read_mercenary_skilldb();
+void do_init_mercenary(bool minimal) {
+ if (minimal)
+ return;
+
+ mercenary->read_db();
+ mercenary->read_skilldb();
- //add_timer_func_list(mercenary_contract, "mercenary_contract");
- return 0;
+ timer->add_func_list(mercenary->contract_end_timer, "merc_contract_end_timer");
}
-int do_final_mercenary(void);
+/*=====================================
+* Default Functions : mercenary.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+void mercenary_defaults(void) {
+ mercenary = &mercenary_s;
+
+ /* vars */
+ memset(mercenary->db,0,sizeof(mercenary->db));
+
+ /* funcs */
+
+ mercenary->init = do_init_mercenary;
+
+ mercenary->class = merc_class;
+ mercenary->get_viewdata = merc_get_viewdata;
+
+ mercenary->create = merc_create;
+ mercenary->data_received = merc_data_received;
+ mercenary->save = mercenary_save;
+
+ mercenary->heal = mercenary_heal;
+ mercenary->dead = mercenary_dead;
+
+ mercenary->delete = merc_delete;
+ mercenary->contract_stop = merc_contract_stop;
+
+ mercenary->get_lifetime = mercenary_get_lifetime;
+ mercenary->get_guild = mercenary_get_guild;
+ mercenary->get_faith = mercenary_get_faith;
+ mercenary->set_faith = mercenary_set_faith;
+ mercenary->get_calls = mercenary_get_calls;
+ mercenary->set_calls = mercenary_set_calls;
+ mercenary->kills = mercenary_kills;
+
+ mercenary->checkskill = mercenary_checkskill;
+ mercenary->read_db = read_mercenarydb;
+ mercenary->read_skilldb = read_mercenary_skilldb;
+
+ mercenary->killbonus = mercenary_killbonus;
+ mercenary->search_index = merc_search_index;
+
+ mercenary->contract_end_timer = merc_contract_end_timer;
+ mercenary->read_db_sub = read_mercenarydb_sub;
+ mercenary->read_skill_db_sub = read_mercenary_skilldb_sub;
+}
diff --git a/src/map/mercenary.h b/src/map/mercenary.h
index 994c7aaa4..270245e96 100644
--- a/src/map/mercenary.h
+++ b/src/map/mercenary.h
@@ -1,11 +1,12 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#ifndef _MERCENARY_H_
-#define _MERCENARY_H_
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
+#ifndef MAP_MERCENARY_H
+#define MAP_MERCENARY_H
#include "status.h" // struct status_data, struct status_change
#include "unit.h" // struct unit_data
+#include "../common/cbasetypes.h"
// number of cells that a mercenary can walk to from it's master before being warped
#define MAX_MER_DISTANCE 15
@@ -28,8 +29,6 @@ struct s_mercenary_db {
} skill[MAX_MERCSKILL];
};
-extern struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS];
-
struct mercenary_data {
struct block_list bl;
struct unit_data ud;
@@ -37,7 +36,6 @@ struct mercenary_data {
struct status_data base_status, battle_status;
struct status_change sc;
struct regen_data regen;
-
struct s_mercenary_db *db;
struct s_mercenary mercenary;
char blockskill[MAX_SKILL];
@@ -46,38 +44,59 @@ struct mercenary_data {
int contract_timer;
unsigned devotion_flag : 1;
- unsigned int masterteleport_timer;
+ int64 masterteleport_timer;
};
-bool merc_class(int class_);
-struct view_data * merc_get_viewdata(int class_);
-
-int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime);
-int merc_data_received(struct s_mercenary *merc, bool flag);
-int mercenary_save(struct mercenary_data *md);
+/*=====================================
+* Interface : mercenary.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+struct mercenary_interface {
-void mercenary_heal(struct mercenary_data *md, int hp, int sp);
-int mercenary_dead(struct mercenary_data *md);
-
-int merc_delete(struct mercenary_data *md, int reply);
-void merc_contract_stop(struct mercenary_data *md);
+ /* vars */
+
+ struct s_mercenary_db db[MAX_MERCENARY_CLASS];
-int mercenary_get_lifetime(struct mercenary_data *md);
-int mercenary_get_guild(struct mercenary_data *md);
-int mercenary_get_faith(struct mercenary_data *md);
-int mercenary_set_faith(struct mercenary_data *md, int value);
-int mercenary_get_calls(struct mercenary_data *md);
-int mercenary_set_calls(struct mercenary_data *md, int value);
-int mercenary_kills(struct mercenary_data *md);
+ /* funcs */
-int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id);
+ void (*init) (bool minimal);
+
+ bool (*class) (int class_);
+ struct view_data * (*get_viewdata) (int class_);
+
+ int (*create) (struct map_session_data *sd, int class_, unsigned int lifetime);
+ int (*data_received) (struct s_mercenary *merc, bool flag);
+ int (*save) (struct mercenary_data *md);
+
+ void (*heal) (struct mercenary_data *md, int hp, int sp);
+ int (*dead) (struct mercenary_data *md);
+
+ int (*delete) (struct mercenary_data *md, int reply);
+ void (*contract_stop) (struct mercenary_data *md);
+
+ int (*get_lifetime) (struct mercenary_data *md);
+ int (*get_guild) (struct mercenary_data *md);
+ int (*get_faith) (struct mercenary_data *md);
+ int (*set_faith) (struct mercenary_data *md, int value);
+ int (*get_calls) (struct mercenary_data *md);
+ int (*set_calls) (struct mercenary_data *md, int value);
+ int (*kills) (struct mercenary_data *md);
+
+ int (*checkskill) (struct mercenary_data *md, uint16 skill_id);
+ int (*read_db) (void);
+ int (*read_skilldb) (void);
+
+ int (*killbonus) (struct mercenary_data *md);
+ int (*search_index) (int class_);
+
+ int (*contract_end_timer) (int tid, int64 tick, int id, intptr_t data);
+ bool (*read_db_sub) (char* str[], int columns, int current);
+ bool (*read_skill_db_sub) (char* str[], int columns, int current);
+};
-/**
- * atcommand.c required
- **/
-int read_mercenarydb(void);
-int read_mercenary_skilldb(void);
+struct mercenary_interface *mercenary;
-int do_init_mercenary(void);
+void mercenary_defaults(void);
-#endif /* _MERCENARY_H_ */
+#endif /* MAP_MERCENARY_H */
diff --git a/src/map/mob.c b/src/map/mob.c
index 6bb40478f..3f1769d37 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -2,46 +2,51 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/timer.h"
-#include "../common/db.h"
-#include "../common/nullpo.h"
-#include "../common/malloc.h"
-#include "../common/showmsg.h"
-#include "../common/ers.h"
-#include "../common/random.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
-#include "../common/socket.h"
+#define HERCULES_CORE
-#include "map.h"
-#include "path.h"
-#include "clif.h"
-#include "intif.h"
-#include "pc.h"
-#include "pet.h"
-#include "status.h"
+#include "../config/core.h" // AUTOLOOT_DISTANCE, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, RENEWAL_DROP, RENEWAL_EXP
#include "mob.h"
-#include "homunculus.h"
-#include "mercenary.h"
+
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "atcommand.h"
+#include "battle.h"
+#include "clif.h"
+#include "date.h"
#include "elemental.h"
#include "guild.h"
+#include "homunculus.h"
+#include "intif.h"
#include "itemdb.h"
-#include "skill.h"
-#include "battle.h"
-#include "party.h"
-#include "npc.h"
#include "log.h"
-#include "script.h"
-#include "atcommand.h"
-#include "date.h"
+#include "map.h"
+#include "mercenary.h"
+#include "npc.h"
+#include "party.h"
+#include "path.h"
+#include "pc.h"
+#include "pet.h"
#include "quest.h"
+#include "script.h"
+#include "skill.h"
+#include "status.h"
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <math.h>
+struct mob_interface mob_s;
#define ACTIVE_AI_RANGE 2 //Distance added on top of 'AREA_SIZE' at which mobs enter active AI mode.
@@ -50,21 +55,10 @@
#define MOB_LAZYSKILLPERC 0 // Probability for mobs far from players from doing their IDLE skill. (rate of 1000 minute)
// Move probability for mobs away from players (rate of 1000 minute)
// in Aegis, this is 100% for mobs that have been activated by players and none otherwise.
-#define MOB_LAZYMOVEPERC(md) (md->state.spotted?1000:0)
+#define MOB_LAZYMOVEPERC(md) ((md)->state.spotted?1000:0)
#define MOB_MAX_DELAY (24*3600*1000)
#define MAX_MINCHASE 30 //Max minimum chase value to use for mobs.
#define RUDE_ATTACKED_COUNT 2 //After how many rude-attacks should the skill be used?
-#define MAX_MOB_CHAT 250 //Max Skill's messages
-
-//Dynamic mob database, allows saving of memory when there's big gaps in the mob_db [Skotlex]
-struct mob_db *mob_db_data[MAX_MOB_DB+1];
-struct mob_db *mob_dummy = NULL; //Dummy mob to be returned when a non-existant one is requested.
-
-struct mob_db *mob_db(int index) { if (index < 0 || index > MAX_MOB_DB || mob_db_data[index] == NULL) return mob_dummy; return mob_db_data[index]; }
-
-//Dynamic mob chat database
-struct mob_chat *mob_chat_db[MAX_MOB_CHAT+1];
-struct mob_chat *mob_chat(short id) { if(id<=0 || id>MAX_MOB_CHAT || mob_chat_db[id]==NULL) return (struct mob_chat*)NULL; return mob_chat_db[id]; }
//Dynamic item drop ratio database for per-item drop ratio modifiers overriding global drop ratios.
#define MAX_ITEMRATIO_MOBS 10
@@ -82,16 +76,16 @@ static struct {
int class_[350];
} summon[MAX_RANDOMMONSTER];
-//Defines the Manuk/Splendide mob groups for the status reductions [Epoque]
-const int mob_manuk[8] = { 1986, 1987, 1988, 1989, 1990, 1997, 1998, 1999 };
-const int mob_splendide[5] = { 1991, 1992, 1993, 1994, 1995 };
-
-/*==========================================
- * Local prototype declaration (only required thing)
- *------------------------------------------*/
-static int mob_makedummymobdb(int);
-static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t data);
-int mob_skill_id2skill_idx(int class_,uint16 skill_id);
+struct mob_db *mob_db(int index) {
+ if (index < 0 || index > MAX_MOB_DB || mob->db_data[index] == NULL)
+ return mob->dummy;
+ return mob->db_data[index];
+}
+struct mob_chat *mob_chat(short id) {
+ if(id <= 0 || id > MAX_MOB_CHAT || mob->chat_db[id] == NULL)
+ return NULL;
+ return mob->chat_db[id];
+}
/*==========================================
* Mob is searched with a name.
@@ -99,28 +93,40 @@ int mob_skill_id2skill_idx(int class_,uint16 skill_id);
int mobdb_searchname(const char *str)
{
int i;
- struct mob_db* mob;
+ struct mob_db* monster;
for(i=0;i<=MAX_MOB_DB;i++){
- mob = mob_db(i);
- if(mob == mob_dummy) //Skip dummy mobs.
+ monster = mob->db(i);
+ if(monster == mob->dummy) //Skip dummy mobs.
continue;
- if(strcmpi(mob->name,str)==0 || strcmpi(mob->jname,str)==0 || strcmpi(mob->sprite,str)==0)
+ if(strcmpi(monster->name,str)==0 || strcmpi(monster->jname,str)==0)
+ return i;
+ if(battle_config.case_sensitive_aegisnames && strcmp(monster->sprite,str)==0)
+ return i;
+ if(!battle_config.case_sensitive_aegisnames && strcasecmp(monster->sprite,str)==0)
return i;
}
return 0;
}
-static int mobdb_searchname_array_sub(struct mob_db* mob, const char *str)
-{
- if (mob == mob_dummy)
+int mobdb_searchname_array_sub(struct mob_db* monster, const char *str, int flag) {
+ if (monster == mob->dummy)
return 1;
- if(!mob->base_exp && !mob->job_exp && mob->spawn[0].qty < 1)
+ if(!monster->base_exp && !monster->job_exp && monster->spawn[0].qty < 1)
return 1; // Monsters with no base/job exp and no spawn point are, by this criteria, considered "slave mobs" and excluded from search results
- if(stristr(mob->jname,str))
- return 0;
- if(stristr(mob->name,str))
- return 0;
- return strcmpi(mob->jname,str);
+ if( !flag ) {
+ if(stristr(monster->jname,str))
+ return 0;
+ if(stristr(monster->name,str))
+ return 0;
+ } else {
+ if(strcmpi(monster->jname,str) == 0)
+ return 0;
+ if(strcmpi(monster->name,str) == 0)
+ return 0;
+ }
+ if (battle_config.case_sensitive_aegisnames)
+ return strcmp(monster->sprite,str);
+ return strcasecmp(monster->sprite,str);
}
/*==========================================
@@ -131,19 +137,19 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time)
struct npc_data *nd;
if ( md->tomb_nid )
- mvptomb_destroy(md);
+ mob->mvptomb_destroy(md);
CREATE(nd, struct npc_data, 1);
- nd->bl.id = md->tomb_nid = npc_get_new_npc_id();
+ nd->bl.id = md->tomb_nid = npc->get_new_npc_id();
- nd->dir = md->ud.dir;
+ nd->dir = md->ud.dir;
nd->bl.m = md->bl.m;
nd->bl.x = md->bl.x;
nd->bl.y = md->bl.y;
nd->bl.type = BL_NPC;
- safestrncpy(nd->name, msg_txt(656), sizeof(nd->name));
+ safestrncpy(nd->name, msg_txt(856), sizeof(nd->name)); // "Tomb"
nd->class_ = 565;
nd->speed = 200;
@@ -157,33 +163,33 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time)
else
nd->u.tomb.killer_name[0] = '\0';
- iMap->addnpc(nd->bl.m, nd);
- iMap->addblock(&nd->bl);
- status_set_viewdata(&nd->bl, nd->class_);
- clif->spawn(&nd->bl);
+ map->addnpc(nd->bl.m, nd);
+ map->addblock(&nd->bl);
+ status->set_viewdata(&nd->bl, nd->class_);
+ clif->spawn(&nd->bl);
}
void mvptomb_destroy(struct mob_data *md) {
struct npc_data *nd;
- if ( (nd = iMap->id2nd(md->tomb_nid)) ) {
+ if ( (nd = map->id2nd(md->tomb_nid)) ) {
int16 m, i;
m = nd->bl.m;
clif->clearunit_area(&nd->bl,CLR_OUTSIGHT);
- iMap->delblock(&nd->bl);
+ map->delblock(&nd->bl);
- ARR_FIND( 0, map[m].npc_num, i, map[m].npc[i] == nd );
- if( !(i == map[m].npc_num) ) {
- map[m].npc_num--;
- map[m].npc[i] = map[m].npc[map[m].npc_num];
- map[m].npc[map[m].npc_num] = NULL;
+ ARR_FIND( 0, map->list[m].npc_num, i, map->list[m].npc[i] == nd );
+ if( !(i == map->list[m].npc_num) ) {
+ map->list[m].npc_num--;
+ map->list[m].npc[i] = map->list[m].npc[map->list[m].npc_num];
+ map->list[m].npc[map->list[m].npc_num] = NULL;
}
- iMap->deliddb(&nd->bl);
+ map->deliddb(&nd->bl);
aFree(nd);
}
@@ -194,17 +200,17 @@ void mvptomb_destroy(struct mob_data *md) {
/*==========================================
* Founds up to N matches. Returns number of matches [Skotlex]
*------------------------------------------*/
-int mobdb_searchname_array(struct mob_db** data, int size, const char *str)
+int mobdb_searchname_array(struct mob_db** data, int size, const char *str, int flag)
{
int count = 0, i;
- struct mob_db* mob;
+ struct mob_db* monster;
for(i=0;i<=MAX_MOB_DB;i++){
- mob = mob_db(i);
- if (mob == mob_dummy || mob_is_clone(i) ) //keep clones out (or you leak player stats)
+ monster = mob->db(i);
+ if (monster == mob->dummy || mob->is_clone(i) ) //keep clones out (or you leak player stats)
continue;
- if (!mobdb_searchname_array_sub(mob, str)) {
+ if (!mob->db_searchname_array_sub(monster, str, flag)) {
if (count < size)
- data[count] = mob;
+ data[count] = monster;
count++;
}
}
@@ -216,9 +222,9 @@ int mobdb_searchname_array(struct mob_db** data, int size, const char *str)
*------------------------------------------*/
int mobdb_checkid(const int id)
{
- if (mob_db(id) == mob_dummy)
+ if (mob->db(id) == mob->dummy)
return 0;
- if (mob_is_clone(id)) //checkid is used mostly for random ID based code, therefore clone mobs are out of the question.
+ if (mob->is_clone(id)) //checkid is used mostly for random ID based code, therefore clone mobs are out of the question.
return 0;
return id;
}
@@ -228,9 +234,9 @@ int mobdb_checkid(const int id)
*------------------------------------------*/
struct view_data * mob_get_viewdata(int class_)
{
- if (mob_db(class_) == mob_dummy)
+ if (mob->db(class_) == mob->dummy)
return 0;
- return &mob_db(class_)->vd;
+ return &mob->db(class_)->vd;
}
/*==========================================
* Cleans up mob-spawn data to make it "valid"
@@ -239,7 +245,7 @@ int mob_parse_dataset(struct spawn_data *data)
{
size_t len;
- if ((!mobdb_checkid(data->class_) && !mob_is_clone(data->class_)) || !data->num)
+ if ((!mob->db_checkid(data->class_) && !mob->is_clone(data->class_)) || !data->num)
return 0;
if( ( len = strlen(data->eventname) ) > 0 )
@@ -251,9 +257,9 @@ int mob_parse_dataset(struct spawn_data *data)
}
if(strcmp(data->name,"--en--")==0)
- safestrncpy(data->name, mob_db(data->class_)->name, sizeof(data->name));
+ safestrncpy(data->name, mob->db(data->class_)->name, sizeof(data->name));
else if(strcmp(data->name,"--ja--")==0)
- safestrncpy(data->name, mob_db(data->class_)->jname, sizeof(data->name));
+ safestrncpy(data->name, mob->db(data->class_)->jname, sizeof(data->name));
return 1;
}
@@ -262,14 +268,14 @@ int mob_parse_dataset(struct spawn_data *data)
*------------------------------------------*/
struct mob_data* mob_spawn_dataset(struct spawn_data *data) {
struct mob_data *md = (struct mob_data*)aCalloc(1, sizeof(struct mob_data));
- md->bl.id= npc_get_new_npc_id();
+ md->bl.id= npc->get_new_npc_id();
md->bl.type = BL_MOB;
md->bl.m = data->m;
md->bl.x = data->x;
md->bl.y = data->y;
md->class_ = data->class_;
md->state.boss = data->state.boss;
- md->db = mob_db(md->class_);
+ md->db = mob->db(md->class_);
if (data->level > 0 && data->level <= MAX_LEVEL)
md->level = data->level;
memcpy(md->name, data->name, NAME_LENGTH);
@@ -284,11 +290,11 @@ struct mob_data* mob_spawn_dataset(struct spawn_data *data) {
md->spawn_timer = INVALID_TIMER;
md->deletetimer = INVALID_TIMER;
md->skill_idx = -1;
- status_set_viewdata(&md->bl, md->class_);
- status_change_init(&md->bl);
- unit_dataset(&md->bl);
+ status->set_viewdata(&md->bl, md->class_);
+ status->change_init(&md->bl);
+ unit->dataset(&md->bl);
- iMap->addiddb(&md->bl);
+ map->addiddb(&md->bl);
return md;
}
@@ -307,7 +313,7 @@ struct mob_data* mob_spawn_dataset(struct spawn_data *data) {
*------------------------------------------*/
int mob_get_random_id(int type, int flag, int lv)
{
- struct mob_db *mob;
+ struct mob_db *monster;
int i=0, class_;
if(type < 0 || type >= MAX_RANDOMMONSTER) {
ShowError("mob_get_random_id: Invalid type (%d) of random monster.\n", type);
@@ -318,25 +324,24 @@ int mob_get_random_id(int type, int flag, int lv)
class_ = summon[type].class_[rnd()%summon[type].qty];
else //Dead branch
class_ = rnd() % MAX_MOB_DB;
- mob = mob_db(class_);
- } while ((mob == mob_dummy ||
- mob_is_clone(class_) ||
- (flag&1 && mob->summonper[type] <= rnd() % 1000000) ||
- (flag&2 && lv < mob->lv) ||
- (flag&4 && mob->status.mode&MD_BOSS) ||
- (flag&8 && mob->spawn[0].qty < 1)
+ monster = mob->db(class_);
+ } while ((monster == mob->dummy ||
+ mob->is_clone(class_) ||
+ (flag&1 && monster->summonper[type] <= rnd() % 1000000) ||
+ (flag&2 && lv < monster->lv) ||
+ (flag&4 && monster->status.mode&MD_BOSS) ||
+ (flag&8 && monster->spawn[0].qty < 1)
) && (i++) < MAX_MOB_DB);
if(i >= MAX_MOB_DB) // no suitable monster found, use fallback for given list
- class_ = mob_db_data[0]->summonper[type];
+ class_ = mob->db_data[0]->summonper[type];
return class_;
}
/*==========================================
* Kill Steal Protection [Zephyrus]
*------------------------------------------*/
-bool mob_ksprotected (struct block_list *src, struct block_list *target)
-{
+bool mob_ksprotected(struct block_list *src, struct block_list *target) {
struct block_list *s_bl, *t_bl;
struct map_session_data
*sd, // Source
@@ -344,14 +349,14 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target)
*t_sd; // Mob Target
struct status_change_entry *sce;
struct mob_data *md;
- unsigned int tick = iTimer->gettick();
+ int64 tick = timer->gettick();
char output[128];
if( !battle_config.ksprotection )
return false; // KS Protection Disabled
if( !(md = BL_CAST(BL_MOB,target)) )
- return false; // Tarjet is not MOB
+ return false; // Target is not MOB
if( (s_bl = battle->get_master(src)) == NULL )
s_bl = src;
@@ -359,14 +364,14 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target)
if( !(sd = BL_CAST(BL_PC,s_bl)) )
return false; // Master is not PC
- t_bl = iMap->id2bl(md->target_id);
+ t_bl = map->id2bl(md->target_id);
if( !t_bl || (s_bl = battle->get_master(t_bl)) == NULL )
s_bl = t_bl;
t_sd = BL_CAST(BL_PC,s_bl);
do {
- if( map[md->bl.m].flag.allowks || map_flag_ks(md->bl.m) )
+ if( map->list[md->bl.m].flag.allowks || map_flag_ks(md->bl.m) )
return false; // Ignores GVG, PVP and AllowKS map flags
if( md->db->mexp || md->master_id )
@@ -386,7 +391,7 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target)
(sce->val2 == 3 && sce->val4 && sce->val4 != t_sd->status.guild_id)) )
break;
- if( (pl_sd = iMap->id2sd(sce->val1)) == NULL || pl_sd->bl.m != md->bl.m )
+ if( (pl_sd = map->id2sd(sce->val1)) == NULL || pl_sd->bl.m != md->bl.m )
break;
if( !pl_sd->state.noks )
@@ -396,7 +401,7 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target)
if( DIFF_TICK(sd->ks_floodprotect_tick, tick) <= 0 )
{
sprintf(output, "[KS Warning!! - Owner : %s]", pl_sd->status.name);
- clif->disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
sd->ks_floodprotect_tick = tick + 2000;
}
@@ -405,7 +410,7 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target)
if( DIFF_TICK(pl_sd->ks_floodprotect_tick, tick) <= 0 )
{
sprintf(output, "[Watch out! %s is trying to KS you!]", sd->status.name);
- clif->disp_onlyself(pl_sd, output, strlen(output));
+ clif_disp_onlyself(pl_sd, output, strlen(output));
pl_sd->ks_floodprotect_tick = tick + 2000;
}
@@ -413,7 +418,7 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target)
return true;
} while(0);
- status_change_start(target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks, sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, 0);
+ status->change_start(NULL, target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks, sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, 0);
return false;
}
@@ -442,68 +447,67 @@ struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int
// Locate spot next to player.
if (bl && (x < 0 || y < 0))
- iMap->search_freecell(bl, m, &x, &y, 1, 1, 0);
+ map->search_freecell(bl, m, &x, &y, 1, 1, 0);
// if none found, pick random position on map
- if (x <= 0 || y <= 0 || iMap->getcell(m,x,y,CELL_CHKNOREACH))
- iMap->search_freecell(NULL, m, &x, &y, -1, -1, 1);
+ if (x <= 0 || x >= map->list[m].xs || y <= 0 || y >= map->list[m].ys)
+ map->search_freecell(NULL, m, &x, &y, -1, -1, 1);
data.x = x;
data.y = y;
- if (!mob_parse_dataset(&data))
+ if (!mob->parse_dataset(&data))
return NULL;
- return mob_spawn_dataset(&data);
+ return mob->spawn_dataset(&data);
}
/*==========================================
* Spawn a single mob on the specified coordinates.
*------------------------------------------*/
-int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai)
-{
+int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai) {
struct mob_data* md = NULL;
int count, lv;
+ bool no_guardian_data = false;
+
+ if( ai && ai&0x200 ) {
+ no_guardian_data = true;
+ ai &=~ 0x200;
+ }
if (m < 0 || amount <= 0)
return 0; // invalid input
lv = (sd) ? sd->status.base_level : 255;
- for (count = 0; count < amount; count++)
- {
- int c = (class_ >= 0) ? class_ : mob_get_random_id(-class_ - 1, (battle_config.random_monster_checklv) ? 3 : 1, lv);
- md = mob_once_spawn_sub((sd) ? &sd->bl : NULL, m, x, y, mobname, c, event, size, ai);
+ for (count = 0; count < amount; count++) {
+ int c = (class_ >= 0) ? class_ : mob->get_random_id(-class_ - 1, (battle_config.random_monster_checklv) ? 3 : 1, lv);
+ md = mob->once_spawn_sub((sd) ? &sd->bl : NULL, m, x, y, mobname, c, event, size, ai);
if (!md)
continue;
- if (class_ == MOBID_EMPERIUM)
- {
- struct guild_castle* gc = guild->mapindex2gc(map[m].index);
+ if ( class_ == MOBID_EMPERIUM && !no_guardian_data ) {
+ struct guild_castle* gc = guild->mapindex2gc(map_id2index(m));
struct guild* g = (gc) ? guild->search(gc->guild_id) : NULL;
- if (gc)
- {
+ if( gc ) {
md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data));
md->guardian_data->castle = gc;
md->guardian_data->number = MAX_GUARDIANS;
- md->guardian_data->guild_id = gc->guild_id;
- if (g)
- {
- md->guardian_data->emblem_id = g->emblem_id;
- memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH);
- }
- else if (gc->guild_id) //Guild not yet available, retry in 5.
- iTimer->add_timer(iTimer->gettick()+5000,mob_spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id);
+ if( g )
+ md->guardian_data->g = g;
+ else if( gc->guild_id ) //Guild not yet available, retry in 5.
+ timer->add(timer->gettick()+5000,mob->spawn_guardian_sub,md->bl.id,gc->guild_id);
}
} // end addition [Valaris]
- mob_spawn(md);
+ mob->spawn(md);
- if (class_ < 0 && battle_config.dead_branch_active)
+ if (class_ < 0 && battle_config.dead_branch_active) {
//Behold Aegis's masterful decisions yet again...
//"I understand the "Aggressive" part, but the "Can Move" and "Can Attack" is just stupid" - Poki#3
- sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE|MD_ANGRY, 0, 60000);
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE|MD_ANGRY, 0, 60000);
+ }
}
return (md) ? md->bl.id : 0; // id of last spawned mob
@@ -542,7 +546,7 @@ int mob_once_spawn_area(struct map_session_data* sd, int16 m, int16 x0, int16 y0
x = rnd()%(x1-x0+1)+x0;
y = rnd()%(y1-y0+1)+y0;
j++;
- } while (iMap->getcell(m,x,y,CELL_CHKNOPASS) && j < max);
+ } while (map->getcell(m,x,y,CELL_CHKNOPASS) && j < max);
if (j == max)
{// attempt to find an available cell failed
@@ -558,26 +562,28 @@ int mob_once_spawn_area(struct map_session_data* sd, int16 m, int16 x0, int16 y0
lx = x;
ly = y;
- id = mob_once_spawn(sd, m, x, y, mobname, class_, 1, event, size, ai);
+ id = mob->once_spawn(sd, m, x, y, mobname, class_, 1, event, size, ai);
}
return id; // id of last spawned mob
}
-/*==========================================
- * Set a Guardian's guild data [Skotlex]
- *------------------------------------------*/
-static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t data)
-{ //Needed because the guild_data may not be available at guardian spawn time.
- struct block_list* bl = iMap->id2bl(id);
+
+/**
+ * Sets a guardian's guild data and liberates castle if couldn't retrieve guild data
+ * @param data (int)guild_id
+ * @retval Always 0
+ * @author Skotlex
+ **/
+int mob_spawn_guardian_sub(int tid, int64 tick, int id, intptr_t data) {
+ //Needed because the guild data may not be available at guardian spawn time.
+ struct block_list* bl = map->id2bl(id);
struct mob_data* md;
struct guild* g;
- int guardup_lv;
- if (bl == NULL) //It is possible mob was already removed from map when the castle has no owner. [Skotlex]
+ if( bl == NULL ) //It is possible mob was already removed from map when the castle has no owner. [Skotlex]
return 0;
- if (bl->type != BL_MOB)
- {
+ if( bl->type != BL_MOB ) {
ShowError("mob_spawn_guardian_sub: Block error!\n");
return 0;
}
@@ -586,30 +592,28 @@ static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t d
nullpo_ret(md->guardian_data);
g = guild->search((int)data);
- if (g == NULL)
- { //Liberate castle, if the guild is not found this is an error! [Skotlex]
+ if( g == NULL ) { //Liberate castle, if the guild is not found this is an error! [Skotlex]
ShowError("mob_spawn_guardian_sub: Couldn't load guild %d!\n", (int)data);
- if (md->class_ == MOBID_EMPERIUM)
- { //Not sure this is the best way, but otherwise we'd be invoking this for ALL guardians spawned later on.
- md->guardian_data->guild_id = 0;
- if (md->guardian_data->castle->guild_id) //Free castle up.
- {
+ //Not sure this is the best way, but otherwise we'd be invoking this for ALL guardians spawned later on.
+ if( md->class_ == MOBID_EMPERIUM && md->guardian_data ) {
+ md->guardian_data->g = NULL;
+ if( md->guardian_data->castle->guild_id ) {//Free castle up.
ShowNotice("Clearing ownership of castle %d (%s)\n", md->guardian_data->castle->castle_id, md->guardian_data->castle->castle_name);
guild->castledatasave(md->guardian_data->castle->castle_id, 1, 0);
}
} else {
- if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible)
+ if( md->guardian_data && md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS
+ && md->guardian_data->castle->guardian[md->guardian_data->number].visible )
guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
- unit_free(&md->bl,CLR_OUTSIGHT); //Remove guardian.
+
+ unit->free(&md->bl,CLR_OUTSIGHT); // Remove guardian.
}
return 0;
}
- guardup_lv = guild->checkskill(g,GD_GUARDUP);
- md->guardian_data->emblem_id = g->emblem_id;
- memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH);
- md->guardian_data->guardup_lv = guardup_lv;
- if( guardup_lv )
- status_calc_mob(md, 0); //Give bonuses.
+
+ if( guild->checkskill(g,GD_GUARDUP) )
+ status_calc_mob(md, SCO_NONE); // Give bonuses.
+
return 0;
}
@@ -626,7 +630,7 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam
memset(&data, 0, sizeof(struct spawn_data));
data.num = 1;
- m=iMap->mapname2mapid(mapname);
+ m=map->mapname2mapid(mapname);
if(m<0)
{
@@ -636,60 +640,55 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam
data.m = m;
data.num = 1;
if(class_<=0) {
- class_ = mob_get_random_id(-class_-1, 1, 99);
+ class_ = mob->get_random_id(-class_-1, 1, 99);
if (!class_) return 0;
}
data.class_ = class_;
- if( !has_index )
- {
+ if( !has_index ) {
guardian = -1;
- }
- else if( guardian < 0 || guardian >= MAX_GUARDIANS )
- {
- ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, class_, map[m].name);
+ } else if( guardian < 0 || guardian >= MAX_GUARDIANS ) {
+ ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, class_, map->list[m].name);
return 0;
}
- if((x<=0 || y<=0) && !iMap->search_freecell(NULL, m, &x, &y, -1,-1, 1))
- {
- ShowWarning("mob_spawn_guardian: Couldn't locate a spawn cell for guardian class %d (index %d) at castle map %s\n",class_, guardian, map[m].name);
+ if((x<=0 || y<=0) && !map->search_freecell(NULL, m, &x, &y, -1,-1, 1)) {
+ ShowWarning("mob_spawn_guardian: Couldn't locate a spawn cell for guardian class %d (index %d) at castle map %s\n",class_, guardian, map->list[m].name);
return 0;
}
data.x = x;
data.y = y;
safestrncpy(data.name, mobname, sizeof(data.name));
safestrncpy(data.eventname, event, sizeof(data.eventname));
- if (!mob_parse_dataset(&data))
+ if (!mob->parse_dataset(&data))
return 0;
- gc=guild->mapname2gc(map[m].name);
- if (gc == NULL)
- {
- ShowError("mob_spawn_guardian: No castle set at map %s\n", map[m].name);
+ gc=guild->mapname2gc(map->list[m].name);
+ if (gc == NULL) {
+ ShowError("mob_spawn_guardian: No castle set at map %s\n", map->list[m].name);
return 0;
}
if (!gc->guild_id)
- ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle with no guild (castle map %s)\n", class_, map[m].name);
+ ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle with no guild (castle map %s)\n", class_, map->list[m].name);
else
g = guild->search(gc->guild_id);
if( has_index && gc->guardian[guardian].id )
{ //Check if guardian already exists, refuse to spawn if so.
- struct mob_data *md2 = (TBL_MOB*)iMap->id2bl(gc->guardian[guardian].id);
- if (md2 && md2->bl.type == BL_MOB &&
- md2->guardian_data && md2->guardian_data->number == guardian)
- {
- ShowError("mob_spawn_guardian: Attempted to spawn guardian in position %d which already has a guardian (castle map %s)\n", guardian, map[m].name);
+ struct mob_data *md2 = (TBL_MOB*)map->id2bl(gc->guardian[guardian].id);
+ if (md2 && md2->bl.type == BL_MOB
+ && md2->guardian_data
+ && md2->guardian_data->number == guardian
+ ) {
+ ShowError("mob_spawn_guardian: Attempted to spawn guardian in position %d which already has a guardian (castle map %s)\n", guardian, map->list[m].name);
return 0;
}
}
- md = mob_spawn_dataset(&data);
+ md = mob->spawn_dataset(&data);
md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data));
md->guardian_data->number = guardian;
- md->guardian_data->guild_id = gc->guild_id;
md->guardian_data->castle = gc;
if( has_index )
{// permanent guardian
@@ -706,14 +705,11 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam
}
gc->temp_guardians[i] = md->bl.id;
}
- if (g)
- {
- md->guardian_data->emblem_id = g->emblem_id;
- memcpy (md->guardian_data->guild_name, g->name, NAME_LENGTH);
- md->guardian_data->guardup_lv = guild->checkskill(g,GD_GUARDUP);
- } else if (md->guardian_data->guild_id)
- iTimer->add_timer(iTimer->gettick()+5000,mob_spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id);
- mob_spawn(md);
+ if( g )
+ md->guardian_data->g = g;
+ else if( gc->guild_id )
+ timer->add(timer->gettick()+5000,mob->spawn_guardian_sub,md->bl.id,gc->guild_id);
+ mob->spawn(md);
return md->bl.id;
}
@@ -727,8 +723,7 @@ int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int
struct spawn_data data;
int16 m;
- if( (m = iMap->mapname2mapid(mapname)) < 0 )
- {
+ if( (m = map->mapname2mapid(mapname)) < 0 ) {
ShowWarning("mob_spawn_bg: Map [%s] not found.\n", mapname);
return 0;
}
@@ -738,14 +733,13 @@ int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int
data.num = 1;
if( class_ <= 0 )
{
- class_ = mob_get_random_id(-class_-1,1,99);
+ class_ = mob->get_random_id(-class_-1,1,99);
if( !class_ ) return 0;
}
data.class_ = class_;
- if( (x <= 0 || y <= 0) && !iMap->search_freecell(NULL, m, &x, &y, -1,-1, 1) )
- {
- ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %d) at map %s\n",class_, bg_id, map[m].name);
+ if( (x <= 0 || y <= 0) && !map->search_freecell(NULL, m, &x, &y, -1,-1, 1) ) {
+ ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %d) at map %s\n",class_, bg_id, map->list[m].name);
return 0;
}
@@ -753,11 +747,11 @@ int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int
data.y = y;
safestrncpy(data.name, mobname, sizeof(data.name));
safestrncpy(data.eventname, event, sizeof(data.eventname));
- if( !mob_parse_dataset(&data) )
+ if( !mob->parse_dataset(&data) )
return 0;
- md = mob_spawn_dataset(&data);
- mob_spawn(md);
+ md = mob->spawn_dataset(&data);
+ mob->spawn(md);
md->bg_id = bg_id; // BG Team ID
return md->bl.id;
@@ -786,30 +780,29 @@ int mob_can_reach(struct mob_data *md,struct block_list *bl,int range, int state
easy = 1;
break;
}
- return unit_can_reach_bl(&md->bl, bl, range, easy, NULL, NULL);
+ return unit->can_reach_bl(&md->bl, bl, range, easy, NULL, NULL);
}
/*==========================================
* Links nearby mobs (supportive mobs)
*------------------------------------------*/
-int mob_linksearch(struct block_list *bl,va_list ap)
-{
+int mob_linksearch(struct block_list *bl,va_list ap) {
struct mob_data *md;
int class_;
struct block_list *target;
- unsigned int tick;
+ int64 tick;
nullpo_ret(bl);
md=(struct mob_data *)bl;
class_ = va_arg(ap, int);
target = va_arg(ap, struct block_list *);
- tick=va_arg(ap, unsigned int);
+ tick = va_arg(ap, int64);
if (md->class_ == class_ && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME
&& !md->target_id)
{
md->last_linktime = tick;
- if( mob_can_reach(md,target,md->db->range2, MSS_FOLLOW) ){ // Reachability judging
+ if( mob->can_reach(md,target,md->db->range2, MSS_FOLLOW) ){ // Reachability judging
md->target_id = target->id;
md->min_chase=md->db->range3;
return 1;
@@ -822,9 +815,8 @@ int mob_linksearch(struct block_list *bl,va_list ap)
/*==========================================
* mob spawn with delay (timer function)
*------------------------------------------*/
-int mob_delayspawn(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct block_list* bl = iMap->id2bl(id);
+int mob_delayspawn(int tid, int64 tick, int id, intptr_t data) {
+ struct block_list* bl = map->id2bl(id);
struct mob_data* md = BL_CAST(BL_MOB, bl);
if( md )
@@ -835,7 +827,7 @@ int mob_delayspawn(int tid, unsigned int tick, int id, intptr_t data)
return 0;
}
md->spawn_timer = INVALID_TIMER;
- mob_spawn(md);
+ mob->spawn(md);
}
return 0;
}
@@ -849,14 +841,14 @@ int mob_setdelayspawn(struct mob_data *md)
struct mob_db *db;
if (!md->spawn) //Doesn't has respawn data!
- return unit_free(&md->bl,CLR_DEAD);
+ return unit->free(&md->bl,CLR_DEAD);
spawntime = md->spawn->delay1; //Base respawn time
if (md->spawn->delay2) //random variance
spawntime+= rnd()%md->spawn->delay2;
//Apply the spawn delay fix [Skotlex]
- db = mob_db(md->spawn->class_);
+ db = mob->db(md->spawn->class_);
mode = db->status.mode;
if (mode & MD_BOSS) { //Bosses
if (battle_config.boss_spawn_delay != 100) {
@@ -876,20 +868,21 @@ int mob_setdelayspawn(struct mob_data *md)
spawntime = 5000;
if( md->spawn_timer != INVALID_TIMER )
- iTimer->delete_timer(md->spawn_timer, mob_delayspawn);
- md->spawn_timer = iTimer->add_timer(iTimer->gettick()+spawntime, mob_delayspawn, md->bl.id, 0);
+ timer->delete(md->spawn_timer, mob->delayspawn);
+ md->spawn_timer = timer->add(timer->gettick()+spawntime, mob->delayspawn, md->bl.id, 0);
return 0;
}
int mob_count_sub(struct block_list *bl, va_list ap) {
- int mobid[10], i;
- ARR_FIND(0, 10, i, (mobid[i] = va_arg(ap, int)) == 0); //fetch till 0
- if (mobid[0]) { //if there one let's check it otherwise go backward
- TBL_MOB *md = BL_CAST(BL_MOB, bl);
- ARR_FIND(0, 10, i, md->class_ == mobid[i]);
- return (i < 10) ? 1 : 0;
- }
- return 1; //backward compatibility
+ int mobid[10] = { 0 }, i;
+ ARR_FIND(0, 10, i, (mobid[i] = va_arg(ap, int)) == 0); //fetch till 0
+ if (mobid[0]) { //if there one let's check it otherwise go backward
+ TBL_MOB *md = BL_CAST(BL_MOB, bl);
+ nullpo_ret(md);
+ ARR_FIND(0, 10, i, md->class_ == mobid[i]);
+ return (i < 10) ? 1 : 0;
+ }
+ return 1; //backward compatibility
}
/*==========================================
@@ -898,18 +891,16 @@ int mob_count_sub(struct block_list *bl, va_list ap) {
int mob_spawn (struct mob_data *md)
{
int i=0;
- unsigned int tick = iTimer->gettick();
- int c =0;
+ int64 tick = timer->gettick();
+ int64 c = 0;
md->last_thinktime = tick;
if (md->bl.prev != NULL)
- unit_remove_map(&md->bl,CLR_RESPAWN);
- else
- if (md->spawn && md->class_ != md->spawn->class_)
- {
+ unit->remove_map(&md->bl,CLR_RESPAWN,ALC_MARK);
+ else if (md->spawn && md->class_ != md->spawn->class_) {
md->class_ = md->spawn->class_;
- status_set_viewdata(&md->bl, md->class_);
- md->db = mob_db(md->class_);
+ status->set_viewdata(&md->bl, md->class_);
+ md->db = mob->db(md->class_);
memcpy(md->name,md->spawn->name,NAME_LENGTH);
}
@@ -918,27 +909,26 @@ int mob_spawn (struct mob_data *md)
md->bl.x = md->spawn->x;
md->bl.y = md->spawn->y;
- if( (md->bl.x == 0 && md->bl.y == 0) || md->spawn->xs || md->spawn->ys )
- { //Monster can be spawned on an area.
- if( !iMap->search_freecell(&md->bl, -1, &md->bl.x, &md->bl.y, md->spawn->xs, md->spawn->ys, battle_config.no_spawn_on_player?4:0) )
- { // retry again later
+ if( (md->bl.x == 0 && md->bl.y == 0) || md->spawn->xs || md->spawn->ys ) {
+ //Monster can be spawned on an area.
+ if( !map->search_freecell(&md->bl, -1, &md->bl.x, &md->bl.y, md->spawn->xs, md->spawn->ys, battle_config.no_spawn_on_player?4:0) ) {
+ // retry again later
if( md->spawn_timer != INVALID_TIMER )
- iTimer->delete_timer(md->spawn_timer, mob_delayspawn);
- md->spawn_timer = iTimer->add_timer(tick+5000,mob_delayspawn,md->bl.id,0);
+ timer->delete(md->spawn_timer, mob->delayspawn);
+ md->spawn_timer = timer->add(tick+5000,mob->delayspawn,md->bl.id,0);
return 1;
}
- }
- else if( battle_config.no_spawn_on_player > 99 && iMap->foreachinrange(mob_count_sub, &md->bl, AREA_SIZE, BL_PC) )
- { // retry again later (players on sight)
+ } else if( battle_config.no_spawn_on_player > 99 && map->foreachinrange(mob->count_sub, &md->bl, AREA_SIZE, BL_PC) ) {
+ // retry again later (players on sight)
if( md->spawn_timer != INVALID_TIMER )
- iTimer->delete_timer(md->spawn_timer, mob_delayspawn);
- md->spawn_timer = iTimer->add_timer(tick+5000,mob_delayspawn,md->bl.id,0);
+ timer->delete(md->spawn_timer, mob->delayspawn);
+ md->spawn_timer = timer->add(tick+5000,mob->delayspawn,md->bl.id,0);
return 1;
}
}
memset(&md->state, 0, sizeof(md->state));
- status_calc_mob(md, 1);
+ status_calc_mob(md, SCO_FIRST);
md->attacked_id = 0;
md->target_id = 0;
md->move_fail_count = 0;
@@ -946,7 +936,7 @@ int mob_spawn (struct mob_data *md)
md->ud.target_to = 0;
if( md->spawn_timer != INVALID_TIMER )
{
- iTimer->delete_timer(md->spawn_timer, mob_delayspawn);
+ timer->delete(md->spawn_timer, mob->delayspawn);
md->spawn_timer = INVALID_TIMER;
}
@@ -977,20 +967,20 @@ int mob_spawn (struct mob_data *md)
// MvP tomb [GreenBox]
if ( md->tomb_nid )
- mvptomb_destroy(md);
+ mob->mvptomb_destroy(md);
- iMap->addblock(&md->bl);
- if( map[md->bl.m].users )
+ map->addblock(&md->bl);
+ if( map->list[md->bl.m].users )
clif->spawn(&md->bl);
skill->unit_move(&md->bl,tick,1);
- mobskill_use(md, tick, MSC_SPAWN);
+ mob->skill_use(md, tick, MSC_SPAWN);
return 0;
}
/*==========================================
* Determines if the mob can change target. [Skotlex]
*------------------------------------------*/
-static int mob_can_changetarget(struct mob_data* md, struct block_list* target, int mode)
+int mob_can_changetarget(struct mob_data* md, struct block_list* target, int mode)
{
// if the monster was provoked ignore the above rule [celest]
if(md->state.provoke_flag)
@@ -1028,10 +1018,10 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist)
nullpo_ret(bl);
// Nothing will be carried out if there is no mind of changing TAGE by TAGE ending.
- if(md->target_id && !mob_can_changetarget(md, bl, status_get_mode(&md->bl)))
+ if(md->target_id && !mob->can_changetarget(md, bl, status_get_mode(&md->bl)))
return 0;
- if(!status_check_skilluse(&md->bl, bl, 0, 0))
+ if(!status->check_skilluse(&md->bl, bl, 0, 0))
return 0;
md->target_id = bl->id; // Since there was no disturbance, it locks on to target.
@@ -1046,7 +1036,7 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist)
/*==========================================
* The ?? routine of an active monster
*------------------------------------------*/
-static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
+int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
{
struct mob_data *md;
struct block_list **target;
@@ -1059,48 +1049,47 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
mode= va_arg(ap,int);
//If can't seek yet, not an enemy, or you can't attack it, skip.
- if ((*target) == bl || !status_check_skilluse(&md->bl, bl, 0, 0))
+ if (md->bl.id == bl->id || (*target) == bl || !status->check_skilluse(&md->bl, bl, 0, 0))
return 0;
- if ((mode&MD_TARGETWEAK) && status_get_lv(bl) >= md->level-5)
+ if ((mode&MD_TARGETWEAK) && status->get_lv(bl) >= md->level-5)
return 0;
if(battle->check_target(&md->bl,bl,BCT_ENEMY)<=0)
return 0;
- switch (bl->type)
- {
- case BL_PC:
- if (((TBL_PC*)bl)->state.gangsterparadise &&
- !(status_get_mode(&md->bl)&MD_BOSS))
- return 0; //Gangster paradise protection.
- default:
- if (battle_config.hom_setting&0x4 &&
- (*target) && (*target)->type == BL_HOM && bl->type != BL_HOM)
- return 0; //For some reason Homun targets are never overriden.
+ switch (bl->type) {
+ case BL_PC:
+ if (((TBL_PC*)bl)->state.gangsterparadise &&
+ !(status_get_mode(&md->bl)&MD_BOSS))
+ return 0; //Gangster paradise protection.
+ default:
+ if (battle_config.hom_setting&0x4 &&
+ (*target) && (*target)->type == BL_HOM && bl->type != BL_HOM)
+ return 0; //For some reason Homun targets are never overridden.
- dist = distance_bl(&md->bl, bl);
- if(
- ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) &&
- battle->check_range(&md->bl,bl,md->db->range2)
- ) { //Pick closest target?
+ dist = distance_bl(&md->bl, bl);
+ if(
+ ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) &&
+ battle->check_range(&md->bl,bl,md->db->range2)
+ ) { //Pick closest target?
- if( map[bl->m].icewall_num &&
- !path_search_long(NULL,bl->m,md->bl.x,md->bl.y,bl->x,bl->y,CELL_CHKICEWALL) ) {
+ if( map->list[bl->m].icewall_num &&
+ !path->search_long(NULL,bl->m,md->bl.x,md->bl.y,bl->x,bl->y,CELL_CHKICEWALL) ) {
- if( !check_distance_bl(&md->bl, bl, status_get_range(&md->bl) ) )
- return 0;
+ if( !check_distance_bl(&md->bl, bl, status_get_range(&md->bl) ) )
+ return 0;
- }
+ }
- (*target) = bl;
- md->target_id=bl->id;
- md->min_chase= dist + md->db->range3;
- if(md->min_chase>MAX_MINCHASE)
- md->min_chase=MAX_MINCHASE;
- return 1;
- }
- break;
+ (*target) = bl;
+ md->target_id=bl->id;
+ md->min_chase= dist + md->db->range3;
+ if(md->min_chase>MAX_MINCHASE)
+ md->min_chase=MAX_MINCHASE;
+ return 1;
+ }
+ break;
}
return 0;
}
@@ -1108,8 +1097,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
/*==========================================
* chase target-change routine.
*------------------------------------------*/
-static int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap)
-{
+int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap) {
struct mob_data *md;
struct block_list **target;
@@ -1118,9 +1106,10 @@ static int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap)
target= va_arg(ap,struct block_list**);
//If can't seek yet, not an enemy, or you can't attack it, skip.
- if ((*target) == bl ||
- battle->check_target(&md->bl,bl,BCT_ENEMY)<=0 ||
- !status_check_skilluse(&md->bl, bl, 0, 0))
+ if( md->bl.id == bl->id || *target == bl
+ || battle->check_target(&md->bl,bl,BCT_ENEMY) <= 0
+ || !status->check_skilluse(&md->bl, bl, 0, 0)
+ )
return 0;
if(battle->check_range (&md->bl, bl, md->status.rhw.range)) {
@@ -1134,7 +1123,7 @@ static int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap)
/*==========================================
* finds nearby bg ally for guardians looking for users to follow.
*------------------------------------------*/
-static int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) {
+int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) {
struct mob_data *md;
struct block_list **target;
@@ -1142,7 +1131,7 @@ static int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) {
md=va_arg(ap,struct mob_data *);
target= va_arg(ap,struct block_list**);
- if( status_check_skilluse(&md->bl, bl, 0, 0) && battle->check_target(&md->bl,bl,BCT_ENEMY)<=0 ) {
+ if( status->check_skilluse(&md->bl, bl, 0, 0) && battle->check_target(&md->bl,bl,BCT_ENEMY)<=0 ) {
(*target) = bl;
}
return 1;
@@ -1151,7 +1140,7 @@ static int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) {
/*==========================================
* loot monster item search
*------------------------------------------*/
-static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
+int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
{
struct mob_data* md;
struct block_list **target;
@@ -1161,7 +1150,7 @@ static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
target= va_arg(ap,struct block_list**);
dist=distance_bl(&md->bl, bl);
- if(mob_can_reach(md,bl,dist+1, MSS_LOOT) &&
+ if(mob->can_reach(md,bl,dist+1, MSS_LOOT) &&
((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) //New target closer than previous one.
) {
(*target) = bl;
@@ -1171,7 +1160,7 @@ static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
return 0;
}
-static int mob_warpchase_sub(struct block_list *bl,va_list ap) {
+int mob_warpchase_sub(struct block_list *bl,va_list ap) {
struct block_list *target;
struct npc_data **target_nd;
struct npc_data *nd;
@@ -1187,12 +1176,12 @@ static int mob_warpchase_sub(struct block_list *bl,va_list ap) {
if(nd->subtype != WARP)
return 0; //Not a warp
- if(nd->u.warp.mapindex != map[target->m].index)
+ if(nd->u.warp.mapindex != map_id2index(target->m))
return 0; //Does not lead to the same map.
cur_distance = distance_blxy(target, nd->u.warp.x, nd->u.warp.y);
- if (cur_distance < *min_distance)
- { //Pick warp that leads closest to target.
+ if (cur_distance < *min_distance) {
+ //Pick warp that leads closest to target.
*target_nd = nd;
*min_distance = cur_distance;
return 1;
@@ -1202,13 +1191,12 @@ static int mob_warpchase_sub(struct block_list *bl,va_list ap) {
/*==========================================
* Processing of slave monsters
*------------------------------------------*/
-static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
-{
+int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) {
struct block_list *bl;
- bl=iMap->id2bl(md->master_id);
+ bl=map->id2bl(md->master_id);
- if (!bl || status_isdead(bl)) {
+ if (!bl || status->isdead(bl)) {
status_kill(&md->bl);
return 1;
}
@@ -1229,7 +1217,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
md->master_dist > MAX_MINCHASE
){
md->master_dist = 0;
- unit_warp(&md->bl,bl->m,bl->x,bl->y,CLR_TELEPORT);
+ unit->warp(&md->bl,bl->m,bl->x,bl->y,CLR_TELEPORT);
return 1;
}
@@ -1237,13 +1225,13 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
return 0;
// Approach master if within view range, chase back to Master's area also if standing on top of the master.
- if((md->master_dist>MOB_SLAVEDISTANCE || md->master_dist == 0) &&
- unit_can_move(&md->bl))
- {
+ if( (md->master_dist>MOB_SLAVEDISTANCE || md->master_dist == 0)
+ && unit->can_move(&md->bl)
+ ) {
short x = bl->x, y = bl->y;
mob_stop_attack(md);
- if(iMap->search_freecell(&md->bl, bl->m, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 1)
- && unit_walktoxy(&md->bl, x, y, 0))
+ if(map->search_freecell(&md->bl, bl->m, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 1)
+ && unit->walktoxy(&md->bl, x, y, 0))
return 1;
}
} else if (bl->m != md->bl.m && map_flag_gvg(md->bl.m)) {
@@ -1255,20 +1243,20 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
//Avoid attempting to lock the master's target too often to avoid unnecessary overload. [Skotlex]
if (DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME && !md->target_id)
{
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
md->last_linktime = tick;
if (ud) {
struct block_list *tbl=NULL;
if (ud->target && ud->state.attack_continue)
- tbl=iMap->id2bl(ud->target);
+ tbl=map->id2bl(ud->target);
else if (ud->skilltarget) {
- tbl = iMap->id2bl(ud->skilltarget);
+ tbl = map->id2bl(ud->skilltarget);
//Required check as skilltarget is not always an enemy. [Skotlex]
if (tbl && battle->check_target(&md->bl, tbl, BCT_ENEMY) <= 0)
tbl = NULL;
}
- if (tbl && status_check_skilluse(&md->bl, tbl, 0, 0)) {
+ if (tbl && status->check_skilluse(&md->bl, tbl, 0, 0)) {
md->target_id=tbl->id;
md->min_chase=md->db->range3+distance_bl(&md->bl, tbl);
if(md->min_chase>MAX_MINCHASE)
@@ -1286,8 +1274,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
* when trying to pick new targets when the current chosen target is
* unreachable.
*------------------------------------------*/
-int mob_unlocktarget(struct mob_data *md, unsigned int tick)
-{
+int mob_unlocktarget(struct mob_data *md, int64 tick) {
nullpo_ret(md);
switch (md->state.skillstate) {
@@ -1299,12 +1286,12 @@ int mob_unlocktarget(struct mob_data *md, unsigned int tick)
case MSS_IDLE:
// Idle skill.
if ((md->target_id || !(++md->ud.walk_count%IDLE_SKILL_INTERVAL)) &&
- mobskill_use(md, tick, -1))
+ mob->skill_use(md, tick, -1))
break;
//Random walk.
if (!md->master_id &&
DIFF_TICK(md->next_walktime, tick) <= 0 &&
- !mob_randomwalk(md,tick))
+ !mob->randomwalk(md,tick))
//Delay next random walk when this one failed.
md->next_walktime=tick+rnd()%3000;
break;
@@ -1319,15 +1306,14 @@ int mob_unlocktarget(struct mob_data *md, unsigned int tick)
if (md->target_id) {
md->target_id=0;
md->ud.target_to = 0;
- unit_set_target(&md->ud, 0);
+ unit->set_target(&md->ud, 0);
}
return 0;
}
/*==========================================
* Random walk
*------------------------------------------*/
-int mob_randomwalk(struct mob_data *md,unsigned int tick)
-{
+int mob_randomwalk(struct mob_data *md, int64 tick) {
const int retrycount=20;
int i,x,y,c,d;
int speed;
@@ -1335,7 +1321,7 @@ int mob_randomwalk(struct mob_data *md,unsigned int tick)
nullpo_ret(md);
if(DIFF_TICK(md->next_walktime,tick)>0 ||
- !unit_can_move(&md->bl) ||
+ !unit->can_move(&md->bl) ||
!(status_get_mode(&md->bl)&MD_CANMOVE))
return 0;
@@ -1348,23 +1334,24 @@ int mob_randomwalk(struct mob_data *md,unsigned int tick)
x+=md->bl.x;
y+=md->bl.y;
- if((iMap->getcell(md->bl.m,x,y,CELL_CHKPASS)) && unit_walktoxy(&md->bl,x,y,1)){
+ if((map->getcell(md->bl.m,x,y,CELL_CHKPASS)) && unit->walktoxy(&md->bl,x,y,1)){
break;
}
}
if(i==retrycount){
md->move_fail_count++;
if(md->move_fail_count>1000){
- ShowWarning("MOB can't move. random spawn %d, class = %d, at %s (%d,%d)\n",md->bl.id,md->class_,map[md->bl.m].name, md->bl.x, md->bl.y);
+ ShowWarning("MOB can't move. random spawn %d, class = %d, at %s (%d,%d)\n",md->bl.id,md->class_,map->list[md->bl.m].name, md->bl.x, md->bl.y);
md->move_fail_count=0;
- mob_spawn(md);
+ mob->spawn(md);
}
return 0;
}
- speed=status_get_speed(&md->bl);
- for(i=c=0;i<md->ud.walkpath.path_len;i++){ // The next walk start time is calculated.
+ speed=status->get_speed(&md->bl);
+ for(i=c=0;i<md->ud.walkpath.path_len;i++) {
+ // The next walk start time is calculated.
if(md->ud.walkpath.path[i]&1)
- c+=speed*14/10;
+ c+=speed*MOVE_DIAGONAL_COST/MOVE_COST;
else
c+=speed;
}
@@ -1385,14 +1372,14 @@ int mob_warpchase(struct mob_data *md, struct block_list *target)
return 0; //No need to do a warp chase.
if (md->ud.walktimer != INVALID_TIMER &&
- iMap->getcell(md->bl.m,md->ud.to_x,md->ud.to_y,CELL_CHKNPC))
+ map->getcell(md->bl.m,md->ud.to_x,md->ud.to_y,CELL_CHKNPC))
return 1; //Already walking to a warp.
//Search for warps within mob's viewing range.
- iMap->foreachinrange (mob_warpchase_sub, &md->bl,
- md->db->range2, BL_NPC, target, &warp, &distance);
+ map->foreachinrange(mob->warpchase_sub, &md->bl,
+ md->db->range2, BL_NPC, target, &warp, &distance);
- if (warp && unit_walktobl(&md->bl, &warp->bl, 1, 1))
+ if (warp && unit->walktobl(&md->bl, &warp->bl, 1, 1))
return 1;
return 0;
}
@@ -1400,8 +1387,7 @@ int mob_warpchase(struct mob_data *md, struct block_list *target)
/*==========================================
* AI of MOB whose is near a Player
*------------------------------------------*/
-static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
-{
+bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
struct block_list *tbl = NULL, *abl = NULL;
int mode;
int view_range, can_move;
@@ -1422,7 +1408,8 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
// Abnormalities
if(( md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE )
- || md->sc.data[SC_BLADESTOP] || md->sc.data[SC__MANHOLE] || md->sc.data[SC_CURSEDCIRCLE_TARGET]) {//Should reset targets.
+ || md->sc.data[SC_DEEP_SLEEP] || md->sc.data[SC_BLADESTOP] || md->sc.data[SC__MANHOLE] || md->sc.data[SC_CURSEDCIRCLE_TARGET]) {
+ //Should reset targets.
md->target_id = md->attacked_id = 0;
return false;
}
@@ -1433,22 +1420,23 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
view_range = md->db->range2;
mode = status_get_mode(&md->bl);
- can_move = (mode&MD_CANMOVE)&&unit_can_move(&md->bl);
-
- if (md->target_id)
- { //Check validity of current target. [Skotlex]
- tbl = iMap->id2bl(md->target_id);
- if (!tbl || tbl->m != md->bl.m ||
- (md->ud.attacktimer == INVALID_TIMER && !status_check_skilluse(&md->bl, tbl, 0, 0)) ||
- (md->ud.walktimer != INVALID_TIMER && !(battle_config.mob_ai&0x1) && !check_distance_bl(&md->bl, tbl, md->min_chase)) ||
- (
- tbl->type == BL_PC &&
- ((((TBL_PC*)tbl)->state.gangsterparadise && !(mode&MD_BOSS)) ||
- ((TBL_PC*)tbl)->invincible_timer != INVALID_TIMER)
- )) { //Unlock current target.
- if (mob_warpchase(md, tbl))
+ can_move = (mode&MD_CANMOVE)&&unit->can_move(&md->bl);
+
+ if (md->target_id) {
+ //Check validity of current target. [Skotlex]
+ tbl = map->id2bl(md->target_id);
+ if (!tbl || tbl->m != md->bl.m
+ || (md->ud.attacktimer == INVALID_TIMER && !status->check_skilluse(&md->bl, tbl, 0, 0))
+ || (md->ud.walktimer != INVALID_TIMER && !(battle_config.mob_ai&0x1) && !check_distance_bl(&md->bl, tbl, md->min_chase))
+ || ( tbl->type == BL_PC
+ && ((((TBL_PC*)tbl)->state.gangsterparadise && !(mode&MD_BOSS))
+ || ((TBL_PC*)tbl)->invincible_timer != INVALID_TIMER)
+ )
+ ) {
+ //Unlock current target.
+ if (mob->warpchase(md, tbl))
return true; //Chasing this target.
- mob_unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Imediately do random walk.
+ mob->unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Immediately do random walk.
tbl = NULL;
}
}
@@ -1463,36 +1451,36 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
(!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1)
|| md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP]
|| md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target.
- || !mob_can_reach(md, tbl, md->min_chase, MSS_RUSH)
+ || !mob->can_reach(md, tbl, md->min_chase, MSS_RUSH)
)
&& md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
- && !mobskill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack
- && can_move && unit_escape(&md->bl, tbl, rnd()%10 +1)) // Attempt escape
+ && !mob->skill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack
+ && can_move && unit->escape(&md->bl, tbl, rnd()%10 +1)) // Attempt escape
{ //Escaped
md->attacked_id = 0;
return true;
}
}
else
- if( (abl = iMap->id2bl(md->attacked_id)) && (!tbl || mob_can_changetarget(md, abl, mode)) )
- {
+ if( (abl = map->id2bl(md->attacked_id)) && (!tbl || mob->can_changetarget(md, abl, mode) || (md->sc.count && md->sc.data[SC__CHAOS]))) {
int dist;
if( md->bl.m != abl->m || abl->prev == NULL
- || (dist = distance_bl(&md->bl, abl)) >= MAX_MINCHASE // Attacker longer than visual area
- || battle->check_target(&md->bl, abl, BCT_ENEMY) <= 0 // Attacker is not enemy of mob
- || (battle_config.mob_ai&0x2 && !status_check_skilluse(&md->bl, abl, 0, 0)) // Cannot normal attack back to Attacker
- || (!battle->check_range(&md->bl, abl, md->status.rhw.range) // Not on Melee Range and ...
- && ( // Reach check
- (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1)
- || md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP]
- || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target.
- || !mob_can_reach(md, abl, dist+md->db->range3, MSS_RUSH)
- )
- ) )
- { // Rude attacked
+ || (dist = distance_bl(&md->bl, abl)) >= MAX_MINCHASE // Attacker longer than visual area
+ || battle->check_target(&md->bl, abl, BCT_ENEMY) <= 0 // Attacker is not enemy of mob
+ || (battle_config.mob_ai&0x2 && !status->check_skilluse(&md->bl, abl, 0, 0)) // Cannot normal attack back to Attacker
+ || (!battle->check_range(&md->bl, abl, md->status.rhw.range) // Not on Melee Range and ...
+ && ( // Reach check
+ (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1)
+ || md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP]
+ || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target.
+ || !mob->can_reach(md, abl, dist+md->db->range3, MSS_RUSH)
+ )
+ )
+ ) {
+ // Rude attacked
if (md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
- && !mobskill_use(md, tick, MSC_RUDEATTACKED) && can_move
- && !tbl && unit_escape(&md->bl, abl, rnd()%10 +1))
+ && !mob->skill_use(md, tick, MSC_RUDEATTACKED) && can_move
+ && !tbl && unit->escape(&md->bl, abl, rnd()%10 +1))
{ //Escaped.
//TODO: Maybe it shouldn't attempt to run if it has another, valid target?
md->attacked_id = 0;
@@ -1500,12 +1488,10 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
}
}
else
- if (!(battle_config.mob_ai&0x2) && !status_check_skilluse(&md->bl, abl, 0, 0))
- {
+ if (!(battle_config.mob_ai&0x2) && !status->check_skilluse(&md->bl, abl, 0, 0)) {
//Can't attack back, but didn't invoke a rude attacked skill...
- }
- else
- { //Attackable
+ } else {
+ //Attackable
if (!tbl || dist < md->status.rhw.range || !check_distance_bl(&md->bl, tbl, dist)
|| battle->get_target(tbl) != md->bl.id)
{ //Change if the new target is closer than the actual one
@@ -1526,26 +1512,23 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
}
// Processing of slave monster
- if (md->master_id > 0 && mob_ai_sub_hard_slavemob(md, tick))
+ if (md->master_id > 0 && mob->ai_sub_hard_slavemob(md, tick))
return true;
// Scan area for targets
- if (!tbl && mode&MD_LOOTER && md->lootitem && DIFF_TICK(tick, md->ud.canact_tick) > 0 &&
- (md->lootitem_count < LOOTITEM_SIZE || battle_config.monster_loot_type != 1))
- { // Scan area for items to loot, avoid trying to loot if the mob is full and can't consume the items.
- iMap->foreachinrange (mob_ai_sub_hard_lootsearch, &md->bl, view_range, BL_ITEM, md, &tbl);
+ if (!tbl && mode&MD_LOOTER && md->lootitem && DIFF_TICK(tick, md->ud.canact_tick) > 0
+ && (md->lootitem_count < LOOTITEM_SIZE || battle_config.monster_loot_type != 1)
+ ) {
+ // Scan area for items to loot, avoid trying to loot if the mob is full and can't consume the items.
+ map->foreachinrange (mob->ai_sub_hard_lootsearch, &md->bl, view_range, BL_ITEM, md, &tbl);
}
- if ((!tbl && mode&MD_AGGRESSIVE) || md->state.skillstate == MSS_FOLLOW)
- {
- iMap->foreachinrange (mob_ai_sub_hard_activesearch, &md->bl, view_range, DEFAULT_ENEMY_TYPE(md), md, &tbl, mode);
- }
- else
- if (mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW))
- {
+ if ((!tbl && mode&MD_AGGRESSIVE) || md->state.skillstate == MSS_FOLLOW) {
+ map->foreachinrange (mob->ai_sub_hard_activesearch, &md->bl, view_range, DEFAULT_ENEMY_TYPE(md), md, &tbl, mode);
+ } else if ((mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) || (md->sc.count && md->sc.data[SC__CHAOS])) {
int search_size;
search_size = view_range<md->status.rhw.range ? view_range:md->status.rhw.range;
- iMap->foreachinrange (mob_ai_sub_hard_changechase, &md->bl, search_size, DEFAULT_ENEMY_TYPE(md), md, &tbl);
+ map->foreachinrange (mob->ai_sub_hard_changechase, &md->bl, search_size, DEFAULT_ENEMY_TYPE(md), md, &tbl);
}
if (!tbl) { //No targets available.
@@ -1556,15 +1539,15 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
if( md->bg_id && mode&MD_CANATTACK ) {
if( md->ud.walktimer != INVALID_TIMER )
return true;/* we are already moving */
- iMap->foreachinrange (mob_ai_sub_hard_bg_ally, &md->bl, view_range, BL_PC, md, &tbl, mode);
+ map->foreachinrange (mob->ai_sub_hard_bg_ally, &md->bl, view_range, BL_PC, md, &tbl, mode);
if( tbl ) {
- if( distance_blxy(&md->bl, tbl->x, tbl->y) <= 3 || unit_walktobl(&md->bl, tbl, 1, 1) )
+ if( distance_blxy(&md->bl, tbl->x, tbl->y) <= 3 || unit->walktobl(&md->bl, tbl, 1, 1) )
return true;/* we're moving or close enough don't unlock the target. */
}
}
//This handles triggering idle walk/skill.
- mob_unlocktarget(md, tick);
+ mob->unlocktarget(md, tick);
return true;
}
@@ -1576,21 +1559,21 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
return true; //Already locked.
if (md->lootitem == NULL)
{ //Can't loot...
- mob_unlocktarget (md, tick);
+ mob->unlocktarget (md, tick);
return true;
}
if (!check_distance_bl(&md->bl, tbl, 1))
{ //Still not within loot range.
if (!(mode&MD_CANMOVE))
{ //A looter that can't move? Real smart.
- mob_unlocktarget(md,tick);
+ mob->unlocktarget(md,tick);
return true;
}
if (!can_move) //Stuck. Wait before walking.
return true;
md->state.skillstate = MSS_LOOT;
- if (!unit_walktobl(&md->bl, tbl, 1, 1))
- mob_unlocktarget(md, tick); //Can't loot...
+ if (!unit->walktobl(&md->bl, tbl, 1, 1))
+ mob->unlocktarget(md, tick); //Can't loot...
return true;
}
//Within looting range.
@@ -1605,7 +1588,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
memcpy (&md->lootitem[md->lootitem_count++], &fitem->item_data, sizeof(md->lootitem[0]));
} else { //Destroy first looted item...
if (md->lootitem[0].card[0] == CARD0_PET)
- intif_delete_petdata( MakeDWord(md->lootitem[0].card[1],md->lootitem[0].card[2]) );
+ intif->delete_petdata( MakeDWord(md->lootitem[0].card[1],md->lootitem[0].card[2]) );
memmove(&md->lootitem[0], &md->lootitem[1], (LOOTITEM_SIZE-1)*sizeof(md->lootitem[0]));
memcpy (&md->lootitem[LOOTITEM_SIZE-1], &fitem->item_data, sizeof(md->lootitem[0]));
}
@@ -1613,11 +1596,11 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
{ //Give them walk act/delay to properly mimic players. [Skotlex]
clif->takeitem(&md->bl,tbl);
md->ud.canact_tick = tick + md->status.amotion;
- unit_set_walkdelay(&md->bl, tick, md->status.amotion, 1);
+ unit->set_walkdelay(&md->bl, tick, md->status.amotion, 1);
}
//Clear item.
- iMap->clearflooritem (tbl);
- mob_unlocktarget (md,tick);
+ map->clearflooritem (tbl);
+ mob->unlocktarget (md,tick);
return true;
}
//Attempt to attack.
@@ -1629,8 +1612,20 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
{ //Target within range, engage
if(tbl->type == BL_PC)
- mob_log_damage(md, tbl, 0); //Log interaction (counts as 'attacker' for the exp bonus)
- unit_attack(&md->bl,tbl->id,1);
+ mob->log_damage(md, tbl, 0); //Log interaction (counts as 'attacker' for the exp bonus)
+
+ if(!(mode&MD_RANDOMTARGET))
+ unit->attack(&md->bl,tbl->id,1);
+ else { // Attack once and find new random target
+ int search_size = (view_range < md->status.rhw.range) ? view_range : md->status.rhw.range;
+ unit->attack(&md->bl,tbl->id,0);
+ tbl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), search_size);
+ // If no target was found, keep atacking the old one
+ if( tbl ) {
+ md->target_id = tbl->id;
+ md->min_chase = md->db->range3;
+ }
+ }
return true;
}
@@ -1638,8 +1633,8 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
if (!(mode&MD_CANMOVE))
{ //Can't chase. Attempt an idle skill before unlocking.
md->state.skillstate = MSS_IDLE;
- if (!mobskill_use(md, tick, -1))
- mob_unlocktarget(md,tick);
+ if (!mob->skill_use(md, tick, -1))
+ mob->unlocktarget(md,tick);
return true;
}
@@ -1647,7 +1642,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
{ //Stuck. Attempt an idle skill
md->state.skillstate = MSS_IDLE;
if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL))
- mobskill_use(md, tick, -1);
+ mob->skill_use(md, tick, -1);
return true;
}
@@ -1659,18 +1654,17 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
return true;
//Follow up if possible.
- if(!mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) ||
- !unit_walktobl(&md->bl, tbl, md->status.rhw.range, 2))
- mob_unlocktarget(md,tick);
+ if(!mob->can_reach(md, tbl, md->min_chase, MSS_RUSH) ||
+ !unit->walktobl(&md->bl, tbl, md->status.rhw.range, 2))
+ mob->unlocktarget(md,tick);
return true;
}
-static int mob_ai_sub_hard_timer(struct block_list *bl,va_list ap)
-{
+int mob_ai_sub_hard_timer(struct block_list *bl, va_list ap) {
struct mob_data *md = (struct mob_data*)bl;
- unsigned int tick = va_arg(ap, unsigned int);
- if (mob_ai_sub_hard(md, tick))
+ int64 tick = va_arg(ap, int64);
+ if (mob->ai_sub_hard(md, tick))
{ //Hard AI triggered.
if(!md->state.spotted)
md->state.spotted = 1;
@@ -1682,11 +1676,10 @@ static int mob_ai_sub_hard_timer(struct block_list *bl,va_list ap)
/*==========================================
* Serious processing for mob in PC field of view (foreachclient)
*------------------------------------------*/
-static int mob_ai_sub_foreachclient(struct map_session_data *sd,va_list ap)
-{
- unsigned int tick;
- tick=va_arg(ap,unsigned int);
- iMap->foreachinrange(mob_ai_sub_hard_timer,&sd->bl, AREA_SIZE+ACTIVE_AI_RANGE, BL_MOB,tick);
+int mob_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) {
+ int64 tick;
+ tick=va_arg(ap, int64);
+ map->foreachinrange(mob->ai_sub_hard_timer,&sd->bl, AREA_SIZE+ACTIVE_AI_RANGE, BL_MOB,tick);
return 0;
}
@@ -1694,19 +1687,18 @@ static int mob_ai_sub_foreachclient(struct map_session_data *sd,va_list ap)
/*==========================================
* Negligent mode MOB AI (PC is not in near)
*------------------------------------------*/
-static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
-{
- unsigned int tick;
+int mob_ai_sub_lazy(struct mob_data *md, va_list args) {
+ int64 tick;
nullpo_ret(md);
if(md->bl.prev == NULL)
return 0;
- tick = va_arg(args,unsigned int);
+ tick = va_arg(args, int64);
- if (battle_config.mob_ai&0x20 && map[md->bl.m].users>0)
- return (int)mob_ai_sub_hard(md, tick);
+ if (battle_config.mob_ai&0x20 && map->list[md->bl.m].users>0)
+ return (int)mob->ai_sub_hard(md, tick);
if (md->bl.prev==NULL || md->status.hp == 0)
return 1;
@@ -1717,7 +1709,7 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
DIFF_TICK(tick,md->last_thinktime) > MIN_MOBTHINKTIME)
{
if (DIFF_TICK(tick,md->last_pcneartime) < battle_config.mob_active_time)
- return (int)mob_ai_sub_hard(md, tick);
+ return (int)mob->ai_sub_hard(md, tick);
md->last_pcneartime = 0;
}
@@ -1727,7 +1719,7 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
DIFF_TICK(tick,md->last_thinktime) > MIN_MOBTHINKTIME)
{
if (DIFF_TICK(tick,md->last_pcneartime) < battle_config.boss_active_time)
- return (int)mob_ai_sub_hard(md, tick);
+ return (int)mob->ai_sub_hard(md, tick);
md->last_pcneartime = 0;
}
@@ -1737,24 +1729,23 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
md->last_thinktime=tick;
if (md->master_id) {
- mob_ai_sub_hard_slavemob (md,tick);
+ mob->ai_sub_hard_slavemob(md,tick);
return 0;
}
- if( DIFF_TICK(md->next_walktime,tick) < 0 && (status_get_mode(&md->bl)&MD_CANMOVE) && unit_can_move(&md->bl) )
- {
- if( map[md->bl.m].users > 0 )
+ if( DIFF_TICK(md->next_walktime,tick) < 0 && (status_get_mode(&md->bl)&MD_CANMOVE) && unit->can_move(&md->bl) ) {
+ if( map->list[md->bl.m].users > 0 )
{
if( rnd()%1000 < MOB_LAZYMOVEPERC(md) )
- mob_randomwalk(md, tick);
+ mob->randomwalk(md, tick);
else
if( rnd()%1000 < MOB_LAZYSKILLPERC ) //Chance to do a mob's idle skill.
- mobskill_use(md, tick, -1);
+ mob->skill_use(md, tick, -1);
}
else
{
if( rnd()%1000 < MOB_LAZYMOVEPERC(md) )
- mob_randomwalk(md, tick);
+ mob->randomwalk(md, tick);
}
}
return 0;
@@ -1763,22 +1754,20 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
/*==========================================
* Negligent processing for mob outside PC field of view (interval timer function)
*------------------------------------------*/
-static int mob_ai_lazy(int tid, unsigned int tick, int id, intptr_t data)
-{
- iMap->map_foreachmob(mob_ai_sub_lazy,tick);
+int mob_ai_lazy(int tid, int64 tick, int id, intptr_t data) {
+ map->foreachmob(mob->ai_sub_lazy,tick);
return 0;
}
/*==========================================
* Serious processing for mob in PC field of view (interval timer function)
*------------------------------------------*/
-static int mob_ai_hard(int tid, unsigned int tick, int id, intptr_t data)
-{
+int mob_ai_hard(int tid, int64 tick, int id, intptr_t data) {
if (battle_config.mob_ai&0x20)
- iMap->map_foreachmob(mob_ai_sub_lazy,tick);
+ map->foreachmob(mob->ai_sub_lazy,tick);
else
- iMap->map_foreachpc(mob_ai_sub_foreachclient,tick);
+ map->foreachpc(mob->ai_sub_foreachclient,tick);
return 0;
}
@@ -1786,12 +1775,11 @@ static int mob_ai_hard(int tid, unsigned int tick, int id, intptr_t data)
/*==========================================
* Initializes the delay drop structure for mob-dropped items.
*------------------------------------------*/
-static struct item_drop* mob_setdropitem(int nameid, int qty, struct item_data *data) {
+struct item_drop* mob_setdropitem(int nameid, int qty, struct item_data *data) {
struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop);
- memset(&drop->item_data, 0, sizeof(struct item));
drop->item_data.nameid = nameid;
drop->item_data.amount = qty;
- drop->item_data.identify = data ? itemdb_isidentified2(data) : itemdb_isidentified(nameid);
+ drop->item_data.identify = data ? itemdb->isidentified2(data) : itemdb->isidentified(nameid);
drop->next = NULL;
return drop;
}
@@ -1799,7 +1787,7 @@ static struct item_drop* mob_setdropitem(int nameid, int qty, struct item_data *
/*==========================================
* Initializes the delay drop structure for mob-looted items.
*------------------------------------------*/
-static struct item_drop* mob_setlootitem(struct item* item)
+struct item_drop* mob_setlootitem(struct item* item)
{
struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop);
memcpy(&drop->item_data, item, sizeof(struct item));
@@ -1810,16 +1798,15 @@ static struct item_drop* mob_setlootitem(struct item* item)
/*==========================================
* item drop with delay (timer function)
*------------------------------------------*/
-static int mob_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data)
-{
+int mob_delay_item_drop(int tid, int64 tick, int id, intptr_t data) {
struct item_drop_list *list;
struct item_drop *ditem, *ditem_prev;
list=(struct item_drop_list *)data;
ditem = list->item;
while (ditem) {
- iMap->addflooritem(&ditem->item_data,ditem->item_data.amount,
- list->m,list->x,list->y,
- list->first_charid,list->second_charid,list->third_charid,0);
+ map->addflooritem(&ditem->item_data,ditem->item_data.amount,
+ list->m,list->x,list->y,
+ list->first_charid,list->second_charid,list->third_charid,0);
ditem_prev = ditem;
ditem = ditem->next;
ers_free(item_drop_ers, ditem_prev);
@@ -1834,20 +1821,20 @@ static int mob_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data
* rate is the drop-rate of the item, required for autoloot.
* flag : Killed only by homunculus?
*------------------------------------------*/
-static void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct item_drop *ditem, int loot, int drop_rate, unsigned short flag)
+void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct item_drop *ditem, int loot, int drop_rate, unsigned short flag)
{
TBL_PC* sd;
//Logs items, dropped by mobs [Lupus]
logs->pick_mob(md, loot?LOG_TYPE_LOOT:LOG_TYPE_PICKDROP_MONSTER, -ditem->item_data.amount, &ditem->item_data, NULL);
- sd = iMap->charid2sd(dlist->first_charid);
- if( sd == NULL ) sd = iMap->charid2sd(dlist->second_charid);
- if( sd == NULL ) sd = iMap->charid2sd(dlist->third_charid);
+ sd = map->charid2sd(dlist->first_charid);
+ if( sd == NULL ) sd = map->charid2sd(dlist->second_charid);
+ if( sd == NULL ) sd = map->charid2sd(dlist->third_charid);
if( sd
&& (drop_rate <= sd->state.autoloot || pc->isautolooting(sd, ditem->item_data.nameid))
- && (battle_config.idle_no_autoloot == 0 || DIFF_TICK(last_tick, sd->idletime) < battle_config.idle_no_autoloot)
+ && (battle_config.idle_no_autoloot == 0 || DIFF_TICK(sockt->last_tick, sd->idletime) < battle_config.idle_no_autoloot)
&& (battle_config.homunculus_autoloot?1:!flag)
#ifdef AUTOLOOT_DISTANCE
&& sd->bl.m == md->bl.m
@@ -1865,9 +1852,8 @@ static void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, str
dlist->item = ditem;
}
-int mob_timer_delete(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct block_list* bl = iMap->id2bl(id);
+int mob_timer_delete(int tid, int64 tick, int id, intptr_t data) {
+ struct block_list* bl = map->id2bl(id);
struct mob_data* md = BL_CAST(BL_MOB, bl);
if( md )
@@ -1879,7 +1865,7 @@ int mob_timer_delete(int tid, unsigned int tick, int id, intptr_t data)
}
//for Alchemist CANNIBALIZE [Lupus]
md->deletetimer = INVALID_TIMER;
- unit_free(bl, CLR_TELEPORT);
+ unit->free(bl, CLR_TELEPORT);
}
return 0;
}
@@ -1904,20 +1890,18 @@ int mob_deleteslave_sub(struct block_list *bl,va_list ap)
/*==========================================
*
*------------------------------------------*/
-int mob_deleteslave(struct mob_data *md)
-{
+int mob_deleteslave(struct mob_data *md) {
nullpo_ret(md);
- iMap->foreachinmap(mob_deleteslave_sub, md->bl.m, BL_MOB,md->bl.id);
+ map->foreachinmap(mob->deleteslave_sub, md->bl.m, BL_MOB,md->bl.id);
return 0;
}
// Mob respawning through KAIZEL or NPC_REBIRTH [Skotlex]
-int mob_respawn(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct block_list *bl = iMap->id2bl(id);
+int mob_respawn(int tid, int64 tick, int id, intptr_t data) {
+ struct block_list *bl = map->id2bl(id);
if(!bl) return 0;
- status_revive(bl, (uint8)data, 0);
+ status->revive(bl, (uint8)data, 0);
return 1;
}
@@ -1976,9 +1960,8 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
case BL_MOB:
{
struct mob_data* md2 = (TBL_MOB*)src;
- if( md2->special_state.ai && md2->master_id )
- {
- struct map_session_data* msd = iMap->id2sd(md2->master_id);
+ if( md2->special_state.ai && md2->master_id ) {
+ struct map_session_data* msd = map->id2sd(md2->master_id);
if( msd )
char_id = msd->status.char_id;
}
@@ -2053,8 +2036,8 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) {
}
//Log damage
if (src)
- mob_log_damage(md, src, damage);
- md->dmgtick = iTimer->gettick();
+ mob->log_damage(md, src, damage);
+ md->dmgtick = timer->gettick();
}
if (battle_config.show_mob_info&3)
@@ -2068,7 +2051,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) {
int i;
for(i = 0; i < DAMAGELOG_SIZE; i++){ // must show hp bar to all char who already hit the mob.
if( md->dmglog[i].id ) {
- struct map_session_data *sd = iMap->charid2sd(md->dmglog[i].id);
+ struct map_session_data *sd = map->charid2sd(md->dmglog[i].id);
if( sd && check_distance_bl(&md->bl, &sd->bl, AREA_SIZE) ) // check if in range
clif->monster_hp_bar(md,sd);
}
@@ -2078,7 +2061,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) {
if( md->special_state.ai == 2 ) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex]
md->state.alchemist = 1;
- mobskill_use(md, iTimer->gettick(), MSC_ALCHEMIST);
+ mob->skill_use(md, timer->gettick(), MSC_ALCHEMIST);
}
}
@@ -2086,9 +2069,8 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) {
* Signals death of mob.
* type&1 -> no drops, type&2 -> no exp
*------------------------------------------*/
-int mob_dead(struct mob_data *md, struct block_list *src, int type)
-{
- struct status_data *status;
+int mob_dead(struct mob_data *md, struct block_list *src, int type) {
+ struct status_data *mstatus;
struct map_session_data *sd = NULL, *tmpsd[DAMAGELOG_SIZE];
struct map_session_data *mvp_sd = NULL, *second_sd = NULL, *third_sd = NULL;
@@ -2098,11 +2080,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
unsigned int base_exp,job_exp;
} pt[DAMAGELOG_SIZE];
int i, temp, count, m = md->bl.m, pnum = 0;
- int dmgbltypes = 0; // bitfield of all bl types, that caused damage to the mob and are elligible for exp distribution
- unsigned int mvp_damage, tick = iTimer->gettick();
+ int dmgbltypes = 0; // bitfield of all bl types, that caused damage to the mob and are eligible for exp distribution
+ unsigned int mvp_damage;
+ int64 tick = timer->gettick();
bool rebirth, homkillonly;
- status = &md->status;
+ mstatus = &md->status;
if( src && src->type == BL_PC )
{
@@ -2116,21 +2099,20 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
if( src )
{ // Use Dead skill only if not killed by Script or Command
md->state.skillstate = MSS_DEAD;
- mobskill_use(md,tick,-1);
+ mob->skill_use(md,tick,-1);
}
- iMap->freeblock_lock();
+ map->freeblock_lock();
memset(pt,0,sizeof(pt));
if(src && src->type == BL_MOB)
- mob_unlocktarget((struct mob_data *)src,tick);
+ mob->unlocktarget((struct mob_data *)src,tick);
// filter out entries not eligible for exp distribution
memset(tmpsd,0,sizeof(tmpsd));
- for(i = 0, count = 0, mvp_damage = 0; i < DAMAGELOG_SIZE && md->dmglog[i].id; i++)
- {
- struct map_session_data* tsd = iMap->charid2sd(md->dmglog[i].id);
+ for(i = 0, count = 0, mvp_damage = 0; i < DAMAGELOG_SIZE && md->dmglog[i].id; i++) {
+ struct map_session_data* tsd = map->charid2sd(md->dmglog[i].id);
if(tsd == NULL)
continue; // skip empty entries
@@ -2175,21 +2157,21 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
}
}
- if(!(type&2) && //No exp
- (!map[m].flag.pvp || battle_config.pvp_exp) && //Pvp no exp rule [MouseJstr]
- (!md->master_id || !md->special_state.ai) && //Only player-summoned mobs do not give exp. [Skotlex]
- (!map[m].flag.nobaseexp || !map[m].flag.nojobexp) //Gives Exp
+ if( !(type&2) //No exp
+ && (!map->list[m].flag.pvp || battle_config.pvp_exp) //Pvp no exp rule [MouseJstr]
+ && (!md->master_id || !md->special_state.ai) //Only player-summoned mobs do not give exp. [Skotlex]
+ && (!map->list[m].flag.nobaseexp || !map->list[m].flag.nojobexp) //Gives Exp
) { //Experience calculation.
int bonus = 100; //Bonus on top of your share (common to all attackers).
if (md->sc.data[SC_RICHMANKIM])
bonus += md->sc.data[SC_RICHMANKIM]->val2;
if(sd) {
- temp = status_get_class(&md->bl);
+ temp = status->get_class(&md->bl);
if(sd->sc.data[SC_MIRACLE]) i = 2; //All mobs are Star Targets
else
ARR_FIND(0, MAX_PC_FEELHATE, i, temp == sd->hate_mob[i] &&
- (battle_config.allow_skill_without_day || sg_info[i].day_func()));
- if(i<MAX_PC_FEELHATE && (temp=pc->checkskill(sd,sg_info[i].bless_id)))
+ (battle_config.allow_skill_without_day || pc->sg_info[i].day_func()));
+ if(i<MAX_PC_FEELHATE && (temp=pc->checkskill(sd,pc->sg_info[i].bless_id)))
bonus += (i==2?20:10)*temp;
}
if(battle_config.mobs_level_up && md->level > md->db->lv) // [Valaris]
@@ -2207,7 +2189,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
per = (double)md->dmglog[i].dmg/(double)md->tdmg;
else {
//eAthena's exp formula based on max hp.
- per = (double)md->dmglog[i].dmg/(double)status->max_hp;
+ per = (double)md->dmglog[i].dmg/(double)mstatus->max_hp;
if (per > 2) per = 2; // prevents unlimited exp gain
}
@@ -2221,7 +2203,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
// change experience for different sized monsters [Valaris]
if (battle_config.mob_size_influence) {
switch( md->special_state.size ) {
- case SZ_MEDIUM:
+ case SZ_SMALL:
per /= 2.;
break;
case SZ_BIG:
@@ -2240,15 +2222,15 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
zeny*=rnd()%250;
}
- if (map[m].flag.nobaseexp || !md->db->base_exp)
+ if (map->list[m].flag.nobaseexp || !md->db->base_exp)
base_exp = 0;
else
- base_exp = (unsigned int)cap_value(md->db->base_exp * per * bonus/100. * map[m].bexp/100., 1, UINT_MAX);
+ base_exp = (unsigned int)cap_value(md->db->base_exp * per * bonus/100. * map->list[m].bexp/100., 1, UINT_MAX);
- if (map[m].flag.nojobexp || !md->db->job_exp || md->dmglog[i].flag == MDLF_HOMUN) //Homun earned job-exp is always lost.
+ if (map->list[m].flag.nojobexp || !md->db->job_exp || md->dmglog[i].flag == MDLF_HOMUN) //Homun earned job-exp is always lost.
job_exp = 0;
else
- job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map[m].jexp/100., 1, UINT_MAX);
+ job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map->list[m].jexp/100., 1, UINT_MAX);
if ( (temp = tmpsd[i]->status.party_id) > 0 ) {
int j;
@@ -2285,7 +2267,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
if(base_exp || job_exp) {
if( md->dmglog[i].flag != MDLF_PET || battle_config.pet_attack_exp_to_master ) {
#ifdef RENEWAL_EXP
- int rate = pc->level_penalty_mod(tmpsd[i], md, 1);
+ int rate = pc->level_penalty_mod(md->level - (tmpsd[i])->status.base_level, md->status.race, md->status.mode, 1);
base_exp = (unsigned int)cap_value(base_exp * rate / 100, 1, UINT_MAX);
job_exp = (unsigned int)cap_value(job_exp * rate / 100, 1, UINT_MAX);
#endif
@@ -2302,7 +2284,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
} //End EXP giving.
- if( !(type&1) && !map[m].flag.nomobloot && !md->state.rebirth && (
+ if( !(type&1) && !map->list[m].flag.nomobloot && !md->state.rebirth && (
!md->special_state.ai || //Non special mob
battle_config.alchemist_summon_reward == 2 || //All summoned give drops
(md->special_state.ai==2 && battle_config.alchemist_summon_reward == 1) //Marine Sphere Drops items.
@@ -2313,10 +2295,10 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
struct item_data* it = NULL;
int drop_rate;
#ifdef RENEWAL_DROP
- int drop_modifier = mvp_sd ? pc->level_penalty_mod(mvp_sd, md, 2) :
- second_sd ? pc->level_penalty_mod(second_sd, md, 2):
- third_sd ? pc->level_penalty_mod(third_sd, md, 2) :
- 100;/* no player was attached, we dont use any modifier (100 = rates are not touched) */
+ int drop_modifier = mvp_sd ? pc->level_penalty_mod( md->level - mvp_sd->status.base_level, md->status.race, md->status.mode, 2) :
+ second_sd ? pc->level_penalty_mod( md->level - second_sd->status.base_level, md->status.race, md->status.mode, 2):
+ third_sd ? pc->level_penalty_mod( md->level - third_sd->status.base_level, md->status.race, md->status.mode, 2) :
+ 100;/* no player was attached, we don't use any modifier (100 = rates are not touched) */
#endif
dlist->m = md->bl.m;
dlist->x = md->bl.x;
@@ -2330,7 +2312,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
{
if (md->db->dropitem[i].nameid <= 0)
continue;
- if ( !(it = itemdb_exists(md->db->dropitem[i].nameid)) )
+ if ( !(it = itemdb->exists(md->db->dropitem[i].nameid)) )
continue;
drop_rate = md->db->dropitem[i].p;
if (drop_rate <= 0) {
@@ -2342,7 +2324,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
// change drops depending on monsters size [Valaris]
if (battle_config.mob_size_influence)
{
- if (md->special_state.size == SZ_MEDIUM && drop_rate >= 2)
+ if (md->special_state.size == SZ_SMALL && drop_rate >= 2)
drop_rate /= 2;
else if( md->special_state.size == SZ_BIG)
drop_rate *= 2;
@@ -2370,33 +2352,49 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
drop_rate = 1;
}
#endif
+ if( sd && sd->status.mod_drop != 100 ) {
+ drop_rate = drop_rate * sd->status.mod_drop / 100;
+ if( drop_rate < 1 )
+ drop_rate = 1;
+ }
+
// attempt to drop the item
if (rnd() % 10000 >= drop_rate)
continue;
if( mvp_sd && it->type == IT_PETEGG ) {
- pet_create_egg(mvp_sd, md->db->dropitem[i].nameid);
+ pet->create_egg(mvp_sd, md->db->dropitem[i].nameid);
continue;
}
- ditem = mob_setdropitem(md->db->dropitem[i].nameid, 1, it);
+ ditem = mob->setdropitem(md->db->dropitem[i].nameid, 1, it);
//A Rare Drop Global Announce by Lupus
if( mvp_sd && drop_rate <= battle_config.rare_drop_announce ) {
char message[128];
sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, it->jname, (float)drop_rate/100);
//MSG: "'%s' won %s's %s (chance: %0.02f%%)"
- intif_broadcast(message,strlen(message)+1,0);
+ intif->broadcast(message, strlen(message)+1, BC_DEFAULT);
}
+
+ /* heres the thing we got the feature set up however we're still discussing how to best define the ids,
+ * so while we discuss, for a small period of time, the list is hardcoded (yes officially only those 2 use it,
+ * thus why we're unsure on how to best place the setting) */
+ /* temp, will not be hardcoded for long thudu. */
+ if( it->nameid == 7782 || it->nameid == 7783 ) /* for when not hardcoded: add a check on mvp bonus drop as well */
+ clif->item_drop_announce(mvp_sd, it->nameid, md->name);
+
// Announce first, or else ditem will be freed. [Lance]
// By popular demand, use base drop rate for autoloot code. [Skotlex]
- mob_item_drop(md, dlist, ditem, 0, md->db->dropitem[i].p, homkillonly);
+ mob->item_drop(md, dlist, ditem, 0, md->db->dropitem[i].p, homkillonly);
}
// Ore Discovery [Celest]
- if (sd == mvp_sd && pc->checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/10 >= rnd()%10000) {
- ditem = mob_setdropitem(itemdb_searchrandomid(IG_FINDINGORE), 1, NULL);
- mob_item_drop(md, dlist, ditem, 0, battle_config.finding_ore_rate/10, homkillonly);
+ if (sd == mvp_sd && pc->checkskill(sd,BS_FINDINGORE) > 0) {
+ if( (temp = itemdb->chain_item(itemdb->chain_cache[ECC_ORE],&i)) ) {
+ ditem = mob->setdropitem(temp, 1, NULL);
+ mob->item_drop(md, dlist, ditem, 0, i, homkillonly);
+ }
}
if(sd) {
@@ -2406,8 +2404,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
{
if ( sd->add_drop[i].race == -md->class_ ||
( sd->add_drop[i].race > 0 && (
- sd->add_drop[i].race & (1<<status->race) ||
- sd->add_drop[i].race & (1<<(status->mode&MD_BOSS?RC_BOSS:RC_NONBOSS))
+ sd->add_drop[i].race & (1<<mstatus->race) ||
+ sd->add_drop[i].race & (1<<(mstatus->mode&MD_BOSS?RC_BOSS:RC_NONBOSS))
)))
{
//check if the bonus item drop rate should be multiplied with mob level/10 [Lupus]
@@ -2424,8 +2422,9 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
if (rnd()%10000 >= drop_rate)
continue;
- itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb_searchrandomid(sd->add_drop[i].group);
- mob_item_drop(md, dlist, mob_setdropitem(itemid,1,NULL), 0, drop_rate, homkillonly);
+ itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb->chain_item(sd->add_drop[i].group,&drop_rate);
+ if( itemid )
+ mob->item_drop(md, dlist, mob->setdropitem(itemid,1,NULL), 0, drop_rate, homkillonly);
}
}
@@ -2440,10 +2439,10 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
// process items looted by the mob
if(md->lootitem) {
for(i = 0; i < md->lootitem_count; i++)
- mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, homkillonly);
+ mob->item_drop(md, dlist, mob->setlootitem(&md->lootitem[i]), 1, 10000, homkillonly);
}
if (dlist->item) //There are drop items.
- iTimer->add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr_t)dlist);
+ timer->add(tick + (!battle_config.delay_battle_damage?500:0), mob->delay_item_drop, 0, (intptr_t)dlist);
else //No drops
ers_free(item_drop_list_ers, dlist);
} else if (md->lootitem && md->lootitem_count) { //Loot MUST drop!
@@ -2456,18 +2455,17 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
dlist->third_charid = (third_sd ? third_sd->status.char_id : 0);
dlist->item = NULL;
for(i = 0; i < md->lootitem_count; i++)
- mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, homkillonly);
- iTimer->add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr_t)dlist);
+ mob->item_drop(md, dlist, mob->setlootitem(&md->lootitem[i]), 1, 10000, homkillonly);
+ timer->add(tick + (!battle_config.delay_battle_damage?500:0), mob->delay_item_drop, 0, (intptr_t)dlist);
}
if(mvp_sd && md->db->mexp > 0 && !md->special_state.ai) {
int log_mvp[2] = {0};
unsigned int mexp;
- struct item item;
double exp;
//mapflag: noexp check [Lorky]
- if (map[m].flag.nobaseexp || type&2)
+ if (map->list[m].flag.nobaseexp || type&2)
exp =1;
else {
exp = md->db->mexp;
@@ -2482,10 +2480,11 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
pc->gainexp(mvp_sd, &md->bl, mexp,0, false);
log_mvp[1] = mexp;
- if( !(map[m].flag.nomvploot || type&1) ) {
+ if( !(map->list[m].flag.nomvploot || type&1) ) {
/* pose them randomly in the list -- so on 100% drop servers it wont always drop the same item */
int mdrop_id[MAX_MVP_DROP];
int mdrop_p[MAX_MVP_DROP];
+ struct item item;
memset(&mdrop_id,0,MAX_MVP_DROP*sizeof(int));
@@ -2504,7 +2503,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
struct item_data *data;
if(mdrop_id[i] <= 0)
continue;
- if(! (data = itemdb_exists(mdrop_id[i])) )
+ if(! (data = itemdb->exists(mdrop_id[i])) )
continue;
temp = mdrop_p[i];
@@ -2515,7 +2514,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
memset(&item,0,sizeof(item));
item.nameid=mdrop_id[i];
- item.identify= itemdb_isidentified2(data);
+ item.identify= itemdb->isidentified2(data);
clif->mvp_item(mvp_sd,item.nameid);
log_mvp[0] = item.nameid;
@@ -2524,12 +2523,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
char message[128];
sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, data->jname, temp/100.);
//MSG: "'%s' won %s's %s (chance: %0.02f%%)"
- intif_broadcast(message,strlen(message)+1,0);
+ intif->broadcast(message, strlen(message)+1, BC_DEFAULT);
}
if((temp = pc->additem(mvp_sd,&item,1,LOG_TYPE_PICKDROP_PLAYER)) != 0) {
clif->additem(mvp_sd,0,0,temp);
- iMap->addflooritem(&item,1,mvp_sd->bl.m,mvp_sd->bl.x,mvp_sd->bl.y,mvp_sd->status.char_id,(second_sd?second_sd->status.char_id:0),(third_sd?third_sd->status.char_id:0),1);
+ map->addflooritem(&item,1,mvp_sd->bl.m,mvp_sd->bl.x,mvp_sd->bl.y,mvp_sd->status.char_id,(second_sd?second_sd->status.char_id:0),(third_sd?third_sd->status.char_id:0),1);
}
//Logs items, MVP prizes [Lupus]
@@ -2541,7 +2540,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
logs->mvpdrop(mvp_sd, md->class_, log_mvp);
}
- if (type&2 && !sd && md->class_ == MOBID_EMPERIUM)
+ if (type&2 && !sd && md->class_ == MOBID_EMPERIUM && md->guardian_data)
//Emperium destroyed by script. Discard mvp character. [Skotlex]
mvp_sd = NULL;
@@ -2559,58 +2558,58 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
if( sd ) {
if( sd->mission_mobid == md->class_) { //TK_MISSION [Skotlex]
- if( ++sd->mission_count >= 100 && (temp = mob_get_random_id(0, 0xE, sd->status.base_level)) ) {
+ if( ++sd->mission_count >= 100 && (temp = mob->get_random_id(0, 0xE, sd->status.base_level)) ) {
pc->addfame(sd, 1);
sd->mission_mobid = temp;
- pc_setglobalreg(sd,"TK_MISSION_ID", temp);
+ pc_setglobalreg(sd,script->add_str("TK_MISSION_ID"), temp);
sd->mission_count = 0;
clif->mission_info(sd, temp, 0);
}
- pc_setglobalreg(sd,"TK_MISSION_COUNT", sd->mission_count);
+ pc_setglobalreg(sd,script->add_str("TK_MISSION_COUNT"), sd->mission_count);
}
if( sd->status.party_id )
- iMap->foreachinrange(quest_update_objective_sub,&md->bl,AREA_SIZE,BL_PC,sd->status.party_id,md->class_);
+ map->foreachinrange(quest->update_objective_sub,&md->bl,AREA_SIZE,BL_PC,sd->status.party_id,md->class_);
else if( sd->avail_quests )
- quest_update_objective(sd, md->class_);
+ quest->update_objective(sd, md->class_);
- if( sd->md && src && src->type != BL_HOM && mob_db(md->class_)->lv > sd->status.base_level/2 )
- mercenary_kills(sd->md);
+ if( sd->md && src && src->type != BL_HOM && mob->db(md->class_)->lv > sd->status.base_level/2 )
+ mercenary->kills(sd->md);
}
if( md->npc_event[0] && !md->state.npc_killmonster ) {
if( sd && battle_config.mob_npc_event_type ) {
pc->setparam(sd, SP_KILLERRID, sd->bl.id);
- npc_event(sd,md->npc_event,0);
+ npc->event(sd,md->npc_event,0);
} else if( mvp_sd ) {
pc->setparam(mvp_sd, SP_KILLERRID, sd?sd->bl.id:0);
- npc_event(mvp_sd,md->npc_event,0);
+ npc->event(mvp_sd,md->npc_event,0);
} else
- npc_event_do(md->npc_event);
+ npc->event_do(md->npc_event);
} else if( mvp_sd && !md->state.npc_killmonster ) {
pc->setparam(mvp_sd, SP_KILLEDRID, md->class_);
- npc_script_event(mvp_sd, NPCE_KILLNPC); // PCKillNPC [Lance]
+ npc->script_event(mvp_sd, NPCE_KILLNPC); // PCKillNPC [Lance]
}
md->status.hp = 1;
}
if(md->deletetimer != INVALID_TIMER) {
- iTimer->delete_timer(md->deletetimer,mob_timer_delete);
+ timer->delete(md->deletetimer,mob->timer_delete);
md->deletetimer = INVALID_TIMER;
}
/**
* Only loops if necessary (e.g. a poring would never need to loop)
**/
if( md->can_summon )
- mob_deleteslave(md);
+ mob->deleteslave(md);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
if( !rebirth ) {
if( pcdb_checkid(md->vd->class_) ) {//Player mobs are not removed automatically by the client.
- /* first we set them dead, then we delay the outsight effect */
+ /* first we set them dead, then we delay the out sight effect */
clif->clearunit_area(&md->bl,CLR_DEAD);
clif->clearunit_delayed(&md->bl, CLR_OUTSIGHT,tick+3000);
} else
@@ -2622,23 +2621,23 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
}
- if(!md->spawn) //Tell status_damage to remove it from memory.
+ if(!md->spawn) //Tell status->damage to remove it from memory.
return 5; // Note: Actually, it's 4. Oh well...
// MvP tomb [GreenBox]
- if (battle_config.mvp_tomb_enabled && md->spawn->state.boss)
- mvptomb_create(md, mvp_sd ? mvp_sd->status.name : NULL, time(NULL));
+ if (battle_config.mvp_tomb_enabled && md->spawn->state.boss && map->list[md->bl.m].flag.notomb != 1)
+ mob->mvptomb_create(md, mvp_sd ? mvp_sd->status.name : NULL, time(NULL));
if( !rebirth ) {
- status_change_clear(&md->bl,1);
- mob_setdelayspawn(md); //Set respawning.
+ status->change_clear(&md->bl,1);
+ mob->setdelayspawn(md); //Set respawning.
}
return 3; //Remove from map.
}
void mob_revive(struct mob_data *md, unsigned int hp)
{
- unsigned int tick = iTimer->gettick();
+ int64 tick = timer->gettick();
md->state.skillstate = MSS_IDLE;
md->last_thinktime = tick;
md->next_walktime = tick+rnd()%50+5000;
@@ -2647,10 +2646,10 @@ void mob_revive(struct mob_data *md, unsigned int hp)
memset(md->dmglog, 0, sizeof(md->dmglog)); // Reset the damage done on the rebirthed monster, otherwise will grant full exp + damage done. [Valaris]
md->tdmg = 0;
if (!md->bl.prev)
- iMap->addblock(&md->bl);
+ map->addblock(&md->bl);
clif->spawn(&md->bl);
skill->unit_move(&md->bl,tick,1);
- mobskill_use(md, tick, MSC_SPAWN);
+ mob->skill_use(md, tick, MSC_SPAWN);
if (battle_config.show_mob_info&3)
clif->charnameack (0, &md->bl);
}
@@ -2663,35 +2662,29 @@ int mob_guardian_guildchange(struct mob_data *md)
if (!md->guardian_data)
return 0;
- if (md->guardian_data->castle->guild_id == 0)
+ if( md->guardian_data->castle->guild_id == 0 )
{ //Castle with no owner? Delete the guardians.
- if (md->class_ == MOBID_EMPERIUM)
- { //But don't delete the emperium, just clear it's guild-data
- md->guardian_data->guild_id = 0;
- md->guardian_data->emblem_id = 0;
- md->guardian_data->guild_name[0] = '\0';
- } else {
+ if( md->class_ == MOBID_EMPERIUM ) //But don't delete the emperium, just clear it's guild-data
+ md->guardian_data->g = NULL;
+ else {
if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible)
guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0);
- unit_free(&md->bl,CLR_OUTSIGHT); //Remove guardian.
+ unit->free(&md->bl,CLR_OUTSIGHT); //Remove guardian.
}
return 0;
}
g = guild->search(md->guardian_data->castle->guild_id);
- if (g == NULL)
+ if( g == NULL )
{ //Properly remove guardian info from Castle data.
- ShowError("mob_guardian_guildchange: New Guild (id %d) does not exists!\n", md->guardian_data->guild_id);
+ ShowError("mob_guardian_guildchange: New Guild (id %d) does not exists!\n", md->guardian_data->castle->guild_id);
if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS)
guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0);
- unit_free(&md->bl,CLR_OUTSIGHT);
+ unit->free(&md->bl,CLR_OUTSIGHT);
return 0;
}
- md->guardian_data->guild_id = g->guild_id;
- md->guardian_data->emblem_id = g->emblem_id;
- md->guardian_data->guardup_lv = guild->checkskill(g,GD_GUARDUP);
- memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH);
+ md->guardian_data->g = g;
return 1;
}
@@ -2706,16 +2699,16 @@ int mob_random_class (int *value, size_t count)
// no count specified, look into the array manually, but take only max 5 elements
if (count < 1) {
count = 0;
- while(count < 5 && mobdb_checkid(value[count])) count++;
+ while(count < 5 && mob->db_checkid(value[count])) count++;
if(count < 1) // nothing found
return 0;
} else {
// check if at least the first value is valid
- if(mobdb_checkid(value[0]) == 0)
+ if(mob->db_checkid(value[0]) == 0)
return 0;
}
//Pick a random value, hoping it exists. [Skotlex]
- return mobdb_checkid(value[rnd()%count]);
+ return mob->db_checkid(value[rnd()%count]);
}
/*==========================================
@@ -2723,8 +2716,8 @@ int mob_random_class (int *value, size_t count)
*------------------------------------------*/
int mob_class_change (struct mob_data *md, int class_)
{
- unsigned int tick = iTimer->gettick();
- int i, c, hp_rate;
+ int64 tick = timer->gettick(), c = 0;
+ int i, hp_rate;
nullpo_ret(md);
@@ -2741,7 +2734,7 @@ int mob_class_change (struct mob_data *md, int class_)
if( md->special_state.ai > 1 )
return 0; //Marine Spheres and Floras.
- if( mob_is_clone(md->class_) )
+ if( mob->is_clone(md->class_) )
return 0; //Clones
if( md->class_ == class_ )
@@ -2749,7 +2742,7 @@ int mob_class_change (struct mob_data *md, int class_)
hp_rate = get_percentage(md->status.hp, md->status.max_hp);
md->class_ = class_;
- md->db = mob_db(class_);
+ md->db = mob->db(class_);
if (battle_config.override_mob_names==1)
memcpy(md->name,md->db->name,NAME_LENGTH);
else
@@ -2757,10 +2750,10 @@ int mob_class_change (struct mob_data *md, int class_)
mob_stop_attack(md);
mob_stop_walking(md, 0);
- unit_skillcastcancel(&md->bl, 0);
- status_set_viewdata(&md->bl, class_);
+ unit->skillcastcancel(&md->bl, 0);
+ status->set_viewdata(&md->bl, class_);
clif->class_change(&md->bl, md->vd->class_, 1);
- status_calc_mob(md, 1);
+ status_calc_mob(md, SCO_FIRST);
md->ud.state.speed_changed = 1; //Speed change update.
if (battle_config.monster_class_change_recover) {
@@ -2793,13 +2786,25 @@ void mob_heal(struct mob_data *md,unsigned int heal)
{
if (battle_config.show_mob_info&3)
clif->charnameack (0, &md->bl);
+
+#if PACKETVER >= 20120404
+ if( !(md->status.mode&MD_BOSS) ){
+ int i;
+ for(i = 0; i < DAMAGELOG_SIZE; i++){ // must show hp bar to all char who already hit the mob.
+ if( md->dmglog[i].id ) {
+ struct map_session_data *sd = map->charid2sd(md->dmglog[i].id);
+ if( sd && check_distance_bl(&md->bl, &sd->bl, AREA_SIZE) ) // check if in range
+ clif->monster_hp_bar(md,sd);
+ }
+ }
+ }
+#endif
}
/*==========================================
* Added by RoVeRT
*------------------------------------------*/
-int mob_warpslave_sub(struct block_list *bl,va_list ap)
-{
+int mob_warpslave_sub(struct block_list *bl,va_list ap) {
struct mob_data *md=(struct mob_data *)bl;
struct block_list *master;
short x,y,range=0;
@@ -2809,8 +2814,8 @@ int mob_warpslave_sub(struct block_list *bl,va_list ap)
if(md->master_id!=master->id)
return 0;
- iMap->search_freecell(master, 0, &x, &y, range, range, 0);
- unit_warp(&md->bl, master->m, x, y,CLR_RESPAWN);
+ map->search_freecell(master, 0, &x, &y, range, range, 0);
+ unit->warp(&md->bl, master->m, x, y,CLR_TELEPORT);
return 1;
}
@@ -2819,16 +2824,15 @@ int mob_warpslave_sub(struct block_list *bl,va_list ap)
* Warps slaves. Range is the area around the master that they can
* appear in randomly.
*------------------------------------------*/
-int mob_warpslave(struct block_list *bl, int range)
-{
+int mob_warpslave(struct block_list *bl, int range) {
if (range < 1)
range = 1; //Min range needed to avoid crashes and stuff. [Skotlex]
- return iMap->foreachinmap(mob_warpslave_sub, bl->m, BL_MOB, bl, range);
+ return map->foreachinmap(mob->warpslave_sub, bl->m, BL_MOB, bl, range);
}
/*==========================================
- * Counts slave sub, curently checking if mob master is the given ID.
+ * Counts slave sub, currently checking if mob master is the given ID.
*------------------------------------------*/
int mob_countslave_sub(struct block_list *bl,va_list ap)
{
@@ -2845,9 +2849,8 @@ int mob_countslave_sub(struct block_list *bl,va_list ap)
/*==========================================
* Counts the number of slaves a mob has on the map.
*------------------------------------------*/
-int mob_countslave(struct block_list *bl)
-{
- return iMap->foreachinmap(mob_countslave_sub, bl->m, BL_MOB,bl->id);
+int mob_countslave(struct block_list *bl) {
+ return map->foreachinmap(mob->countslave_sub, bl->m, BL_MOB,bl->id);
}
/*==========================================
@@ -2870,14 +2873,14 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id)
data.state.size = md2->special_state.size;
data.state.ai = md2->special_state.ai;
- if(mobdb_checkid(value[0]) == 0)
+ if(mob->db_checkid(value[0]) == 0)
return 0;
/**
* Flags this monster is able to summon; saves a worth amount of memory upon deletion
**/
md2->can_summon = 1;
- while(count < 5 && mobdb_checkid(value[count])) count++;
+ while(count < 5 && mob->db_checkid(value[count])) count++;
if(count < 1) return 0;
if (amount > 0 && amount < count) { //Do not start on 0, pick some random sub subset [Skotlex]
k = rnd()%count;
@@ -2891,10 +2894,10 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id)
for(;k<amount;k++) {
short x,y;
data.class_ = value[k%count]; //Summon slaves in round-robin fashion. [Skotlex]
- if (mobdb_checkid(data.class_) == 0)
+ if (mob->db_checkid(data.class_) == 0)
continue;
- if (iMap->search_freecell(&md2->bl, 0, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 0)) {
+ if (map->search_freecell(&md2->bl, 0, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 0)) {
data.x = x;
data.y = y;
} else {
@@ -2908,15 +2911,15 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id)
else
strcpy(data.name,"--ja--");
- if (!mob_parse_dataset(&data))
+ if (!mob->parse_dataset(&data))
continue;
- md= mob_spawn_dataset(&data);
+ md= mob->spawn_dataset(&data);
if(skill_id == NPC_SUMMONSLAVE){
md->master_id=md2->bl.id;
md->special_state.ai = md2->special_state.ai;
}
- mob_spawn(md);
+ mob->spawn(md);
if (hp_rate) //Scale HP
md->status.hp = md->status.max_hp*hp_rate/100;
@@ -2927,17 +2930,17 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id)
switch (battle_config.slaves_inherit_mode) {
case 1: //Always aggressive
if (!(md->status.mode&MD_AGGRESSIVE))
- sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0);
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0);
break;
case 2: //Always passive
if (md->status.mode&MD_AGGRESSIVE)
- sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0);
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0);
break;
default: //Copy master.
if (md2->status.mode&MD_AGGRESSIVE)
- sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0);
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0);
else
- sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0);
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0);
break;
}
}
@@ -2954,8 +2957,8 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id)
*------------------------------------------*/
int mob_skill_id2skill_idx(int class_,uint16 skill_id)
{
- int i, max = mob_db(class_)->maxskill;
- struct mob_skill *ms=mob_db(class_)->skill;
+ int i, max = mob->db(class_)->maxskill;
+ struct mob_skill *ms=mob->db(class_)->skill;
if(ms==NULL)
return -1;
@@ -2993,8 +2996,7 @@ int mob_getfriendhprate_sub(struct block_list *bl,va_list ap)
(*fr) = bl;
return 1;
}
-static struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,int max_rate)
-{
+struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,int max_rate) {
struct block_list *fr=NULL;
int type = BL_MOB;
@@ -3003,17 +3005,15 @@ static struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,i
if (md->special_state.ai) //Summoned creatures. [Skotlex]
type = BL_PC;
- iMap->foreachinrange(mob_getfriendhprate_sub, &md->bl, 8, type,md,min_rate,max_rate,&fr);
+ map->foreachinrange(mob->getfriendhprate_sub, &md->bl, 8, type,md,min_rate,max_rate,&fr);
return fr;
}
/*==========================================
* Check hp rate of its master
*------------------------------------------*/
-struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md,int rate)
-{
- if( md && md->master_id > 0 )
- {
- struct block_list *bl = iMap->id2bl(md->master_id);
+struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md,int rate) {
+ if( md && md->master_id > 0 ) {
+ struct block_list *bl = map->id2bl(md->master_id);
if( bl && get_percentage(status_get_hp(bl), status_get_max_hp(bl)) < rate )
return bl;
}
@@ -3055,25 +3055,24 @@ int mob_getfriendstatus_sub(struct block_list *bl,va_list ap)
return 0;
}
-struct mob_data *mob_getfriendstatus(struct mob_data *md,int cond1,int cond2)
-{
+struct mob_data *mob_getfriendstatus(struct mob_data *md,int cond1,int cond2) {
struct mob_data* fr = NULL;
nullpo_ret(md);
- iMap->foreachinrange(mob_getfriendstatus_sub, &md->bl, 8,BL_MOB, md,cond1,cond2,&fr);
+ map->foreachinrange(mob->getfriendstatus_sub, &md->bl, 8,BL_MOB, md,cond1,cond2,&fr);
return fr;
}
/*==========================================
* Skill use judging
*------------------------------------------*/
-int mobskill_use(struct mob_data *md, unsigned int tick, int event)
-{
+int mobskill_use(struct mob_data *md, int64 tick, int event) {
struct mob_skill *ms;
struct block_list *fbl = NULL; //Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex]
struct block_list *bl;
struct mob_data *fmd = NULL;
int i,j,n;
+ short skill_target;
nullpo_ret(md);
nullpo_ret(ms = md->db->skill);
@@ -3139,20 +3138,20 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
}
flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF); break;
case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp%
- flag = ((fbl = mob_getfriendhprate(md, 0, ms[i].cond2)) != NULL); break;
+ flag = ((fbl = mob->getfriendhprate(md, 0, ms[i].cond2)) != NULL); break;
case MSC_FRIENDHPINRATE :
- flag = ((fbl = mob_getfriendhprate(md, ms[i].cond2, ms[i].val[0])) != NULL); break;
+ flag = ((fbl = mob->getfriendhprate(md, ms[i].cond2, ms[i].val[0])) != NULL); break;
case MSC_FRIENDSTATUSON: // friend status[num] on
case MSC_FRIENDSTATUSOFF: // friend status[num] off
- flag = ((fmd = mob_getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); break;
+ flag = ((fmd = mob->getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); break;
case MSC_SLAVELT: // slave < num
- flag = (mob_countslave(&md->bl) < c2 ); break;
+ flag = (mob->countslave(&md->bl) < c2 ); break;
case MSC_ATTACKPCGT: // attack pc > num
- flag = (unit_counttargeted(&md->bl) > c2); break;
+ flag = (unit->counttargeted(&md->bl) > c2); break;
case MSC_SLAVELE: // slave <= num
- flag = (mob_countslave(&md->bl) <= c2 ); break;
+ flag = (mob->countslave(&md->bl) <= c2 ); break;
case MSC_ATTACKPCGE: // attack pc >= num
- flag = (unit_counttargeted(&md->bl) >= c2); break;
+ flag = (unit->counttargeted(&md->bl) >= c2); break;
case MSC_AFTERSKILL:
flag = (md->ud.skill_id == c2); break;
case MSC_RUDEATTACKED:
@@ -3160,9 +3159,9 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
if (flag) md->state.attacked_count = 0; //Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex]
break;
case MSC_MASTERHPLTMAXRATE:
- flag = ((fbl = mob_getmasterhpltmaxrate(md, ms[i].cond2)) != NULL); break;
+ flag = ((fbl = mob->getmasterhpltmaxrate(md, ms[i].cond2)) != NULL); break;
case MSC_MASTERATTACKED:
- flag = (md->master_id > 0 && (fbl=iMap->id2bl(md->master_id)) && unit_counttargeted(fbl) > 0); break;
+ flag = (md->master_id > 0 && (fbl=map->id2bl(md->master_id)) && unit->counttargeted(fbl) > 0); break;
case MSC_ALCHEMIST:
flag = (md->state.alchemist);
break;
@@ -3172,10 +3171,12 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
if (!flag)
continue; //Skill requisite failed to be fulfilled.
+
//Execute skill
+ skill_target = (md->db->status.mode&MD_RANDOMTARGET)? MST_RANDOM : ms[i].target;
if (skill->get_casttype(ms[i].skill_id) == CAST_GROUND) {//Ground skill.
short x, y;
- switch (ms[i].target) {
+ switch (skill_target) {
case MST_RANDOM: //Pick a random enemy within skill range.
bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md),
skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv));
@@ -3185,12 +3186,12 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
case MST_AROUND6:
case MST_AROUND7:
case MST_AROUND8:
- bl = iMap->id2bl(md->target_id);
+ bl = map->id2bl(md->target_id);
break;
case MST_MASTER:
bl = &md->bl;
if (md->master_id)
- bl = iMap->id2bl(md->master_id);
+ bl = map->id2bl(md->master_id);
if (bl) //Otherwise, fall through.
break;
case MST_FRIEND:
@@ -3205,34 +3206,34 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
x = bl->x;
y = bl->y;
// Look for an area to cast the spell around...
- if (ms[i].target >= MST_AROUND1 || ms[i].target >= MST_AROUND5) {
- j = ms[i].target >= MST_AROUND1?
- (ms[i].target-MST_AROUND1) +1:
- (ms[i].target-MST_AROUND5) +1;
- iMap->search_freecell(&md->bl, md->bl.m, &x, &y, j, j, 3);
+ if (skill_target >= MST_AROUND1 || skill_target >= MST_AROUND5) {
+ j = skill_target >= MST_AROUND1?
+ (skill_target-MST_AROUND1) +1:
+ (skill_target-MST_AROUND5) +1;
+ map->search_freecell(&md->bl, md->bl.m, &x, &y, j, j, 3);
}
md->skill_idx = i;
- iMap->freeblock_lock();
- if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) ||
- !unit_skilluse_pos2(&md->bl, x, y,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel) )
- {
- iMap->freeblock_unlock();
+ map->freeblock_lock();
+ if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv))
+ || !unit->skilluse_pos2(&md->bl, x, y,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel)
+ ) {
+ map->freeblock_unlock();
continue;
}
} else {
- //Targetted skill
- switch (ms[i].target) {
+ //Targeted skill
+ switch (skill_target) {
case MST_RANDOM: //Pick a random enemy within skill range.
bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md),
skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv));
break;
case MST_TARGET:
- bl = iMap->id2bl(md->target_id);
+ bl = map->id2bl(md->target_id);
break;
case MST_MASTER:
bl = &md->bl;
if (md->master_id)
- bl = iMap->id2bl(md->master_id);
+ bl = map->id2bl(md->master_id);
if (bl) //Otherwise, fall through.
break;
case MST_FRIEND:
@@ -3250,17 +3251,17 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
if (!bl) continue;
md->skill_idx = i;
- iMap->freeblock_lock();
- if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) ||
- !unit_skilluse_id2(&md->bl, bl->id,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel) )
- {
- iMap->freeblock_unlock();
+ map->freeblock_lock();
+ if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv))
+ || !unit->skilluse_id2(&md->bl, bl->id,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel)
+ ) {
+ map->freeblock_unlock();
continue;
}
}
//Skill used. Post-setups...
if ( ms[ i ].msg_id ){ //Display color message [SnakeDrak]
- struct mob_chat *mc = mob_chat(ms[i].msg_id);
+ struct mob_chat *mc = mob->chat(ms[i].msg_id);
char temp[CHAT_SIZE_MAX];
char name[NAME_LENGTH];
snprintf(name, sizeof name,"%s", md->name);
@@ -3274,7 +3275,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
md->skilldelay[j]=tick;
} else
md->skilldelay[i]=tick;
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
//No skill was used.
@@ -3284,8 +3285,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event)
/*==========================================
* Skill use event processing
*------------------------------------------*/
-int mobskill_event(struct mob_data *md, struct block_list *src, unsigned int tick, int flag)
-{
+int mobskill_event(struct mob_data *md, struct block_list *src, int64 tick, int flag) {
int target_id, res = 0;
if(md->bl.prev == NULL || md->status.hp <= 0)
@@ -3296,13 +3296,13 @@ int mobskill_event(struct mob_data *md, struct block_list *src, unsigned int tic
md->target_id = src->id;
if (flag == -1)
- res = mobskill_use(md, tick, MSC_CASTTARGETED);
+ res = mob->skill_use(md, tick, MSC_CASTTARGETED);
else if ((flag&0xffff) == MSC_SKILLUSED)
- res = mobskill_use(md, tick, flag);
+ res = mob->skill_use(md, tick, flag);
else if (flag&BF_SHORT)
- res = mobskill_use(md, tick, MSC_CLOSEDATTACKED);
+ res = mob->skill_use(md, tick, MSC_CLOSEDATTACKED);
else if (flag&BF_LONG && !(flag&BF_MAGIC)) //Long-attacked should not include magic.
- res = mobskill_use(md, tick, MSC_LONGRANGEATTACKED);
+ res = mob->skill_use(md, tick, MSC_LONGRANGEATTACKED);
if (!res)
//Restore previous target only if skill condition failed to trigger. [Skotlex]
@@ -3319,53 +3319,52 @@ int mob_is_clone(int class_)
{
if(class_ < MOB_CLONE_START || class_ > MOB_CLONE_END)
return 0;
- if (mob_db(class_) == mob_dummy)
+ if (mob->db(class_) == mob->dummy)
return 0;
return class_;
}
//Flag values:
-//&1: Set special ai (fight mobs, not players)
+//&1: Set special AI (fight mobs, not players)
//If mode is not passed, a default aggressive mode is used.
//If master_id is passed, clone is attached to him.
//Returns: ID of newly crafted copy.
-int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, int mode, int flag, unsigned int duration)
-{
+int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, int mode, int flag, unsigned int duration) {
int class_;
int i,j,h,inf,skill_id, fd;
struct mob_data *md;
struct mob_skill *ms;
struct mob_db* db;
- struct status_data *status;
+ struct status_data *mstatus;
nullpo_ret(sd);
if(pc_isdead(sd) && master_id && flag&1)
return 0;
- ARR_FIND( MOB_CLONE_START, MOB_CLONE_END, class_, mob_db_data[class_] == NULL );
+ ARR_FIND( MOB_CLONE_START, MOB_CLONE_END, class_, mob->db_data[class_] == NULL );
if(class_ >= MOB_CLONE_END)
return 0;
- db = mob_db_data[class_]=(struct mob_db*)aCalloc(1, sizeof(struct mob_db));
- status = &db->status;
+ db = mob->db_data[class_]=(struct mob_db*)aCalloc(1, sizeof(struct mob_db));
+ mstatus = &db->status;
strcpy(db->sprite,sd->status.name);
strcpy(db->name,sd->status.name);
strcpy(db->jname,sd->status.name);
- db->lv=status_get_lv(&sd->bl);
- memcpy(status, &sd->base_status, sizeof(struct status_data));
- status->rhw.atk2= status->dex + status->rhw.atk + status->rhw.atk2; //Max ATK
- status->rhw.atk = status->dex; //Min ATK
- if (status->lhw.atk) {
- status->lhw.atk2= status->dex + status->lhw.atk + status->lhw.atk2; //Max ATK
- status->lhw.atk = status->dex; //Min ATK
+ db->lv=status->get_lv(&sd->bl);
+ memcpy(mstatus, &sd->base_status, sizeof(struct status_data));
+ mstatus->rhw.atk2= mstatus->dex + mstatus->rhw.atk + mstatus->rhw.atk2; //Max ATK
+ mstatus->rhw.atk = mstatus->dex; //Min ATK
+ if (mstatus->lhw.atk) {
+ mstatus->lhw.atk2= mstatus->dex + mstatus->lhw.atk + mstatus->lhw.atk2; //Max ATK
+ mstatus->lhw.atk = mstatus->dex; //Min ATK
}
if (mode) //User provided mode.
- status->mode = mode;
+ mstatus->mode = mode;
else if (flag&1) //Friendly Character, remove looting.
- status->mode &= ~MD_LOOTER;
- status->hp = status->max_hp;
- status->sp = status->max_sp;
+ mstatus->mode &= ~MD_LOOTER;
+ mstatus->hp = mstatus->max_hp;
+ mstatus->sp = mstatus->max_sp;
memcpy(&db->vd, &sd->vd, sizeof(struct view_data));
db->base_exp=1;
db->job_exp=1;
@@ -3384,18 +3383,18 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
//Go Backwards to give better priority to advanced skills.
for (i=0,j = MAX_SKILL_TREE-1;j>=0 && i< MAX_MOBSKILL ;j--) {
- int idx = skill_tree[pc->class2idx(sd->status.class_)][j].idx;
- skill_id = skill_tree[pc->class2idx(sd->status.class_)][j].id;
+ int idx = pc->skill_tree[pc->class2idx(sd->status.class_)][j].idx;
+ skill_id = pc->skill_tree[pc->class2idx(sd->status.class_)][j].id;
if (!skill_id || sd->status.skill[idx].lv < 1 ||
- (skill_db[idx].inf2&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL))
+ (skill->db[idx].inf2&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL))
)
continue;
- for(h = 0; h < map[sd->bl.m].zone->disabled_skills_count; h++) {
- if( skill_id == map[sd->bl.m].zone->disabled_skills[h]->nameid && map[sd->bl.m].zone->disabled_skills[h]->subtype == MZS_CLONE ) {
+ for(h = 0; h < map->list[sd->bl.m].zone->disabled_skills_count; h++) {
+ if( skill_id == map->list[sd->bl.m].zone->disabled_skills[h]->nameid && map->list[sd->bl.m].zone->disabled_skills[h]->subtype == MZS_CLONE ) {
break;
}
}
- if( h < map[sd->bl.m].zone->disabled_skills_count )
+ if( h < map->list[sd->bl.m].zone->disabled_skills_count )
continue;
//Normal aggressive mob, disable skills that cannot help them fight
//against players (those with flags UF_NOMOB and UF_NOPC are specific
@@ -3420,7 +3419,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
ms[i].casttime = skill->cast_fix(&sd->bl,skill_id, ms[i].skill_lv);
ms[i].delay = 5000+skill->delay_fix(&sd->bl,skill_id, ms[i].skill_lv);
- inf = skill_db[idx].inf;
+ inf = skill->db[idx].inf;
if (inf&INF_ATTACK_SKILL) {
ms[i].target = MST_TARGET;
ms[i].cond1 = MSC_ALWAYS;
@@ -3509,7 +3508,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
sd->fd = fd;
//Finally, spawn it.
- md = mob_once_spawn_sub(&sd->bl, m, x, y, "--en--", class_, event, SZ_SMALL, AI_NONE);
+ md = mob->once_spawn_sub(&sd->bl, m, x, y, "--en--", class_, event, SZ_MEDIUM, AI_NONE);
if (!md) return 0; //Failed?
md->special_state.clone = 1;
@@ -3522,12 +3521,12 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
if (duration) //Auto Delete after a while.
{
if( md->deletetimer != INVALID_TIMER )
- iTimer->delete_timer(md->deletetimer, mob_timer_delete);
- md->deletetimer = iTimer->add_timer (iTimer->gettick() + duration, mob_timer_delete, md->bl.id, 0);
+ timer->delete(md->deletetimer, mob->timer_delete);
+ md->deletetimer = timer->add(timer->gettick() + duration, mob->timer_delete, md->bl.id, 0);
}
}
- mob_spawn(md);
+ mob->spawn(md);
return md->bl.id;
}
@@ -3536,11 +3535,11 @@ int mob_clone_delete(struct mob_data *md)
{
const int class_ = md->class_;
if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END
- && mob_db_data[class_]!=NULL) {
- aFree(mob_db_data[class_]);
- mob_db_data[class_]=NULL;
+ && mob->db_data[class_]!=NULL) {
+ aFree(mob->db_data[class_]);
+ mob->db_data[class_]=NULL;
//Clear references to the db
- md->db = mob_dummy;
+ md->db = mob->dummy;
md->vd = NULL;
return 1;
}
@@ -3553,50 +3552,50 @@ int mob_clone_delete(struct mob_data *md)
/*==========================================
* Since un-setting [ mob ] up was used, it is an initial provisional value setup.
*------------------------------------------*/
-static int mob_makedummymobdb(int class_)
+int mob_makedummymobdb(int class_)
{
- if (mob_dummy != NULL)
+ if (mob->dummy != NULL)
{
- if (mob_db(class_) == mob_dummy)
- return 1; //Using the mob_dummy data already. [Skotlex]
+ if (mob->db(class_) == mob->dummy)
+ return 1; //Using the mob->dummy data already. [Skotlex]
if (class_ > 0 && class_ <= MAX_MOB_DB)
{ //Remove the mob data so that it uses the dummy data instead.
- aFree(mob_db_data[class_]);
- mob_db_data[class_] = NULL;
+ aFree(mob->db_data[class_]);
+ mob->db_data[class_] = NULL;
}
return 0;
}
//Initialize dummy data.
- mob_dummy = (struct mob_db*)aCalloc(1, sizeof(struct mob_db)); //Initializing the dummy mob.
- sprintf(mob_dummy->sprite,"DUMMY");
- sprintf(mob_dummy->name,"Dummy");
- sprintf(mob_dummy->jname,"Dummy");
- mob_dummy->lv=1;
- mob_dummy->status.max_hp=1000;
- mob_dummy->status.max_sp=1;
- mob_dummy->status.rhw.range=1;
- mob_dummy->status.rhw.atk=7;
- mob_dummy->status.rhw.atk2=10;
- mob_dummy->status.str=1;
- mob_dummy->status.agi=1;
- mob_dummy->status.vit=1;
- mob_dummy->status.int_=1;
- mob_dummy->status.dex=6;
- mob_dummy->status.luk=2;
- mob_dummy->status.speed=300;
- mob_dummy->status.adelay=1000;
- mob_dummy->status.amotion=500;
- mob_dummy->status.dmotion=500;
- mob_dummy->base_exp=2;
- mob_dummy->job_exp=1;
- mob_dummy->range2=10;
- mob_dummy->range3=10;
+ mob->dummy = (struct mob_db*)aCalloc(1, sizeof(struct mob_db)); //Initializing the dummy mob.
+ sprintf(mob->dummy->sprite,"DUMMY");
+ sprintf(mob->dummy->name,"Dummy");
+ sprintf(mob->dummy->jname,"Dummy");
+ mob->dummy->lv=1;
+ mob->dummy->status.max_hp=1000;
+ mob->dummy->status.max_sp=1;
+ mob->dummy->status.rhw.range=1;
+ mob->dummy->status.rhw.atk=7;
+ mob->dummy->status.rhw.atk2=10;
+ mob->dummy->status.str=1;
+ mob->dummy->status.agi=1;
+ mob->dummy->status.vit=1;
+ mob->dummy->status.int_=1;
+ mob->dummy->status.dex=6;
+ mob->dummy->status.luk=2;
+ mob->dummy->status.speed=300;
+ mob->dummy->status.adelay=1000;
+ mob->dummy->status.amotion=500;
+ mob->dummy->status.dmotion=500;
+ mob->dummy->base_exp=2;
+ mob->dummy->job_exp=1;
+ mob->dummy->range2=10;
+ mob->dummy->range3=10;
return 0;
}
//Adjusts the drop rate of item according to the criteria given. [Skotlex]
-static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned short rate_min, unsigned short rate_max)
+unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned short rate_min, unsigned short rate_max)
{
double rate = baserate;
@@ -3612,13 +3611,13 @@ static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned shor
}
/**
- * Check if global item drop rate is overriden for given item
+ * Check if global item drop rate is overridden for given item
* in db/mob_item_ratio.txt
* @param nameid ID of the item
* @param mob_id ID of the monster
* @param rate_adjust pointer to store ratio if found
*/
-static void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust)
+void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust)
{
if( item_drop_ratio_db[nameid] ) {
if( item_drop_ratio_db[nameid]->mob_id[0] ) { // only for listed mobs
@@ -3631,14 +3630,23 @@ static void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust)
*rate_adjust = item_drop_ratio_db[nameid]->drop_ratio;
}
}
-
+/* (mob_parse_dbrow)_cap_value */
+static inline int mob_parse_dbrow_cap_value(int class_, int min, int max, int value) {
+ if( value > max ) {
+ ShowError("mob_parse_dbrow: for class '%d', field value '%d' is higher than the maximum '%d'! capping...\n", class_, value, max);
+ return max;
+ } else if ( value < min ) {
+ ShowError("mob_parse_dbrow: for class '%d', field value '%d' is lower than the minimum '%d'! capping...\n", class_, value, min);
+ return min;
+ }
+ return value;
+}
/*==========================================
* processes one mobdb entry
*------------------------------------------*/
-static bool mob_parse_dbrow(char** str)
-{
+bool mob_parse_dbrow(char** str) {
struct mob_db *db, entry;
- struct status_data *status;
+ struct status_data *mstatus;
int class_, i, k;
double exp, maxhp;
struct mob_data data;
@@ -3662,7 +3670,7 @@ static bool mob_parse_dbrow(char** str)
memset(&entry, 0, sizeof(entry));
db = &entry;
- status = &db->status;
+ mstatus = &db->status;
db->vd.class_ = class_;
safestrncpy(db->sprite, str[1], sizeof(db->sprite));
@@ -3670,8 +3678,8 @@ static bool mob_parse_dbrow(char** str)
safestrncpy(db->name, str[3], sizeof(db->name));
db->lv = atoi(str[4]);
db->lv = cap_value(db->lv, 1, USHRT_MAX);
- status->max_hp = atoi(str[5]);
- status->max_sp = atoi(str[6]);
+ mstatus->max_hp = atoi(str[5]);
+ mstatus->max_sp = atoi(str[6]);
exp = (double)atoi(str[7]) * (double)battle_config.base_exp_rate / 100.;
db->base_exp = (unsigned int)cap_value(exp, 0, UINT_MAX);
@@ -3679,24 +3687,28 @@ static bool mob_parse_dbrow(char** str)
exp = (double)atoi(str[8]) * (double)battle_config.job_exp_rate / 100.;
db->job_exp = (unsigned int)cap_value(exp, 0, UINT_MAX);
- status->rhw.range = atoi(str[9]);
- status->rhw.atk = atoi(str[10]);
- status->rhw.atk2 = atoi(str[11]);
- status->def = atoi(str[12]);
- status->mdef = atoi(str[13]);
- status->str = atoi(str[14]);
- status->agi = atoi(str[15]);
- status->vit = atoi(str[16]);
- status->int_ = atoi(str[17]);
- status->dex = atoi(str[18]);
- status->luk = atoi(str[19]);
+ mstatus->rhw.range = atoi(str[9]);
+
+ mstatus->rhw.atk = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[10]));
+ mstatus->rhw.atk2 = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[11]));
+
+ mstatus->def = mob_parse_dbrow_cap_value(class_,DEFTYPE_MIN,DEFTYPE_MAX,atoi(str[12]));
+ mstatus->mdef = mob_parse_dbrow_cap_value(class_,DEFTYPE_MIN,DEFTYPE_MAX,atoi(str[13]));
+
+ mstatus->str = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[14]));
+ mstatus->agi = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[15]));
+ mstatus->vit = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[16]));
+ mstatus->int_ = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[17]));
+ mstatus->dex = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[18]));
+ mstatus->luk = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[19]));
+
//All status should be min 1 to prevent divisions by zero from some skills. [Skotlex]
- if (status->str < 1) status->str = 1;
- if (status->agi < 1) status->agi = 1;
- if (status->vit < 1) status->vit = 1;
- if (status->int_< 1) status->int_= 1;
- if (status->dex < 1) status->dex = 1;
- if (status->luk < 1) status->luk = 1;
+ if (mstatus->str < 1) mstatus->str = 1;
+ if (mstatus->agi < 1) mstatus->agi = 1;
+ if (mstatus->vit < 1) mstatus->vit = 1;
+ if (mstatus->int_< 1) mstatus->int_= 1;
+ if (mstatus->dex < 1) mstatus->dex = 1;
+ if (mstatus->luk < 1) mstatus->luk = 1;
db->range2 = atoi(str[20]);
db->range3 = atoi(str[21]);
@@ -3711,52 +3723,52 @@ static bool mob_parse_dbrow(char** str)
db->range3 = db->range2;
}
- status->size = atoi(str[22]);
- status->race = atoi(str[23]);
+ mstatus->size = atoi(str[22]);
+ mstatus->race = atoi(str[23]);
i = atoi(str[24]); //Element
- status->def_ele = i%10;
- status->ele_lv = i/20;
- if (status->def_ele >= ELE_MAX) {
- ShowError("mob_parse_dbrow: Invalid element type %d for monster ID %d (max=%d).\n", status->def_ele, class_, ELE_MAX-1);
+ mstatus->def_ele = i%10;
+ mstatus->ele_lv = i/20;
+ if (mstatus->def_ele >= ELE_MAX) {
+ ShowError("mob_parse_dbrow: Invalid element type %d for monster ID %d (max=%d).\n", mstatus->def_ele, class_, ELE_MAX-1);
return false;
}
- if (status->ele_lv < 1 || status->ele_lv > 4) {
- ShowError("mob_parse_dbrow: Invalid element level %d for monster ID %d, must be in range 1-4.\n", status->ele_lv, class_);
+ if (mstatus->ele_lv < 1 || mstatus->ele_lv > 4) {
+ ShowError("mob_parse_dbrow: Invalid element level %d for monster ID %d, must be in range 1-4.\n", mstatus->ele_lv, class_);
return false;
}
- status->mode = (int)strtol(str[25], NULL, 0);
+ mstatus->mode = (int)strtol(str[25], NULL, 0);
if (!battle_config.monster_active_enable)
- status->mode &= ~MD_AGGRESSIVE;
+ mstatus->mode &= ~MD_AGGRESSIVE;
- status->speed = atoi(str[26]);
- status->aspd_rate = 1000;
+ mstatus->speed = atoi(str[26]);
+ mstatus->aspd_rate = 1000;
i = atoi(str[27]);
- status->adelay = cap_value(i, battle_config.monster_max_aspd*2, 4000);
+ mstatus->adelay = cap_value(i, battle_config.monster_max_aspd*2, 4000);
i = atoi(str[28]);
- status->amotion = cap_value(i, battle_config.monster_max_aspd, 2000);
+ mstatus->amotion = cap_value(i, battle_config.monster_max_aspd, 2000);
//If the attack animation is longer than the delay, the client crops the attack animation!
//On aegis there is no real visible effect of having a recharge-time less than amotion anyway.
- if (status->adelay < status->amotion)
- status->adelay = status->amotion;
- status->dmotion = atoi(str[29]);
+ if (mstatus->adelay < mstatus->amotion)
+ mstatus->adelay = mstatus->amotion;
+ mstatus->dmotion = atoi(str[29]);
if(battle_config.monster_damage_delay_rate != 100)
- status->dmotion = status->dmotion * battle_config.monster_damage_delay_rate / 100;
+ mstatus->dmotion = mstatus->dmotion * battle_config.monster_damage_delay_rate / 100;
// Fill in remaining status data by using a dummy monster.
data.bl.type = BL_MOB;
data.level = db->lv;
- memcpy(&data.status, status, sizeof(struct status_data));
- status_calc_misc(&data.bl, status, db->lv);
+ memcpy(&data.status, mstatus, sizeof(struct status_data));
+ status->calc_misc(&data.bl, mstatus, db->lv);
// MVP EXP Bonus: MEXP
- // Some new MVP's MEXP multipled by high exp-rate cause overflow. [LuzZza]
+ // Some new MVP's MEXP multiple by high exp-rate cause overflow. [LuzZza]
exp = (double)atoi(str[30]) * (double)battle_config.mvp_exp_rate / 100.;
db->mexp = (unsigned int)cap_value(exp, 0, UINT_MAX);
//Now that we know if it is an mvp or not, apply battle_config modifiers [Skotlex]
- maxhp = (double)status->max_hp;
+ maxhp = (double)mstatus->max_hp;
if (db->mexp > 0) { //Mvp
if (battle_config.mvp_hp_rate != 100)
maxhp = maxhp * (double)battle_config.mvp_hp_rate / 100.;
@@ -3764,12 +3776,12 @@ static bool mob_parse_dbrow(char** str)
if (battle_config.monster_hp_rate != 100)
maxhp = maxhp * (double)battle_config.monster_hp_rate / 100.;
- status->max_hp = (unsigned int)cap_value(maxhp, 1, UINT_MAX);
- if(status->max_sp < 1) status->max_sp = 1;
+ mstatus->max_hp = (unsigned int)cap_value(maxhp, 1, UINT_MAX);
+ if(mstatus->max_sp < 1) mstatus->max_sp = 1;
//Since mobs always respawn with full life...
- status->hp = status->max_hp;
- status->sp = status->max_sp;
+ mstatus->hp = mstatus->max_hp;
+ mstatus->sp = mstatus->max_sp;
// MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per
for(i = 0; i < MAX_MVP_DROP; i++) {
@@ -3779,13 +3791,13 @@ static bool mob_parse_dbrow(char** str)
db->mvpitem[i].p = 0; //No item....
continue;
}
- item_dropratio_adjust(db->mvpitem[i].nameid, class_, &rate_adjust);
- db->mvpitem[i].p = mob_drop_adjust(atoi(str[32+i*2]), rate_adjust, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max);
+ mob->item_dropratio_adjust(db->mvpitem[i].nameid, class_, &rate_adjust);
+ db->mvpitem[i].p = mob->drop_adjust(atoi(str[32+i*2]), rate_adjust, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max);
//calculate and store Max available drop chance of the MVP item
if (db->mvpitem[i].p) {
struct item_data *id;
- id = itemdb_search(db->mvpitem[i].nameid);
+ id = itemdb->search(db->mvpitem[i].nameid);
if (id->maxchance == -1 || (id->maxchance < db->mvpitem[i].p/10 + 1) ) {
//item has bigger drop chance or sold in shops
id->maxchance = db->mvpitem[i].p/10 + 1; //reduce MVP drop info to not spoil common drop rate
@@ -3803,7 +3815,7 @@ static bool mob_parse_dbrow(char** str)
db->dropitem[i].p = 0; //No drop.
continue;
}
- id = itemdb_search(db->dropitem[i].nameid);
+ id = itemdb->search(db->dropitem[i].nameid);
type = id->type;
rate = atoi(str[k+1]);
if( (class_ >= 1324 && class_ <= 1363) || (class_ >= 1938 && class_ <= 1946) )
@@ -3813,38 +3825,38 @@ static bool mob_parse_dbrow(char** str)
ratemax = battle_config.item_drop_treasure_max;
}
else switch (type)
- { // Added suport to restrict normal drops of MVP's [Reddozen]
+ { // Added support to restrict normal drops of MVP's [Reddozen]
case IT_HEALING:
- rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_heal_boss : battle_config.item_rate_heal;
+ rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_heal_boss : battle_config.item_rate_heal;
ratemin = battle_config.item_drop_heal_min;
ratemax = battle_config.item_drop_heal_max;
break;
case IT_USABLE:
case IT_CASH:
- rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_use_boss : battle_config.item_rate_use;
+ rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_use_boss : battle_config.item_rate_use;
ratemin = battle_config.item_drop_use_min;
ratemax = battle_config.item_drop_use_max;
break;
case IT_WEAPON:
case IT_ARMOR:
case IT_PETARMOR:
- rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_equip_boss : battle_config.item_rate_equip;
+ rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_equip_boss : battle_config.item_rate_equip;
ratemin = battle_config.item_drop_equip_min;
ratemax = battle_config.item_drop_equip_max;
break;
case IT_CARD:
- rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_card_boss : battle_config.item_rate_card;
+ rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_card_boss : battle_config.item_rate_card;
ratemin = battle_config.item_drop_card_min;
ratemax = battle_config.item_drop_card_max;
break;
default:
- rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_common_boss : battle_config.item_rate_common;
+ rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_common_boss : battle_config.item_rate_common;
ratemin = battle_config.item_drop_common_min;
ratemax = battle_config.item_drop_common_max;
break;
}
- item_dropratio_adjust(id->nameid, class_, &rate_adjust);
- db->dropitem[i].p = mob_drop_adjust(rate, rate_adjust, ratemin, ratemax);
+ mob->item_dropratio_adjust(id->nameid, class_, &rate_adjust);
+ db->dropitem[i].p = mob->drop_adjust(rate, rate_adjust, ratemin, ratemax);
//calculate and store Max available drop chance of the item
if( db->dropitem[i].p && (class_ < 1324 || class_ > 1363) && (class_ < 1938 || class_ > 1946) )
@@ -3865,68 +3877,62 @@ static bool mob_parse_dbrow(char** str)
id->mob[k].id = class_;
}
}
-
// Finally insert monster's data into the database.
- if (mob_db_data[class_] == NULL)
- mob_db_data[class_] = (struct mob_db*)aCalloc(1, sizeof(struct mob_db));
+ if (mob->db_data[class_] == NULL)
+ mob->db_data[class_] = (struct mob_db*)aMalloc(sizeof(struct mob_db));
else
//Copy over spawn data
- memcpy(&db->spawn, mob_db_data[class_]->spawn, sizeof(db->spawn));
+ memcpy(&db->spawn, mob->db_data[class_]->spawn, sizeof(db->spawn));
- memcpy(mob_db_data[class_], db, sizeof(struct mob_db));
+ memcpy(mob->db_data[class_], db, sizeof(struct mob_db));
return true;
}
/*==========================================
* mob_db.txt reading
*------------------------------------------*/
-static bool mob_readdb_sub(char* fields[], int columns, int current)
-{
- return mob_parse_dbrow(fields);
+bool mob_readdb_sub(char* fields[], int columns, int current) {
+ return mob->parse_dbrow(fields);
}
-static void mob_readdb(void)
-{
+void mob_readdb(void) {
const char* filename[] = {
DBPATH"mob_db.txt",
"mob_db2.txt" };
int fi;
- for( fi = 0; fi < ARRAYLENGTH(filename); ++fi )
- {
- if(fi > 0)
- {
- char path[256];
- sprintf(path, "%s/%s", iMap->db_path, filename[fi]);
- if(!exists(path))
- {
+ for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) {
+ if(fi > 0) {
+ char filepath[256];
+ sprintf(filepath, "%s/%s", map->db_path, filename[fi]);
+ if(!exists(filepath)) {
continue;
}
}
- sv->readdb(iMap->db_path, filename[fi], ',', 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, -1, &mob_readdb_sub);
+ sv->readdb(map->db_path, filename[fi], ',', 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, -1, mob->readdb_sub);
}
+ mob->name_constants();
}
/*==========================================
* mob_db table reading
*------------------------------------------*/
-static int mob_read_sqldb(void)
-{
- const char* mob_db_name[] = { iMap->mob_db_db, iMap->mob_db2_db };
+int mob_read_sqldb(void) {
+ const char* mob_db_name[] = { map->mob_db_db, map->mob_db2_db };
int fi;
for( fi = 0; fi < ARRAYLENGTH(mob_db_name); ++fi ) {
uint32 lines = 0, count = 0;
// retrieve all rows from the mob database
- if( SQL_ERROR == SQL->Query(mmysql_handle, "SELECT * FROM `%s`", mob_db_name[fi]) ) {
- Sql_ShowDebug(mmysql_handle);
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT * FROM `%s`", mob_db_name[fi]) ) {
+ Sql_ShowDebug(map->mysql_handle);
continue;
}
// process rows one by one
- while( SQL_SUCCESS == SQL->NextRow(mmysql_handle) ) {
+ while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) {
// wrap the result into a TXT-compatible format
char line[1024];
char* str[31+2*MAX_MVP_DROP+2*MAX_MOB_DROP];
@@ -3938,37 +3944,52 @@ static int mob_read_sqldb(void)
{
char* data;
size_t len;
- SQL->GetData(mmysql_handle, i, &data, &len);
+ SQL->GetData(map->mysql_handle, i, &data, &len);
strcpy(p, data);
str[i] = p;
p+= len + 1;
}
- if (!mob_parse_dbrow(str))
+ if (!mob->parse_dbrow(str))
continue;
count++;
}
// free the query result
- SQL->FreeResult(mmysql_handle);
+ SQL->FreeResult(map->mysql_handle);
- ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_db_name[fi]);
+ ShowStatus("Done reading '"CL_WHITE"%"PRIu32""CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_db_name[fi]);
}
+ mob->name_constants();
return 0;
}
+void mob_name_constants(void) {
+ int i;
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = "Mob Database (Likely an invalid or conflicting SpriteName)";
+#endif // ENABLE_CASE_CHECK
+ for (i = 0; i < MAX_MOB_DB; i++) {
+ if (mob->db_data[i] && !mob->is_clone(i))
+ script->set_constant2(mob->db_data[i]->sprite, i, 0);
+ }
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = NULL;
+#endif // ENABLE_CASE_CHECK
+}
+
/*==========================================
* MOB display graphic change data reading
*------------------------------------------*/
-static bool mob_readdb_mobavail(char* str[], int columns, int current)
+bool mob_readdb_mobavail(char* str[], int columns, int current)
{
int class_, k;
class_=atoi(str[0]);
- if(mob_db(class_) == mob_dummy) // invalid class (probably undefined in db)
+ if(mob->db(class_) == mob->dummy) // invalid class (probably undefined in db)
{
ShowWarning("mob_readdb_mobavail: Unknown mob id %d.\n", class_);
return false;
@@ -3976,24 +3997,24 @@ static bool mob_readdb_mobavail(char* str[], int columns, int current)
k=atoi(str[1]);
- memset(&mob_db_data[class_]->vd, 0, sizeof(struct view_data));
- mob_db_data[class_]->vd.class_=k;
+ memset(&mob->db_data[class_]->vd, 0, sizeof(struct view_data));
+ mob->db_data[class_]->vd.class_=k;
//Player sprites
if(pcdb_checkid(k) && columns==12) {
- mob_db_data[class_]->vd.sex=atoi(str[2]);
- mob_db_data[class_]->vd.hair_style=atoi(str[3]);
- mob_db_data[class_]->vd.hair_color=atoi(str[4]);
- mob_db_data[class_]->vd.weapon=atoi(str[5]);
- mob_db_data[class_]->vd.shield=atoi(str[6]);
- mob_db_data[class_]->vd.head_top=atoi(str[7]);
- mob_db_data[class_]->vd.head_mid=atoi(str[8]);
- mob_db_data[class_]->vd.head_bottom=atoi(str[9]);
- mob_db_data[class_]->option=atoi(str[10])&~(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE);
- mob_db_data[class_]->vd.cloth_color=atoi(str[11]); // Monster player dye option - Valaris
+ mob->db_data[class_]->vd.sex=atoi(str[2]);
+ mob->db_data[class_]->vd.hair_style=atoi(str[3]);
+ mob->db_data[class_]->vd.hair_color=atoi(str[4]);
+ mob->db_data[class_]->vd.weapon=atoi(str[5]);
+ mob->db_data[class_]->vd.shield=atoi(str[6]);
+ mob->db_data[class_]->vd.head_top=atoi(str[7]);
+ mob->db_data[class_]->vd.head_mid=atoi(str[8]);
+ mob->db_data[class_]->vd.head_bottom=atoi(str[9]);
+ mob->db_data[class_]->option=atoi(str[10])&~(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE);
+ mob->db_data[class_]->vd.cloth_color=atoi(str[11]); // Monster player dye option - Valaris
}
else if(columns==3)
- mob_db_data[class_]->vd.head_bottom=atoi(str[2]); // mob equipment [Valaris]
+ mob->db_data[class_]->vd.head_bottom=atoi(str[2]); // mob equipment [Valaris]
else if( columns != 2 )
return false;
@@ -4003,7 +4024,7 @@ static bool mob_readdb_mobavail(char* str[], int columns, int current)
/*==========================================
* Reading of random monster data
*------------------------------------------*/
-static int mob_read_randommonster(void)
+int mob_read_randommonster(void)
{
FILE *fp;
char line[1024];
@@ -4020,8 +4041,8 @@ static int mob_read_randommonster(void)
for( i = 0; i < ARRAYLENGTH(mobfile) && i < MAX_RANDOMMONSTER; i++ ) {
unsigned int count = 0;
- mob_db_data[0]->summonper[i] = 1002; // Default fallback value, in case the database does not provide one
- sprintf(line, "%s/%s", iMap->db_path, mobfile[i]);
+ mob->db_data[0]->summonper[i] = 1002; // Default fallback value, in case the database does not provide one
+ sprintf(line, "%s/%s", map->db_path, mobfile[i]);
fp=fopen(line,"r");
if(fp==NULL){
ShowError("can't read %s\n",line);
@@ -4043,10 +4064,10 @@ static int mob_read_randommonster(void)
continue;
class_ = atoi(str[0]);
- if(mob_db(class_) == mob_dummy)
+ if(mob->db(class_) == mob->dummy)
continue;
count++;
- mob_db_data[class_]->summonper[i]=atoi(str[2]);
+ mob->db_data[class_]->summonper[i]=atoi(str[2]);
if (i) {
if( summon[i].qty < ARRAYLENGTH(summon[i].class_) ) //MvPs
summon[i].class_[summon[i].qty++] = class_;
@@ -4057,11 +4078,11 @@ static int mob_read_randommonster(void)
}
}
if (i && !summon[i].qty) { //At least have the default here.
- summon[i].class_[0] = mob_db_data[0]->summonper[i];
+ summon[i].class_[0] = mob->db_data[0]->summonper[i];
summon[i].qty = 1;
}
fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",count,mobfile[i]);
+ ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",count,mobfile[i]);
}
return 0;
}
@@ -4070,7 +4091,7 @@ static int mob_read_randommonster(void)
* processes one mob_chat_db entry [SnakeDrak]
* @param last_msg_id ensures that only one error message per mob id is printed
*------------------------------------------*/
-static bool mob_parse_row_chatdb(char** str, const char* source, int line, int* last_msg_id)
+bool mob_parse_row_chatdb(char** str, const char* source, int line, int* last_msg_id)
{
char* msg;
struct mob_chat *ms;
@@ -4088,14 +4109,14 @@ static bool mob_parse_row_chatdb(char** str, const char* source, int line, int*
return false;
}
- if (mob_chat_db[msg_id] == NULL)
- mob_chat_db[msg_id] = (struct mob_chat*)aCalloc(1, sizeof (struct mob_chat));
+ if (mob->chat_db[msg_id] == NULL)
+ mob->chat_db[msg_id] = (struct mob_chat*)aCalloc(1, sizeof (struct mob_chat));
- ms = mob_chat_db[msg_id];
+ ms = mob->chat_db[msg_id];
//MSG ID
ms->msg_id=msg_id;
//Color
- ms->color=strtoul(str[1],NULL,0);
+ ms->color=(unsigned int)strtoul(str[1],NULL,0);
//Message
msg = str[2];
len = strlen(msg);
@@ -4128,23 +4149,20 @@ static bool mob_parse_row_chatdb(char** str, const char* source, int line, int*
/*==========================================
* mob_chat_db.txt reading [SnakeDrak]
*-------------------------------------------------------------------------*/
-static void mob_readchatdb(void)
-{
+void mob_readchatdb(void) {
char arc[]="mob_chat_db.txt";
uint32 lines=0, count=0;
- char line[1024], path[256];
+ char line[1024], filepath[256];
int i, tmp=0;
FILE *fp;
- sprintf(path, "%s/%s", iMap->db_path, arc);
- fp=fopen(path, "r");
- if(fp == NULL)
- {
- ShowWarning("mob_readchatdb: File not found \"%s\", skipping.\n", path);
+ sprintf(filepath, "%s/%s", map->db_path, arc);
+ fp=fopen(filepath, "r");
+ if(fp == NULL) {
+ ShowWarning("mob_readchatdb: File not found \"%s\", skipping.\n", filepath);
return;
}
- while(fgets(line, sizeof(line), fp))
- {
+ while(fgets(line, sizeof(line), fp)) {
char *str[3], *p, *np;
int j=0;
@@ -4172,19 +4190,19 @@ static void mob_readchatdb(void)
continue;
}
- if( !mob_parse_row_chatdb(str, path, lines, &tmp) )
+ if( !mob->parse_row_chatdb(str, filepath, lines, &tmp) )
continue;
count++;
}
fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, arc);
+ ShowStatus("Done reading '"CL_WHITE"%"PRIu32""CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, arc);
}
/*==========================================
* processes one mob_skill_db entry
*------------------------------------------*/
-static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
+bool mob_parse_row_mobskilldb(char** str, int columns, int current)
{
static const struct {
char str[32];
@@ -4266,7 +4284,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
mob_id = atoi(str[0]);
- if (mob_id > 0 && mob_db(mob_id) == mob_dummy)
+ if (mob_id > 0 && mob->db(mob_id) == mob->dummy)
{
if (mob_id != last_mob_id) {
ShowError("mob_parse_row_mobskilldb: Non existant Mob id %d\n", mob_id);
@@ -4277,8 +4295,8 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
if( strcmp(str[1],"clear")==0 ){
if (mob_id < 0)
return false;
- memset(mob_db_data[mob_id]->skill,0,sizeof(struct mob_skill));
- mob_db_data[mob_id]->maxskill=0;
+ memset(mob->db_data[mob_id]->skill,0,sizeof(struct mob_skill));
+ mob->db_data[mob_id]->maxskill=0;
return true;
}
@@ -4287,11 +4305,11 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
memset(&gms, 0, sizeof (struct mob_skill));
ms = &gms;
} else {
- ARR_FIND( 0, MAX_MOBSKILL, i, (ms = &mob_db_data[mob_id]->skill[i])->skill_id == 0 );
+ ARR_FIND( 0, MAX_MOBSKILL, i, (ms = &mob->db_data[mob_id]->skill[i])->skill_id == 0 );
if( i == MAX_MOBSKILL )
{
if (mob_id != last_mob_id) {
- ShowError("mob_parse_row_mobskilldb: Too many skills for monster %d[%s]\n", mob_id, mob_db_data[mob_id]->sprite);
+ ShowError("mob_parse_row_mobskilldb: Too many skills for monster %d[%s]\n", mob_id, mob->db_data[mob_id]->sprite);
last_mob_id = mob_id;
}
return false;
@@ -4313,7 +4331,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
if (mob_id < 0)
ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for all mobs\n", j);
else
- ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for mob %d (%s)\n", j, mob_id, mob_db_data[mob_id]->sprite);
+ ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for mob %d (%s)\n", j, mob_id, mob->db_data[mob_id]->sprite);
return false;
}
ms->skill_id=j;
@@ -4354,14 +4372,14 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
if ( skill->get_casttype2(sidx) == CAST_GROUND) {//Ground skill.
if (ms->target > MST_AROUND) {
ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target for ground skill %d (%s) for %s.\n",
- ms->skill_id, skill_db[sidx].name,
- mob_id < 0?"all mobs":mob_db_data[mob_id]->sprite);
+ ms->skill_id, skill->db[sidx].name,
+ mob_id < 0?"all mobs":mob->db_data[mob_id]->sprite);
ms->target = MST_TARGET;
}
} else if (ms->target > MST_MASTER) {
ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s.\n",
- ms->skill_id, skill_db[sidx].name,
- mob_id < 0?"all mobs":mob_db_data[mob_id]->sprite);
+ ms->skill_id, skill->db[sidx].name,
+ mob_id < 0?"all mobs":mob->db_data[mob_id]->sprite);
ms->target = MST_TARGET;
}
@@ -4389,7 +4407,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
ms->val[4]=(int)strtol(str[16],NULL,0);
if(ms->skill_id == NPC_EMOTION && mob_id>0 &&
- ms->val[1] == mob_db(mob_id)->status.mode)
+ ms->val[1] == mob->db(mob_id)->status.mode)
{
ms->val[1] = 0;
ms->val[4] = 1; //request to return mode to normal.
@@ -4408,7 +4426,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
else
ms->emotion=-1;
- if(str[18]!=NULL && mob_chat_db[atoi(str[18])]!=NULL)
+ if(str[18]!=NULL && mob->chat_db[atoi(str[18])]!=NULL)
ms->msg_id=atoi(str[18]);
else
ms->msg_id=0;
@@ -4418,9 +4436,9 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
mob_id *= -1;
for (i = 1; i < MAX_MOB_DB; i++)
{
- if (mob_db_data[i] == NULL)
+ if (mob->db_data[i] == NULL)
continue;
- if (mob_db_data[i]->status.mode&MD_BOSS)
+ if (mob->db_data[i]->status.mode&MD_BOSS)
{
if (!(mob_id&2)) //Skill not for bosses
continue;
@@ -4428,15 +4446,15 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
if (!(mob_id&1)) //Skill not for normal enemies.
continue;
- ARR_FIND( 0, MAX_MOBSKILL, j, mob_db_data[i]->skill[j].skill_id == 0 );
+ ARR_FIND( 0, MAX_MOBSKILL, j, mob->db_data[i]->skill[j].skill_id == 0 );
if(j==MAX_MOBSKILL)
continue;
- memcpy (&mob_db_data[i]->skill[j], ms, sizeof(struct mob_skill));
- mob_db_data[i]->maxskill=j+1;
+ memcpy (&mob->db_data[i]->skill[j], ms, sizeof(struct mob_skill));
+ mob->db_data[i]->maxskill=j+1;
}
} else //Skill set on a single mob.
- mob_db_data[mob_id]->maxskill=i+1;
+ mob->db_data[mob_id]->maxskill=i+1;
return true;
}
@@ -4444,31 +4462,27 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
/*==========================================
* mob_skill_db.txt reading
*------------------------------------------*/
-static void mob_readskilldb(void) {
+void mob_readskilldb(void) {
const char* filename[] = {
DBPATH"mob_skill_db.txt",
"mob_skill_db2.txt" };
int fi;
- if( battle_config.mob_skill_rate == 0 )
- {
+ if( battle_config.mob_skill_rate == 0 ) {
ShowStatus("Mob skill use disabled. Not reading mob skills.\n");
return;
}
- for( fi = 0; fi < ARRAYLENGTH(filename); ++fi )
- {
- if(fi > 0)
- {
- char path[256];
- sprintf(path, "%s/%s", iMap->db_path, filename[fi]);
- if(!exists(path))
- {
+ for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) {
+ if(fi > 0) {
+ char filepath[256];
+ sprintf(filepath, "%s/%s", map->db_path, filename[fi]);
+ if(!exists(filepath)) {
continue;
}
}
- sv->readdb(iMap->db_path, filename[fi], ',', 19, 19, -1, &mob_parse_row_mobskilldb);
+ sv->readdb(map->db_path, filename[fi], ',', 19, 19, -1, mob->parse_row_mobskilldb);
}
}
@@ -4477,9 +4491,8 @@ static void mob_readskilldb(void) {
* not overly sure if this is all correct
* seems to work though...
*/
-static int mob_read_sqlskilldb(void)
-{
- const char* mob_skill_db_name[] = { iMap->mob_skill_db_db, iMap->mob_skill_db2_db };
+int mob_read_sqlskilldb(void) {
+ const char* mob_skill_db_name[] = { map->mob_skill_db_db, map->mob_skill_db2_db };
int fi;
if( battle_config.mob_skill_rate == 0 ) {
@@ -4492,13 +4505,13 @@ static int mob_read_sqlskilldb(void)
uint32 lines = 0, count = 0;
// retrieve all rows from the mob skill database
- if( SQL_ERROR == SQL->Query(mmysql_handle, "SELECT * FROM `%s`", mob_skill_db_name[fi]) ) {
- Sql_ShowDebug(mmysql_handle);
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT * FROM `%s`", mob_skill_db_name[fi]) ) {
+ Sql_ShowDebug(map->mysql_handle);
continue;
}
// process rows one by one
- while( SQL_SUCCESS == SQL->NextRow(mmysql_handle) ) {
+ while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) {
// wrap the result into a TXT-compatible format
char* str[19];
char* dummy = "";
@@ -4506,20 +4519,20 @@ static int mob_read_sqlskilldb(void)
++lines;
for( i = 0; i < 19; ++i )
{
- SQL->GetData(mmysql_handle, i, &str[i], NULL);
+ SQL->GetData(map->mysql_handle, i, &str[i], NULL);
if( str[i] == NULL ) str[i] = dummy; // get rid of NULL columns
}
- if (!mob_parse_row_mobskilldb(str, 19, count))
+ if (!mob->parse_row_mobskilldb(str, 19, count))
continue;
count++;
}
// free the query result
- SQL->FreeResult(mmysql_handle);
+ SQL->FreeResult(map->mysql_handle);
- ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_skill_db_name[fi]);
+ ShowStatus("Done reading '"CL_WHITE"%"PRIu32""CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_skill_db_name[fi]);
}
return 0;
}
@@ -4527,7 +4540,7 @@ static int mob_read_sqlskilldb(void)
/*==========================================
* mob_race2_db.txt reading
*------------------------------------------*/
-static bool mob_readdb_race2(char* fields[], int columns, int current)
+bool mob_readdb_race2(char* fields[], int columns, int current)
{
int race, mobid, i;
@@ -4542,12 +4555,12 @@ static bool mob_readdb_race2(char* fields[], int columns, int current)
for(i = 1; i<columns; i++)
{
mobid = atoi(fields[i]);
- if (mob_db(mobid) == mob_dummy)
+ if (mob->db(mobid) == mob->dummy)
{
ShowWarning("mob_readdb_race2: Unknown mob id %d for race2 %d.\n", mobid, race);
continue;
}
- mob_db_data[mobid]->race2 = race;
+ mob->db_data[mobid]->race2 = race;
}
return true;
}
@@ -4555,12 +4568,12 @@ static bool mob_readdb_race2(char* fields[], int columns, int current)
/**
* Read mob_item_ratio.txt
*/
-static bool mob_readdb_itemratio(char* str[], int columns, int current)
+bool mob_readdb_itemratio(char* str[], int columns, int current)
{
int nameid, ratio, i;
nameid = atoi(str[0]);
- if( itemdb_exists(nameid) == NULL )
+ if( itemdb->exists(nameid) == NULL )
{
ShowWarning("itemdb_read_itemratio: Invalid item id %d.\n", nameid);
return false;
@@ -4581,33 +4594,36 @@ static bool mob_readdb_itemratio(char* str[], int columns, int current)
/**
* read all mob-related databases
*/
-static void mob_load(void)
-{
- sv->readdb(iMap->db_path, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, &mob_readdb_itemratio); // must be read before mobdb
- mob_readchatdb();
- if (iMap->db_use_sqldbs)
- {
- mob_read_sqldb();
- mob_read_sqlskilldb();
+void mob_load(bool minimal) {
+ if (minimal) {
+ // Only read the mob db in minimal mode
+ mob->readdb();
+ return;
}
- else
- {
- mob_readdb();
- mob_readskilldb();
+ sv->readdb(map->db_path, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, mob->readdb_itemratio); // must be read before mobdb
+ mob->readchatdb();
+ if (map->db_use_sql_mob_db) {
+ mob->read_sqldb();
}
- sv->readdb(iMap->db_path, "mob_avail.txt", ',', 2, 12, -1, &mob_readdb_mobavail);
- mob_read_randommonster();
- sv->readdb(iMap->db_path, DBPATH"mob_race2_db.txt", ',', 2, 20, -1, &mob_readdb_race2);
+ if (map->db_use_sql_mob_skill_db) {
+ mob->read_sqlskilldb();
+ } else {
+ mob->readdb();
+ mob->readskilldb();
+ }
+ sv->readdb(map->db_path, "mob_avail.txt", ',', 2, 12, -1, mob->readdb_mobavail);
+ mob->read_randommonster();
+ sv->readdb(map->db_path, DBPATH"mob_race2_db.txt", ',', 2, 20, -1, mob->readdb_race2);
}
void mob_reload(void) {
int i;
-
+
//Mob skills need to be cleared before re-reading them. [Skotlex]
for (i = 0; i < MAX_MOB_DB; i++)
- if (mob_db_data[i]) {
- memset(&mob_db_data[i]->skill,0,sizeof(mob_db_data[i]->skill));
- mob_db_data[i]->maxskill=0;
+ if (mob->db_data[i] && !mob->is_clone(i)) {
+ memset(&mob->db_data[i]->skill,0,sizeof(mob->db_data[i]->skill));
+ mob->db_data[i]->maxskill=0;
}
// Clear item_drop_ratio_db
@@ -4618,39 +4634,42 @@ void mob_reload(void) {
}
}
- mob_load();
+ mob->load(false);
}
void mob_clear_spawninfo()
{ //Clears spawn related information for a script reload.
int i;
for (i = 0; i < MAX_MOB_DB; i++)
- if (mob_db_data[i])
- memset(&mob_db_data[i]->spawn,0,sizeof(mob_db_data[i]->spawn));
+ if (mob->db_data[i])
+ memset(&mob->db_data[i]->spawn,0,sizeof(mob->db_data[i]->spawn));
}
/*==========================================
* Circumference initialization of mob
*------------------------------------------*/
-int do_init_mob(void)
-{ //Initialize the mob database
- memset(mob_db_data,0,sizeof(mob_db_data)); //Clear the array
- mob_db_data[0] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db)); //This mob is used for random spawns
- mob_makedummymobdb(0); //The first time this is invoked, it creates the dummy mob
- item_drop_ers = ers_new(sizeof(struct item_drop),"mob.c::item_drop_ers",ERS_OPT_NONE);
+int do_init_mob(bool minimal) {
+ // Initialize the mob database
+ memset(mob->db_data,0,sizeof(mob->db_data)); //Clear the array
+ mob->db_data[0] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db)); //This mob is used for random spawns
+ mob->makedummymobdb(0); //The first time this is invoked, it creates the dummy mob
+ item_drop_ers = ers_new(sizeof(struct item_drop),"mob.c::item_drop_ers",ERS_OPT_CLEAN);
item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"mob.c::item_drop_list_ers",ERS_OPT_NONE);
- mob_load();
+ mob->load(minimal);
- iTimer->add_timer_func_list(mob_delayspawn,"mob_delayspawn");
- iTimer->add_timer_func_list(mob_delay_item_drop,"mob_delay_item_drop");
- iTimer->add_timer_func_list(mob_ai_hard,"mob_ai_hard");
- iTimer->add_timer_func_list(mob_ai_lazy,"mob_ai_lazy");
- iTimer->add_timer_func_list(mob_timer_delete,"mob_timer_delete");
- iTimer->add_timer_func_list(mob_spawn_guardian_sub,"mob_spawn_guardian_sub");
- iTimer->add_timer_func_list(mob_respawn,"mob_respawn");
- iTimer->add_timer_interval(iTimer->gettick()+MIN_MOBTHINKTIME,mob_ai_hard,0,0,MIN_MOBTHINKTIME);
- iTimer->add_timer_interval(iTimer->gettick()+MIN_MOBTHINKTIME*10,mob_ai_lazy,0,0,MIN_MOBTHINKTIME*10);
+ if (minimal)
+ return 0;
+
+ timer->add_func_list(mob->delayspawn,"mob_delayspawn");
+ timer->add_func_list(mob->delay_item_drop,"mob_delay_item_drop");
+ timer->add_func_list(mob->ai_hard,"mob_ai_hard");
+ timer->add_func_list(mob->ai_lazy,"mob_ai_lazy");
+ timer->add_func_list(mob->timer_delete,"mob_timer_delete");
+ timer->add_func_list(mob->spawn_guardian_sub,"mob_spawn_guardian_sub");
+ timer->add_func_list(mob->respawn,"mob_respawn");
+ timer->add_interval(timer->gettick()+MIN_MOBTHINKTIME,mob->ai_hard,0,0,MIN_MOBTHINKTIME);
+ timer->add_interval(timer->gettick()+MIN_MOBTHINKTIME*10,mob->ai_lazy,0,0,MIN_MOBTHINKTIME*10);
return 0;
}
@@ -4661,25 +4680,25 @@ int do_init_mob(void)
int do_final_mob(void)
{
int i;
- if (mob_dummy)
+ if (mob->dummy)
{
- aFree(mob_dummy);
- mob_dummy = NULL;
+ aFree(mob->dummy);
+ mob->dummy = NULL;
}
for (i = 0; i <= MAX_MOB_DB; i++)
{
- if (mob_db_data[i] != NULL)
+ if (mob->db_data[i] != NULL)
{
- aFree(mob_db_data[i]);
- mob_db_data[i] = NULL;
+ aFree(mob->db_data[i]);
+ mob->db_data[i] = NULL;
}
}
for (i = 0; i <= MAX_MOB_CHAT; i++)
{
- if (mob_chat_db[i] != NULL)
+ if (mob->chat_db[i] != NULL)
{
- aFree(mob_chat_db[i]);
- mob_chat_db[i] = NULL;
+ aFree(mob->chat_db[i]);
+ mob->chat_db[i] = NULL;
}
}
for (i = 0; i < MAX_ITEMDB; i++)
@@ -4694,3 +4713,116 @@ int do_final_mob(void)
ers_destroy(item_drop_list_ers);
return 0;
}
+
+void mob_defaults(void) {
+ //Defines the Manuk/Splendide mob groups for the status reductions [Epoque]
+ const int mob_manuk[8] = { 1986, 1987, 1988, 1989, 1990, 1997, 1998, 1999 };
+ const int mob_splendide[5] = { 1991, 1992, 1993, 1994, 1995 };
+
+ mob = &mob_s;
+
+ memset(mob->db_data, 0, sizeof(mob->db_data));
+ mob->dummy = NULL;
+ memset(mob->chat_db, 0, sizeof(mob->chat_db));
+
+ memcpy(mob->manuk, mob_manuk, sizeof(mob->manuk));
+ memcpy(mob->splendide, mob_splendide, sizeof(mob->splendide));
+ /* */
+ mob->reload = mob_reload;
+ mob->init = do_init_mob;
+ mob->final = do_final_mob;
+ /* */
+ mob->db = mob_db;
+ mob->chat = mob_chat;
+ mob->makedummymobdb = mob_makedummymobdb;
+ mob->spawn_guardian_sub = mob_spawn_guardian_sub;
+ mob->skill_id2skill_idx = mob_skill_id2skill_idx;
+ mob->db_searchname = mobdb_searchname;
+ mob->db_searchname_array_sub = mobdb_searchname_array_sub;
+ mob->mvptomb_create = mvptomb_create;
+ mob->mvptomb_destroy = mvptomb_destroy;
+ mob->db_searchname_array = mobdb_searchname_array;
+ mob->db_checkid = mobdb_checkid;
+ mob->get_viewdata = mob_get_viewdata;
+ mob->parse_dataset = mob_parse_dataset;
+ mob->spawn_dataset = mob_spawn_dataset;
+ mob->get_random_id = mob_get_random_id;
+ mob->ksprotected = mob_ksprotected;
+ mob->once_spawn_sub = mob_once_spawn_sub;
+ mob->once_spawn = mob_once_spawn;
+ mob->once_spawn_area = mob_once_spawn_area;
+ mob->spawn_guardian = mob_spawn_guardian;
+ mob->spawn_bg = mob_spawn_bg;
+ mob->can_reach = mob_can_reach;
+ mob->linksearch = mob_linksearch;
+ mob->delayspawn = mob_delayspawn;
+ mob->setdelayspawn = mob_setdelayspawn;
+ mob->count_sub = mob_count_sub;
+ mob->spawn = mob_spawn;
+ mob->can_changetarget = mob_can_changetarget;
+ mob->target = mob_target;
+ mob->ai_sub_hard_activesearch = mob_ai_sub_hard_activesearch;
+ mob->ai_sub_hard_changechase = mob_ai_sub_hard_changechase;
+ mob->ai_sub_hard_bg_ally = mob_ai_sub_hard_bg_ally;
+ mob->ai_sub_hard_lootsearch = mob_ai_sub_hard_lootsearch;
+ mob->warpchase_sub = mob_warpchase_sub;
+ mob->ai_sub_hard_slavemob = mob_ai_sub_hard_slavemob;
+ mob->unlocktarget = mob_unlocktarget;
+ mob->randomwalk = mob_randomwalk;
+ mob->warpchase = mob_warpchase;
+ mob->ai_sub_hard = mob_ai_sub_hard;
+ mob->ai_sub_hard_timer = mob_ai_sub_hard_timer;
+ mob->ai_sub_foreachclient = mob_ai_sub_foreachclient;
+ mob->ai_sub_lazy = mob_ai_sub_lazy;
+ mob->ai_lazy = mob_ai_lazy;
+ mob->ai_hard = mob_ai_hard;
+ mob->setdropitem = mob_setdropitem;
+ mob->setlootitem = mob_setlootitem;
+ mob->delay_item_drop = mob_delay_item_drop;
+ mob->item_drop = mob_item_drop;
+ mob->timer_delete = mob_timer_delete;
+ mob->deleteslave_sub = mob_deleteslave_sub;
+ mob->deleteslave = mob_deleteslave;
+ mob->respawn = mob_respawn;
+ mob->log_damage = mob_log_damage;
+ mob->damage = mob_damage;
+ mob->dead = mob_dead;
+ mob->revive = mob_revive;
+ mob->guardian_guildchange = mob_guardian_guildchange;
+ mob->random_class = mob_random_class;
+ mob->class_change = mob_class_change;
+ mob->heal = mob_heal;
+ mob->warpslave_sub = mob_warpslave_sub;
+ mob->warpslave = mob_warpslave;
+ mob->countslave_sub = mob_countslave_sub;
+ mob->countslave = mob_countslave;
+ mob->summonslave = mob_summonslave;
+ mob->getfriendhprate_sub = mob_getfriendhprate_sub;
+ mob->getfriendhprate = mob_getfriendhprate;
+ mob->getmasterhpltmaxrate = mob_getmasterhpltmaxrate;
+ mob->getfriendstatus_sub = mob_getfriendstatus_sub;
+ mob->getfriendstatus = mob_getfriendstatus;
+ mob->skill_use = mobskill_use;
+ mob->skill_event = mobskill_event;
+ mob->is_clone = mob_is_clone;
+ mob->clone_spawn = mob_clone_spawn;
+ mob->clone_delete = mob_clone_delete;
+ mob->drop_adjust = mob_drop_adjust;
+ mob->item_dropratio_adjust = item_dropratio_adjust;
+ mob->parse_dbrow = mob_parse_dbrow;
+ mob->readdb_sub = mob_readdb_sub;
+ mob->readdb = mob_readdb;
+ mob->read_sqldb = mob_read_sqldb;
+ mob->name_constants = mob_name_constants;
+ mob->readdb_mobavail = mob_readdb_mobavail;
+ mob->read_randommonster = mob_read_randommonster;
+ mob->parse_row_chatdb = mob_parse_row_chatdb;
+ mob->readchatdb = mob_readchatdb;
+ mob->parse_row_mobskilldb = mob_parse_row_mobskilldb;
+ mob->readskilldb = mob_readskilldb;
+ mob->read_sqlskilldb = mob_read_sqlskilldb;
+ mob->readdb_race2 = mob_readdb_race2;
+ mob->readdb_itemratio = mob_readdb_itemratio;
+ mob->load = mob_load;
+ mob->clear_spawninfo = mob_clear_spawninfo;
+}
diff --git a/src/map/mob.h b/src/map/mob.h
index 34e5a81c0..c8d43dbb2 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -1,19 +1,19 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _MOB_H_
-#define _MOB_H_
+#ifndef MAP_MOB_H
+#define MAP_MOB_H
-#include "../common/mmo.h" // struct item
-#include "guild.h" // struct guardian_data
#include "map.h" // struct status_data, struct view_data, struct mob_skill
-#include "status.h" // struct status data, struct status_change
-#include "unit.h" // unit_stop_walking(), unit_stop_attack()
-#include "npc.h"
+#include "status.h" // struct status_data, struct status_change
+#include "unit.h" // struct unit_data
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h" // struct item
#define MAX_RANDOMMONSTER 5
-// Change this to increase the table size in your mob_db to accomodate a larger mob database.
+// Change this to increase the table size in your mob_db to accommodate a larger mob database.
// Be sure to note that IDs 4001 to 4048 are reserved for advanced/baby/expanded classes.
// Notice that the last 1000 entries are used for player clones, so always set this to desired value +1000
#define MAX_MOB_DB 4000
@@ -35,12 +35,10 @@
#define MOB_CLONE_START (MAX_MOB_DB-999)
#define MOB_CLONE_END MAX_MOB_DB
-//Used to determine default enemy type of mobs (for use in eachinrange calls)
-#define DEFAULT_ENEMY_TYPE(md) (md->special_state.ai?BL_CHAR:BL_MOB|BL_PC|BL_HOM|BL_MER)
+//Used to determine default enemy type of mobs (for use in each in range calls)
+#define DEFAULT_ENEMY_TYPE(md) ((md)->special_state.ai?BL_CHAR:BL_MOB|BL_PC|BL_HOM|BL_MER)
-//Externals for the status effects. [Epoque]
-extern const int mob_manuk[8];
-extern const int mob_splendide[5];
+#define MAX_MOB_CHAT 250 //Max Skill's messages
//Mob skill states.
enum MobSkillState {
@@ -64,8 +62,8 @@ enum MobDamageLogFlag
};
enum size {
- SZ_SMALL = 0,
- SZ_MEDIUM,
+ SZ_MEDIUM = 0,
+ SZ_SMALL,
SZ_BIG,
};
@@ -92,7 +90,7 @@ struct mob_skill {
struct mob_chat {
unsigned short msg_id;
- unsigned long color;
+ unsigned int color;
char msg[CHAT_SIZE_MAX];
};
@@ -129,7 +127,7 @@ struct mob_data {
char name[NAME_LENGTH];
struct {
unsigned int size : 2; //Small/Big monsters.
- unsigned int ai : 4; //Special ai for summoned monsters.
+ unsigned int ai : 4; //Special AI for summoned monsters.
//0: Normal mob.
//1: Standard summon, attacks mobs.
//2: Alchemist Marine Sphere
@@ -167,7 +165,7 @@ struct mob_data {
int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs)
unsigned int bg_id; // BattleGround System
- unsigned int next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick;
+ int64 next_walktime, last_thinktime, last_linktime, last_pcneartime, dmgtick;
short move_fail_count;
short lootitem_count;
short min_chase;
@@ -176,7 +174,7 @@ struct mob_data {
int master_id,master_dist;
int8 skill_idx;// key of array
- unsigned int skilldelay[MAX_MOBSKILL];
+ int64 skilldelay[MAX_MOBSKILL];
char npc_event[EVENT_NAME_LENGTH];
/**
* Did this monster summon something?
@@ -243,78 +241,126 @@ struct item_drop_list {
struct item_drop* item; // linked list of drops
};
-struct mob_db* mob_db(int class_);
-int mobdb_searchname(const char *str);
-int mobdb_searchname_array(struct mob_db** data, int size, const char *str);
-int mobdb_checkid(const int id);
-struct view_data* mob_get_viewdata(int class_);
-
-struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m,
- short x, short y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai);
-
-int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y,
- const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai);
-
-int mob_once_spawn_area(struct map_session_data* sd, int16 m,
- int16 x0, int16 y0, int16 x1, int16 y1, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai);
-
-bool mob_ksprotected (struct block_list *src, struct block_list *target);
-
-int mob_spawn_guardian(const char* mapname, int16 x, int16 y, const char* mobname, int class_, const char* event, int guardian, bool has_index); // Spawning Guardians [Valaris]
-int mob_spawn_bg(const char* mapname, int16 x, int16 y, const char* mobname, int class_, const char* event, unsigned int bg_id);
-int mob_guardian_guildchange(struct mob_data *md); //Change Guardian's ownership. [Skotlex]
-
-int mob_randomwalk(struct mob_data *md,unsigned int tick);
-int mob_warpchase(struct mob_data *md, struct block_list *target);
-int mob_target(struct mob_data *md,struct block_list *bl,int dist);
-int mob_unlocktarget(struct mob_data *md, unsigned int tick);
-struct mob_data* mob_spawn_dataset(struct spawn_data *data);
-int mob_spawn(struct mob_data *md);
-int mob_delayspawn(int tid, unsigned int tick, int id, intptr_t data);
-int mob_setdelayspawn(struct mob_data *md);
-int mob_parse_dataset(struct spawn_data *data);
-void mob_log_damage(struct mob_data *md, struct block_list *src, int damage);
-void mob_damage(struct mob_data *md, struct block_list *src, int damage);
-int mob_dead(struct mob_data *md, struct block_list *src, int type);
-void mob_revive(struct mob_data *md, unsigned int hp);
-void mob_heal(struct mob_data *md,unsigned int heal);
-
-#define mob_stop_walking(md, type) unit_stop_walking(&(md)->bl, type)
-#define mob_stop_attack(md) unit_stop_attack(&(md)->bl)
-#define mob_is_battleground(md) ( map[(md)->bl.m].flag.battleground && ((md)->class_ == MOBID_BARRICADE2 || ((md)->class_ >= MOBID_FOOD_STOR && (md)->class_ <= MOBID_PINK_CRYST)) )
-#define mob_is_gvg(md) (map[(md)->bl.m].flag.gvg_castle && ( (md)->class_ == MOBID_EMPERIUM || (md)->class_ == MOBID_BARRICADE1 || (md)->class_ == MOBID_GUARIDAN_STONE1 || (md)->class_ == MOBID_GUARIDAN_STONE2) )
-#define mob_is_treasure(md) (((md)->class_ >= MOBID_TREAS01 && (md)->class_ <= MOBID_TREAS40) || ((md)->class_ >= MOBID_TREAS41 && (md)->class_ <= MOBID_TREAS49))
-
-void mob_clear_spawninfo();
-int do_init_mob(void);
-int do_final_mob(void);
-int mob_timer_delete(int tid, unsigned int tick, int id, intptr_t data);
-int mob_deleteslave(struct mob_data *md);
+#define mob_stop_walking(md, type) (unit->stop_walking(&(md)->bl, (type)))
+#define mob_stop_attack(md) (unit->stop_attack(&(md)->bl))
-int mob_random_class (int *value, size_t count);
-int mob_get_random_id(int type, int flag, int lv);
-int mob_class_change(struct mob_data *md,int class_);
-int mob_warpslave(struct block_list *bl, int range);
-int mob_linksearch(struct block_list *bl,va_list ap);
-
-int mobskill_use(struct mob_data *md,unsigned int tick,int event);
-int mobskill_event(struct mob_data *md,struct block_list *src,unsigned int tick, int flag);
-int mobskill_castend_id( int tid, unsigned int tick, int id,int data );
-int mobskill_castend_pos( int tid, unsigned int tick, int id,int data );
-int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id);
-int mob_countslave(struct block_list *bl);
-int mob_count_sub(struct block_list *bl, va_list ap);
-
-int mob_is_clone(int class_);
+#define mob_is_battleground(md) ( map->list[(md)->bl.m].flag.battleground && ((md)->class_ == MOBID_BARRICADE2 || ((md)->class_ >= MOBID_FOOD_STOR && (md)->class_ <= MOBID_PINK_CRYST)) )
+#define mob_is_gvg(md) (map->list[(md)->bl.m].flag.gvg_castle && ( (md)->class_ == MOBID_EMPERIUM || (md)->class_ == MOBID_BARRICADE1 || (md)->class_ == MOBID_GUARIDAN_STONE1 || (md)->class_ == MOBID_GUARIDAN_STONE2) )
+#define mob_is_treasure(md) (((md)->class_ >= MOBID_TREAS01 && (md)->class_ <= MOBID_TREAS40) || ((md)->class_ >= MOBID_TREAS41 && (md)->class_ <= MOBID_TREAS49))
-int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, int mode, int flag, unsigned int duration);
-int mob_clone_delete(struct mob_data *md);
+struct mob_interface {
+ //Dynamic mob database, allows saving of memory when there's big gaps in the mob_db [Skotlex]
+ struct mob_db *db_data[MAX_MOB_DB+1];
+ struct mob_db *dummy; //Dummy mob to be returned when a non-existant one is requested.
+ //Dynamic mob chat database
+ struct mob_chat *chat_db[MAX_MOB_CHAT+1];
+ //Defines the Manuk/Splendide mob groups for the status reductions [Epoque]
+ int manuk[8];
+ int splendide[5];
+ /* */
+ int (*init) (bool mimimal);
+ int (*final) (void);
+ void (*reload) (void);
+ /* */
+ struct mob_db* (*db) (int index);
+ struct mob_chat* (*chat) (short id);
+ int (*makedummymobdb) (int);
+ int (*spawn_guardian_sub) (int tid, int64 tick, int id, intptr_t data);
+ int (*skill_id2skill_idx) (int class_, uint16 skill_id);
+ int (*db_searchname) (const char *str);
+ int (*db_searchname_array_sub) (struct mob_db *monster, const char *str, int flag);
+ // MvP Tomb System
+ void (*mvptomb_create) (struct mob_data *md, char *killer, time_t time);
+ void (*mvptomb_destroy) (struct mob_data *md);
+ int (*db_searchname_array) (struct mob_db **data, int size, const char *str, int flag);
+ int (*db_checkid) (const int id);
+ struct view_data* (*get_viewdata) (int class_);
+ int (*parse_dataset) (struct spawn_data *data);
+ struct mob_data* (*spawn_dataset) (struct spawn_data *data);
+ int (*get_random_id) (int type, int flag, int lv);
+ bool (*ksprotected) (struct block_list *src, struct block_list *target);
+ struct mob_data* (*once_spawn_sub) (struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai);
+ int (*once_spawn) (struct map_session_data *sd, int16 m, int16 x, int16 y, const char *mobname, int class_, int amount, const char *event, unsigned int size, unsigned int ai);
+ int (*once_spawn_area) (struct map_session_data *sd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, const char *mobname, int class_, int amount, const char *event, unsigned int size, unsigned int ai);
+ int (*spawn_guardian) (const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index);
+ int (*spawn_bg) (const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id);
+ int (*can_reach) (struct mob_data *md, struct block_list *bl, int range, int state);
+ int (*linksearch) (struct block_list *bl, va_list ap);
+ int (*delayspawn) (int tid, int64 tick, int id, intptr_t data);
+ int (*setdelayspawn) (struct mob_data *md);
+ int (*count_sub) (struct block_list *bl, va_list ap);
+ int (*spawn) (struct mob_data *md);
+ int (*can_changetarget) (struct mob_data *md, struct block_list *target, int mode);
+ int (*target) (struct mob_data *md, struct block_list *bl, int dist);
+ int (*ai_sub_hard_activesearch) (struct block_list *bl, va_list ap);
+ int (*ai_sub_hard_changechase) (struct block_list *bl, va_list ap);
+ int (*ai_sub_hard_bg_ally) (struct block_list *bl, va_list ap);
+ int (*ai_sub_hard_lootsearch) (struct block_list *bl, va_list ap);
+ int (*warpchase_sub) (struct block_list *bl, va_list ap);
+ int (*ai_sub_hard_slavemob) (struct mob_data *md, int64 tick);
+ int (*unlocktarget) (struct mob_data *md, int64 tick);
+ int (*randomwalk) (struct mob_data *md, int64 tick);
+ int (*warpchase) (struct mob_data *md, struct block_list *target);
+ bool (*ai_sub_hard) (struct mob_data *md, int64 tick);
+ int (*ai_sub_hard_timer) (struct block_list *bl, va_list ap);
+ int (*ai_sub_foreachclient) (struct map_session_data *sd, va_list ap);
+ int (*ai_sub_lazy) (struct mob_data *md, va_list args);
+ int (*ai_lazy) (int tid, int64 tick, int id, intptr_t data);
+ int (*ai_hard) (int tid, int64 tick, int id, intptr_t data);
+ struct item_drop* (*setdropitem) (int nameid, int qty, struct item_data *data);
+ struct item_drop* (*setlootitem) (struct item *item);
+ int (*delay_item_drop) (int tid, int64 tick, int id, intptr_t data);
+ void (*item_drop) (struct mob_data *md, struct item_drop_list *dlist, struct item_drop *ditem, int loot, int drop_rate, unsigned short flag);
+ int (*timer_delete) (int tid, int64 tick, int id, intptr_t data);
+ int (*deleteslave_sub) (struct block_list *bl, va_list ap);
+ int (*deleteslave) (struct mob_data *md);
+ int (*respawn) (int tid, int64 tick, int id, intptr_t data);
+ void (*log_damage) (struct mob_data *md, struct block_list *src, int damage);
+ void (*damage) (struct mob_data *md, struct block_list *src, int damage);
+ int (*dead) (struct mob_data *md, struct block_list *src, int type);
+ void (*revive) (struct mob_data *md, unsigned int hp);
+ int (*guardian_guildchange) (struct mob_data *md);
+ int (*random_class) (int *value, size_t count);
+ int (*class_change) (struct mob_data *md, int class_);
+ void (*heal) (struct mob_data *md, unsigned int heal);
+ int (*warpslave_sub) (struct block_list *bl, va_list ap);
+ int (*warpslave) (struct block_list *bl, int range);
+ int (*countslave_sub) (struct block_list *bl, va_list ap);
+ int (*countslave) (struct block_list *bl);
+ int (*summonslave) (struct mob_data *md2, int *value, int amount, uint16 skill_id);
+ int (*getfriendhprate_sub) (struct block_list *bl, va_list ap);
+ struct block_list* (*getfriendhprate) (struct mob_data *md, int min_rate, int max_rate);
+ struct block_list* (*getmasterhpltmaxrate) (struct mob_data *md, int rate);
+ int (*getfriendstatus_sub) (struct block_list *bl, va_list ap);
+ struct mob_data* (*getfriendstatus) (struct mob_data *md, int cond1, int cond2);
+ int (*skill_use) (struct mob_data *md, int64 tick, int event);
+ int (*skill_event) (struct mob_data *md, struct block_list *src, int64 tick, int flag);
+ int (*is_clone) (int class_);
+ int (*clone_spawn) (struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, int mode, int flag, unsigned int duration);
+ int (*clone_delete) (struct mob_data *md);
+ unsigned int (*drop_adjust) (int baserate, int rate_adjust, unsigned short rate_min, unsigned short rate_max);
+ void (*item_dropratio_adjust) (int nameid, int mob_id, int *rate_adjust);
+ bool (*parse_dbrow) (char **str);
+ bool (*readdb_sub) (char *fields[], int columns, int current);
+ void (*readdb) (void);
+ int (*read_sqldb) (void);
+ void (*name_constants) (void);
+ bool (*readdb_mobavail) (char *str[], int columns, int current);
+ int (*read_randommonster) (void);
+ bool (*parse_row_chatdb) (char **str, const char *source, int line, int *last_msg_id);
+ void (*readchatdb) (void);
+ bool (*parse_row_mobskilldb) (char **str, int columns, int current);
+ void (*readskilldb) (void);
+ int (*read_sqlskilldb) (void);
+ bool (*readdb_race2) (char *fields[], int columns, int current);
+ bool (*readdb_itemratio) (char *str[], int columns, int current);
+ void (*load) (bool minimal);
+ void (*clear_spawninfo) ();
+};
-void mob_reload(void);
+struct mob_interface *mob;
-// MvP Tomb System
-void mvptomb_create(struct mob_data *md, char *killer, time_t time);
-void mvptomb_destroy(struct mob_data *md);
+void mob_defaults(void);
-#endif /* _MOB_H_ */
+#endif /* MAP_MOB_H */
diff --git a/src/map/npc.c b/src/map/npc.c
index 46e6d0fd2..f1c6f4fbd 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2,49 +2,46 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/malloc.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
-#include "../common/ers.h"
-#include "../common/db.h"
-#include "../common/socket.h"
-#include "map.h"
-#include "log.h"
-#include "clif.h"
-#include "intif.h"
-#include "pc.h"
-#include "status.h"
-#include "itemdb.h"
-#include "script.h"
-#include "mob.h"
-#include "pet.h"
-#include "instance.h"
-#include "battle.h"
-#include "skill.h"
-#include "unit.h"
+#define HERCULES_CORE
+
+#include "../config/core.h" // NPC_SECURE_TIMEOUT_INPUT, NPC_SECURE_TIMEOUT_MENU, NPC_SECURE_TIMEOUT_NEXT, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL
#include "npc.h"
-#include "chat.h"
+#include <errno.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
#include <time.h>
-#include <errno.h>
-
-struct npc_data* fake_nd;
+#include "battle.h"
+#include "chat.h"
+#include "clif.h"
+#include "instance.h"
+#include "intif.h"
+#include "itemdb.h"
+#include "log.h"
+#include "map.h"
+#include "mob.h"
+#include "pc.h"
+#include "pet.h"
+#include "script.h"
+#include "skill.h"
+#include "status.h"
+#include "unit.h"
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-// linked list of npc source files
-struct npc_src_list {
- struct npc_src_list* next;
- char name[4]; // dynamic array, the structure is allocated with extra bytes (string length)
-};
-static struct npc_src_list* npc_src_files = NULL;
+struct npc_interface npc_s;
static int npc_id=START_NPC_NUM;
static int npc_warp=0;
@@ -54,50 +51,17 @@ static int npc_mob=0;
static int npc_delay_mob=0;
static int npc_cache_mob=0;
-/// Returns a new npc id that isn't being used in id_db.
-/// Fatal error if nothing is available.
-int npc_get_new_npc_id(void) {
- if( npc_id >= START_NPC_NUM && !iMap->blid_exists(npc_id) )
- return npc_id++;// available
- else {// find next id
- int base_id = npc_id;
- while( base_id != ++npc_id ) {
- if( npc_id < START_NPC_NUM )
- npc_id = START_NPC_NUM;
- if( !iMap->blid_exists(npc_id) )
- return npc_id++;// available
- }
- // full loop, nothing available
- ShowFatalError("npc_get_new_npc_id: All ids are taken. Exiting...");
- exit(1);
- }
-}
-
-static DBMap* ev_db; // const char* event_name -> struct event_data*
-static DBMap* npcname_db; // const char* npc_name -> struct npc_data*
-
-struct event_data {
- struct npc_data *nd;
- int pos;
-};
-
-static struct eri *timer_event_ers; //For the npc timer data. [Skotlex]
-
-/* hello */
static char *npc_last_path;
static char *npc_last_ref;
-
-struct npc_path_data {
- char* path;
- unsigned short references;
-};
struct npc_path_data *npc_last_npd;
-static DBMap *npc_path_db;
//For holding the view data of npc classes. [Skotlex]
static struct view_data npc_viewdb[MAX_NPC_CLASS];
static struct view_data npc_viewdb2[MAX_NPC_CLASS2_END-MAX_NPC_CLASS2_START];
+/* for speedup */
+unsigned int npc_market_qty[MAX_INVENTORY];
+
static struct script_event_s
{ //Holds pointers to the commonly executed scripts for speedup. [Skotlex]
struct event_data *event[UCHAR_MAX];
@@ -119,7 +83,26 @@ struct view_data* npc_get_viewdata(int class_)
return NULL;
}
-static int npc_isnear_sub(struct block_list* bl, va_list args) {
+/// Returns a new npc id that isn't being used in id_db.
+/// Fatal error if nothing is available.
+int npc_get_new_npc_id(void) {
+ if( npc_id >= START_NPC_NUM && !map->blid_exists(npc_id) )
+ return npc_id++;// available
+ else {// find next id
+ int base_id = npc_id;
+ while( base_id != ++npc_id ) {
+ if( npc_id < START_NPC_NUM )
+ npc_id = START_NPC_NUM;
+ if( !map->blid_exists(npc_id) )
+ return npc_id++;// available
+ }
+ // full loop, nothing available
+ ShowFatalError("npc_get_new_npc_id: All ids are taken. Exiting...");
+ exit(1);
+ }
+}
+
+int npc_isnear_sub(struct block_list* bl, va_list args) {
struct npc_data *nd = (struct npc_data*)bl;
if( nd->option & (OPTION_HIDE|OPTION_INVISIBLE) )
@@ -129,12 +112,11 @@ static int npc_isnear_sub(struct block_list* bl, va_list args) {
}
bool npc_isnear(struct block_list * bl) {
-
- if( battle_config.min_npc_vendchat_distance > 0 &&
- iMap->foreachinrange(npc_isnear_sub,bl, battle_config.min_npc_vendchat_distance, BL_NPC) )
- return true;
-
- return false;
+ if( battle_config.min_npc_vendchat_distance > 0
+ && map->foreachinrange(npc->isnear_sub,bl, battle_config.min_npc_vendchat_distance, BL_NPC) )
+ return true;
+
+ return false;
}
int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd)
@@ -147,8 +129,8 @@ int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd)
if( pc_ishiding(sd) )
return 1; // Can't trigger 'OnTouch_'. try 'OnTouch' later.
- snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_name);
- return npc_event(sd,name,1);
+ snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script->config.ontouch_name);
+ return npc->event(sd,name,1);
}
int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd)
@@ -158,8 +140,8 @@ int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd)
if( sd->areanpc_id == nd->bl.id )
return 0;
- snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch2_name);
- return npc_event(sd,name,2);
+ snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script->config.ontouch2_name);
+ return npc->event(sd,name,2);
}
/*==========================================
@@ -178,13 +160,13 @@ int npc_enable_sub(struct block_list *bl, va_list ap)
if (nd->option&OPTION_INVISIBLE)
return 1;
- if( npc_ontouch_event(sd,nd) > 0 && npc_ontouch2_event(sd,nd) > 0 )
+ if( npc->ontouch_event(sd,nd) > 0 && npc->ontouch2_event(sd,nd) > 0 )
{ // failed to run OnTouch event, so just click the npc
if (sd->npc_id != 0)
return 0;
pc_stop_walking(sd,1);
- npc_click(sd,nd);
+ npc->click(sd,nd);
}
}
return 0;
@@ -195,7 +177,7 @@ int npc_enable_sub(struct block_list *bl, va_list ap)
*------------------------------------------*/
int npc_enable(const char* name, int flag)
{
- struct npc_data* nd = npc_name2id(name);
+ struct npc_data* nd = npc->name2id(name);
if ( nd == NULL ) {
ShowError("npc_enable: Attempted to %s a non-existing NPC '%s' (flag=%d).\n", (flag&3) ? "show" : "hide", name, flag);
@@ -222,8 +204,8 @@ int npc_enable(const char* name, int flag)
} else
clif->changeoption(&nd->bl);
- if( flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0) ) //check if player standing on a OnTouchArea
- iMap->foreachinarea( npc_enable_sub, nd->bl.m, nd->bl.x-nd->u.scr.xs, nd->bl.y-nd->u.scr.ys, nd->bl.x+nd->u.scr.xs, nd->bl.y+nd->u.scr.ys, BL_PC, nd );
+ if( flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0) ) //check if player standing on a OnTouchArea
+ map->foreachinarea( npc->enable_sub, nd->bl.m, nd->bl.x-nd->u.scr.xs, nd->bl.y-nd->u.scr.ys, nd->bl.x+nd->u.scr.xs, nd->bl.y+nd->u.scr.ys, BL_PC, nd );
return 0;
}
@@ -233,19 +215,19 @@ int npc_enable(const char* name, int flag)
*------------------------------------------*/
struct npc_data* npc_name2id(const char* name)
{
- return (struct npc_data *) strdb_get(npcname_db, name);
+ return (struct npc_data *) strdb_get(npc->name_db, name);
}
/**
* For the Secure NPC Timeout option (check config/Secure.h) [RR]
**/
-#ifdef SECURE_NPCTIMEOUT
/**
* Timer to check for idle time and timeout the dialog if necessary
**/
-int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int npc_rr_secure_timeout_timer(int tid, int64 tick, int id, intptr_t data) {
+#ifdef SECURE_NPCTIMEOUT
struct map_session_data* sd = NULL;
unsigned int timeout = NPC_SECURE_TIMEOUT_NEXT;
- if( (sd = iMap->id2sd(id)) == NULL || !sd->npc_id ) {
+ if( (sd = map->id2sd(id)) == NULL || !sd->npc_id ) {
if( sd ) sd->npc_idle_timer = INVALID_TIMER;
return 0;//Not logged in anymore OR no longer attached to a npc
}
@@ -276,10 +258,10 @@ int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t dat
clif->scriptclear(sd,sd->npc_id);
sd->npc_idle_timer = INVALID_TIMER;
} else //Create a new instance of ourselves to continue
- sd->npc_idle_timer = iTimer->add_timer(iTimer->gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc_rr_secure_timeout_timer,sd->bl.id,0);
+ sd->npc_idle_timer = timer->add(timer->gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc->secure_timeout_timer,sd->bl.id,0);
+#endif
return 0;
}
-#endif
/*==========================================
* Dequeue event and add timer for execution (100ms)
@@ -294,7 +276,7 @@ int npc_event_dequeue(struct map_session_data* sd)
sd->state.using_fake_npc = 0;
}
if (sd->st) {
- script_free_state(sd->st);
+ script->free_state(sd->st);
sd->st = NULL;
}
sd->npc_id = 0;
@@ -313,24 +295,39 @@ int npc_event_dequeue(struct map_session_data* sd)
return 1;
}
+/**
+ * @see DBCreateData
+ */
+DBData npc_event_export_create(DBKey key, va_list args)
+{
+ struct linkdb_node** head_ptr;
+ CREATE(head_ptr, struct linkdb_node*, 1);
+ *head_ptr = NULL;
+ return DB->ptr2data(head_ptr);
+}
+
/*==========================================
* exports a npc event label
* called from npc_parse_script
*------------------------------------------*/
-static int npc_event_export(struct npc_data *nd, int i)
+int npc_event_export(struct npc_data *nd, int i)
{
char* lname = nd->u.scr.label_list[i].name;
int pos = nd->u.scr.label_list[i].pos;
if ((lname[0] == 'O' || lname[0] == 'o') && (lname[1] == 'N' || lname[1] == 'n')) {
struct event_data *ev;
+ struct linkdb_node **label_linkdb = NULL;
char buf[EVENT_NAME_LENGTH];
snprintf(buf, ARRAYLENGTH(buf), "%s::%s", nd->exname, lname);
+ if (strdb_exists(npc->ev_db, buf)) // There was already another event of the same name?
+ return 1;
// generate the data and insert it
CREATE(ev, struct event_data, 1);
ev->nd = nd;
ev->pos = pos;
- if (strdb_put(ev_db, buf, ev)) // There was already another event of the same name?
- return 1;
+ strdb_put(npc->ev_db, buf, ev);
+ label_linkdb = strdb_ensure(npc->ev_label_db, lname, npc->event_export_create);
+ linkdb_insert(label_linkdb, nd, ev);
}
return 0;
}
@@ -340,99 +337,80 @@ int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char
/**
* Exec name (NPC events) on player or global
* Do on all NPC when called with foreach
- * @see DBApply
*/
-int npc_event_doall_sub(DBKey key, DBData *data, va_list ap)
+void npc_event_doall_sub(void *key, void *data, va_list ap)
{
- const char* p = key.str;
- struct event_data* ev;
+ struct event_data* ev = data;
int* c;
const char* name;
int rid;
- nullpo_ret(ev = DB->data2ptr(data));
- nullpo_ret(c = va_arg(ap, int *));
- nullpo_ret(name = va_arg(ap, const char *));
+ nullpo_retv(c = va_arg(ap, int*));
+ nullpo_retv(name = va_arg(ap, const char*));
rid = va_arg(ap, int);
- p = strchr(p, ':'); // match only the event name
- if( p && strcmpi(name, p) == 0 /* && !ev->nd->src_id */ ) // Do not run on duplicates. [Paradox924X]
+ if (ev /* && !ev->nd->src_id */) // Do not run on duplicates. [Paradox924X]
{
- if(rid) // a player may only have 1 script running at the same time
- npc_event_sub(iMap->id2sd(rid),ev,key.str);
- else
- run_script(ev->nd->u.scr.script,ev->pos,rid,ev->nd->bl.id);
+ if(rid) { // a player may only have 1 script running at the same time
+ char buf[EVENT_NAME_LENGTH];
+ snprintf(buf, ARRAYLENGTH(buf), "%s::%s", ev->nd->exname, name);
+ npc->event_sub(map->id2sd(rid), ev, buf);
+ }
+ else {
+ script->run(ev->nd->u.scr.script, ev->pos, rid, ev->nd->bl.id);
+ }
(*c)++;
}
-
- return 0;
}
-/**
- * @see DBApply
- */
-static int npc_event_do_sub(DBKey key, DBData *data, va_list ap)
+// runs the specified event (supports both single-npc and global events)
+int npc_event_do(const char* name)
{
- const char* p = key.str;
- struct event_data* ev;
- int* c;
- const char* name;
-
- nullpo_ret(ev = DB->data2ptr(data));
- nullpo_ret(c = va_arg(ap, int *));
- nullpo_ret(name = va_arg(ap, const char *));
-
- if( p && strcmpi(name, p) == 0 ) {
- run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id);
- (*c)++;
+ if( name[0] == ':' && name[1] == ':' ) {
+ return npc->event_doall(name+2); // skip leading "::"
+ }
+ else {
+ struct event_data *ev = strdb_get(npc->ev_db, name);
+ if (ev) {
+ script->run(ev->nd->u.scr.script, ev->pos, 0, ev->nd->bl.id);
+ return 1;
+ }
}
-
return 0;
}
-// runs the specified event (supports both single-npc and global events)
-int npc_event_do(const char* name)
+// runs the specified event, with a RID attached (global only)
+int npc_event_doall_id(const char* name, int rid)
{
int c = 0;
+ struct linkdb_node **label_linkdb = strdb_get(npc->ev_label_db, name);
- if( name[0] == ':' && name[1] == ':' )
- ev_db->foreach(ev_db,npc_event_doall_sub,&c,name,0);
- else
- ev_db->foreach(ev_db,npc_event_do_sub,&c,name);
+ if (label_linkdb == NULL)
+ return 0;
+ linkdb_foreach(label_linkdb, npc->event_doall_sub, &c, name, rid);
return c;
}
// runs the specified event (global only)
int npc_event_doall(const char* name)
{
- return npc_event_doall_id(name, 0);
-}
-
-// runs the specified event, with a RID attached (global only)
-int npc_event_doall_id(const char* name, int rid)
-{
- int c = 0;
- char buf[64];
- safesnprintf(buf, sizeof(buf), "::%s", name);
- ev_db->foreach(ev_db,npc_event_doall_sub,&c,buf,rid);
- return c;
+ return npc->event_doall_id(name, 0);
}
/*==========================================
* Clock event execution
* OnMinute/OnClock/OnHour/OnDay/OnDDHHMM
*------------------------------------------*/
-int npc_event_do_clock(int tid, unsigned int tick, int id, intptr_t data)
-{
+int npc_event_do_clock(int tid, int64 tick, int id, intptr_t data) {
static struct tm ev_tm_b; // tracks previous execution time
- time_t timer;
+ time_t clock;
struct tm* t;
char buf[64];
int c = 0;
- timer = time(NULL);
- t = localtime(&timer);
+ clock = time(NULL);
+ t = localtime(&clock);
if (t->tm_min != ev_tm_b.tm_min ) {
char* day;
@@ -449,37 +427,40 @@ int npc_event_do_clock(int tid, unsigned int tick, int id, intptr_t data)
}
sprintf(buf,"OnMinute%02d",t->tm_min);
- c += npc_event_doall(buf);
+ c += npc->event_doall(buf);
sprintf(buf,"OnClock%02d%02d",t->tm_hour,t->tm_min);
- c += npc_event_doall(buf);
+ c += npc->event_doall(buf);
sprintf(buf,"On%s%02d%02d",day,t->tm_hour,t->tm_min);
- c += npc_event_doall(buf);
+ c += npc->event_doall(buf);
}
if (t->tm_hour != ev_tm_b.tm_hour) {
sprintf(buf,"OnHour%02d",t->tm_hour);
- c += npc_event_doall(buf);
+ c += npc->event_doall(buf);
}
if (t->tm_mday != ev_tm_b.tm_mday) {
sprintf(buf,"OnDay%02d%02d",t->tm_mon+1,t->tm_mday);
- c += npc_event_doall(buf);
+ c += npc->event_doall(buf);
}
memcpy(&ev_tm_b,t,sizeof(ev_tm_b));
return c;
}
-/*==========================================
- * OnInit Event execution (the start of the event and watch)
- *------------------------------------------*/
-void npc_event_do_oninit(void)
+/**
+ * OnInit event execution (the start of the event and watch)
+ * @param reload Is the server reloading?
+ **/
+void npc_event_do_oninit( bool reload )
{
- ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs."CL_CLL"\n", npc_event_doall("OnInit"));
+ ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs."CL_CLL"\n", npc->event_doall("OnInit"));
- iTimer->add_timer_interval(iTimer->gettick()+100,npc_event_do_clock,0,0,1000);
+ // This interval has already been added on startup
+ if( !reload )
+ timer->add_interval(timer->gettick()+100,npc->event_do_clock,0,0,1000);
}
/*==========================================
@@ -488,10 +469,10 @@ void npc_event_do_oninit(void)
*------------------------------------------*/
int npc_timerevent_export(struct npc_data *nd, int i)
{
- int t = 0, k = 0;
+ int t = 0, len = 0;
char *lname = nd->u.scr.label_list[i].name;
int pos = nd->u.scr.label_list[i].pos;
- if (sscanf(lname, "OnTimer%d%n", &t, &k) == 1 && lname[k] == '\0') {
+ if (sscanf(lname, "OnTimer%d%n", &t, &len) == 1 && lname[len] == '\0') {
// Timer event
struct npc_timerevent_list *te = nd->u.scr.timer_event;
int j, k = nd->u.scr.timeramount;
@@ -522,25 +503,22 @@ struct timer_event_data {
/*==========================================
* triger 'OnTimerXXXX' events
*------------------------------------------*/
-int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data)
-{
+int npc_timerevent(int tid, int64 tick, int id, intptr_t data) {
int old_rid, old_timer;
- unsigned int old_tick;
- struct npc_data* nd=(struct npc_data *)iMap->id2bl(id);
+ int64 old_tick;
+ struct npc_data* nd=(struct npc_data *)map->id2bl(id);
struct npc_timerevent_list *te;
struct timer_event_data *ted = (struct timer_event_data*)data;
struct map_session_data *sd=NULL;
- if( nd == NULL )
- {
+ if( nd == NULL ) {
ShowError("npc_timerevent: NPC not found??\n");
return 0;
}
- if( ted->rid && !(sd = iMap->id2sd(ted->rid)) )
- {
+ if( ted->rid && !(sd = map->id2sd(ted->rid)) ) {
ShowError("npc_timerevent: Attached player not found.\n");
- ers_free(timer_event_ers, ted);
+ ers_free(npc->timer_event_ers, ted);
return 0;
}
@@ -550,9 +528,9 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data)
old_timer = nd->u.scr.timer;
// Set the values of the timer
- nd->u.scr.rid = sd?sd->bl.id:0; //attached rid
- nd->u.scr.timertick = tick; //current time tick
- nd->u.scr.timer = ted->time; //total time from beginning to now
+ nd->u.scr.rid = sd?sd->bl.id:0; //attached rid
+ nd->u.scr.timertick = tick; //current time tick
+ nd->u.scr.timer = ted->time; //total time from beginning to now
// Locate the event
te = nd->u.scr.timer_event + ted->next;
@@ -561,13 +539,12 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data)
ted->next++;
if( nd->u.scr.timeramount > ted->next )
{
- int next;
- next = nd->u.scr.timer_event[ ted->next ].timer - nd->u.scr.timer_event[ ted->next - 1 ].timer;
+ int next = nd->u.scr.timer_event[ ted->next ].timer - nd->u.scr.timer_event[ ted->next - 1 ].timer;
ted->time += next;
if( sd )
- sd->npc_timer_id = iTimer->add_timer(tick+next,npc_timerevent,id,(intptr_t)ted);
+ sd->npc_timer_id = timer->add(tick+next,npc->timerevent,id,(intptr_t)ted);
else
- nd->u.scr.timerid = iTimer->add_timer(tick+next,npc_timerevent,id,(intptr_t)ted);
+ nd->u.scr.timerid = timer->add(tick+next,npc->timerevent,id,(intptr_t)ted);
}
else
{
@@ -576,11 +553,11 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data)
else
nd->u.scr.timerid = INVALID_TIMER;
- ers_free(timer_event_ers, ted);
+ ers_free(npc->timer_event_ers, ted);
}
// Run the script
- run_script(nd->u.scr.script,te->pos,nd->u.scr.rid,nd->bl.id);
+ script->run(nd->u.scr.script,te->pos,nd->u.scr.rid,nd->bl.id);
nd->u.scr.rid = old_rid; // Attached-rid should be restored anyway.
if( sd )
@@ -594,10 +571,9 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data)
/*==========================================
* Start/Resume NPC timer
*------------------------------------------*/
-int npc_timerevent_start(struct npc_data* nd, int rid)
-{
+int npc_timerevent_start(struct npc_data* nd, int rid) {
int j;
- unsigned int tick = iTimer->gettick();
+ int64 tick = timer->gettick();
struct map_session_data *sd = NULL; //Player to whom script is attached.
nullpo_ret(nd);
@@ -605,45 +581,41 @@ int npc_timerevent_start(struct npc_data* nd, int rid)
// Check if there is an OnTimer Event
ARR_FIND( 0, nd->u.scr.timeramount, j, nd->u.scr.timer_event[j].timer > nd->u.scr.timer );
- if( nd->u.scr.rid > 0 && !(sd = iMap->id2sd(nd->u.scr.rid)) )
- { // Failed to attach timer to this player.
+ if( nd->u.scr.rid > 0 && !(sd = map->id2sd(nd->u.scr.rid)) ) {
+ // Failed to attach timer to this player.
ShowError("npc_timerevent_start: Attached player not found!\n");
return 1;
}
-
// Check if timer is already started.
- if( sd )
- {
+ if( sd ) {
if( sd->npc_timer_id != INVALID_TIMER )
return 0;
- }
- else if( nd->u.scr.timerid != INVALID_TIMER || nd->u.scr.timertick )
+ } else if( nd->u.scr.timerid != INVALID_TIMER || nd->u.scr.timertick )
return 0;
- if (j < nd->u.scr.timeramount)
- {
+ if (j < nd->u.scr.timeramount) {
int next;
struct timer_event_data *ted;
// Arrange for the next event
- ted = ers_alloc(timer_event_ers, struct timer_event_data);
+ ted = ers_alloc(npc->timer_event_ers, struct timer_event_data);
ted->next = j; // Set event index
ted->time = nd->u.scr.timer_event[j].timer;
next = nd->u.scr.timer_event[j].timer - nd->u.scr.timer;
if( sd )
{
ted->rid = sd->bl.id; // Attach only the player if attachplayerrid was used.
- sd->npc_timer_id = iTimer->add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr_t)ted);
+ sd->npc_timer_id = timer->add(tick+next,npc->timerevent,nd->bl.id,(intptr_t)ted);
}
else
{
ted->rid = 0;
nd->u.scr.timertick = tick; // Set when timer is started
- nd->u.scr.timerid = iTimer->add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr_t)ted);
+ nd->u.scr.timerid = timer->add(tick+next,npc->timerevent,nd->bl.id,(intptr_t)ted);
}
- }
- else if (!sd)
- {
+
+ } else if (!sd) {
nd->u.scr.timertick = tick;
+
}
return 0;
@@ -659,12 +631,10 @@ int npc_timerevent_stop(struct npc_data* nd)
nullpo_ret(nd);
- if( nd->u.scr.rid && !(sd = iMap->id2sd(nd->u.scr.rid)) )
- {
+ if( nd->u.scr.rid && !(sd = map->id2sd(nd->u.scr.rid)) ) {
ShowError("npc_timerevent_stop: Attached player not found!\n");
return 1;
}
-
tid = sd?&sd->npc_timer_id:&nd->u.scr.timerid;
if( *tid == INVALID_TIMER && (sd || !nd->u.scr.timertick) ) // Nothing to stop
return 0;
@@ -672,16 +642,16 @@ int npc_timerevent_stop(struct npc_data* nd)
// Delete timer
if ( *tid != INVALID_TIMER )
{
- td = iTimer->get_timer(*tid);
+ td = timer->get(*tid);
if( td && td->data )
- ers_free(timer_event_ers, (void*)td->data);
- iTimer->delete_timer(*tid,npc_timerevent);
+ ers_free(npc->timer_event_ers, (void*)td->data);
+ timer->delete(*tid,npc->timerevent);
*tid = INVALID_TIMER;
}
if( !sd && nd->u.scr.timertick )
{
- nd->u.scr.timer += DIFF_TICK(iTimer->gettick(),nd->u.scr.timertick); // Set 'timer' to the time that has passed since the beginning of the timers
+ nd->u.scr.timer += DIFF_TICK32(timer->gettick(),nd->u.scr.timertick); // Set 'timer' to the time that has passed since the beginning of the timers
nd->u.scr.timertick = 0; // Set 'tick' to zero so that we know it's off.
}
@@ -696,19 +666,19 @@ void npc_timerevent_quit(struct map_session_data* sd)
struct npc_data* nd;
struct timer_event_data *ted;
- // Check timer existance
+ // Check timer existence
if( sd->npc_timer_id == INVALID_TIMER )
return;
- if( !(td = iTimer->get_timer(sd->npc_timer_id)) )
+ if( !(td = timer->get(sd->npc_timer_id)) )
{
sd->npc_timer_id = INVALID_TIMER;
return;
}
// Delete timer
- nd = (struct npc_data *)iMap->id2bl(td->id);
+ nd = (struct npc_data *)map->id2bl(td->id);
ted = (struct timer_event_data*)td->data;
- iTimer->delete_timer(sd->npc_timer_id, npc_timerevent);
+ timer->delete(sd->npc_timer_id, npc->timerevent);
sd->npc_timer_id = INVALID_TIMER;
// Execute OnTimerQuit
@@ -718,7 +688,7 @@ void npc_timerevent_quit(struct map_session_data* sd)
struct event_data *ev;
snprintf(buf, ARRAYLENGTH(buf), "%s::OnTimerQuit", nd->exname);
- ev = (struct event_data*)strdb_get(ev_db, buf);
+ ev = (struct event_data*)strdb_get(npc->ev_db, buf);
if( ev && ev->nd != nd )
{
ShowWarning("npc_timerevent_quit: Unable to execute \"OnTimerQuit\", two NPCs have the same event name [%s]!\n",buf);
@@ -727,7 +697,7 @@ void npc_timerevent_quit(struct map_session_data* sd)
if( ev )
{
int old_rid,old_timer;
- unsigned int old_tick;
+ int64 old_tick;
//Set timer related info.
old_rid = (nd->u.scr.rid == sd->bl.id ? 0 : nd->u.scr.rid); // Detach rid if the last attached player logged off.
@@ -735,11 +705,11 @@ void npc_timerevent_quit(struct map_session_data* sd)
old_timer = nd->u.scr.timer;
nd->u.scr.rid = sd->bl.id;
- nd->u.scr.timertick = iTimer->gettick();
+ nd->u.scr.timertick = timer->gettick();
nd->u.scr.timer = ted->time;
//Execute label
- run_script(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id);
+ script->run(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id);
//Restore previous data.
nd->u.scr.rid = old_rid;
@@ -747,23 +717,22 @@ void npc_timerevent_quit(struct map_session_data* sd)
nd->u.scr.timertick = old_tick;
}
}
- ers_free(timer_event_ers, ted);
+ ers_free(npc->timer_event_ers, ted);
}
/*==========================================
* Get the tick value of an NPC timer
* If it's stopped, return stopped time
*------------------------------------------*/
-int npc_gettimerevent_tick(struct npc_data* nd)
-{
- int tick;
+int64 npc_gettimerevent_tick(struct npc_data* nd) {
+ int64 tick;
nullpo_ret(nd);
// TODO: Get player attached timer's tick. Now we can just get it by using 'getnpctimer' inside OnTimer event.
tick = nd->u.scr.timer; // The last time it's active(start, stop or event trigger)
if( nd->u.scr.timertick ) // It's a running timer
- tick += DIFF_TICK(iTimer->gettick(), nd->u.scr.timertick);
+ tick += DIFF_TICK(timer->gettick(), nd->u.scr.timertick);
return tick;
}
@@ -785,11 +754,11 @@ int npc_settimerevent_tick(struct npc_data* nd, int newtimer)
nd->u.scr.rid = 0;
// Check if timer is started
- flag = (nd->u.scr.timerid != INVALID_TIMER);
+ flag = (nd->u.scr.timerid != INVALID_TIMER || nd->u.scr.timertick);
- if( flag ) npc_timerevent_stop(nd);
+ if( flag ) npc->timerevent_stop(nd);
nd->u.scr.timer = newtimer;
- if( flag ) npc_timerevent_start(nd, -1);
+ if( flag ) npc->timerevent_start(nd, -1);
nd->u.scr.rid = old_rid;
return 0;
@@ -804,7 +773,7 @@ int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char
ARR_FIND( 0, MAX_EVENTQUEUE, i, sd->eventqueue[i][0] == '\0' );
if( i < MAX_EVENTQUEUE )
{
- safestrncpy(sd->eventqueue[i],eventname,50); //Event enqueued.
+ safestrncpy(sd->eventqueue[i],eventname,EVENT_NAME_LENGTH); //Event enqueued.
return 0;
}
@@ -814,10 +783,10 @@ int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char
if( ev->nd->option&OPTION_INVISIBLE )
{
//Disabled npc, shouldn't trigger event.
- npc_event_dequeue(sd);
+ npc->event_dequeue(sd);
return 2;
}
- run_script(ev->nd->u.scr.script,ev->pos,sd->bl.id,ev->nd->bl.id);
+ script->run(ev->nd->u.scr.script,ev->pos,sd->bl.id,ev->nd->bl.id);
return 0;
}
@@ -826,7 +795,7 @@ int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char
*------------------------------------------*/
int npc_event(struct map_session_data* sd, const char* eventname, int ontouch)
{
- struct event_data* ev = (struct event_data*)strdb_get(ev_db, eventname);
+ struct event_data* ev = (struct event_data*)strdb_get(npc->ev_db, eventname);
struct npc_data *nd;
nullpo_ret(sd);
@@ -847,20 +816,19 @@ int npc_event(struct map_session_data* sd, const char* eventname, int ontouch)
break;
}
- return npc_event_sub(sd,ev,eventname);
+ return npc->event_sub(sd,ev,eventname);
}
/*==========================================
* Sub chk then execute area event type
*------------------------------------------*/
-int npc_touch_areanpc_sub(struct block_list *bl, va_list ap)
-{
+int npc_touch_areanpc_sub(struct block_list *bl, va_list ap) {
struct map_session_data *sd;
int pc_id;
char *name;
nullpo_ret(bl);
- nullpo_ret((sd = iMap->id2sd(bl->id)));
+ nullpo_ret((sd = map->id2sd(bl->id)));
pc_id = va_arg(ap,int);
name = va_arg(ap,char*);
@@ -872,7 +840,7 @@ int npc_touch_areanpc_sub(struct block_list *bl, va_list ap)
if( pc_id == sd->bl.id )
return 0;
- npc_event(sd,name,1);
+ npc->event(sd,name,1);
return 1;
}
@@ -881,9 +849,8 @@ int npc_touch_areanpc_sub(struct block_list *bl, va_list ap)
* Chk if sd is still touching his assigned npc.
* If not, it unsets it and searches for another player in range.
*------------------------------------------*/
-int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap)
-{
- struct npc_data *nd = iMap->id2nd(sd->touching_id);
+int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap) {
+ struct npc_data *nd = map->id2nd(sd->touching_id);
short xs, ys;
if( !nd || nd->touching_id != sd->bl.id )
@@ -900,8 +867,8 @@ int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap)
char name[EVENT_NAME_LENGTH];
nd->touching_id = sd->touching_id = 0;
- snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_name);
- iMap->forcountinarea(npc_touch_areanpc_sub,nd->bl.m,nd->bl.x - xs,nd->bl.y - ys,nd->bl.x + xs,nd->bl.y + ys,1,BL_PC,sd->bl.id,name);
+ snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script->config.ontouch_name);
+ map->forcountinarea(npc->touch_areanpc_sub,nd->bl.m,nd->bl.x - xs,nd->bl.y - ys,nd->bl.x + xs,nd->bl.y + ys,1,BL_PC,sd->bl.id,name);
}
return 0;
}
@@ -922,51 +889,53 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
//if(sd->npc_id)
// return 1;
- for(i=0;i<map[m].npc_num;i++) {
- if (map[m].npc[i]->option&OPTION_INVISIBLE) {
+ for(i=0;i<map->list[m].npc_num;i++) {
+ if (map->list[m].npc[i]->option&OPTION_INVISIBLE) {
f=0; // a npc was found, but it is disabled; don't print warning
continue;
}
- switch(map[m].npc[i]->subtype) {
+ switch(map->list[m].npc[i]->subtype) {
case WARP:
- xs=map[m].npc[i]->u.warp.xs;
- ys=map[m].npc[i]->u.warp.ys;
+ xs=map->list[m].npc[i]->u.warp.xs;
+ ys=map->list[m].npc[i]->u.warp.ys;
break;
case SCRIPT:
- xs=map[m].npc[i]->u.scr.xs;
- ys=map[m].npc[i]->u.scr.ys;
+ xs=map->list[m].npc[i]->u.scr.xs;
+ ys=map->list[m].npc[i]->u.scr.ys;
break;
default:
continue;
}
- if( x >= map[m].npc[i]->bl.x-xs && x <= map[m].npc[i]->bl.x+xs
- && y >= map[m].npc[i]->bl.y-ys && y <= map[m].npc[i]->bl.y+ys )
+ if( x >= map->list[m].npc[i]->bl.x-xs && x <= map->list[m].npc[i]->bl.x+xs
+ && y >= map->list[m].npc[i]->bl.y-ys && y <= map->list[m].npc[i]->bl.y+ys )
break;
}
- if( i == map[m].npc_num )
- {
+ if( i == map->list[m].npc_num ) {
if( f == 1 ) // no npc found
- ShowError("npc_touch_areanpc : stray NPC cell/NPC not found in the block on coordinates '%s',%d,%d\n", map[m].name, x, y);
+ ShowError("npc_touch_areanpc : stray NPC cell/NPC not found in the block on coordinates '%s',%d,%d\n", map->list[m].name, x, y);
return 1;
}
- switch(map[m].npc[i]->subtype) {
+ switch(map->list[m].npc[i]->subtype) {
case WARP:
if( pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]) )
break; // hidden chars cannot use warps
- pc->setpos(sd,map[m].npc[i]->u.warp.mapindex,map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,CLR_OUTSIGHT);
+ pc->setpos(sd,map->list[m].npc[i]->u.warp.mapindex,map->list[m].npc[i]->u.warp.x,map->list[m].npc[i]->u.warp.y,CLR_OUTSIGHT);
break;
case SCRIPT:
- for (j = i; j < map[m].npc_num; j++) {
- if (map[m].npc[j]->subtype != WARP) {
+ for (j = i; j < map->list[m].npc_num; j++) {
+ if (map->list[m].npc[j]->subtype != WARP) {
continue;
}
- if ((sd->bl.x >= (map[m].npc[j]->bl.x - map[m].npc[j]->u.warp.xs) && sd->bl.x <= (map[m].npc[j]->bl.x + map[m].npc[j]->u.warp.xs)) &&
- (sd->bl.y >= (map[m].npc[j]->bl.y - map[m].npc[j]->u.warp.ys) && sd->bl.y <= (map[m].npc[j]->bl.y + map[m].npc[j]->u.warp.ys))) {
+ if ((sd->bl.x >= (map->list[m].npc[j]->bl.x - map->list[m].npc[j]->u.warp.xs)
+ && sd->bl.x <= (map->list[m].npc[j]->bl.x + map->list[m].npc[j]->u.warp.xs))
+ && (sd->bl.y >= (map->list[m].npc[j]->bl.y - map->list[m].npc[j]->u.warp.ys)
+ && sd->bl.y <= (map->list[m].npc[j]->bl.y + map->list[m].npc[j]->u.warp.ys))
+ ) {
if( pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]) )
break; // hidden chars cannot use warps
- pc->setpos(sd,map[m].npc[j]->u.warp.mapindex,map[m].npc[j]->u.warp.x,map[m].npc[j]->u.warp.y,CLR_OUTSIGHT);
+ pc->setpos(sd,map->list[m].npc[j]->u.warp.mapindex,map->list[m].npc[j]->u.warp.x,map->list[m].npc[j]->u.warp.y,CLR_OUTSIGHT);
found_warp = 1;
break;
}
@@ -976,16 +945,16 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
break;
}
- if( npc_ontouch_event(sd,map[m].npc[i]) > 0 && npc_ontouch2_event(sd,map[m].npc[i]) > 0 )
+ if( npc->ontouch_event(sd,map->list[m].npc[i]) > 0 && npc->ontouch2_event(sd,map->list[m].npc[i]) > 0 )
{ // failed to run OnTouch event, so just click the npc
- struct unit_data *ud = unit_bl2ud(&sd->bl);
+ struct unit_data *ud = unit->bl2ud(&sd->bl);
if( ud && ud->walkpath.path_pos < ud->walkpath.path_len )
{ // Since walktimer always == INVALID_TIMER at this time, we stop walking manually. [Inkfish]
clif->fixpos(&sd->bl);
ud->walkpath.path_pos = ud->walkpath.path_len;
}
- sd->areanpc_id = map[m].npc[i]->bl.id;
- npc_click(sd,map[m].npc[i]);
+ sd->areanpc_id = map->list[m].npc[i]->bl.id;
+ npc->click(sd,map->list[m].npc[i]);
}
break;
}
@@ -1001,46 +970,45 @@ int npc_touch_areanpc2(struct mob_data *md)
struct event_data* ev;
int xs, ys;
- for( i = 0; i < map[m].npc_num; i++ ) {
- if( map[m].npc[i]->option&OPTION_INVISIBLE )
+ for( i = 0; i < map->list[m].npc_num; i++ ) {
+ if( map->list[m].npc[i]->option&OPTION_INVISIBLE )
continue;
- switch( map[m].npc[i]->subtype ) {
+ switch( map->list[m].npc[i]->subtype ) {
case WARP:
if( !( battle_config.mob_warp&1 ) )
continue;
- xs = map[m].npc[i]->u.warp.xs;
- ys = map[m].npc[i]->u.warp.ys;
+ xs = map->list[m].npc[i]->u.warp.xs;
+ ys = map->list[m].npc[i]->u.warp.ys;
break;
case SCRIPT:
- xs = map[m].npc[i]->u.scr.xs;
- ys = map[m].npc[i]->u.scr.ys;
+ xs = map->list[m].npc[i]->u.scr.xs;
+ ys = map->list[m].npc[i]->u.scr.ys;
break;
default:
continue; // Keep Searching
}
- if( x >= map[m].npc[i]->bl.x-xs && x <= map[m].npc[i]->bl.x+xs && y >= map[m].npc[i]->bl.y-ys && y <= map[m].npc[i]->bl.y+ys )
- { // In the npc touch area
- switch( map[m].npc[i]->subtype )
- {
+ if( x >= map->list[m].npc[i]->bl.x-xs && x <= map->list[m].npc[i]->bl.x+xs && y >= map->list[m].npc[i]->bl.y-ys && y <= map->list[m].npc[i]->bl.y+ys ) {
+ // In the npc touch area
+ switch( map->list[m].npc[i]->subtype ) {
case WARP:
- xs = iMap->mapindex2mapid(map[m].npc[i]->u.warp.mapindex);
+ xs = map->mapindex2mapid(map->list[m].npc[i]->u.warp.mapindex);
if( m < 0 )
break; // Cannot Warp between map servers
- if( unit_warp(&md->bl, xs, map[m].npc[i]->u.warp.x, map[m].npc[i]->u.warp.y, CLR_OUTSIGHT) == 0 )
+ if( unit->warp(&md->bl, xs, map->list[m].npc[i]->u.warp.x, map->list[m].npc[i]->u.warp.y, CLR_OUTSIGHT) == 0 )
return 1; // Warped
break;
case SCRIPT:
- if( map[m].npc[i]->bl.id == md->areanpc_id )
+ if( map->list[m].npc[i]->bl.id == md->areanpc_id )
break; // Already touch this NPC
- snprintf(eventname, ARRAYLENGTH(eventname), "%s::OnTouchNPC", map[m].npc[i]->exname);
- if( (ev = (struct event_data*)strdb_get(ev_db, eventname)) == NULL || ev->nd == NULL )
+ snprintf(eventname, ARRAYLENGTH(eventname), "%s::OnTouchNPC", map->list[m].npc[i]->exname);
+ if( (ev = (struct event_data*)strdb_get(npc->ev_db, eventname)) == NULL || ev->nd == NULL )
break; // No OnTouchNPC Event
- md->areanpc_id = map[m].npc[i]->bl.id;
+ md->areanpc_id = map->list[m].npc[i]->bl.id;
id = md->bl.id; // Stores Unique ID
- run_script(ev->nd->u.scr.script, ev->pos, md->bl.id, ev->nd->bl.id);
- if( iMap->id2md(id) == NULL ) return 1; // Not Warped, but killed
+ script->run(ev->nd->u.scr.script, ev->pos, md->bl.id, ev->nd->bl.id);
+ if( map->id2md(id) == NULL ) return 1; // Not Warped, but killed
break;
}
@@ -1055,8 +1023,7 @@ int npc_touch_areanpc2(struct mob_data *md)
//Flag determines the type of object to check for:
//&1: NPC Warps
//&2: NPCs with on-touch events.
-int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range)
-{
+int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) {
int i;
int x0,y0,x1,y1;
int xs,ys;
@@ -1064,49 +1031,49 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range)
if (range < 0) return 0;
x0 = max(x-range, 0);
y0 = max(y-range, 0);
- x1 = min(x+range, map[m].xs-1);
- y1 = min(y+range, map[m].ys-1);
+ x1 = min(x+range, map->list[m].xs-1);
+ y1 = min(y+range, map->list[m].ys-1);
//First check for npc_cells on the range given
i = 0;
for (ys = y0; ys <= y1 && !i; ys++) {
- for(xs = x0; xs <= x1 && !i; xs++){
- if (iMap->getcell(m,xs,ys,CELL_CHKNPC))
+ for(xs = x0; xs <= x1 && !i; xs++) {
+ if (map->getcell(m,xs,ys,CELL_CHKNPC))
i = 1;
}
}
if (!i) return 0; //No NPC_CELLs.
//Now check for the actual NPC on said range.
- for(i=0;i<map[m].npc_num;i++) {
- if (map[m].npc[i]->option&OPTION_INVISIBLE)
+ for(i=0;i<map->list[m].npc_num;i++) {
+ if (map->list[m].npc[i]->option&OPTION_INVISIBLE)
continue;
- switch(map[m].npc[i]->subtype) {
+ switch(map->list[m].npc[i]->subtype) {
case WARP:
if (!(flag&1))
continue;
- xs=map[m].npc[i]->u.warp.xs;
- ys=map[m].npc[i]->u.warp.ys;
+ xs=map->list[m].npc[i]->u.warp.xs;
+ ys=map->list[m].npc[i]->u.warp.ys;
break;
case SCRIPT:
if (!(flag&2))
continue;
- xs=map[m].npc[i]->u.scr.xs;
- ys=map[m].npc[i]->u.scr.ys;
+ xs=map->list[m].npc[i]->u.scr.xs;
+ ys=map->list[m].npc[i]->u.scr.ys;
break;
default:
continue;
}
- if( x1 >= map[m].npc[i]->bl.x-xs && x0 <= map[m].npc[i]->bl.x+xs
- && y1 >= map[m].npc[i]->bl.y-ys && y0 <= map[m].npc[i]->bl.y+ys )
+ if( x1 >= map->list[m].npc[i]->bl.x-xs && x0 <= map->list[m].npc[i]->bl.x+xs
+ && y1 >= map->list[m].npc[i]->bl.y-ys && y0 <= map->list[m].npc[i]->bl.y+ys )
break; // found a npc
}
- if (i==map[m].npc_num)
+ if (i==map->list[m].npc_num)
return 0;
- return (map[m].npc[i]->bl.id);
+ return (map->list[m].npc[i]->bl.id);
}
/*==========================================
@@ -1141,7 +1108,7 @@ struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* b
*------------------------------------------*/
int npc_globalmessage(const char* name, const char* mes)
{
- struct npc_data* nd = npc_name2id(name);
+ struct npc_data* nd = npc->name2id(name);
char temp[100];
if (!nd)
@@ -1154,28 +1121,27 @@ int npc_globalmessage(const char* name, const char* mes)
}
// MvP tomb [GreenBox]
-void run_tomb(struct map_session_data* sd, struct npc_data* nd)
-{
+void run_tomb(struct map_session_data* sd, struct npc_data* nd) {
char buffer[200];
- char time[10];
+ char time[10];
- strftime(time, sizeof(time), "%H:%M", localtime(&nd->u.tomb.kill_time));
+ strftime(time, sizeof(time), "%H:%M", localtime(&nd->u.tomb.kill_time));
// TODO: Find exact color?
- snprintf(buffer, sizeof(buffer), msg_txt(657), nd->u.tomb.md->db->name);
- clif->scriptmes(sd, nd->bl.id, buffer);
+ snprintf(buffer, sizeof(buffer), msg_txt(857), nd->u.tomb.md->db->name); // "[ ^EE0000%s^000000 ]"
+ clif->scriptmes(sd, nd->bl.id, buffer);
- clif->scriptmes(sd, nd->bl.id, msg_txt(658));
+ clif->scriptmes(sd, nd->bl.id, msg_txt(858)); // "Has met its demise"
- snprintf(buffer, sizeof(buffer), msg_txt(659), time);
- clif->scriptmes(sd, nd->bl.id, buffer);
+ snprintf(buffer, sizeof(buffer), msg_txt(859), time); // "Time of death : ^EE0000%s^000000"
+ clif->scriptmes(sd, nd->bl.id, buffer);
- clif->scriptmes(sd, nd->bl.id, msg_txt(660));
+ clif->scriptmes(sd, nd->bl.id, msg_txt(860)); // "Defeated by"
- snprintf(buffer, sizeof(buffer), msg_txt(661), nd->u.tomb.killer_name[0] ? nd->u.tomb.killer_name : "Unknown");
- clif->scriptmes(sd, nd->bl.id, buffer);
+ snprintf(buffer, sizeof(buffer), msg_txt(861), nd->u.tomb.killer_name[0] ? nd->u.tomb.killer_name : msg_txt(15)); // "[^EE0000%s^000000]" / "Unknown"
+ clif->scriptmes(sd, nd->bl.id, buffer);
- clif->scriptclose(sd, nd->bl.id);
+ clif->scriptclose(sd, nd->bl.id);
}
/*==========================================
@@ -1186,14 +1152,27 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd)
{
nullpo_retr(1, sd);
+ // This usually happens when the player clicked on a NPC that has the view id
+ // of a mob, to activate this kind of npc it's needed to be in a 2,2 range
+ // from it. If the OnTouch area of a npc, coincides with the 2,2 range of
+ // another it's expected that the OnTouch event be put first in stack, because
+ // unit_walktoxy_timer is executed before any other function in this case.
+ // So it's best practice to put an 'end;' before OnTouch events in npcs that
+ // have view ids of mobs to avoid this "issue" [Panikon]
if (sd->npc_id != 0) {
- ShowError("npc_click: npc_id != 0\n");
+ // The player clicked a npc after entering an OnTouch area
+ if( sd->areanpc_id != sd->npc_id )
+ ShowError("npc_click: npc_id != 0\n");
+
return 1;
}
- if(!nd) return 1;
- if ((nd = npc_checknear(sd,&nd->bl)) == NULL)
+ if( !nd )
return 1;
+
+ if ((nd = npc->checknear(sd,&nd->bl)) == NULL)
+ return 1;
+
//Hidden/Disabled npc.
if (nd->class_ < 0 || nd->option&(OPTION_INVISIBLE|OPTION_HIDE))
return 1;
@@ -1206,10 +1185,14 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd)
clif->cashshop_show(sd,nd);
break;
case SCRIPT:
- run_script(nd->u.scr.script,0,sd->bl.id,nd->bl.id);
+ if( nd->u.scr.shop && nd->u.scr.shop->items && nd->u.scr.trader ) {
+ if( !npc->trader_open(sd,nd) )
+ return 1;
+ } else
+ script->run(nd->u.scr.script,0,sd->bl.id,nd->bl.id);
break;
case TOMB:
- run_tomb(sd,nd);
+ npc->run_tomb(sd,nd);
break;
}
@@ -1219,22 +1202,22 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd)
/*==========================================
*
*------------------------------------------*/
-int npc_scriptcont(struct map_session_data* sd, int id, bool closing)
-{
+int npc_scriptcont(struct map_session_data* sd, int id, bool closing) {
+ struct block_list *target = map->id2bl(id);
nullpo_retr(1, sd);
if( id != sd->npc_id ){
- TBL_NPC* nd_sd=(TBL_NPC*)iMap->id2bl(sd->npc_id);
- TBL_NPC* nd=(TBL_NPC*)iMap->id2bl(id);
+ TBL_NPC* nd_sd=(TBL_NPC*)map->id2bl(sd->npc_id);
+ TBL_NPC* nd = BL_CAST(BL_NPC, target);
ShowDebug("npc_scriptcont: %s (sd->npc_id=%d) is not %s (id=%d).\n",
nd_sd?(char*)nd_sd->name:"'Unknown NPC'", (int)sd->npc_id,
nd?(char*)nd->name:"'Unknown NPC'", (int)id);
return 1;
}
-
- if(id != fake_nd->bl.id) { // Not item script
- if ((npc_checknear(sd,iMap->id2bl(id))) == NULL){
- ShowWarning("npc_scriptcont: failed npc_checknear test.\n");
+
+ if(id != npc->fake_nd->bl.id) { // Not item script
+ if ((npc->checknear(sd,target)) == NULL){
+ ShowWarning("npc_scriptcont: failed npc->checknear test.\n");
return 1;
}
}
@@ -1245,19 +1228,22 @@ int npc_scriptcont(struct map_session_data* sd, int id, bool closing)
/**
* Update the last NPC iteration
**/
- sd->npc_idle_tick = iTimer->gettick();
+ sd->npc_idle_tick = timer->gettick();
#endif
/**
* WPE can get to this point with a progressbar; we deny it.
**/
- if( sd->progressbar.npc_id && DIFF_TICK(sd->progressbar.timeout,iTimer->gettick()) > 0 )
+ if( sd->progressbar.npc_id && DIFF_TICK(sd->progressbar.timeout,timer->gettick()) > 0 )
return 1;
-
+
+ if( !sd->st )
+ return 1;
+
if( closing && sd->st->state == CLOSE )
sd->st->state = END;
- run_script_main(sd->st);
+ script->run_main(sd->st);
return 0;
}
@@ -1265,25 +1251,30 @@ int npc_scriptcont(struct map_session_data* sd, int id, bool closing)
/*==========================================
* Chk if valid call then open buy or selling list
*------------------------------------------*/
-int npc_buysellsel(struct map_session_data* sd, int id, int type)
-{
+int npc_buysellsel(struct map_session_data* sd, int id, int type) {
struct npc_data *nd;
nullpo_retr(1, sd);
- if ((nd = npc_checknear(sd,iMap->id2bl(id))) == NULL)
+ if ((nd = npc->checknear(sd,map->id2bl(id))) == NULL)
return 1;
- if (nd->subtype!=SHOP) {
- ShowError("no such shop npc : %d\n",id);
+ if ( nd->subtype != SHOP && !(nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->items) ) {
+
+ if( nd->subtype == SCRIPT )
+ ShowError("npc_buysellsel: trader '%s' has no shop list!\n",nd->exname);
+ else
+ ShowError("npc_buysellsel: no such shop npc %d (%s)\n",id,nd->exname);
+
if (sd->npc_id == id)
- sd->npc_id=0;
+ sd->npc_id = 0;
return 1;
}
- if (nd->option & OPTION_INVISIBLE) // can't buy if npc is not visible (hack?)
+
+ if (nd->option & OPTION_INVISIBLE) // can't buy if npc is not visible (hack?)
return 1;
- if( nd->class_ < 0 && !sd->state.callshop )
- {// not called through a script and is not a visible NPC so an invalid call
+
+ if( nd->class_ < 0 && !sd->state.callshop ) {// not called through a script and is not a visible NPC so an invalid call
return 1;
}
@@ -1296,92 +1287,114 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type)
} else {
clif->selllist(sd);
}
+
return 0;
}
+
/*==========================================
* Cash Shop Buy List
*------------------------------------------*/
-int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short* item_list)
-{
- int i, j, nameid, amount, new_, w, vt;
- struct npc_data *nd = (struct npc_data *)iMap->id2bl(sd->npc_shopid);
-
- if( !nd || nd->subtype != CASHSHOP )
- return 1;
-
- if( sd->state.trading )
- return 4;
-
- new_ = 0;
- w = 0;
- vt = 0; // Global Value
-
- // Validating Process ----------------------------------------------------
- for( i = 0; i < count; i++ )
- {
- nameid = item_list[i*2+1];
- amount = item_list[i*2+0];
-
- if( !itemdb_exists(nameid) || amount <= 0 )
- return 5;
-
- ARR_FIND(0,nd->u.shop.count,j,nd->u.shop.shop_item[j].nameid == nameid);
- if( j == nd->u.shop.count || nd->u.shop.shop_item[j].value <= 0 )
- return 5;
-
- if( !itemdb_isstackable(nameid) && amount > 1 )
- {
- ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
- amount = item_list[i*2+0] = 1;
- }
-
- switch( pc->checkadditem(sd,nameid,amount) )
- {
- case ADDITEM_NEW:
- new_++;
- break;
- case ADDITEM_OVERAMOUNT:
- return 3;
- }
-
- vt += nd->u.shop.shop_item[j].value * amount;
- w += itemdb_weight(nameid) * amount;
- }
-
- if( w + sd->weight > sd->max_weight )
- return 3;
- if( pc->inventoryblank(sd) < new_ )
- return 3;
- if( points > vt ) points = vt;
-
- // Payment Process ----------------------------------------------------
- if( sd->kafraPoints < points || sd->cashPoints < (vt - points) )
- return 6;
- pc->paycash(sd,vt,points);
-
- // Delivery Process ----------------------------------------------------
- for( i = 0; i < count; i++ )
- {
- struct item item_tmp;
-
- nameid = item_list[i*2+1];
- amount = item_list[i*2+0];
-
- memset(&item_tmp,0,sizeof(item_tmp));
-
- if( !pet_create_egg(sd,nameid) )
- {
- item_tmp.nameid = nameid;
- item_tmp.identify = 1;
- pc->additem(sd,&item_tmp,amount,LOG_TYPE_NPC);
- }
- }
-
- return 0;
+int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short* item_list) {
+ int i, j, nameid, amount, new_, w, vt;
+ struct npc_data *nd = NULL;
+ struct npc_item_list *shop = NULL;
+ unsigned short shop_size = 0;
+
+ if( sd->state.trading )
+ return ERROR_TYPE_EXCHANGE;
+
+ if( count <= 0 )
+ return ERROR_TYPE_ITEM_ID;
+
+ if( points < 0 )
+ return ERROR_TYPE_MONEY;
+
+ if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) )
+ return ERROR_TYPE_NPC;
+
+ if( nd->subtype != CASHSHOP ) {
+ if( nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type != NST_ZENY && nd->u.scr.shop->type != NST_MARKET ) {
+ shop = nd->u.scr.shop->item;
+ shop_size = nd->u.scr.shop->items;
+ } else
+ return ERROR_TYPE_NPC;
+ } else {
+ shop = nd->u.shop.shop_item;
+ shop_size = nd->u.shop.count;
+ }
+
+ new_ = 0;
+ w = 0;
+ vt = 0; // Global Value
+
+ // Validating Process ----------------------------------------------------
+ for( i = 0; i < count; i++ ) {
+ nameid = item_list[i*2+1];
+ amount = item_list[i*2+0];
+
+ if( !itemdb->exists(nameid) || amount <= 0 )
+ return ERROR_TYPE_ITEM_ID;
+
+ ARR_FIND(0,shop_size,j,shop[j].nameid == nameid);
+ if( j == shop_size || shop[j].value <= 0 )
+ return ERROR_TYPE_ITEM_ID;
+
+ if( !itemdb->isstackable(nameid) && amount > 1 ) {
+ ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of non-stackable item %d!\n",
+ sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
+ amount = item_list[i*2+0] = 1;
+ }
+
+ switch( pc->checkadditem(sd,nameid,amount) ) {
+ case ADDITEM_NEW:
+ new_++;
+ break;
+ case ADDITEM_OVERAMOUNT:
+ return ERROR_TYPE_INVENTORY_WEIGHT;
+ }
+
+ vt += shop[j].value * amount;
+ w += itemdb_weight(nameid) * amount;
+ }
+
+ if( w + sd->weight > sd->max_weight )
+ return ERROR_TYPE_INVENTORY_WEIGHT;
+
+ if( pc->inventoryblank(sd) < new_ )
+ return ERROR_TYPE_INVENTORY_WEIGHT;
+
+ if( points > vt ) points = vt;
+
+ // Payment Process ----------------------------------------------------
+ if( nd->subtype == SCRIPT && nd->u.scr.shop->type == NST_CUSTOM ) {
+ if( !npc->trader_pay(nd,sd,vt,points) )
+ return ERROR_TYPE_MONEY;
+ } else {
+ if( sd->kafraPoints < points || sd->cashPoints < (vt - points) )
+ return ERROR_TYPE_MONEY;
+ pc->paycash(sd,vt,points);
+ }
+ // Delivery Process ----------------------------------------------------
+ for( i = 0; i < count; i++ ) {
+ struct item item_tmp;
+
+ nameid = item_list[i*2+1];
+ amount = item_list[i*2+0];
+
+ memset(&item_tmp,0,sizeof(item_tmp));
+
+ if( !pet->create_egg(sd,nameid) ) {
+ item_tmp.nameid = nameid;
+ item_tmp.identify = 1;
+ pc->additem(sd,&item_tmp,amount,LOG_TYPE_NPC);
+ }
+ }
+
+ return ERROR_TYPE_NONE;
}
//npc_buylist for script-controlled shops.
-static int npc_buylist_sub(struct map_session_data* sd, int n, unsigned short* item_list, struct npc_data* nd)
+int npc_buylist_sub(struct map_session_data* sd, int n, unsigned short* item_list, struct npc_data* nd)
{
char npc_ev[EVENT_NAME_LENGTH];
int i;
@@ -1389,93 +1402,314 @@ static int npc_buylist_sub(struct map_session_data* sd, int n, unsigned short* i
int key_amount = 0;
// discard old contents
- script_cleararray_pc(sd, "@bought_nameid", (void*)0);
- script_cleararray_pc(sd, "@bought_quantity", (void*)0);
+ script->cleararray_pc(sd, "@bought_nameid", (void*)0);
+ script->cleararray_pc(sd, "@bought_quantity", (void*)0);
// save list of bought items
- for( i = 0; i < n; i++ )
- {
- script_setarray_pc(sd, "@bought_nameid", i, (void*)(intptr_t)item_list[i*2+1], &key_nameid);
- script_setarray_pc(sd, "@bought_quantity", i, (void*)(intptr_t)item_list[i*2], &key_amount);
+ for( i = 0; i < n; i++ ) {
+ script->setarray_pc(sd, "@bought_nameid", i, (void*)(intptr_t)item_list[i*2+1], &key_nameid);
+ script->setarray_pc(sd, "@bought_quantity", i, (void*)(intptr_t)item_list[i*2], &key_amount);
}
// invoke event
snprintf(npc_ev, ARRAYLENGTH(npc_ev), "%s::OnBuyItem", nd->exname);
- npc_event(sd, npc_ev, 0);
+ npc->event(sd, npc_ev, 0);
return 0;
}
+/**
+ * Loads persistent NPC Market Data from SQL
+ **/
+void npc_market_fromsql(void) {
+ SqlStmt* stmt = SQL->StmtMalloc(map->mysql_handle);
+ char name[NAME_LENGTH+1];
+ int itemid;
+ int amount;
+
+ if ( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `name`, `itemid`, `amount` FROM `%s`", map->npc_market_data_db)
+ || SQL_ERROR == SQL->StmtExecute(stmt)
+ ) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return;
+ }
+
+ SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name[0], sizeof(name), NULL, NULL);
+ SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &itemid, 0, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 2, SQLDT_INT, &amount, 0, NULL, NULL);
+
+ while ( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) {
+ struct npc_data *nd = NULL;
+ unsigned short i;
+
+ if( !(nd = npc->name2id(name)) ) {
+ ShowError("npc_market_fromsql: NPC '%s' not found! skipping...\n",name);
+ npc->market_delfromsql_sub(name, USHRT_MAX);
+ continue;
+ } else if ( nd->subtype != SCRIPT || !nd->u.scr.shop || !nd->u.scr.shop->items || nd->u.scr.shop->type != NST_MARKET ) {
+ ShowError("npc_market_fromsql: NPC '%s' is not proper for market, skipping...\n",name);
+ npc->market_delfromsql_sub(name, USHRT_MAX);
+ continue;
+ }
+
+ for(i = 0; i < nd->u.scr.shop->items; i++) {
+ if( nd->u.scr.shop->item[i].nameid == itemid ) {
+ nd->u.scr.shop->item[i].qty = amount;
+ break;
+ }
+ }
+
+ if( i == nd->u.scr.shop->items ) {
+ ShowError("npc_market_fromsql: NPC '%s' does not sell item %d (qty %d), deleting...\n",name,itemid,amount);
+ npc->market_delfromsql_sub(name, itemid);
+ continue;
+ }
+
+ }
+
+ SQL->StmtFree(stmt);
+}
+/**
+ * Saves persistent NPC Market Data into SQL
+ **/
+void npc_market_tosql(struct npc_data *nd, unsigned short index) {
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `%s` VALUES ('%s','%d','%d')",
+ map->npc_market_data_db, nd->exname, nd->u.scr.shop->item[index].nameid, nd->u.scr.shop->item[index].qty) )
+ Sql_ShowDebug(map->mysql_handle);
+}
+/**
+ * Removes persistent NPC Market Data from SQL
+ */
+void npc_market_delfromsql_sub(const char *npcname, unsigned short index) {
+ if( index == USHRT_MAX ) {
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s'", map->npc_market_data_db, npcname) )
+ Sql_ShowDebug(map->mysql_handle);
+ } else {
+ if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `name`='%s' AND `itemid`='%d' LIMIT 1",
+ map->npc_market_data_db, npcname, index) )
+ Sql_ShowDebug(map->mysql_handle);
+ }
+}
+/**
+ * Removes persistent NPC Market Data from SQL
+ **/
+void npc_market_delfromsql(struct npc_data *nd, unsigned short index) {
+ npc->market_delfromsql_sub(nd->exname, index == USHRT_MAX ? index : nd->u.scr.shop->item[index].nameid);
+}
+/**
+ * Judges whether to allow and spawn a trader's window.
+ **/
+bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) {
+
+ if( !nd->u.scr.shop || !nd->u.scr.shop->items )
+ return false;
+
+ switch( nd->u.scr.shop->type ) {
+ case NST_ZENY:
+ sd->state.callshop = 1;
+ clif->npcbuysell(sd,nd->bl.id);
+ return true;/* we skip sd->npc_shopid, npc->buysell will set it then when the player selects */
+ case NST_MARKET: {
+ unsigned short i;
+
+ for(i = 0; i < nd->u.scr.shop->items; i++) {
+ if( nd->u.scr.shop->item[i].qty )
+ break;
+ }
+
+ /* nothing to display, no items available */
+ if( i == nd->u.scr.shop->items ) {
+ clif->colormes(sd->fd,COLOR_RED, msg_txt(881));
+ return false;
+ }
+ clif->npc_market_open(sd,nd);
+ }
+ break;
+ default:
+ clif->cashshop_show(sd,nd);
+ break;
+ }
+
+ sd->npc_shopid = nd->bl.id;
+
+ return true;
+}
+/**
+ * Creates (npc_data)->u.scr.shop and updates all duplicates across the server to match the created pointer
+ *
+ * @param master id of the original npc
+ **/
+void npc_trader_update(int master) {
+ DBIterator* iter;
+ struct block_list* bl;
+ struct npc_data *master_nd = map->id2nd(master);
+
+ CREATE(master_nd->u.scr.shop,struct npc_shop_data,1);
+
+ iter = db_iterator(map->id_db);
+
+ for( bl = (struct block_list*)dbi_first(iter); dbi_exists(iter); bl = (struct block_list*)dbi_next(iter) ) {
+ if( bl->type == BL_NPC ) {
+ struct npc_data* nd = (struct npc_data*)bl;
+
+ if( nd->src_id == master ) {
+ nd->u.scr.shop = master_nd->u.scr.shop;
+ }
+ }
+ }
+
+ dbi_destroy(iter);
+}
+/**
+ * Tries to issue a CountFunds event to the shop.
+ *
+ * @param nd shop
+ * @param sd player
+ **/
+void npc_trader_count_funds(struct npc_data *nd, struct map_session_data *sd) {
+ char evname[EVENT_NAME_LENGTH];
+ struct event_data *ev = NULL;
+
+ npc->trader_funds[0] = npc->trader_funds[1] = 0;/* clear */
+
+ switch( nd->u.scr.shop->type ) {
+ case NST_CASH:
+ npc->trader_funds[0] = sd->cashPoints;
+ npc->trader_funds[1] = sd->kafraPoints;
+ return;
+ case NST_CUSTOM:
+ break;
+ default:
+ ShowError("npc_trader_count_funds: unsupported shop type %d\n",nd->u.scr.shop->type);
+ return;
+ }
+
+ snprintf(evname, EVENT_NAME_LENGTH, "%s::OnCountFunds",nd->exname);
+
+ if ( (ev = strdb_get(npc->ev_db, evname)) )
+ script->run(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);
+ else
+ ShowError("npc_trader_count_funds: '%s' event '%s' not found, operation failed\n",nd->exname,evname);
+
+ /* the callee will rely on npc->trader_funds, upon success script->run updates them */
+}
+/**
+ * Tries to issue a payment to the NPC Event capable of handling it
+ *
+ * @param nd shop
+ * @param sd player
+ * @param price total cost
+ * @param points the amount input in the shop by the user to use from the secondary currency (if any is being employed)
+ *
+ * @return bool whether it was successful (if the script does not respond it will fail)
+ **/
+bool npc_trader_pay(struct npc_data *nd, struct map_session_data *sd, int price, int points) {
+ char evname[EVENT_NAME_LENGTH];
+ struct event_data *ev = NULL;
+
+ npc->trader_ok = false;/* clear */
+
+ snprintf(evname, EVENT_NAME_LENGTH, "%s::OnPayFunds",nd->exname);
+
+ if ( (ev = strdb_get(npc->ev_db, evname)) ) {
+ pc->setreg(sd,script->add_str("@price"),price);
+ pc->setreg(sd,script->add_str("@points"),points);
+
+ script->run(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);
+ } else
+ ShowError("npc_trader_pay: '%s' event '%s' not found, operation failed\n",nd->exname,evname);
+
+ return npc->trader_ok;/* run script will deal with it */
+}
/*==========================================
* Cash Shop Buy
*------------------------------------------*/
-int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points)
-{
- struct npc_data *nd = (struct npc_data *)iMap->id2bl(sd->npc_shopid);
+int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points) {
+ struct npc_data *nd = NULL;
struct item_data *item;
+ struct npc_item_list *shop = NULL;
int i, price, w;
-
+ unsigned short shop_size = 0;
+
if( amount <= 0 )
- return 5;
+ return ERROR_TYPE_ITEM_ID;
if( points < 0 )
- return 6;
-
- if( !nd || nd->subtype != CASHSHOP )
- return 1;
+ return ERROR_TYPE_MONEY;
if( sd->state.trading )
- return 4;
+ return ERROR_TYPE_EXCHANGE;
+
+ if( !(nd = (struct npc_data *)map->id2bl(sd->npc_shopid)) )
+ return ERROR_TYPE_NPC;
- if( (item = itemdb_exists(nameid)) == NULL )
- return 5; // Invalid Item
+ if( (item = itemdb->exists(nameid)) == NULL )
+ return ERROR_TYPE_ITEM_ID; // Invalid Item
- ARR_FIND(0, nd->u.shop.count, i, nd->u.shop.shop_item[i].nameid == nameid);
- if( i == nd->u.shop.count )
- return 5;
- if( nd->u.shop.shop_item[i].value <= 0 )
- return 5;
+ if( nd->subtype != CASHSHOP ) {
+ if( nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type != NST_ZENY && nd->u.scr.shop->type != NST_MARKET ) {
+ shop = nd->u.scr.shop->item;
+ shop_size = nd->u.scr.shop->items;
+ } else
+ return ERROR_TYPE_NPC;
+ } else {
+ shop = nd->u.shop.shop_item;
+ shop_size = nd->u.shop.count;
+ }
+
+ ARR_FIND(0, shop_size, i, shop[i].nameid == nameid);
+
+ if( i == shop_size )
+ return ERROR_TYPE_ITEM_ID;
+
+ if( shop[i].value <= 0 )
+ return ERROR_TYPE_ITEM_ID;
- if(!itemdb_isstackable(nameid) && amount > 1)
- {
- ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n",
+ if(!itemdb->isstackable(nameid) && amount > 1) {
+ ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of non-stackable item %d!\n",
sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
amount = 1;
}
- switch( pc->checkadditem(sd, nameid, amount) )
- {
+ switch( pc->checkadditem(sd, nameid, amount) ) {
case ADDITEM_NEW:
if( pc->inventoryblank(sd) == 0 )
- return 3;
+ return ERROR_TYPE_INVENTORY_WEIGHT;
break;
case ADDITEM_OVERAMOUNT:
- return 3;
+ return ERROR_TYPE_INVENTORY_WEIGHT;
}
w = item->weight * amount;
if( w + sd->weight > sd->max_weight )
- return 3;
+ return ERROR_TYPE_INVENTORY_WEIGHT;
- if( (double)nd->u.shop.shop_item[i].value * amount > INT_MAX )
- {
+ if( (double)shop[i].value * amount > INT_MAX ) {
ShowWarning("npc_cashshop_buy: Item '%s' (%d) price overflow attempt!\n", item->name, nameid);
ShowDebug("(NPC:'%s' (%s,%d,%d), player:'%s' (%d/%d), value:%d, amount:%d)\n",
- nd->exname, map[nd->bl.m].name, nd->bl.x, nd->bl.y, sd->status.name, sd->status.account_id, sd->status.char_id, nd->u.shop.shop_item[i].value, amount);
- return 5;
+ nd->exname, map->list[nd->bl.m].name, nd->bl.x, nd->bl.y,
+ sd->status.name, sd->status.account_id, sd->status.char_id,
+ shop[i].value, amount);
+ return ERROR_TYPE_ITEM_ID;
}
- price = nd->u.shop.shop_item[i].value * amount;
+ price = shop[i].value * amount;
+
if( points > price )
points = price;
- if( (sd->kafraPoints < points) || (sd->cashPoints < price - points) )
- return 6;
-
- pc->paycash(sd, price, points);
+ if( nd->subtype == SCRIPT && nd->u.scr.shop->type == NST_CUSTOM ) {
+ if( !npc->trader_pay(nd,sd,price,points) )
+ return ERROR_TYPE_MONEY;
+ } else {
+ if( (sd->kafraPoints < points) || (sd->cashPoints < price - points) )
+ return ERROR_TYPE_MONEY;
+
+ pc->paycash(sd, price, points);
+ }
- if( !pet_create_egg(sd, nameid) )
- {
+ if( !pet->create_egg(sd, nameid) ) {
struct item item_tmp;
memset(&item_tmp, 0, sizeof(struct item));
item_tmp.nameid = nameid;
@@ -1484,114 +1718,124 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po
pc->additem(sd,&item_tmp, amount, LOG_TYPE_NPC);
}
- return 0;
+ return ERROR_TYPE_NONE;
}
/// Player item purchase from npc shop.
///
/// @param item_list 'n' pairs <amount,itemid>
/// @return result code for clif->parse_NpcBuyListSend
-int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
-{
+int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) {
struct npc_data* nd;
+ struct npc_item_list *shop = NULL;
double z;
int i,j,w,skill_t,new_, idx = skill->get_index(MC_DISCOUNT);
-
+ unsigned short shop_size = 0;
+
nullpo_retr(3, sd);
nullpo_retr(3, item_list);
-
- nd = npc_checknear(sd,iMap->id2bl(sd->npc_shopid));
+
+ nd = npc->checknear(sd,map->id2bl(sd->npc_shopid));
if( nd == NULL )
return 3;
- if( nd->subtype != SHOP )
- return 3;
-
+
+ if( nd->subtype != SHOP ) {
+ if( nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type == NST_ZENY ) {
+ shop = nd->u.scr.shop->item;
+ shop_size = nd->u.scr.shop->items;
+ } else
+ return 3;
+ } else {
+ shop = nd->u.shop.shop_item;
+ shop_size = nd->u.shop.count;
+ }
+
z = 0;
w = 0;
new_ = 0;
// process entries in buy list, one by one
for( i = 0; i < n; ++i ) {
int nameid, amount, value;
-
+
// find this entry in the shop's sell list
- ARR_FIND( 0, nd->u.shop.count, j,
- item_list[i*2+1] == nd->u.shop.shop_item[j].nameid || //Normal items
- item_list[i*2+1] == itemdb_viewid(nd->u.shop.shop_item[j].nameid) //item_avail replacement
- );
-
- if( j == nd->u.shop.count )
+ ARR_FIND( 0, shop_size, j,
+ item_list[i*2+1] == shop[j].nameid || //Normal items
+ item_list[i*2+1] == itemdb_viewid(shop[j].nameid) //item_avail replacement
+ );
+
+ if( j == shop_size )
return 3; // no such item in shop
-
+
amount = item_list[i*2+0];
- nameid = item_list[i*2+1] = nd->u.shop.shop_item[j].nameid; //item_avail replacement
- value = nd->u.shop.shop_item[j].value;
-
- if( !itemdb_exists(nameid) )
+ nameid = item_list[i*2+1] = shop[j].nameid; //item_avail replacement
+ value = shop[j].value;
+
+ if( !itemdb->exists(nameid) )
return 3; // item no longer in itemdb
-
- if( !itemdb_isstackable(nameid) && amount > 1 ) {
+
+ if( !itemdb->isstackable(nameid) && amount > 1 ) {
//Exploit? You can't buy more than 1 of equipment types o.O
- ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n",
- sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
+ ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of non-stackable item %d!\n",
+ sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
amount = item_list[i*2+0] = 1;
}
-
+
if( nd->master_nd ) {
// Script-controlled shops decide by themselves, what can be bought and for what price.
continue;
}
-
+
switch( pc->checkadditem(sd,nameid,amount) ) {
case ADDITEM_EXIST:
break;
-
+
case ADDITEM_NEW:
new_++;
break;
-
+
case ADDITEM_OVERAMOUNT:
return 2;
}
-
+
value = pc->modifybuyvalue(sd,value);
-
+
z += (double)value * amount;
w += itemdb_weight(nameid) * amount;
}
-
+
if( nd->master_nd != NULL ) //Script-based shops.
- return npc_buylist_sub(sd,n,item_list,nd->master_nd);
-
+ return npc->buylist_sub(sd,n,item_list,nd->master_nd);
+
if( z > (double)sd->status.zeny )
return 1; // Not enough Zeny
if( w + sd->weight > sd->max_weight )
return 2; // Too heavy
if( pc->inventoryblank(sd) < new_ )
return 3; // Not enough space to store items
-
+
pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL);
-
+
for( i = 0; i < n; ++i ) {
int nameid = item_list[i*2+1];
int amount = item_list[i*2+0];
struct item item_tmp;
-
+
if (itemdb_type(nameid) == IT_PETEGG)
- pet_create_egg(sd, nameid);
+ pet->create_egg(sd, nameid);
else {
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = nameid;
item_tmp.identify = 1;
-
+
pc->additem(sd,&item_tmp,amount,LOG_TYPE_NPC);
}
}
-
+
// custom merchant shop exp bonus
if( battle_config.shop_exp > 0 && z > 0 && (skill_t = pc->checkskill2(sd,idx)) > 0 ) {
if( sd->status.skill[idx].flag >= SKILL_FLAG_REPLACED_LV_0 )
skill_t = sd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0;
-
+
if( skill_t > 0 ) {
z = z * (double)skill_t * (double)battle_config.shop_exp/10000.;
if( z < 1 )
@@ -1599,13 +1843,123 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
pc->gainexp(sd,NULL,0,(int)z, false);
}
}
-
+
return 0;
}
+/**
+ * parses incoming npc market purchase list
+ **/
+int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, struct packet_npc_market_purchase *p) {
+ struct npc_data* nd;
+ struct npc_item_list *shop = NULL;
+ double z;
+ int i,j,w,new_;
+ unsigned short shop_size = 0;
+
+ nullpo_retr(1, sd);
+ nullpo_retr(1, p);
+
+ nd = npc->checknear(sd,map->id2bl(sd->npc_shopid));
+
+ if( nd == NULL || nd->subtype != SCRIPT || !list_size || !nd->u.scr.shop || nd->u.scr.shop->type != NST_MARKET )
+ return 1;
+
+ shop = nd->u.scr.shop->item;
+ shop_size = nd->u.scr.shop->items;
+
+ z = 0;
+ w = 0;
+ new_ = 0;
+
+ // process entries in buy list, one by one
+ for( i = 0; i < list_size; ++i ) {
+ int nameid, amount, value;
+
+ // find this entry in the shop's sell list
+ ARR_FIND( 0, shop_size, j,
+ p->list[i].ITID == shop[j].nameid || //Normal items
+ p->list[i].ITID == itemdb_viewid(shop[j].nameid) //item_avail replacement
+ );
+
+ if( j == shop_size ) /* TODO find official response for this */
+ return 1; // no such item in shop
+
+ if( p->list[i].qty > shop[j].qty )
+ return 1;
+
+ amount = p->list[i].qty;
+ nameid = p->list[i].ITID = shop[j].nameid; //item_avail replacement
+ value = shop[j].value;
+ npc_market_qty[i] = j;
+
+ if( !itemdb->exists(nameid) ) /* TODO find official response for this */
+ return 1; // item no longer in itemdb
+
+ if( !itemdb->isstackable(nameid) && amount > 1 ) {
+ //Exploit? You can't buy more than 1 of equipment types o.O
+ ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of non-stackable item %d!\n",
+ sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
+ amount = p->list[i].qty = 1;
+ }
+
+ switch( pc->checkadditem(sd,nameid,amount) ) {
+ case ADDITEM_EXIST:
+ break;
+
+ case ADDITEM_NEW:
+ new_++;
+ break;
+
+ case ADDITEM_OVERAMOUNT: /* TODO find official response for this */
+ return 1;
+ }
+
+ z += (double)value * amount;
+ w += itemdb_weight(nameid) * amount;
+ }
+
+ if( z > (double)sd->status.zeny ) /* TODO find official response for this */
+ return 1; // Not enough Zeny
+
+ if( w + sd->weight > sd->max_weight ) /* TODO find official response for this */
+ return 1; // Too heavy
+
+ if( pc->inventoryblank(sd) < new_ ) /* TODO find official response for this */
+ return 1; // Not enough space to store items
+
+ pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL);
+
+ for( i = 0; i < list_size; ++i ) {
+ int nameid = p->list[i].ITID;
+ int amount = p->list[i].qty;
+ struct item item_tmp;
+
+ j = npc_market_qty[i];
+
+ if( p->list[i].qty > shop[j].qty ) /* wohoo someone tampered with the packet. */
+ return 1;
+
+ shop[j].qty -= amount;
+
+ npc->market_tosql(nd,j);
+
+ if (itemdb_type(nameid) == IT_PETEGG)
+ pet->create_egg(sd, nameid);
+ else {
+ memset(&item_tmp,0,sizeof(item_tmp));
+ item_tmp.nameid = nameid;
+ item_tmp.identify = 1;
+
+ pc->additem(sd,&item_tmp,amount,LOG_TYPE_NPC);
+ }
+ }
+
+ return 0;
+}
/// npc_selllist for script-controlled shops
-static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_list, struct npc_data* nd)
+int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_list, struct npc_data* nd)
{
char npc_ev[EVENT_NAME_LENGTH];
char card_slot[NAME_LENGTH];
@@ -1618,17 +1972,17 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short*
int key_card[MAX_SLOTS];
// discard old contents
- script_cleararray_pc(sd, "@sold_nameid", (void*)0);
- script_cleararray_pc(sd, "@sold_quantity", (void*)0);
- script_cleararray_pc(sd, "@sold_refine", (void*)0);
- script_cleararray_pc(sd, "@sold_attribute", (void*)0);
- script_cleararray_pc(sd, "@sold_identify", (void*)0);
+ script->cleararray_pc(sd, "@sold_nameid", (void*)0);
+ script->cleararray_pc(sd, "@sold_quantity", (void*)0);
+ script->cleararray_pc(sd, "@sold_refine", (void*)0);
+ script->cleararray_pc(sd, "@sold_attribute", (void*)0);
+ script->cleararray_pc(sd, "@sold_identify", (void*)0);
for( j = 0; j < MAX_SLOTS; j++ )
{// clear each of the card slot entries
key_card[j] = 0;
snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1);
- script_cleararray_pc(sd, card_slot, (void*)0);
+ script->cleararray_pc(sd, card_slot, (void*)0);
}
// save list of to be sold items
@@ -1636,26 +1990,26 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short*
{
idx = item_list[i*2]-2;
- script_setarray_pc(sd, "@sold_nameid", i, (void*)(intptr_t)sd->status.inventory[idx].nameid, &key_nameid);
- script_setarray_pc(sd, "@sold_quantity", i, (void*)(intptr_t)item_list[i*2+1], &key_amount);
+ script->setarray_pc(sd, "@sold_nameid", i, (void*)(intptr_t)sd->status.inventory[idx].nameid, &key_nameid);
+ script->setarray_pc(sd, "@sold_quantity", i, (void*)(intptr_t)item_list[i*2+1], &key_amount);
- if( itemdb_isequip(sd->status.inventory[idx].nameid) )
+ if( itemdb->isequip(sd->status.inventory[idx].nameid) )
{// process equipment based information into the arrays
- script_setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->status.inventory[idx].refine, &key_refine);
- script_setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute);
- script_setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->status.inventory[idx].identify, &key_identify);
+ script->setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->status.inventory[idx].refine, &key_refine);
+ script->setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute);
+ script->setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->status.inventory[idx].identify, &key_identify);
for( j = 0; j < MAX_SLOTS; j++ )
{// store each of the cards from the equipment in the array
snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1);
- script_setarray_pc(sd, card_slot, i, (void*)(intptr_t)sd->status.inventory[idx].card[j], &key_card[j]);
+ script->setarray_pc(sd, card_slot, i, (void*)(intptr_t)sd->status.inventory[idx].card[j], &key_card[j]);
}
}
}
// invoke event
snprintf(npc_ev, ARRAYLENGTH(npc_ev), "%s::OnSellItem", nd->exname);
- npc_event(sd, npc_ev, 0);
+ npc->event(sd, npc_ev, 0);
return 0;
}
@@ -1664,19 +2018,24 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short*
///
/// @param item_list 'n' pairs <index,amount>
/// @return result code for clif->parse_NpcSellListSend
-int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
-{
+int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) {
double z;
- int i,skill_t, idx = skill->get_index(MC_OVERCHARGE);
+ int i,skill_t, skill_idx = skill->get_index(MC_OVERCHARGE);
struct npc_data *nd;
nullpo_retr(1, sd);
nullpo_retr(1, item_list);
- if( ( nd = npc_checknear(sd, iMap->id2bl(sd->npc_shopid)) ) == NULL || nd->subtype != SHOP ) {
+ if( ( nd = npc->checknear(sd, map->id2bl(sd->npc_shopid)) ) == NULL ) {
return 1;
}
+ if( nd->subtype != SHOP ) {
+ if( !(nd->subtype == SCRIPT && nd->u.scr.shop && nd->u.scr.shop->type == NST_ZENY) )
+ return 1;
+ }
+
+
z = 0;
// verify the sell list
@@ -1706,7 +2065,7 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
}
if( nd->master_nd ) { // Script-controlled shops
- return npc_selllist_sub(sd, n, item_list, nd->master_nd);
+ return npc->selllist_sub(sd, n, item_list, nd->master_nd);
}
// delete items
@@ -1717,8 +2076,8 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
amount = item_list[i*2+1];
if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) {
- if( search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0 ) {
- intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2]));
+ if( pet->search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0 ) {
+ intif->delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2]));
}
}
@@ -1731,9 +2090,9 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
pc->getzeny(sd, (int)z, LOG_TYPE_NPC, NULL);
// custom merchant shop exp bonus
- if( battle_config.shop_exp > 0 && z > 0 && ( skill_t = pc->checkskill2(sd,idx) ) > 0) {
- if( sd->status.skill[idx].flag >= SKILL_FLAG_REPLACED_LV_0 )
- skill_t = sd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0;
+ if( battle_config.shop_exp > 0 && z > 0 && ( skill_t = pc->checkskill2(sd,skill_idx) ) > 0) {
+ if( sd->status.skill[skill_idx].flag >= SKILL_FLAG_REPLACED_LV_0 )
+ skill_t = sd->status.skill[skill_idx].flag - SKILL_FLAG_REPLACED_LV_0;
if( skill_t > 0 ) {
z = z * (double)skill_t * (double)battle_config.shop_exp/10000.;
@@ -1754,103 +2113,122 @@ int npc_remove_map(struct npc_data* nd) {
if(nd->bl.prev == NULL || nd->bl.m < 0)
return 1; //Not assigned to a map.
- m = nd->bl.m;
+ m = nd->bl.m;
clif->clearunit_area(&nd->bl,CLR_RESPAWN);
- npc_unsetcells(nd);
- iMap->delblock(&nd->bl);
- //Remove npc from map[].npc list. [Skotlex]
- ARR_FIND( 0, map[m].npc_num, i, map[m].npc[i] == nd );
- if( i == map[m].npc_num ) return 2; //failed to find it?
-
- map[m].npc_num--;
- map[m].npc[i] = map[m].npc[map[m].npc_num];
- map[m].npc[map[m].npc_num] = NULL;
+ npc->unsetcells(nd);
+ map->delblock(&nd->bl);
+ //Remove npc from map->list[].npc list. [Skotlex]
+ ARR_FIND( 0, map->list[m].npc_num, i, map->list[m].npc[i] == nd );
+ if( i == map->list[m].npc_num ) return 2; //failed to find it?
+
+ map->list[m].npc_num--;
+ map->list[m].npc[i] = map->list[m].npc[map->list[m].npc_num];
+ map->list[m].npc[map->list[m].npc_num] = NULL;
return 0;
}
/**
* @see DBApply
*/
-static int npc_unload_ev(DBKey key, DBData *data, va_list ap)
+int npc_unload_ev(DBKey key, DBData *data, va_list ap)
{
struct event_data* ev = DB->data2ptr(data);
char* npcname = va_arg(ap, char *);
if(strcmp(ev->nd->exname,npcname)==0){
- db_remove(ev_db, key);
+ db_remove(npc->ev_db, key);
return 1;
}
return 0;
}
+/**
+ * @see DBApply
+ */
+int npc_unload_ev_label(DBKey key, DBData *data, va_list ap)
+{
+ struct linkdb_node **label_linkdb = DB->data2ptr(data);
+ struct npc_data* nd = va_arg(ap, struct npc_data *);
+
+ linkdb_erase(label_linkdb, nd);
+
+ return 0;
+}
+
//Chk if npc matches src_id, then unload.
//Sub-function used to find duplicates.
-static int npc_unload_dup_sub(struct npc_data* nd, va_list args)
+int npc_unload_dup_sub(struct npc_data* nd, va_list args)
{
int src_id;
src_id = va_arg(args, int);
if (nd->src_id == src_id)
- npc_unload(nd, true);
+ npc->unload(nd, true);
return 0;
}
//Removes all npcs that are duplicates of the passed one. [Skotlex]
-void npc_unload_duplicates(struct npc_data* nd)
-{
- iMap->map_foreachnpc(npc_unload_dup_sub,nd->bl.id);
+void npc_unload_duplicates(struct npc_data* nd) {
+ map->foreachnpc(npc->unload_dup_sub,nd->bl.id);
}
//Removes an npc from map and db.
//Single is to free name (for duplicates).
int npc_unload(struct npc_data* nd, bool single) {
+ unsigned int i;
+
nullpo_ret(nd);
- npc_remove_map(nd);
- iMap->deliddb(&nd->bl);
+ npc->remove_map(nd);
+ map->deliddb(&nd->bl);
if( single )
- strdb_remove(npcname_db, nd->exname);
+ strdb_remove(npc->name_db, nd->exname);
if (nd->chat_id) // remove npc chatroom object and kick users
- chat_deletenpcchat(nd);
+ chat->delete_npc_chat(nd);
#ifdef PCRE_SUPPORT
- npc_chat_finalize(nd); // deallocate npc PCRE data structures
+ npc_chat->finalize(nd); // deallocate npc PCRE data structures
#endif
if( single && nd->path ) {
struct npc_path_data* npd = NULL;
if( nd->path && nd->path != npc_last_ref ) {
- npd = strdb_get(npc_path_db, nd->path);
+ npd = strdb_get(npc->path_db, nd->path);
}
if( npd && --npd->references == 0 ) {
- strdb_remove(npc_path_db, nd->path);/* remove from db */
+ strdb_remove(npc->path_db, nd->path);/* remove from db */
aFree(nd->path);/* remove now that no other instances exist */
}
}
+
+ if( single && nd->bl.m != -1 )
+ map->remove_questinfo(nd->bl.m,nd);
- if( (nd->subtype == SHOP || nd->subtype == CASHSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao]
+ if( nd->src_id == 0 && ( nd->subtype == SHOP || nd->subtype == CASHSHOP ) ) //src check for duplicate shops [Orcao]
aFree(nd->u.shop.shop_item);
else if( nd->subtype == SCRIPT ) {
struct s_mapiterator* iter;
struct block_list* bl;
- if( single )
- ev_db->foreach(ev_db,npc_unload_ev,nd->exname); //Clean up all events related
+ if( single ) {
+ npc->ev_db->foreach(npc->ev_db,npc->unload_ev,nd->exname); //Clean up all events related
+ npc->ev_label_db->foreach(npc->ev_label_db,npc->unload_ev_label,nd);
+ }
iter = mapit_geteachpc();
for( bl = (struct block_list*)mapit->first(iter); mapit->exists(iter); bl = (struct block_list*)mapit->next(iter) ) {
struct map_session_data *sd = ((TBL_PC*)bl);
if( sd && sd->npc_timer_id != INVALID_TIMER ) {
- const struct TimerData *td = iTimer->get_timer(sd->npc_timer_id);
+ const struct TimerData *td = timer->get(sd->npc_timer_id);
if( td && td->id != nd->bl.id )
continue;
if( td && td->data )
- ers_free(timer_event_ers, (void*)td->data);
- iTimer->delete_timer(sd->npc_timer_id, npc_timerevent);
+ ers_free(npc->timer_event_ers, (void*)td->data);
+ timer->delete(sd->npc_timer_id, npc->timerevent);
sd->npc_timer_id = INVALID_TIMER;
}
}
@@ -1858,17 +2236,16 @@ int npc_unload(struct npc_data* nd, bool single) {
if (nd->u.scr.timerid != INVALID_TIMER) {
const struct TimerData *td;
- td = iTimer->get_timer(nd->u.scr.timerid);
+ td = timer->get(nd->u.scr.timerid);
if (td && td->data)
- ers_free(timer_event_ers, (void*)td->data);
- iTimer->delete_timer(nd->u.scr.timerid, npc_timerevent);
+ ers_free(npc->timer_event_ers, (void*)td->data);
+ timer->delete(nd->u.scr.timerid, npc->timerevent);
}
if (nd->u.scr.timer_event)
aFree(nd->u.scr.timer_event);
if (nd->src_id == 0) {
if(nd->u.scr.script) {
- script_stop_instances(nd->bl.id);
- script_free_code(nd->u.scr.script);
+ script->free_code(nd->u.scr.script);
nd->u.scr.script = NULL;
}
if (nd->u.scr.label_list) {
@@ -1876,16 +2253,30 @@ int npc_unload(struct npc_data* nd, bool single) {
nd->u.scr.label_list = NULL;
nd->u.scr.label_list_num = 0;
}
+ if(nd->u.scr.shop) {
+ if(nd->u.scr.shop->item)
+ aFree(nd->u.scr.shop->item);
+ aFree(nd->u.scr.shop);
+ }
}
if( nd->u.scr.guild_id )
guild->flag_remove(nd);
}
- if( nd->ud != &npc_base_ud ) {
+ if( nd->ud != &npc->base_ud ) {
aFree(nd->ud);
nd->ud = NULL;
}
+ for( i = 0; i < nd->hdatac; i++ ) {
+ if( nd->hdata[i]->flag.free ) {
+ aFree(nd->hdata[i]->data);
+ }
+ aFree(nd->hdata[i]);
+ }
+ if( nd->hdata )
+ aFree(nd->hdata);
+
aFree(nd);
return 0;
@@ -1896,9 +2287,9 @@ int npc_unload(struct npc_data* nd, bool single) {
//
/// Clears the npc source file list
-static void npc_clearsrcfile(void)
+void npc_clearsrcfile(void)
{
- struct npc_src_list* file = npc_src_files;
+ struct npc_src_list* file = npc->src_files;
struct npc_src_list* file_tofree;
while( file != NULL )
@@ -1907,7 +2298,7 @@ static void npc_clearsrcfile(void)
file = file->next;
aFree(file_tofree);
}
- npc_src_files = NULL;
+ npc->src_files = NULL;
}
/// Adds a npc source file (or removes all)
@@ -1918,12 +2309,12 @@ void npc_addsrcfile(const char* name)
if( strcmpi(name, "clear") == 0 )
{
- npc_clearsrcfile();
+ npc->clearsrcfile();
return;
}
// prevent multiple insert of source files
- file = npc_src_files;
+ file = npc->src_files;
while( file != NULL )
{
if( strcmp(name, file->name) == 0 )
@@ -1936,7 +2327,7 @@ void npc_addsrcfile(const char* name)
file->next = NULL;
safestrncpy(file->name, name, strlen(name) + 1);
if( file_prev == NULL )
- npc_src_files = file;
+ npc->src_files = file;
else
file_prev->next = file;
}
@@ -1944,12 +2335,12 @@ void npc_addsrcfile(const char* name)
/// Removes a npc source file (or all)
void npc_delsrcfile(const char* name)
{
- struct npc_src_list* file = npc_src_files;
+ struct npc_src_list* file = npc->src_files;
struct npc_src_list* file_prev = NULL;
if( strcmpi(name, "all") == 0 )
{
- npc_clearsrcfile();
+ npc->clearsrcfile();
return;
}
@@ -1957,8 +2348,8 @@ void npc_delsrcfile(const char* name)
{
if( strcmp(file->name, name) == 0 )
{
- if( npc_src_files == file )
- npc_src_files = file->next;
+ if( npc->src_files == file )
+ npc->src_files = file->next;
else
file_prev->next = file->next;
aFree(file);
@@ -1971,8 +2362,7 @@ void npc_delsrcfile(const char* name)
/// Parses and sets the name and exname of a npc.
/// Assumes that m, x and y are already set in nd.
-static void npc_parsename(struct npc_data* nd, const char* name, const char* start, const char* buffer, const char* filepath)
-{
+void npc_parsename(struct npc_data* nd, const char* name, const char* start, const char* buffer, const char* filepath) {
const char* p;
struct npc_data* dnd;// duplicate npc
char newname[NAME_LENGTH];
@@ -1982,7 +2372,7 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta
if( p ) { // <Display name>::<Unique name>
size_t len = p-name;
if( len > NAME_LENGTH ) {
- ShowWarning("npc_parsename: Display name of '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
+ ShowWarning("npc_parsename: Display name of '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
safestrncpy(nd->name, name, sizeof(nd->name));
} else {
memcpy(nd->name, name, len);
@@ -1990,23 +2380,23 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta
}
len = strlen(p+2);
if( len > NAME_LENGTH )
- ShowWarning("npc_parsename: Unique name of '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
+ ShowWarning("npc_parsename: Unique name of '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
safestrncpy(nd->exname, p+2, sizeof(nd->exname));
} else {// <Display name>
size_t len = strlen(name);
if( len > NAME_LENGTH )
- ShowWarning("npc_parsename: Name '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
+ ShowWarning("npc_parsename: Name '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
safestrncpy(nd->name, name, sizeof(nd->name));
safestrncpy(nd->exname, name, sizeof(nd->exname));
}
if( *nd->exname == '\0' || strstr(nd->exname,"::") != NULL ) {// invalid
snprintf(newname, ARRAYLENGTH(newname), "0_%d_%d_%d", nd->bl.m, nd->bl.x, nd->bl.y);
- ShowWarning("npc_parsename: Invalid unique name in file '%s', line'%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname);
+ ShowWarning("npc_parsename: Invalid unique name in file '%s', line '%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname);
safestrncpy(nd->exname, newname, sizeof(nd->exname));
}
- if( (dnd=npc_name2id(nd->exname)) != NULL ) {// duplicate unique name, generate new one
+ if( (dnd=npc->name2id(nd->exname)) != NULL ) {// duplicate unique name, generate new one
char this_mapname[32];
char other_mapname[32];
int i = 0;
@@ -2014,12 +2404,12 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta
do {
++i;
snprintf(newname, ARRAYLENGTH(newname), "%d_%d_%d_%d", i, nd->bl.m, nd->bl.x, nd->bl.y);
- } while( npc_name2id(newname) != NULL );
+ } while( npc->name2id(newname) != NULL );
- strcpy(this_mapname, (nd->bl.m==-1?"(not on a map)":mapindex_id2name(map[nd->bl.m].index)));
- strcpy(other_mapname, (dnd->bl.m==-1?"(not on a map)":mapindex_id2name(map[dnd->bl.m].index)));
+ strcpy(this_mapname, (nd->bl.m == -1 ? "(not on a map)" : mapindex_id2name(map_id2index(nd->bl.m))));
+ strcpy(other_mapname, (dnd->bl.m == -1 ? "(not on a map)" : mapindex_id2name(map_id2index(dnd->bl.m))));
- ShowWarning("npc_parsename: Duplicate unique name in file '%s', line'%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname);
+ ShowWarning("npc_parsename: Duplicate unique name in file '%s', line '%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname);
ShowDebug("this npc:\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n", nd->name, nd->exname, this_mapname, nd->bl.x, nd->bl.y);
ShowDebug("other npc in '%s' :\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n",dnd->path, dnd->name, dnd->exname, other_mapname, dnd->bl.x, dnd->bl.y);
safestrncpy(nd->exname, newname, sizeof(nd->exname));
@@ -2028,9 +2418,9 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta
if( npc_last_path != filepath ) {
struct npc_path_data * npd = NULL;
- if( !(npd = strdb_get(npc_path_db,filepath) ) ) {
+ if( !(npd = strdb_get(npc->path_db,filepath) ) ) {
CREATE(npd, struct npc_path_data, 1);
- strdb_put(npc_path_db, filepath, npd);
+ strdb_put(npc->path_db, filepath, npd);
CREATE(npd->path, char, strlen(filepath)+1);
safestrncpy(npd->path, filepath, strlen(filepath)+1);
@@ -2051,27 +2441,74 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta
}
}
+// Parse View
+// Support for using Constants in place of NPC View IDs.
+int npc_parseview(const char* w4, const char* start, const char* buffer, const char* filepath) {
+ int val = -1, i = 0;
+ char viewid[1024]; // Max size of name from const.txt, see script->read_constdb.
+
+ // Extract view ID / constant
+ while (w4[i] != '\0') {
+ if (ISSPACE(w4[i]) || w4[i] == '/' || w4[i] == ',')
+ break;
+
+ i++;
+ }
+
+ safestrncpy(viewid, w4, i+=1);
+
+ // Check if view id is not an ID (only numbers).
+ if(!npc->viewisid(viewid))
+ {
+ // Check if constant exists and get its value.
+ if(!script->get_constant(viewid, &val)) {
+ ShowWarning("npc_parseview: Invalid NPC constant '%s' specified in file '%s', line'%d'. Defaulting to INVISIBLE_CLASS. \n", viewid, filepath, strline(buffer,start-buffer));
+ val = INVISIBLE_CLASS;
+ }
+ } else {
+ // NPC has an ID specified for view id.
+ val = atoi(w4);
+ }
+
+ return val;
+}
+
+// View is ID
+// Checks if given view is an ID or constant.
+bool npc_viewisid(const char * viewid)
+{
+ if(atoi(viewid) != -1)
+ {
+ // Loop through view, looking for non-numeric character.
+ while (*viewid) {
+ if (ISDIGIT(*viewid++) == 0) return false;
+ }
+ }
+
+ return true;
+}
+
//Add then display an npc warp on map
struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y) {
int i, flag = 0;
struct npc_data *nd;
CREATE(nd, struct npc_data, 1);
- nd->bl.id = npc_get_new_npc_id();
- iMap->addnpc(from_mapid, nd);
+ nd->bl.id = npc->get_new_npc_id();
+ map->addnpc(from_mapid, nd);
nd->bl.prev = nd->bl.next = NULL;
nd->bl.m = from_mapid;
nd->bl.x = from_x;
nd->bl.y = from_y;
safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname));
- if (npc_name2id(nd->exname) != NULL)
+ if (npc->name2id(nd->exname) != NULL)
flag = 1;
if (flag == 1)
snprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp_%d_%d_%d", from_mapid, from_x, from_y);
- for( i = 0; npc_name2id(nd->exname) != NULL; ++i )
+ for( i = 0; npc->name2id(nd->exname) != NULL; ++i )
snprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp%d_%d_%d_%d", i, from_mapid, from_x, from_y);
safestrncpy(nd->name, nd->exname, ARRAYLENGTH(nd->name));
@@ -2088,20 +2525,19 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
nd->u.warp.ys = xs;
nd->bl.type = BL_NPC;
nd->subtype = WARP;
- npc_setcells(nd);
- iMap->addblock(&nd->bl);
- status_set_viewdata(&nd->bl, nd->class_);
- nd->ud = &npc_base_ud;
- if( map[nd->bl.m].users )
+ npc->setcells(nd);
+ map->addblock(&nd->bl);
+ status->set_viewdata(&nd->bl, nd->class_);
+ nd->ud = &npc->base_ud;
+ if( map->list[nd->bl.m].users )
clif->spawn(&nd->bl);
- strdb_put(npcname_db, nd->exname, nd);
+ strdb_put(npc->name_db, nd->exname, nd);
return nd;
}
/// Parses a warp npc.
-static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
-{
+const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) {
int x, y, xs, ys, to_x, to_y, m;
unsigned short i;
char mapname[32], to_mapname[32];
@@ -2110,34 +2546,36 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
// w1=<from map name>,<fromX>,<fromY>,<facing>
// w4=<spanx>,<spany>,<to map name>,<toX>,<toY>
if( sscanf(w1, "%31[^,],%d,%d", mapname, &x, &y) != 3
- || sscanf(w4, "%d,%d,%31[^,],%d,%d", &xs, &ys, to_mapname, &to_x, &to_y) != 5 )
- {
+ || sscanf(w4, "%d,%d,%31[^,],%d,%d", &xs, &ys, to_mapname, &to_x, &to_y) != 5
+ ) {
ShowError("npc_parse_warp: Invalid warp definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
- m = iMap->mapname2mapid(mapname);
- i = mapindex_name2id(to_mapname);
- if( i == 0 )
- {
+ m = map->mapname2mapid(mapname);
+ i = mapindex->name2id(to_mapname);
+ if( i == 0 ) {
ShowError("npc_parse_warp: Unknown destination map in file '%s', line '%d' : %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), to_mapname, w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
- if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) {
- ShowError("npc_parse_warp: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map[m].name, x, y, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer));
+ if( m != -1 && ( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) ) {
+ ShowError("npc_parse_warp: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map->list[m].name, x, y, map->list[m].xs, map->list[m].ys,filepath,strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');;//try next
}
CREATE(nd, struct npc_data, 1);
- nd->bl.id = npc_get_new_npc_id();
- iMap->addnpc(m, nd);
+ nd->bl.id = npc->get_new_npc_id();
+ map->addnpc(m, nd);
nd->bl.prev = nd->bl.next = NULL;
nd->bl.m = m;
nd->bl.x = x;
nd->bl.y = y;
- npc_parsename(nd, w3, start, buffer, filepath);
+ npc->parsename(nd, w3, start, buffer, filepath);
if (!battle_config.warp_point_debug)
nd->class_ = WARP_CLASS;
@@ -2153,86 +2591,108 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
npc_warp++;
nd->bl.type = BL_NPC;
nd->subtype = WARP;
- npc_setcells(nd);
- iMap->addblock(&nd->bl);
- status_set_viewdata(&nd->bl, nd->class_);
- nd->ud = &npc_base_ud;
- if( map[nd->bl.m].users )
+ npc->setcells(nd);
+ map->addblock(&nd->bl);
+ status->set_viewdata(&nd->bl, nd->class_);
+ nd->ud = &npc->base_ud;
+ if( map->list[nd->bl.m].users )
clif->spawn(&nd->bl);
- strdb_put(npcname_db, nd->exname, nd);
+ strdb_put(npc->name_db, nd->exname, nd);
return strchr(start,'\n');// continue
}
-/// Parses a shop/cashshop npc.
-static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
-{
+/**
+ * Parses a SHOP/CASHSHOP npc
+ * @param retval Pointer to the status, used to know whether there was an error or not, if so it will be EXIT_FAILURE
+ * @retval Parsing position (currently only '\n')
+ **/
+const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) {
//TODO: could be rewritten to NOT need this temp array [ultramage]
- #define MAX_SHOPITEM 100
- struct npc_item_list items[MAX_SHOPITEM];
+ // We could use nd->u.shop.shop_item to store directly the items, but this could lead
+ // to unecessary memory usage by the server, using a temp dynamic array is the
+ // best way to do this without having to do multiple reallocs [Panikon]
+ struct npc_item_list *items = NULL;
+ size_t items_count = 40; // Starting items size
+
char *p;
int x, y, dir, m, i;
struct npc_data *nd;
enum npc_subtype type;
- if( strcmp(w1,"-") == 0 ) {// 'floating' shop?
+ if( strcmp(w1,"-") == 0 ) {
+ // 'floating' shop
x = y = dir = 0;
m = -1;
} else {// w1=<map name>,<x>,<y>,<facing>
char mapname[32];
if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4
- || strchr(w4, ',') == NULL )
- {
+ || strchr(w4, ',') == NULL
+ ) {
ShowError("npc_parse_shop: Invalid shop definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
- m = iMap->mapname2mapid(mapname);
+ m = map->mapname2mapid(mapname);
}
- if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) {
- ShowError("npc_parse_shop: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map[m].name, x, y, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer));
- return strchr(start,'\n');;//try next
+ if( m != -1 && ( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) ) {
+ ShowError("npc_parse_shop: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map->list[m].name, x, y, map->list[m].xs, map->list[m].ys,filepath,strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
+ return strchr(start,'\n');//try next
}
- if( !strcasecmp(w2,"cashshop") )
+ if( strcmp(w2,"cashshop") == 0 )
type = CASHSHOP;
else
type = SHOP;
+ items = aMalloc(sizeof(items[0])*items_count);
+
p = strchr(w4,',');
- for( i = 0; i < ARRAYLENGTH(items) && p; ++i )
- {
+ for( i = 0; p; ++i ) {
int nameid, value;
struct item_data* id;
- if( sscanf(p, ",%d:%d", &nameid, &value) != 2 )
- {
+
+ if( i == items_count-1 ) { // Grow array
+ items_count *= 2;
+ items = aRealloc(items, sizeof(items[0])*items_count);
+ }
+
+ if( sscanf(p, ",%d:%d", &nameid, &value) != 2 ) {
ShowError("npc_parse_shop: Invalid item definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
break;
}
- if( (id = itemdb_exists(nameid)) == NULL )
- {
+ if( (id = itemdb->exists(nameid)) == NULL ) {
ShowWarning("npc_parse_shop: Invalid sell item in file '%s', line '%d' (id '%d').\n", filepath, strline(buffer,start-buffer), nameid);
p = strchr(p+1,',');
+ if (retval) *retval = EXIT_FAILURE;
continue;
}
- if( value < 0 )
- {
+ if( value < 0 ) {
+ if( value != -1 )
+ ShowWarning("npc_parse_shop: Item %s [%d] with invalid selling value '%d' in file '%s', line '%d', defaulting to buy price...\n",
+ id->name, nameid, value, filepath, strline(buffer,start-buffer));
+
if( type == SHOP ) value = id->value_buy;
else value = 0; // Cashshop doesn't have a "buy price" in the item_db
}
- if( type == SHOP && value == 0 )
- { // NPC selling items for free!
+ if( type == SHOP && value == 0 ) {
+ // NPC selling items for free!
ShowWarning("npc_parse_shop: Item %s [%d] is being sold for FREE in file '%s', line '%d'.\n",
id->name, nameid, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
- if( type == SHOP && value*0.75 < id->value_sell*1.24 )
- {// Exploit possible: you can buy and sell back with profit
- ShowWarning("npc_parse_shop: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) at file '%s', line '%d'.\n",
+ if( type == SHOP && value*0.75 < id->value_sell*1.24 ) {
+ // Exploit possible: you can buy and sell back with profit
+ ShowWarning("npc_parse_shop: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) in file '%s', line '%d'.\n",
id->name, nameid, value, (int)(value*0.75), id->value_sell, (int)(id->value_sell*1.24), filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
//for logs filters, atcommands and iteminfo script command
if( id->maxchance == 0 )
@@ -2242,95 +2702,79 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
items[i].value = value;
p = strchr(p+1,',');
}
- if( i == 0 )
- {
+ if( i == 0 ) {
ShowWarning("npc_parse_shop: Ignoring empty shop in file '%s', line '%d'.\n", filepath, strline(buffer,start-buffer));
+ aFree(items);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// continue
}
CREATE(nd, struct npc_data, 1);
CREATE(nd->u.shop.shop_item, struct npc_item_list, i);
- memcpy(nd->u.shop.shop_item, items, sizeof(struct npc_item_list)*i);
+ memcpy(nd->u.shop.shop_item, items, sizeof(items[0])*i);
+ aFree(items);
+
nd->u.shop.count = i;
nd->bl.prev = nd->bl.next = NULL;
nd->bl.m = m;
nd->bl.x = x;
nd->bl.y = y;
- nd->bl.id = npc_get_new_npc_id();
- npc_parsename(nd, w3, start, buffer, filepath);
- nd->class_ = m==-1?-1:atoi(w4);
+ nd->bl.id = npc->get_new_npc_id();
+ npc->parsename(nd, w3, start, buffer, filepath);
+ nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath);
nd->speed = 200;
++npc_shop;
nd->bl.type = BL_NPC;
nd->subtype = type;
if( m >= 0 ) {// normal shop npc
- iMap->addnpc(m,nd);
- iMap->addblock(&nd->bl);
- status_set_viewdata(&nd->bl, nd->class_);
- nd->ud = &npc_base_ud;
+ map->addnpc(m,nd);
+ map->addblock(&nd->bl);
+ status->set_viewdata(&nd->bl, nd->class_);
+ nd->ud = &npc->base_ud;
nd->dir = dir;
- if( map[nd->bl.m].users )
+ if( map->list[nd->bl.m].users )
clif->spawn(&nd->bl);
- } else {// 'floating' shop?
- iMap->addiddb(&nd->bl);
+ } else {// 'floating' shop
+ map->addiddb(&nd->bl);
}
- strdb_put(npcname_db, nd->exname, nd);
+ strdb_put(npc->name_db, nd->exname, nd);
return strchr(start,'\n');// continue
}
-/**
- * NPC other label
- * Not sure, seem to add label in a chainlink
- * @see DBApply
- */
-int npc_convertlabel_db(DBKey key, DBData *data, va_list ap)
-{
- const char* lname = (const char*)key.str;
- int lpos = DB->data2i(data);
- struct npc_label_list** label_list;
- int* label_list_num;
- const char* filepath;
- struct npc_label_list* label;
- const char *p;
- int len;
-
- nullpo_ret(label_list = va_arg(ap,struct npc_label_list**));
- nullpo_ret(label_list_num = va_arg(ap,int*));
- nullpo_ret(filepath = va_arg(ap,const char*));
-
- // In case of labels not terminated with ':', for user defined function support
- p = lname;
- while( ISALNUM(*p) || *p == '_' )
- ++p;
- len = p-lname;
-
- // here we check if the label fit into the buffer
- if( len > 23 )
- {
- ShowError("npc_parse_script: label name longer than 23 chars! '%s'\n (%s)", lname, filepath);
- return 0;
- }
-
- if( *label_list == NULL )
- {
- *label_list = (struct npc_label_list *) aCalloc (1, sizeof(struct npc_label_list));
- *label_list_num = 0;
- } else
- *label_list = (struct npc_label_list *) aRealloc (*label_list, sizeof(struct npc_label_list)*(*label_list_num+1));
- label = *label_list+*label_list_num;
+void npc_convertlabel_db(struct npc_label_list* label_list, const char *filepath) {
+ int i;
+
+ for( i = 0; i < script->label_count; i++ ) {
+ const char* lname = script->get_str(script->labels[i].key);
+ int lpos = script->labels[i].pos;
+ struct npc_label_list* label;
+ const char *p;
+ size_t len;
+
+ // In case of labels not terminated with ':', for user defined function support
+ p = lname;
- safestrncpy(label->name, lname, sizeof(label->name));
- label->pos = lpos;
- ++(*label_list_num);
+ while( ISALNUM(*p) || *p == '_' )
+ ++p;
+ len = p-lname;
- return 0;
+ // here we check if the label fit into the buffer
+ if( len > 23 ) {
+ ShowError("npc_parse_script: label name longer than 23 chars! (%s) in file '%s'.\n", lname, filepath);
+ return;
+ }
+
+ label = &label_list[i];
+
+ safestrncpy(label->name, lname, sizeof(label->name));
+ label->pos = lpos;
+ }
}
// Skip the contents of a script.
-static const char* npc_skip_script(const char* start, const char* buffer, const char* filepath)
-{
+const char* npc_skip_script(const char* start, const char* buffer, const char* filepath, int *retval) {
const char* p;
int curly_count;
@@ -2339,16 +2783,16 @@ static const char* npc_skip_script(const char* start, const char* buffer, const
// initial bracket (assumes the previous part is ok)
p = strchr(start,'{');
- if( p == NULL )
- {
- ShowError("npc_skip_script: Missing left curly in file '%s', line'%d'.", filepath, strline(buffer,start-buffer));
+ if( p == NULL ) {
+ ShowError("npc_skip_script: Missing left curly in file '%s', line '%d'.\n", filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
}
// skip everything
for( curly_count = 1; curly_count > 0 ; )
{
- p = skip_space(p+1) ;
+ p = script->skip_space(p+1) ;
if( *p == '}' )
{// right curly
--curly_count;
@@ -2361,23 +2805,23 @@ static const char* npc_skip_script(const char* start, const char* buffer, const
{// string
for( ++p; *p != '"' ; ++p )
{
- if( *p == '\\' && (unsigned char)p[-1] <= 0x7e )
+ if( *p == '\\' && (unsigned char)p[-1] <= 0x7e ) {
++p;// escape sequence (not part of a multibyte character)
- else if( *p == '\0' )
- {
- script_error(buffer, filepath, 0, "Unexpected end of string.", p);
+ } else if( *p == '\0' ) {
+ script->error(buffer, filepath, 0, "Unexpected end of string.", p);
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
- }
- else if( *p == '\n' )
- {
- script_error(buffer, filepath, 0, "Unexpected newline at string.", p);
+ } else if( *p == '\n' ) {
+ script->error(buffer, filepath, 0, "Unexpected newline at string.", p);
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
}
}
}
else if( *p == '\0' )
{// end of buffer
- ShowError("Missing %d right curlys at file '%s', line '%d'.\n", curly_count, filepath, strline(buffer,p-buffer));
+ ShowError("Missing %d right curlys in file '%s', line '%d'.\n", curly_count, filepath, strline(buffer,p-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
}
}
@@ -2390,10 +2834,10 @@ static const char* npc_skip_script(const char* start, const char* buffer, const
/// -%TAB%script%TAB%<NPC Name>%TAB%-1,{<code>}
/// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>}
/// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>,{<code>}
-static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, bool runOnInit) {
- int x, y, dir = 0, m, xs = 0, ys = 0, class_ = 0; // [Valaris] thanks to fov
+const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval) {
+ int x, y, dir = 0, m, xs = 0, ys = 0; // [Valaris] thanks to fov
char mapname[32];
- struct script_code *script;
+ struct script_code *scriptroot;
int i;
const char* end;
const char* script_start;
@@ -2407,15 +2851,13 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
x = 0;
y = 0;
m = -1;
- }
- else
- {// npc in a map
- if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 )
- {
+ } else {// npc in a map
+ if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 ) {
ShowError("npc_parse_script: Invalid placement format for a script in file '%s', line '%d'. Skipping the rest of file...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// unknown format, don't continue
}
- m = iMap->mapname2mapid(mapname);
+ m = map->mapname2mapid(mapname);
}
script_start = strstr(start,",{");
@@ -2423,34 +2865,33 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
if( strstr(w4,",{") == NULL || script_start == NULL || (end != NULL && script_start > end) )
{
ShowError("npc_parse_script: Missing left curly ',{' in file '%s', line '%d'. Skipping the rest of the file.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
}
++script_start;
- end = npc_skip_script(script_start, buffer, filepath);
+ end = npc->skip_script(script_start, buffer, filepath, retval);
if( end == NULL )
return NULL;// (simple) parse error, don't continue
- script = parse_script(script_start, filepath, strline(buffer,script_start-buffer), SCRIPT_USE_LABEL_DB);
+ scriptroot = script->parse(script_start, filepath, strline(buffer,script_start-buffer), SCRIPT_USE_LABEL_DB, retval);
label_list = NULL;
label_list_num = 0;
- if( script )
- {
- DBMap* label_db = script_get_label_db();
- label_db->foreach(label_db, npc_convertlabel_db, &label_list, &label_list_num, filepath);
- db_clear(label_db); // not needed anymore, so clear the db
+ if( script->label_count ) {
+ CREATE(label_list,struct npc_label_list,script->label_count);
+ label_list_num = script->label_count;
+ npc->convertlabel_db(label_list,filepath);
}
CREATE(nd, struct npc_data, 1);
- if( sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3 )
+ if( sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2 )
{// OnTouch area defined
nd->u.scr.xs = xs;
nd->u.scr.ys = ys;
}
else
{// no OnTouch area
- class_ = atoi(w4);
nd->u.scr.xs = -1;
nd->u.scr.ys = -1;
}
@@ -2459,57 +2900,61 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
nd->bl.m = m;
nd->bl.x = x;
nd->bl.y = y;
- npc_parsename(nd, w3, start, buffer, filepath);
- nd->bl.id = npc_get_new_npc_id();
- nd->class_ = class_;
+ npc->parsename(nd, w3, start, buffer, filepath);
+ nd->bl.id = npc->get_new_npc_id();
+ nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath);
nd->speed = 200;
- nd->u.scr.script = script;
+ nd->u.scr.script = scriptroot;
nd->u.scr.label_list = label_list;
nd->u.scr.label_list_num = label_list_num;
-
+ if( options&NPO_TRADER )
+ nd->u.scr.trader = true;
+ nd->u.scr.shop = NULL;
+
++npc_script;
nd->bl.type = BL_NPC;
nd->subtype = SCRIPT;
if( m >= 0 ) {
- iMap->addnpc(m, nd);
- nd->ud = &npc_base_ud;
+ map->addnpc(m, nd);
+ nd->ud = &npc->base_ud;
nd->dir = dir;
- npc_setcells(nd);
- iMap->addblock(&nd->bl);
- if( class_ >= 0 ) {
- status_set_viewdata(&nd->bl, nd->class_);
- if( map[nd->bl.m].users )
+ npc->setcells(nd);
+ map->addblock(&nd->bl);
+ if( nd->class_ >= 0 ) {
+ status->set_viewdata(&nd->bl, nd->class_);
+ if( map->list[nd->bl.m].users )
clif->spawn(&nd->bl);
}
} else {
- // we skip iMap->addnpc, but still add it to the list of ID's
- iMap->addiddb(&nd->bl);
+ // we skip map->addnpc, but still add it to the list of ID's
+ map->addiddb(&nd->bl);
}
- strdb_put(npcname_db, nd->exname, nd);
+ strdb_put(npc->name_db, nd->exname, nd);
//-----------------------------------------
// Loop through labels to export them as necessary
for (i = 0; i < nd->u.scr.label_list_num; i++) {
- if (npc_event_export(nd, i)) {
- ShowWarning("npc_parse_script : duplicate event %s::%s (%s)\n",
+ if (npc->event_export(nd, i)) {
+ ShowWarning("npc_parse_script: duplicate event %s::%s in file '%s'.\n",
nd->exname, nd->u.scr.label_list[i].name, filepath);
+ if (retval) *retval = EXIT_FAILURE;
}
- npc_timerevent_export(nd, i);
+ npc->timerevent_export(nd, i);
}
nd->u.scr.timerid = INVALID_TIMER;
- if( runOnInit ) {
+ if( options&NPO_ONINIT ) {
char evname[EVENT_NAME_LENGTH];
struct event_data *ev;
snprintf(evname, ARRAYLENGTH(evname), "%s::OnInit", nd->exname);
- if( ( ev = (struct event_data*)strdb_get(ev_db, evname) ) ) {
+ if( ( ev = (struct event_data*)strdb_get(npc->ev_db, evname) ) ) {
//Execute OnInit
- run_script(nd->u.scr.script,ev->pos,0,nd->bl.id);
+ script->run(nd->u.scr.script,ev->pos,0,nd->bl.id);
}
}
@@ -2523,9 +2968,9 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
/// shop/cashshop/npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>
/// npc: -%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>
/// npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>
-const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
-{
- int x, y, dir, m, xs = -1, ys = -1, class_ = 0;
+/// !!Only NPO_ONINIT is available trough options!!
+const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval) {
+ int x, y, dir, m, xs = -1, ys = -1;
char mapname[32];
char srcname[128];
int i;
@@ -2543,14 +2988,16 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
// get the npc being duplicated
if( w2[length-1] != ')' || length <= 11 || length-11 >= sizeof(srcname) )
{// does not match 'duplicate(%127s)', name is empty or too long
- ShowError("npc_parse_script: bad duplicate name in file '%s', line '%d' : %s\n", filepath, strline(buffer,start-buffer), w2);
+ ShowError("npc_parse_script: bad duplicate name in file '%s', line '%d': %s\n", filepath, strline(buffer,start-buffer), w2);
+ if (retval) *retval = EXIT_FAILURE;
return end;// next line, try to continue
}
safestrncpy(srcname, w2+10, length-10);
- dnd = npc_name2id(srcname);
+ dnd = npc->name2id(srcname);
if( dnd == NULL) {
- ShowError("npc_parse_script: original npc not found for duplicate in file '%s', line '%d' : %s\n", filepath, strline(buffer,start-buffer), srcname);
+ ShowError("npc_parse_script: original npc not found for duplicate in file '%s', line '%d': %s\n", filepath, strline(buffer,start-buffer), srcname);
+ if (retval) *retval = EXIT_FAILURE;
return end;// next line, try to continue
}
src_id = dnd->bl.id;
@@ -2561,24 +3008,28 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
x = y = dir = 0;
m = -1;
} else {
- if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 )// <map name>,<x>,<y>,<facing>
- {
+ int fields = sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir);
+ if( type == WARP && fields == 3 ) { // <map name>,<x>,<y>
+ dir = 0;
+ } else if( fields != 4 ) {// <map name>,<x>,<y>,<facing>
ShowError("npc_parse_duplicate: Invalid placement format for duplicate in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return end;// next line, try to continue
}
- m = iMap->mapname2mapid(mapname);
+ m = map->mapname2mapid(mapname);
}
- if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) {
- ShowError("npc_parse_duplicate: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map[m].name, x, y, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer));
+ if( m != -1 && ( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) ) {
+ ShowError("npc_parse_duplicate: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map->list[m].name, x, y, map->list[m].xs, map->list[m].ys,filepath,strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return end;//try next
}
if( type == WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2 );// <spanx>,<spany>
- else if( type == SCRIPT && sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3);// <sprite id>,<triggerX>,<triggerY>
- else if( type != WARP ) class_ = atoi(w4);// <sprite id>
- else {
+ else if( type == SCRIPT && sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2);// <sprite id>,<triggerX>,<triggerY>
+ else if( type == WARP ) {
ShowError("npc_parse_duplicate: Invalid span format for duplicate warp in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return end;// next line, try to continue
}
@@ -2588,9 +3039,9 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
nd->bl.m = m;
nd->bl.x = x;
nd->bl.y = y;
- npc_parsename(nd, w3, start, buffer, filepath);
- nd->bl.id = npc_get_new_npc_id();
- nd->class_ = class_;
+ npc->parsename(nd, w3, start, buffer, filepath);
+ nd->bl.id = npc->get_new_npc_id();
+ nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath);
nd->speed = 200;
nd->src_id = src_id;
nd->bl.type = BL_NPC;
@@ -2603,6 +3054,8 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
nd->u.scr.script = dnd->u.scr.script;
nd->u.scr.label_list = dnd->u.scr.label_list;
nd->u.scr.label_list_num = dnd->u.scr.label_list_num;
+ nd->u.scr.shop = dnd->u.scr.shop;
+ nd->u.scr.trader = dnd->u.scr.trader;
break;
case SHOP:
@@ -2628,21 +3081,21 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
//Add the npc to its location
if( m >= 0 ) {
- iMap->addnpc(m, nd);
- nd->ud = &npc_base_ud;
+ map->addnpc(m, nd);
+ nd->ud = &npc->base_ud;
nd->dir = dir;
- npc_setcells(nd);
- iMap->addblock(&nd->bl);
- if( class_ >= 0 ) {
- status_set_viewdata(&nd->bl, nd->class_);
- if( map[nd->bl.m].users )
+ npc->setcells(nd);
+ map->addblock(&nd->bl);
+ if( nd->class_ >= 0 ) {
+ status->set_viewdata(&nd->bl, nd->class_);
+ if( map->list[nd->bl.m].users )
clif->spawn(&nd->bl);
}
} else {
- // we skip iMap->addnpc, but still add it to the list of ID's
- iMap->addiddb(&nd->bl);
+ // we skip map->addnpc, but still add it to the list of ID's
+ map->addiddb(&nd->bl);
}
- strdb_put(npcname_db, nd->exname, nd);
+ strdb_put(npc->name_db, nd->exname, nd);
if( type != SCRIPT )
return end;
@@ -2650,43 +3103,58 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
//-----------------------------------------
// Loop through labels to export them as necessary
for (i = 0; i < nd->u.scr.label_list_num; i++) {
- if (npc_event_export(nd, i)) {
- ShowWarning("npc_parse_duplicate : duplicate event %s::%s (%s)\n",
+ if (npc->event_export(nd, i)) {
+ ShowWarning("npc_parse_duplicate: duplicate event %s::%s in file '%s'.\n",
nd->exname, nd->u.scr.label_list[i].name, filepath);
+ if (retval) *retval = EXIT_FAILURE;
}
- npc_timerevent_export(nd, i);
+ npc->timerevent_export(nd, i);
}
nd->u.scr.timerid = INVALID_TIMER;
+ if( type == SCRIPT && options&NPO_ONINIT ) {
+ // From npc_parse_script
+ char evname[EVENT_NAME_LENGTH];
+ struct event_data *ev;
+
+ snprintf(evname, ARRAYLENGTH(evname), "%s::OnInit", nd->exname);
+
+ if( ( ev = (struct event_data*)strdb_get(npc->ev_db, evname) ) ) {
+
+ //Execute OnInit
+ script->run(nd->u.scr.script,ev->pos,0,nd->bl.id);
+
+ }
+ }
return end;
}
int npc_duplicate4instance(struct npc_data *snd, int16 m) {
char newname[NAME_LENGTH];
- if( map[m].instance_id == -1 )
+ if( m == -1 || map->list[m].instance_id == -1 )
return 1;
- snprintf(newname, ARRAYLENGTH(newname), "dup_%d_%d", map[m].instance_id, snd->bl.id);
- if( npc_name2id(newname) != NULL ) { // Name already in use
- ShowError("npc_duplicate4instance: the npcname (%s) is already in use while trying to duplicate npc %s in instance %d.\n", newname, snd->exname, map[m].instance_id);
+ snprintf(newname, ARRAYLENGTH(newname), "dup_%d_%d", map->list[m].instance_id, snd->bl.id);
+ if( npc->name2id(newname) != NULL ) { // Name already in use
+ ShowError("npc_duplicate4instance: the npcname (%s) is already in use while trying to duplicate npc %s in instance %d.\n", newname, snd->exname, map->list[m].instance_id);
return 1;
}
if( snd->subtype == WARP ) { // Adjust destination, if instanced
struct npc_data *wnd = NULL; // New NPC
- int dm = iMap->mapindex2mapid(snd->u.warp.mapindex), im;
+ int dm = map->mapindex2mapid(snd->u.warp.mapindex), im;
if( dm < 0 ) return 1;
- if( ( im = instance->mapid2imapid(dm, map[m].instance_id) ) == -1 ) {
- ShowError("npc_duplicate4instance: warp (%s) leading to instanced map (%s), but instance map is not attached to current instance.\n", map[dm].name, snd->exname);
+ if( ( im = instance->mapid2imapid(dm, map->list[m].instance_id) ) == -1 ) {
+ ShowError("npc_duplicate4instance: warp (%s) leading to instanced map (%s), but instance map is not attached to current instance.\n", map->list[dm].name, snd->exname);
return 1;
}
CREATE(wnd, struct npc_data, 1);
- wnd->bl.id = npc_get_new_npc_id();
- iMap->addnpc(m, wnd);
+ wnd->bl.id = npc->get_new_npc_id();
+ map->addnpc(m, wnd);
wnd->bl.prev = wnd->bl.next = NULL;
wnd->bl.m = m;
wnd->bl.x = snd->bl.x;
@@ -2702,18 +3170,18 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
wnd->u.warp.ys = snd->u.warp.ys;
wnd->bl.type = BL_NPC;
wnd->subtype = WARP;
- npc_setcells(wnd);
- iMap->addblock(&wnd->bl);
- status_set_viewdata(&wnd->bl, wnd->class_);
- wnd->ud = &npc_base_ud;
- if( map[wnd->bl.m].users )
+ npc->setcells(wnd);
+ map->addblock(&wnd->bl);
+ status->set_viewdata(&wnd->bl, wnd->class_);
+ wnd->ud = &npc->base_ud;
+ if( map->list[wnd->bl.m].users )
clif->spawn(&wnd->bl);
- strdb_put(npcname_db, wnd->exname, wnd);
+ strdb_put(npc->name_db, wnd->exname, wnd);
} else {
static char w1[50], w2[50], w3[50], w4[50];
const char* stat_buf = "- call from instancing subsystem -\n";
- snprintf(w1, sizeof(w1), "%s,%d,%d,%d", map[m].name, snd->bl.x, snd->bl.y, snd->dir);
+ snprintf(w1, sizeof(w1), "%s,%d,%d,%d", map->list[m].name, snd->bl.x, snd->bl.y, snd->dir);
snprintf(w2, sizeof(w2), "duplicate(%s)", snd->exname);
snprintf(w3, sizeof(w3), "%s::%s", snd->name, newname);
@@ -2722,7 +3190,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
else
snprintf(w4, sizeof(w4), "%d", snd->class_);
- npc_parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "INSTANCING");
+ npc->parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "INSTANCING", NPO_NONE, NULL);
}
return 0;
@@ -2746,14 +3214,14 @@ void npc_setcells(struct npc_data* nd) {
return; // Other types doesn't have touch area
}
- if (m < 0 || xs < 0 || ys < 0 || map[m].cell == (struct mapcell *)0xdeadbeaf) //invalid range or map
+ if (m < 0 || xs < 0 || ys < 0 || map->list[m].cell == (struct mapcell *)0xdeadbeaf) //invalid range or map
return;
for (i = y-ys; i <= y+ys; i++) {
for (j = x-xs; j <= x+xs; j++) {
- if (iMap->getcell(m, j, i, CELL_CHKNOPASS))
+ if (map->getcell(m, j, i, CELL_CHKNOPASS))
continue;
- map[m].setcell(m, j, i, CELL_NPC, true);
+ map->list[m].setcell(m, j, i, CELL_NPC, true);
}
}
}
@@ -2762,7 +3230,7 @@ int npc_unsetcells_sub(struct block_list* bl, va_list ap) {
struct npc_data *nd = (struct npc_data*)bl;
int id = va_arg(ap,int);
if (nd->bl.id == id) return 0;
- npc_setcells(nd);
+ npc->setcells(nd);
return 1;
}
@@ -2770,44 +3238,49 @@ void npc_unsetcells(struct npc_data* nd) {
int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys;
int i,j, x0, x1, y0, y1;
- if (nd->subtype == WARP) {
- xs = nd->u.warp.xs;
- ys = nd->u.warp.ys;
- } else {
- xs = nd->u.scr.xs;
- ys = nd->u.scr.ys;
+ switch(nd->subtype) {
+ case WARP:
+ xs = nd->u.warp.xs;
+ ys = nd->u.warp.ys;
+ break;
+ case SCRIPT:
+ xs = nd->u.scr.xs;
+ ys = nd->u.scr.ys;
+ break;
+ default:
+ return; // Other types doesn't have touch area
}
- if (m < 0 || xs < 0 || ys < 0 || map[m].cell == (struct mapcell *)0xdeadbeaf)
+ if (m < 0 || xs < 0 || ys < 0 || map->list[m].cell == (struct mapcell *)0xdeadbeaf)
return;
//Locate max range on which we can locate npc cells
//FIXME: does this really do what it's supposed to do? [ultramage]
- for(x0 = x-xs; x0 > 0 && iMap->getcell(m, x0, y, CELL_CHKNPC); x0--);
- for(x1 = x+xs; x1 < map[m].xs-1 && iMap->getcell(m, x1, y, CELL_CHKNPC); x1++);
- for(y0 = y-ys; y0 > 0 && iMap->getcell(m, x, y0, CELL_CHKNPC); y0--);
- for(y1 = y+ys; y1 < map[m].ys-1 && iMap->getcell(m, x, y1, CELL_CHKNPC); y1++);
+ for(x0 = x-xs; x0 > 0 && map->getcell(m, x0, y, CELL_CHKNPC); x0--);
+ for(x1 = x+xs; x1 < map->list[m].xs-1 && map->getcell(m, x1, y, CELL_CHKNPC); x1++);
+ for(y0 = y-ys; y0 > 0 && map->getcell(m, x, y0, CELL_CHKNPC); y0--);
+ for(y1 = y+ys; y1 < map->list[m].ys-1 && map->getcell(m, x, y1, CELL_CHKNPC); y1++);
//Erase this npc's cells
for (i = y-ys; i <= y+ys; i++)
for (j = x-xs; j <= x+xs; j++)
- map[m].setcell(m, j, i, CELL_NPC, false);
+ map->list[m].setcell(m, j, i, CELL_NPC, false);
//Re-deploy NPC cells for other nearby npcs.
- iMap->foreachinarea( npc_unsetcells_sub, m, x0, y0, x1, y1, BL_NPC, nd->bl.id );
+ map->foreachinarea( npc->unsetcells_sub, m, x0, y0, x1, y1, BL_NPC, nd->bl.id );
}
void npc_movenpc(struct npc_data* nd, int16 x, int16 y)
{
const int16 m = nd->bl.m;
- if (m < 0 || nd->bl.prev == NULL) return; //Not on a map.
+ if (m < 0 || nd->bl.prev == NULL) return; //Not on a map.
- x = cap_value(x, 0, map[m].xs-1);
- y = cap_value(y, 0, map[m].ys-1);
+ x = cap_value(x, 0, map->list[m].xs-1);
+ y = cap_value(y, 0, map->list[m].ys-1);
- iMap->foreachinrange(clif->outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl);
- iMap->moveblock(&nd->bl, x, y, iTimer->gettick());
- iMap->foreachinrange(clif->insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl);
+ map->foreachinrange(clif->outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl);
+ map->moveblock(&nd->bl, x, y, timer->gettick());
+ map->foreachinrange(clif->insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl);
}
/// Changes the display name of the npc.
@@ -2819,7 +3292,7 @@ void npc_setdisplayname(struct npc_data* nd, const char* newname)
nullpo_retv(nd);
safestrncpy(nd->name, newname, sizeof(nd->name));
- if( map[nd->bl.m].users )
+ if( map->list[nd->bl.m].users )
clif->charnameack(0, &nd->bl);
}
@@ -2827,25 +3300,24 @@ void npc_setdisplayname(struct npc_data* nd, const char* newname)
///
/// @param nd Target npc
/// @param class_ New display class
-void npc_setclass(struct npc_data* nd, short class_)
-{
+void npc_setclass(struct npc_data* nd, short class_) {
nullpo_retv(nd);
if( nd->class_ == class_ )
return;
- if( map[nd->bl.m].users )
+ if( map->list[nd->bl.m].users )
clif->clearunit_area(&nd->bl, CLR_OUTSIGHT);// fade out
nd->class_ = class_;
- status_set_viewdata(&nd->bl, class_);
- if( map[nd->bl.m].users )
+ status->set_viewdata(&nd->bl, class_);
+ if( map->list[nd->bl.m].users )
clif->spawn(&nd->bl);// fade in
}
// @commands (script based)
int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const char* message, const char* eventname)
{
- struct event_data* ev = (struct event_data*)strdb_get(ev_db, eventname);
+ struct event_data* ev = (struct event_data*)strdb_get(npc->ev_db, eventname);
struct npc_data *nd;
struct script_state *st;
int i = 0, j = 0, k = 0;
@@ -2859,7 +3331,6 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
}
if( sd->npc_id != 0 ) { // Enqueue the event trigger.
- int i;
ARR_FIND( 0, MAX_EVENTQUEUE, i, sd->eventqueue[i][0] == '\0' );
if( i < MAX_EVENTQUEUE ) {
safestrncpy(sd->eventqueue[i],eventname,50); //Event enqueued.
@@ -2871,12 +3342,12 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
}
if( ev->nd->option&OPTION_INVISIBLE ) { // Disabled npc, shouldn't trigger event.
- npc_event_dequeue(sd);
+ npc->event_dequeue(sd);
return 2;
}
- st = script_alloc_state(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);
- setd_sub(st, NULL, ".@atcmd_command$", 0, (void *)command, NULL);
+ st = script->alloc_state(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);
+ script->setd_sub(st, NULL, ".@atcmd_command$", 0, (void *)command, NULL);
// split atcmd parameters based on spaces
temp = (char*)aMalloc(strlen(message) + 1);
@@ -2889,7 +3360,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
temp[k] = '\0';
k = 0;
if( temp[0] != '\0' ) {
- setd_sub( st, NULL, ".@atcmd_parameters$", j++, (void *)temp, NULL );
+ script->setd_sub( st, NULL, ".@atcmd_parameters$", j++, (void *)temp, NULL );
}
} else {
temp[k] = message[i];
@@ -2897,46 +3368,44 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
}
}
- setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)__64BPTRSIZE(j), NULL);
+ script->setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)h64BPTRSIZE(j), NULL);
aFree(temp);
- run_script_main(st);
+ script->run_main(st);
return 0;
}
/// Parses a function.
/// function%TAB%script%TAB%<function name>%TAB%{<code>}
-static const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
-{
+const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) {
DBMap* func_db;
DBData old_data;
- struct script_code *script;
+ struct script_code *scriptroot;
const char* end;
const char* script_start;
script_start = strstr(start,"\t{");
end = strchr(start,'\n');
- if( *w4 != '{' || script_start == NULL || (end != NULL && script_start > end) )
- {
+ if( *w4 != '{' || script_start == NULL || (end != NULL && script_start > end) ) {
ShowError("npc_parse_function: Missing left curly '%%TAB%%{' in file '%s', line '%d'. Skipping the rest of the file.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return NULL;// can't continue
}
++script_start;
- end = npc_skip_script(script_start,buffer,filepath);
+ end = npc->skip_script(script_start,buffer,filepath, retval);
if( end == NULL )
return NULL;// (simple) parse error, don't continue
- script = parse_script(script_start, filepath, strline(buffer,start-buffer), SCRIPT_RETURN_EMPTY_SCRIPT);
- if( script == NULL )// parse error, continue
+ scriptroot = script->parse(script_start, filepath, strline(buffer,start-buffer), SCRIPT_RETURN_EMPTY_SCRIPT, retval);
+ if( scriptroot == NULL )// parse error, continue
return end;
- func_db = script_get_userfunc_db();
- if (func_db->put(func_db, DB->str2key(w3), DB->ptr2data(script), &old_data))
- {
+ func_db = script->userfunc_db;
+ if (func_db->put(func_db, DB->str2key(w3), DB->ptr2data(scriptroot), &old_data)) {
struct script_code *oldscript = (struct script_code*)DB->data2ptr(&old_data);
- ShowInfo("npc_parse_function: Overwriting user function [%s] (%s:%d)\n", w3, filepath, strline(buffer,start-buffer));
- script_free_vars(oldscript->script_vars);
+ ShowWarning("npc_parse_function: Overwriting user function [%s] in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
+ script->free_vars(oldscript->local.vars);
aFree(oldscript->script_buf);
aFree(oldscript);
}
@@ -2950,143 +3419,142 @@ static const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, co
* Parse Mob 2 - Actually Spawns Mob
* [Wizputer]
*------------------------------------------*/
-void npc_parse_mob2(struct spawn_data* mob)
+void npc_parse_mob2(struct spawn_data* mobspawn)
{
int i;
- for( i = mob->active; i < mob->num; ++i ) {
- struct mob_data* md = mob_spawn_dataset(mob);
- md->spawn = mob;
+ for( i = mobspawn->active; i < mobspawn->num; ++i ) {
+ struct mob_data* md = mob->spawn_dataset(mobspawn);
+ md->spawn = mobspawn;
md->spawn->active++;
- mob_spawn(md);
+ mob->spawn(md);
}
}
-static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
-{
+const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) {
int num, class_, m,x,y,xs,ys, i,j;
int mob_lv = -1, ai = -1, size = -1;
char mapname[32], mobname[NAME_LENGTH];
- struct spawn_data mob, *data;
+ struct spawn_data mobspawn, *data;
struct mob_db* db;
- memset(&mob, 0, sizeof(struct spawn_data));
+ memset(&mobspawn, 0, sizeof(struct spawn_data));
- mob.state.boss = !strcmpi(w2,"boss_monster");
+ mobspawn.state.boss = (strcmp(w2,"boss_monster") == 0 ? 1 : 0);
// w1=<map name>,<x>,<y>,<xs>,<ys>
// w3=<mob name>{,<mob level>}
// w4=<mob id>,<amount>,<delay1>,<delay2>,<event>{,<mob size>,<mob ai>}
if( sscanf(w1, "%31[^,],%d,%d,%d,%d", mapname, &x, &y, &xs, &ys) < 3
- || sscanf(w3, "%23[^,],%d", mobname, &mob_lv) < 1
- || sscanf(w4, "%d,%d,%u,%u,%127[^,],%d,%d[^\t\r\n]", &class_, &num, &mob.delay1, &mob.delay2, mob.eventname, &size, &ai) < 2 )
- {
+ || sscanf(w3, "%23[^,],%d", mobname, &mob_lv) < 1
+ || sscanf(w4, "%d,%d,%u,%u,%127[^,],%d,%d[^\t\r\n]", &class_, &num, &mobspawn.delay1, &mobspawn.delay2, mobspawn.eventname, &size, &ai) < 2
+ ) {
ShowError("npc_parse_mob: Invalid mob definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
- if( mapindex_name2id(mapname) == 0 )
- {
+ if( mapindex->name2id(mapname) == 0 ) {
ShowError("npc_parse_mob: Unknown map '%s' in file '%s', line '%d'.\n", mapname, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
- m = iMap->mapname2mapid(mapname);
+ m = map->mapname2mapid(mapname);
if( m < 0 )//Not loaded on this map-server instance.
return strchr(start,'\n');// skip and continue
- mob.m = (unsigned short)m;
+ mobspawn.m = (unsigned short)m;
- if( x < 0 || x >= map[mob.m].xs || y < 0 || y >= map[mob.m].ys )
- {
- ShowError("npc_parse_mob: Spawn coordinates out of range: %s (%d,%d), map size is (%d,%d) - %s %s (file '%s', line '%d').\n", map[mob.m].name, x, y, (map[mob.m].xs-1), (map[mob.m].ys-1), w1, w3, filepath, strline(buffer,start-buffer));
+ if( x < 0 || x >= map->list[mobspawn.m].xs || y < 0 || y >= map->list[mobspawn.m].ys ) {
+ ShowError("npc_parse_mob: Spawn coordinates out of range: %s (%d,%d), map size is (%d,%d) - %s %s in file '%s', line '%d'.\n", map->list[mobspawn.m].name, x, y, (map->list[mobspawn.m].xs-1), (map->list[mobspawn.m].ys-1), w1, w3, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
// check monster ID if exists!
- if( mobdb_checkid(class_) == 0 )
- {
- ShowError("npc_parse_mob: Unknown mob ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer));
+ if( mob->db_checkid(class_) == 0 ) {
+ ShowError("npc_parse_mob: Unknown mob ID %d in file '%s', line '%d'.\n", class_, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
- if( num < 1 || num > 1000 )
- {
- ShowError("npc_parse_mob: Invalid number of monsters %d, must be inside the range [1,1000] (file '%s', line '%d').\n", num, filepath, strline(buffer,start-buffer));
+ if( num < 1 || num > 1000 ) {
+ ShowError("npc_parse_mob: Invalid number of monsters %d, must be inside the range [1,1000] in file '%s', line '%d'.\n", num, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
- if( (mob.state.size < 0 || mob.state.size > 2) && size != -1 )
- {
- ShowError("npc_parse_mob: Invalid size number %d for mob ID %d (file '%s', line '%d').\n", mob.state.size, class_, filepath, strline(buffer, start - buffer));
+ if( (mobspawn.state.size < 0 || mobspawn.state.size > 2) && size != -1 ) {
+ ShowError("npc_parse_mob: Invalid size number %d for mob ID %d in file '%s', line '%d'.\n", mobspawn.state.size, class_, filepath, strline(buffer, start - buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start, '\n');
}
- if( (mob.state.ai < 0 || mob.state.ai > 4) && ai != -1 )
- {
- ShowError("npc_parse_mob: Invalid ai %d for mob ID %d (file '%s', line '%d').\n", mob.state.ai, class_, filepath, strline(buffer, start - buffer));
+ if( (mobspawn.state.ai < 0 || mobspawn.state.ai > 4) && ai != -1 ) {
+ ShowError("npc_parse_mob: Invalid ai %d for mob ID %d in file '%s', line '%d'.\n", mobspawn.state.ai, class_, filepath, strline(buffer, start - buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start, '\n');
}
- if( (mob_lv == 0 || mob_lv > MAX_LEVEL) && mob_lv != -1 )
- {
- ShowError("npc_parse_mob: Invalid level %d for mob ID %d (file '%s', line '%d').\n", mob_lv, class_, filepath, strline(buffer, start - buffer));
+ if( (mob_lv == 0 || mob_lv > MAX_LEVEL) && mob_lv != -1 ) {
+ ShowError("npc_parse_mob: Invalid level %d for mob ID %d in file '%s', line '%d'.\n", mob_lv, class_, filepath, strline(buffer, start - buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start, '\n');
}
- mob.num = (unsigned short)num;
- mob.active = 0;
- mob.class_ = (short) class_;
- mob.x = (unsigned short)x;
- mob.y = (unsigned short)y;
- mob.xs = (signed short)xs;
- mob.ys = (signed short)ys;
+ mobspawn.num = (unsigned short)num;
+ mobspawn.active = 0;
+ mobspawn.class_ = (short) class_;
+ mobspawn.x = (unsigned short)x;
+ mobspawn.y = (unsigned short)y;
+ mobspawn.xs = (signed short)xs;
+ mobspawn.ys = (signed short)ys;
if (mob_lv > 0 && mob_lv <= MAX_LEVEL)
- mob.level = mob_lv;
+ mobspawn.level = mob_lv;
if (size > 0 && size <= 2)
- mob.state.size = size;
+ mobspawn.state.size = size;
if (ai > 0 && ai <= 4)
- mob.state.ai = ai;
+ mobspawn.state.ai = ai;
- if (mob.num > 1 && battle_config.mob_count_rate != 100) {
- if ((mob.num = mob.num * battle_config.mob_count_rate / 100) < 1)
- mob.num = 1;
+ if (mobspawn.num > 1 && battle_config.mob_count_rate != 100) {
+ if ((mobspawn.num = mobspawn.num * battle_config.mob_count_rate / 100) < 1)
+ mobspawn.num = 1;
}
- if (battle_config.force_random_spawn || (mob.x == 0 && mob.y == 0))
- { //Force a random spawn anywhere on the map.
- mob.x = mob.y = 0;
- mob.xs = mob.ys = -1;
+ if (battle_config.force_random_spawn || (mobspawn.x == 0 && mobspawn.y == 0)) {
+ //Force a random spawn anywhere on the map.
+ mobspawn.x = mobspawn.y = 0;
+ mobspawn.xs = mobspawn.ys = -1;
}
- if(mob.delay1>0xfffffff || mob.delay2>0xfffffff) {
- ShowError("npc_parse_mob: Invalid spawn delays %u %u (file '%s', line '%d').\n", mob.delay1, mob.delay2, filepath, strline(buffer,start-buffer));
+ if(mobspawn.delay1>0xfffffff || mobspawn.delay2>0xfffffff) {
+ ShowError("npc_parse_mob: Invalid spawn delays %u %u in file '%s', line '%d'.\n", mobspawn.delay1, mobspawn.delay2, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
//Use db names instead of the spawn file ones.
if(battle_config.override_mob_names==1)
- strcpy(mob.name,"--en--");
+ strcpy(mobspawn.name,"--en--");
else if (battle_config.override_mob_names==2)
- strcpy(mob.name,"--ja--");
+ strcpy(mobspawn.name,"--ja--");
else
- safestrncpy(mob.name, mobname, sizeof(mob.name));
+ safestrncpy(mobspawn.name, mobname, sizeof(mobspawn.name));
//Verify dataset.
- if( !mob_parse_dataset(&mob) )
- {
- ShowError("npc_parse_mob: Invalid dataset for monster ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer));
+ if( !mob->parse_dataset(&mobspawn) ) {
+ ShowError("npc_parse_mob: Invalid dataset for monster ID %d in file '%s', line '%d'.\n", class_, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
//Update mob spawn lookup database
- db = mob_db(class_);
- for( i = 0; i < ARRAYLENGTH(db->spawn); ++i )
- {
- if (map[mob.m].index == db->spawn[i].mapindex)
- { //Update total
- db->spawn[i].qty += mob.num;
+ db = mob->db(class_);
+ for( i = 0; i < ARRAYLENGTH(db->spawn); ++i ) {
+ if (map_id2index(mobspawn.m) == db->spawn[i].mapindex) {
+ //Update total
+ db->spawn[i].qty += mobspawn.num;
//Re-sort list
for( j = i; j > 0 && db->spawn[j-1].qty < db->spawn[i].qty; --j );
- if( j != i )
- {
+ if( j != i ) {
xs = db->spawn[i].mapindex;
ys = db->spawn[i].qty;
memmove(&db->spawn[j+1], &db->spawn[j], (i-j)*sizeof(db->spawn[0]));
@@ -3095,33 +3563,33 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
}
break;
}
- if (mob.num > db->spawn[i].qty)
- { //Insert into list
+ if (mobspawn.num > db->spawn[i].qty) {
+ //Insert into list
memmove(&db->spawn[i+1], &db->spawn[i], sizeof(db->spawn) -(i+1)*sizeof(db->spawn[0]));
- db->spawn[i].mapindex = map[mob.m].index;
- db->spawn[i].qty = mob.num;
+ db->spawn[i].mapindex = map_id2index(mobspawn.m);
+ db->spawn[i].qty = mobspawn.num;
break;
}
}
//Now that all has been validated. We allocate the actual memory that the re-spawn data will use.
data = (struct spawn_data*)aMalloc(sizeof(struct spawn_data));
- memcpy(data, &mob, sizeof(struct spawn_data));
+ memcpy(data, &mobspawn, sizeof(struct spawn_data));
// spawn / cache the new mobs
- if( battle_config.dynamic_mobs && iMap->addmobtolist(data->m, data) >= 0 ) {
+ if( battle_config.dynamic_mobs && map->addmobtolist(data->m, data) >= 0 ) {
data->state.dynamic = true;
npc_cache_mob += data->num;
// check if target map has players
// (usually shouldn't occur when map server is just starting,
// but not the case when we do @reloadscript
- if( map[data->m].users > 0 ) {
- npc_parse_mob2(data);
+ if( map->list[data->m].users > 0 ) {
+ npc->parse_mob2(data);
}
} else {
data->state.dynamic = false;
- npc_parse_mob2(data);
+ npc->parse_mob2(data);
npc_delay_mob += data->num;
}
@@ -3134,7 +3602,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
* eg : bat_c01 mapflag battleground 2
* also chking if mapflag conflict with another
*------------------------------------------*/
-const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) {
+const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) {
int16 m;
char mapname[32];
int state = 1;
@@ -3143,12 +3611,14 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
if( sscanf(w1, "%31[^,]", mapname) != 1 )
{
ShowError("npc_parse_mapflag: Invalid mapflag definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
- m = iMap->mapname2mapid(mapname);
- if( m < 0 )
- {
- ShowWarning("npc_parse_mapflag: Unknown map in file '%s', line '%d' : %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", mapname, filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ m = map->mapname2mapid(mapname);
+ if (m < 0) {
+ ShowWarning("npc_parse_mapflag: Unknown map in file '%s', line '%d': %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n",
+ filepath, strline(buffer,start-buffer), mapname, w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
return strchr(start,'\n');// skip and continue
}
@@ -3160,77 +3630,80 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
int savex, savey;
if (state == 0)
; //Map flag disabled.
- else if (!strcmpi(w4, "SavePoint")) {
- map[m].save.map = 0;
- map[m].save.x = -1;
- map[m].save.y = -1;
+ else if (w4 && !strcmpi(w4, "SavePoint")) {
+ map->list[m].save.map = 0;
+ map->list[m].save.x = -1;
+ map->list[m].save.y = -1;
} else if (sscanf(w4, "%31[^,],%d,%d", savemap, &savex, &savey) == 3) {
- map[m].save.map = mapindex_name2id(savemap);
- map[m].save.x = savex;
- map[m].save.y = savey;
- if (!map[m].save.map) {
- ShowWarning("npc_parse_mapflag: Specified save point map '%s' for mapflag 'nosave' not found (file '%s', line '%d'), using 'SavePoint'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", savemap, filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
- map[m].save.x = -1;
- map[m].save.y = -1;
+ map->list[m].save.map = mapindex->name2id(savemap);
+ map->list[m].save.x = savex;
+ map->list[m].save.y = savey;
+ if (!map->list[m].save.map) {
+ ShowWarning("npc_parse_mapflag: Specified save point map '%s' for mapflag 'nosave' not found in file '%s', line '%d', using 'SavePoint'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", savemap, filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ if (retval) *retval = EXIT_FAILURE;
+ map->list[m].save.x = -1;
+ map->list[m].save.y = -1;
}
}
- map[m].flag.nosave = state;
+ map->list[m].flag.nosave = state;
}
else if (!strcmpi(w3,"autotrade"))
- map[m].flag.autotrade=state;
+ map->list[m].flag.autotrade=state;
else if (!strcmpi(w3,"allowks"))
- map[m].flag.allowks=state; // [Kill Steal Protection]
+ map->list[m].flag.allowks=state; // [Kill Steal Protection]
else if (!strcmpi(w3,"town"))
- map[m].flag.town=state;
+ map->list[m].flag.town=state;
else if (!strcmpi(w3,"nomemo"))
- map[m].flag.nomemo=state;
+ map->list[m].flag.nomemo=state;
else if (!strcmpi(w3,"noteleport"))
- map[m].flag.noteleport=state;
+ map->list[m].flag.noteleport=state;
else if (!strcmpi(w3,"nowarp"))
- map[m].flag.nowarp=state;
+ map->list[m].flag.nowarp=state;
else if (!strcmpi(w3,"nowarpto"))
- map[m].flag.nowarpto=state;
+ map->list[m].flag.nowarpto=state;
else if (!strcmpi(w3,"noreturn"))
- map[m].flag.noreturn=state;
+ map->list[m].flag.noreturn=state;
else if (!strcmpi(w3,"monster_noteleport"))
- map[m].flag.monster_noteleport=state;
+ map->list[m].flag.monster_noteleport=state;
else if (!strcmpi(w3,"nobranch"))
- map[m].flag.nobranch=state;
+ map->list[m].flag.nobranch=state;
else if (!strcmpi(w3,"nopenalty")) {
- map[m].flag.noexppenalty=state;
- map[m].flag.nozenypenalty=state;
+ map->list[m].flag.noexppenalty=state;
+ map->list[m].flag.nozenypenalty=state;
}
else if (!strcmpi(w3,"pvp")) {
struct map_zone_data *zone;
- map[m].flag.pvp = state;
- if( state && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) ) {
- map[m].flag.gvg = 0;
- map[m].flag.gvg_dungeon = 0;
- map[m].flag.gvg_castle = 0;
- ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
- }
- if( state && map[m].flag.battleground ) {
- map[m].flag.battleground = 0;
- ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
- }
- if( state && (zone = strdb_get(zone_db, MAP_ZONE_PVP_NAME)) && map[m].zone != zone ) {
- iMap->zone_change(m,zone,start,buffer,filepath);
+ map->list[m].flag.pvp = state;
+ if( state && (map->list[m].flag.gvg || map->list[m].flag.gvg_dungeon || map->list[m].flag.gvg_castle) ) {
+ map->list[m].flag.gvg = 0;
+ map->list[m].flag.gvg_dungeon = 0;
+ map->list[m].flag.gvg_castle = 0;
+ ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
+ }
+ if( state && map->list[m].flag.battleground ) {
+ map->list[m].flag.battleground = 0;
+ ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
+ }
+ if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)) && map->list[m].zone != zone ) {
+ map->zone_change(m,zone,start,buffer,filepath);
} else if ( !state ) {
- map[m].zone = &map_zone_pk;
+ map->list[m].zone = &map->zone_pk;
}
}
else if (!strcmpi(w3,"pvp_noparty"))
- map[m].flag.pvp_noparty=state;
+ map->list[m].flag.pvp_noparty=state;
else if (!strcmpi(w3,"pvp_noguild"))
- map[m].flag.pvp_noguild=state;
+ map->list[m].flag.pvp_noguild=state;
else if (!strcmpi(w3, "pvp_nightmaredrop")) {
char drop_arg1[16], drop_arg2[16];
int drop_per = 0;
- if (sscanf(w4, "%[^,],%[^,],%d", drop_arg1, drop_arg2, &drop_per) == 3) {
+ if (sscanf(w4, "%15[^,],%15[^,],%d", drop_arg1, drop_arg2, &drop_per) == 3) {
int drop_id = 0, drop_type = 0;
if (!strcmpi(drop_arg1, "random"))
drop_id = -1;
- else if (itemdb_exists((drop_id = atoi(drop_arg1))) == NULL)
+ else if (itemdb->exists((drop_id = atoi(drop_arg1))) == NULL)
drop_id = 0;
if (!strcmpi(drop_arg2, "inventory"))
drop_type = 1;
@@ -3240,150 +3713,157 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
drop_type = 3;
if (drop_id != 0) {
- RECREATE(map[m].drop_list, struct map_drop_list, ++map[m].drop_list_count);
- map[m].drop_list[map[m].drop_list_count-1].drop_id = drop_id;
- map[m].drop_list[map[m].drop_list_count-1].drop_type = drop_type;
- map[m].drop_list[map[m].drop_list_count-1].drop_per = drop_per;
- map[m].flag.pvp_nightmaredrop = 1;
+ RECREATE(map->list[m].drop_list, struct map_drop_list, ++map->list[m].drop_list_count);
+ map->list[m].drop_list[map->list[m].drop_list_count-1].drop_id = drop_id;
+ map->list[m].drop_list[map->list[m].drop_list_count-1].drop_type = drop_type;
+ map->list[m].drop_list[map->list[m].drop_list_count-1].drop_per = drop_per;
+ map->list[m].flag.pvp_nightmaredrop = 1;
}
} else if (!state) //Disable
- map[m].flag.pvp_nightmaredrop = 0;
+ map->list[m].flag.pvp_nightmaredrop = 0;
}
else if (!strcmpi(w3,"pvp_nocalcrank"))
- map[m].flag.pvp_nocalcrank=state;
+ map->list[m].flag.pvp_nocalcrank=state;
else if (!strcmpi(w3,"gvg")) {
struct map_zone_data *zone;
- map[m].flag.gvg = state;
- if( state && map[m].flag.pvp ) {
- map[m].flag.pvp = 0;
- ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+ map->list[m].flag.gvg = state;
+ if( state && map->list[m].flag.pvp ) {
+ map->list[m].flag.pvp = 0;
+ ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
- if( state && map[m].flag.battleground ) {
- map[m].flag.battleground = 0;
- ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+ if( state && map->list[m].flag.battleground ) {
+ map->list[m].flag.battleground = 0;
+ ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
- if( state && (zone = strdb_get(zone_db, MAP_ZONE_GVG_NAME)) && map[m].zone != zone ) {
- iMap->zone_change(m,zone,start,buffer,filepath);
+ if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_GVG_NAME)) && map->list[m].zone != zone ) {
+ map->zone_change(m,zone,start,buffer,filepath);
}
}
else if (!strcmpi(w3,"gvg_noparty"))
- map[m].flag.gvg_noparty=state;
+ map->list[m].flag.gvg_noparty=state;
else if (!strcmpi(w3,"gvg_dungeon")) {
- map[m].flag.gvg_dungeon=state;
- if (state) map[m].flag.pvp=0;
+ map->list[m].flag.gvg_dungeon=state;
+ if (state) map->list[m].flag.pvp=0;
}
else if (!strcmpi(w3,"gvg_castle")) {
- map[m].flag.gvg_castle=state;
- if (state) map[m].flag.pvp=0;
+ map->list[m].flag.gvg_castle=state;
+ if (state) map->list[m].flag.pvp=0;
}
else if (!strcmpi(w3,"battleground")) {
struct map_zone_data *zone;
if( state ) {
if( sscanf(w4, "%d", &state) == 1 )
- map[m].flag.battleground = state;
+ map->list[m].flag.battleground = state;
else
- map[m].flag.battleground = 1; // Default value
+ map->list[m].flag.battleground = 1; // Default value
} else
- map[m].flag.battleground = 0;
+ map->list[m].flag.battleground = 0;
- if( map[m].flag.battleground && map[m].flag.pvp ) {
- map[m].flag.pvp = 0;
- ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+ if( map->list[m].flag.battleground && map->list[m].flag.pvp ) {
+ map->list[m].flag.pvp = 0;
+ ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing PvP flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
- if( map[m].flag.battleground && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) ) {
- map[m].flag.gvg = 0;
- map[m].flag.gvg_dungeon = 0;
- map[m].flag.gvg_castle = 0;
- ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+ if( map->list[m].flag.battleground && (map->list[m].flag.gvg || map->list[m].flag.gvg_dungeon || map->list[m].flag.gvg_castle) ) {
+ map->list[m].flag.gvg = 0;
+ map->list[m].flag.gvg_dungeon = 0;
+ map->list[m].flag.gvg_castle = 0;
+ ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
}
- if( state && (zone = strdb_get(zone_db, MAP_ZONE_BG_NAME)) && map[m].zone != zone ) {
- iMap->zone_change(m,zone,start,buffer,filepath);
+ if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_BG_NAME)) && map->list[m].zone != zone ) {
+ map->zone_change(m,zone,start,buffer,filepath);
}
}
else if (!strcmpi(w3,"noexppenalty"))
- map[m].flag.noexppenalty=state;
+ map->list[m].flag.noexppenalty=state;
else if (!strcmpi(w3,"nozenypenalty"))
- map[m].flag.nozenypenalty=state;
+ map->list[m].flag.nozenypenalty=state;
else if (!strcmpi(w3,"notrade"))
- map[m].flag.notrade=state;
+ map->list[m].flag.notrade=state;
else if (!strcmpi(w3,"novending"))
- map[m].flag.novending=state;
+ map->list[m].flag.novending=state;
else if (!strcmpi(w3,"nodrop"))
- map[m].flag.nodrop=state;
+ map->list[m].flag.nodrop=state;
else if (!strcmpi(w3,"noskill"))
- map[m].flag.noskill=state;
+ map->list[m].flag.noskill=state;
else if (!strcmpi(w3,"noicewall"))
- map[m].flag.noicewall=state;
+ map->list[m].flag.noicewall=state;
else if (!strcmpi(w3,"snow"))
- map[m].flag.snow=state;
+ map->list[m].flag.snow=state;
else if (!strcmpi(w3,"clouds"))
- map[m].flag.clouds=state;
+ map->list[m].flag.clouds=state;
else if (!strcmpi(w3,"clouds2"))
- map[m].flag.clouds2=state;
+ map->list[m].flag.clouds2=state;
else if (!strcmpi(w3,"fog"))
- map[m].flag.fog=state;
+ map->list[m].flag.fog=state;
else if (!strcmpi(w3,"fireworks"))
- map[m].flag.fireworks=state;
+ map->list[m].flag.fireworks=state;
else if (!strcmpi(w3,"sakura"))
- map[m].flag.sakura=state;
+ map->list[m].flag.sakura=state;
else if (!strcmpi(w3,"leaves"))
- map[m].flag.leaves=state;
+ map->list[m].flag.leaves=state;
else if (!strcmpi(w3,"nightenabled"))
- map[m].flag.nightenabled=state;
+ map->list[m].flag.nightenabled=state;
else if (!strcmpi(w3,"noexp")) {
- map[m].flag.nobaseexp=state;
- map[m].flag.nojobexp=state;
+ map->list[m].flag.nobaseexp=state;
+ map->list[m].flag.nojobexp=state;
}
else if (!strcmpi(w3,"nobaseexp"))
- map[m].flag.nobaseexp=state;
+ map->list[m].flag.nobaseexp=state;
else if (!strcmpi(w3,"nojobexp"))
- map[m].flag.nojobexp=state;
+ map->list[m].flag.nojobexp=state;
else if (!strcmpi(w3,"noloot")) {
- map[m].flag.nomobloot=state;
- map[m].flag.nomvploot=state;
+ map->list[m].flag.nomobloot=state;
+ map->list[m].flag.nomvploot=state;
}
else if (!strcmpi(w3,"nomobloot"))
- map[m].flag.nomobloot=state;
+ map->list[m].flag.nomobloot=state;
else if (!strcmpi(w3,"nomvploot"))
- map[m].flag.nomvploot=state;
+ map->list[m].flag.nomvploot=state;
else if (!strcmpi(w3,"nocommand")) {
if (state) {
if (sscanf(w4, "%d", &state) == 1)
- map[m].nocommand =state;
+ map->list[m].nocommand =state;
else //No level specified, block everyone.
- map[m].nocommand =100;
+ map->list[m].nocommand =100;
} else
- map[m].nocommand=0;
+ map->list[m].nocommand=0;
}
else if (!strcmpi(w3,"jexp")) {
- map[m].jexp = (state) ? atoi(w4) : 100;
- if( map[m].jexp < 0 ) map[m].jexp = 100;
- map[m].flag.nojobexp = (map[m].jexp==0)?1:0;
+ map->list[m].jexp = (state) ? atoi(w4) : 100;
+ if( map->list[m].jexp < 0 ) map->list[m].jexp = 100;
+ map->list[m].flag.nojobexp = (map->list[m].jexp==0)?1:0;
}
else if (!strcmpi(w3,"bexp")) {
- map[m].bexp = (state) ? atoi(w4) : 100;
- if( map[m].bexp < 0 ) map[m].bexp = 100;
- map[m].flag.nobaseexp = (map[m].bexp==0)?1:0;
+ map->list[m].bexp = (state) ? atoi(w4) : 100;
+ if( map->list[m].bexp < 0 ) map->list[m].bexp = 100;
+ map->list[m].flag.nobaseexp = (map->list[m].bexp==0)?1:0;
}
else if (!strcmpi(w3,"loadevent"))
- map[m].flag.loadevent=state;
+ map->list[m].flag.loadevent=state;
else if (!strcmpi(w3,"nochat"))
- map[m].flag.nochat=state;
+ map->list[m].flag.nochat=state;
else if (!strcmpi(w3,"partylock"))
- map[m].flag.partylock=state;
+ map->list[m].flag.partylock=state;
else if (!strcmpi(w3,"guildlock"))
- map[m].flag.guildlock=state;
+ map->list[m].flag.guildlock=state;
else if (!strcmpi(w3,"reset"))
- map[m].flag.reset=state;
+ map->list[m].flag.reset=state;
+ else if (!strcmpi(w3,"notomb"))
+ map->list[m].flag.notomb=state;
else if (!strcmpi(w3,"adjust_unit_duration")) {
int skill_id, k;
char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH];
- int len = strlen(w4);
+ size_t len = w4 ? strlen(w4) : 0;
modifier[0] = '\0';
- memcpy(skill_name, w4, MAP_ZONE_MAPFLAG_LENGTH);
+ if( w4 )
+ memcpy(skill_name, w4, MAP_ZONE_MAPFLAG_LENGTH);
for(k = 0; k < len; k++) {
if( skill_name[k] == '\t' ) {
@@ -3394,50 +3874,55 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
}
if( modifier[0] == '\0' ) {
- ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else if( !( skill_id = skill->name2id(skill_name) ) || !skill->get_unit_id( skill->name2id(skill_name), 0) ) {
- ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n",skill_name, map[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n",skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else if ( atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) {
- ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n", atoi(modifier), skill_name, map[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n", atoi(modifier), skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else {
- int idx = map[m].unit_count;
+ int idx = map->list[m].unit_count;
- ARR_FIND(0, idx, k, map[m].units[k]->skill_id == skill_id);
+ ARR_FIND(0, idx, k, map->list[m].units[k]->skill_id == skill_id);
if( k < idx ) {
if( atoi(modifier) != 100 )
- map[m].units[k]->modifier = (unsigned short)atoi(modifier);
+ map->list[m].units[k]->modifier = (unsigned short)atoi(modifier);
else { /* remove */
int cursor = 0;
- aFree(map[m].units[k]);
- map[m].units[k] = NULL;
+ aFree(map->list[m].units[k]);
+ map->list[m].units[k] = NULL;
for( k = 0; k < idx; k++ ) {
- if( map[m].units[k] == NULL )
+ if( map->list[m].units[k] == NULL )
continue;
- memmove(&map[m].units[cursor], &map[m].units[k], sizeof(struct mapflag_skill_adjust));
-
+ map->list[m].units[cursor] = map->list[m].units[k];
+
cursor++;
}
- if( !( map[m].unit_count = cursor ) ) {
- aFree(map[m].units);
- map[m].units = NULL;
+ if( !( map->list[m].unit_count = cursor ) ) {
+ aFree(map->list[m].units);
+ map->list[m].units = NULL;
}
}
} else if( atoi(modifier) != 100 ) {
- RECREATE(map[m].units, struct mapflag_skill_adjust*, ++map[m].unit_count);
- CREATE(map[m].units[idx],struct mapflag_skill_adjust,1);
- map[m].units[idx]->skill_id = (unsigned short)skill_id;
- map[m].units[idx]->modifier = (unsigned short)atoi(modifier);
+ RECREATE(map->list[m].units, struct mapflag_skill_adjust*, ++map->list[m].unit_count);
+ CREATE(map->list[m].units[idx],struct mapflag_skill_adjust,1);
+ map->list[m].units[idx]->skill_id = (unsigned short)skill_id;
+ map->list[m].units[idx]->modifier = (unsigned short)atoi(modifier);
}
}
} else if (!strcmpi(w3,"adjust_skill_damage")) {
int skill_id, k;
char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH];
- int len = strlen(w4);
+ size_t len = w4 ? strlen(w4) : 0;
modifier[0] = '\0';
- memcpy(skill_name, w4, MAP_ZONE_MAPFLAG_LENGTH);
+
+ if( w4 )
+ memcpy(skill_name, w4, MAP_ZONE_MAPFLAG_LENGTH);
for(k = 0; k < len; k++) {
if( skill_name[k] == '\t' ) {
@@ -3448,78 +3933,95 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
}
if( modifier[0] == '\0' ) {
- ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_skill_damage' flag! removing flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else if( !( skill_id = skill->name2id(skill_name) ) ) {
- ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_skill_damage' flag! removing flag from %s (file '%s', line '%d').\n", skill_name, map[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else if ( atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) {
- ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_skill_damage' flag! removing flag from %s (file '%s', line '%d').\n", atoi(modifier), skill_name, map[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", atoi(modifier), skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
} else {
- int idx = map[m].skill_count;
-
- ARR_FIND(0, idx, k, map[m].skills[k]->skill_id == skill_id);
+ int idx = map->list[m].skill_count;
+
+ ARR_FIND(0, idx, k, map->list[m].skills[k]->skill_id == skill_id);
if( k < idx ) {
if( atoi(modifier) != 100 )
- map[m].skills[k]->modifier = (unsigned short)atoi(modifier);
+ map->list[m].skills[k]->modifier = (unsigned short)atoi(modifier);
else { /* remove */
int cursor = 0;
- aFree(map[m].skills[k]);
- map[m].skills[k] = NULL;
+ aFree(map->list[m].skills[k]);
+ map->list[m].skills[k] = NULL;
for( k = 0; k < idx; k++ ) {
- if( map[m].skills[k] == NULL )
+ if( map->list[m].skills[k] == NULL )
continue;
- memmove(&map[m].skills[cursor], &map[m].skills[k], sizeof(struct mapflag_skill_adjust));
-
+ map->list[m].skills[cursor] = map->list[m].skills[k];
+
cursor++;
}
- if( !( map[m].skill_count = cursor ) ) {
- aFree(map[m].skills);
- map[m].skills = NULL;
+ if( !( map->list[m].skill_count = cursor ) ) {
+ aFree(map->list[m].skills);
+ map->list[m].skills = NULL;
}
}
} else if( atoi(modifier) != 100 ) {
- RECREATE(map[m].skills, struct mapflag_skill_adjust*, ++map[m].skill_count);
- CREATE(map[m].skills[idx],struct mapflag_skill_adjust,1);
- map[m].skills[idx]->skill_id = (unsigned short)skill_id;
- map[m].skills[idx]->modifier = (unsigned short)atoi(modifier);
+ RECREATE(map->list[m].skills, struct mapflag_skill_adjust*, ++map->list[m].skill_count);
+ CREATE(map->list[m].skills[idx],struct mapflag_skill_adjust,1);
+ map->list[m].skills[idx]->skill_id = (unsigned short)skill_id;
+ map->list[m].skills[idx]->modifier = (unsigned short)atoi(modifier);
}
}
} else if (!strcmpi(w3,"zone")) {
struct map_zone_data *zone;
- if( !(zone = strdb_get(zone_db, w4)) ) {
- ShowWarning("npc_parse_mapflag: Invalid zone '%s'! removing flag from %s (file '%s', line '%d').\n", w4, map[m].name, filepath, strline(buffer,start-buffer));
- } else if( map[m].zone != zone ) {
- iMap->zone_change(m,zone,start,buffer,filepath);
+ if( !(zone = strdb_get(map->zone_db, w4)) ) {
+ ShowWarning("npc_parse_mapflag: Invalid zone '%s'! removing flag from %s in file '%s', line '%d'.\n", w4, map->list[m].name, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
+ } else if( map->list[m].zone != zone ) {
+ map->zone_change(m,zone,start,buffer,filepath);
}
} else if ( !strcmpi(w3,"nomapchannelautojoin") ) {
- map[m].flag.chsysnolocalaj = state;
+ map->list[m].flag.chsysnolocalaj = state;
} else if ( !strcmpi(w3,"invincible_time_inc") ) {
- map[m].invincible_time_inc = (state) ? atoi(w4) : 0;
+ map->list[m].invincible_time_inc = (state) ? atoi(w4) : 0;
} else if ( !strcmpi(w3,"noknockback") ) {
- map[m].flag.noknockback = state;
+ map->list[m].flag.noknockback = state;
} else if ( !strcmpi(w3,"weapon_damage_rate") ) {
- map[m].weapon_damage_rate = (state) ? atoi(w4) : 100;
+ map->list[m].weapon_damage_rate = (state) ? atoi(w4) : 100;
} else if ( !strcmpi(w3,"magic_damage_rate") ) {
- map[m].magic_damage_rate = (state) ? atoi(w4) : 100;
+ map->list[m].magic_damage_rate = (state) ? atoi(w4) : 100;
} else if ( !strcmpi(w3,"misc_damage_rate") ) {
- map[m].misc_damage_rate = (state) ? atoi(w4) : 100;
+ map->list[m].misc_damage_rate = (state) ? atoi(w4) : 100;
} else if ( !strcmpi(w3,"short_damage_rate") ) {
- map[m].short_damage_rate = (state) ? atoi(w4) : 100;
+ map->list[m].short_damage_rate = (state) ? atoi(w4) : 100;
} else if ( !strcmpi(w3,"long_damage_rate") ) {
- map[m].long_damage_rate = (state) ? atoi(w4) : 100;
- } else
- ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer));
+ map->list[m].long_damage_rate = (state) ? atoi(w4) : 100;
+ } else if ( !strcmpi(w3,"src4instance") ) {
+ map->list[m].flag.src4instance = (state) ? 1 : 0;
+ } else if ( !strcmpi(w3,"nocashshop") ) {
+ map->list[m].flag.nocashshop = (state) ? 1 : 0;
+ } else {
+ ShowError("npc_parse_mapflag: unrecognized mapflag '%s' in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
+ if (retval) *retval = EXIT_FAILURE;
+ }
return strchr(start,'\n');// continue
}
-//Read file and create npc/func/mapflag/monster... accordingly.
-//@runOnInit should we exec OnInit when it's done ?
-void npc_parsesrcfile(const char* filepath, bool runOnInit)
-{
+/**
+ * Parses a script file and creates NPCs/functions/mapflags/monsters/etc
+ * accordingly.
+ *
+ * @param filepath File name and path.
+ * @param runOnInit Whether the OnInit label should be called.
+ * @retval EXIT_SUCCESS if filepath was loaded correctly.
+ * @retval EXIT_FAILURE if there were errors/warnings when loading filepath.
+ */
+int npc_parsesrcfile(const char* filepath, bool runOnInit) {
+ int success = EXIT_SUCCESS;
int16 m, x, y;
int lines = 0;
FILE* fp;
@@ -3529,10 +4031,9 @@ void npc_parsesrcfile(const char* filepath, bool runOnInit)
// read whole file to buffer
fp = fopen(filepath, "rb");
- if( fp == NULL )
- {
+ if( fp == NULL ) {
ShowError("npc_parsesrcfile: File not found '%s'.\n", filepath);
- return;
+ return EXIT_FAILURE;
}
fseek(fp, 0, SEEK_END);
len = ftell(fp);
@@ -3540,103 +4041,118 @@ void npc_parsesrcfile(const char* filepath, bool runOnInit)
fseek(fp, 0, SEEK_SET);
len = fread(buffer, sizeof(char), len, fp);
buffer[len] = '\0';
- if( ferror(fp) )
- {
+ if( ferror(fp) ) {
ShowError("npc_parsesrcfile: Failed to read file '%s' - %s\n", filepath, strerror(errno));
aFree(buffer);
fclose(fp);
- return;
+ return EXIT_FAILURE;
}
fclose(fp);
+ if ((unsigned char)buffer[0] == 0xEF && (unsigned char)buffer[1] == 0xBB && (unsigned char)buffer[2] == 0xBF) {
+ // UTF-8 BOM. This is most likely an error on the user's part, because:
+ // - BOM is discouraged in UTF-8, and the only place where you see it is Notepad and such.
+ // - It's unlikely that the user wants to use UTF-8 data here, since we don't really support it, nor does the client by default.
+ // - If the user really wants to use UTF-8 (instead of latin1, EUC-KR, SJIS, etc), then they can still do it <without BOM>.
+ // More info at http://unicode.org/faq/utf_bom.html#bom5 and http://en.wikipedia.org/wiki/Byte_order_mark#UTF-8
+ ShowError("npc_parsesrcfile: Detected unsupported UTF-8 BOM in file '%s'. Stopping (please consider using another character set.)\n", filepath);
+ aFree(buffer);
+ fclose(fp);
+ return EXIT_FAILURE;
+ }
+
// parse buffer
- for( p = skip_space(buffer); p && *p ; p = skip_space(p) )
- {
+ for( p = script->skip_space(buffer); p && *p ; p = script->skip_space(p) ) {
int pos[9];
char w1[2048], w2[2048], w3[2048], w4[2048];
int i, count;
lines++;
// w1<TAB>w2<TAB>w3<TAB>w4
- count = sv->parse(p, len+buffer-p, 0, '\t', pos, ARRAYLENGTH(pos), (e_svopt)(SV_TERMINATE_LF|SV_TERMINATE_CRLF));
+ count = sv->parse(p, (int)(len+buffer-p), 0, '\t', pos, ARRAYLENGTH(pos), (e_svopt)(SV_TERMINATE_LF|SV_TERMINATE_CRLF));
if( count < 0 )
{
ShowError("npc_parsesrcfile: Parse error in file '%s', line '%d'. Stopping...\n", filepath, strline(buffer,p-buffer));
+ success = EXIT_FAILURE;
break;
}
// fill w1
- if( pos[3]-pos[2] > ARRAYLENGTH(w1)-1 )
+ if( pos[3]-pos[2] > ARRAYLENGTH(w1)-1 ) {
ShowWarning("npc_parsesrcfile: w1 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[3]-pos[2], filepath, strline(buffer,p-buffer));
+ success = EXIT_FAILURE;
+ }
i = min(pos[3]-pos[2], ARRAYLENGTH(w1)-1);
memcpy(w1, p+pos[2], i*sizeof(char));
w1[i] = '\0';
// fill w2
- if( pos[5]-pos[4] > ARRAYLENGTH(w2)-1 )
+ if( pos[5]-pos[4] > ARRAYLENGTH(w2)-1 ) {
ShowWarning("npc_parsesrcfile: w2 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[5]-pos[4], filepath, strline(buffer,p-buffer));
+ success = EXIT_FAILURE;
+ }
i = min(pos[5]-pos[4], ARRAYLENGTH(w2)-1);
memcpy(w2, p+pos[4], i*sizeof(char));
w2[i] = '\0';
// fill w3
- if( pos[7]-pos[6] > ARRAYLENGTH(w3)-1 )
+ if( pos[7]-pos[6] > ARRAYLENGTH(w3)-1 ) {
ShowWarning("npc_parsesrcfile: w3 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[7]-pos[6], filepath, strline(buffer,p-buffer));
+ success = EXIT_FAILURE;
+ }
i = min(pos[7]-pos[6], ARRAYLENGTH(w3)-1);
memcpy(w3, p+pos[6], i*sizeof(char));
w3[i] = '\0';
// fill w4 (to end of line)
- if( pos[1]-pos[8] > ARRAYLENGTH(w4)-1 )
+ if( pos[1]-pos[8] > ARRAYLENGTH(w4)-1 ) {
ShowWarning("npc_parsesrcfile: w4 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[1]-pos[8], filepath, strline(buffer,p-buffer));
- if( pos[8] != -1 )
- {
+ success = EXIT_FAILURE;
+ }
+ if( pos[8] != -1 ) {
i = min(pos[1]-pos[8], ARRAYLENGTH(w4)-1);
memcpy(w4, p+pos[8], i*sizeof(char));
w4[i] = '\0';
- }
- else
+ } else {
w4[0] = '\0';
+ }
- if( count < 3 )
- {// Unknown syntax
+ if( count < 3 ) {
+ // Unknown syntax
ShowError("npc_parsesrcfile: Unknown syntax in file '%s', line '%d'. Stopping...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4);
+ success = EXIT_FAILURE;
break;
}
- if( strcmp(w1,"-") !=0 && strcasecmp(w1,"function") != 0 )
+ if( strcmp(w1,"-") != 0 && strcmp(w1,"function") != 0 )
{// w1 = <map name>,<x>,<y>,<facing>
char mapname[MAP_NAME_LENGTH*2];
x = y = 0;
sscanf(w1,"%23[^,],%hd,%hd[^,]",mapname,&x,&y);
- if( !mapindex_name2id(mapname) )
- {// Incorrect map, we must skip the script info...
+ if( !mapindex->name2id(mapname) ) {
+ // Incorrect map, we must skip the script info...
ShowError("npc_parsesrcfile: Unknown map '%s' in file '%s', line '%d'. Skipping line...\n", mapname, filepath, strline(buffer,p-buffer));
- if( strcasecmp(w2,"script") == 0 && count > 3 )
- {
- if((p = npc_skip_script(p,buffer,filepath)) == NULL)
- {
+ success = EXIT_FAILURE;
+ if( strcmp(w2,"script") == 0 && count > 3 ) {
+ if((p = npc->skip_script(p,buffer,filepath, &success)) == NULL) {
break;
}
}
p = strchr(p,'\n');// next line
continue;
}
- m = iMap->mapname2mapid(mapname);
- if( m < 0 )
- {// "mapname" is not assigned to this server, we must skip the script info...
- if( strcasecmp(w2,"script") == 0 && count > 3 )
- {
- if((p = npc_skip_script(p,buffer,filepath)) == NULL)
- {
+ m = map->mapname2mapid(mapname);
+ if( m < 0 ) {
+ // "mapname" is not assigned to this server, we must skip the script info...
+ if( strcmp(w2,"script") == 0 && count > 3 ) {
+ if((p = npc->skip_script(p,buffer,filepath, &success)) == NULL) {
break;
}
}
p = strchr(p,'\n');// next line
continue;
}
- if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys) {
+ if (x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys) {
ShowError("npc_parsesrcfile: Unknown coordinates ('%d', '%d') for map '%s' in file '%s', line '%d'. Skipping line...\n", x, y, mapname, filepath, strline(buffer,p-buffer));
- if( strcasecmp(w2,"script") == 0 && count > 3 )
- {
- if((p = npc_skip_script(p,buffer,filepath)) == NULL)
- {
+ success = EXIT_FAILURE;
+ if( strcmp(w2,"script") == 0 && count > 3 ) {
+ if((p = npc->skip_script(p,buffer,filepath, &success)) == NULL) {
break;
}
}
@@ -3645,42 +4161,71 @@ void npc_parsesrcfile(const char* filepath, bool runOnInit)
}
}
- if( strcasecmp(w2,"warp") == 0 && count > 3 )
+ if( strcmp(w2,"mapflag") == 0 && count >= 3 )
{
- p = npc_parse_warp(w1,w2,w3,w4, p, buffer, filepath);
+ p = npc->parse_mapflag(w1, w2, trim(w3), trim(w4), p, buffer, filepath, &success);
}
- else if( (!strcasecmp(w2,"shop") || !strcasecmp(w2,"cashshop")) && count > 3 )
+ else if( count == 3 ) {
+ ShowError("npc_parsesrcfile: Unable to parse, probably a missing TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4);
+ p = strchr(p,'\n');// skip and continue
+ success = EXIT_FAILURE;
+ }
+ else if( strcmp(w2,"script") == 0 )
{
- p = npc_parse_shop(w1,w2,w3,w4, p, buffer, filepath);
+ if( strcmp(w1,"function") == 0 ) {
+ p = npc->parse_function(w1, w2, w3, w4, p, buffer, filepath, &success);
+ } else {
+#ifdef ENABLE_CASE_CHECK
+ if( strcasecmp(w1, "function") == 0 ) DeprecationWarning("npc_parsesrcfile", w1, "function", filepath, strline(buffer, p-buffer)); // TODO
+#endif // ENABLE_CASE_CHECK
+ p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit?NPO_ONINIT:NPO_NONE, &success);
+ }
}
- else if( strcasecmp(w2,"script") == 0 && count > 3 )
+ else if( strcmp(w2,"trader") == 0 ) {
+ p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,(runOnInit?NPO_ONINIT:NPO_NONE)|NPO_TRADER, &success);
+ }
+ else if( strcmp(w2,"warp") == 0 )
{
- if( strcasecmp(w1,"function") == 0 )
- p = npc_parse_function(w1, w2, w3, w4, p, buffer, filepath);
- else
- p = npc_parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit);
+ p = npc->parse_warp(w1,w2,w3,w4, p, buffer, filepath, &success);
}
- else if( (i=0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) && count > 3 )
+ else if( (i=0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) )
{
- p = npc_parse_duplicate(w1,w2,w3,w4, p, buffer, filepath);
+ p = npc->parse_duplicate(w1,w2,w3,w4, p, buffer, filepath, (runOnInit?NPO_ONINIT:NPO_NONE), &success);
}
- else if( (strcmpi(w2,"monster") == 0 || strcmpi(w2,"boss_monster") == 0) && count > 3 )
+ else if( (strcmp(w2,"monster") == 0 || strcmp(w2,"boss_monster") == 0) )
{
- p = npc_parse_mob(w1, w2, w3, w4, p, buffer, filepath);
+ p = npc->parse_mob(w1, w2, w3, w4, p, buffer, filepath, &success);
}
- else if( strcmpi(w2,"mapflag") == 0 && count >= 3 )
+ else if( (strcmp(w2,"shop") == 0 || strcmp(w2,"cashshop") == 0) )
{
- p = npc_parse_mapflag(w1, w2, trim(w3), trim(w4), p, buffer, filepath);
+ p = npc->parse_shop(w1,w2,w3,w4, p, buffer, filepath, &success);
}
else
{
+#ifdef ENABLE_CASE_CHECK
+ if( strcasecmp(w2, "warp") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "warp", filepath, strline(buffer, p-buffer)); } // TODO
+ else if( strcasecmp(w2,"shop") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "shop", filepath, strline(buffer, p-buffer)); } // TODO
+ else if( strcasecmp(w2,"cashshop") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "cashshop", filepath, strline(buffer, p-buffer)); } // TODO
+ else if( strcasecmp(w2, "script") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "script", filepath, strline(buffer, p-buffer)); } // TODO
+ else if( strcasecmp(w2,"trader") == 0 ) DeprecationWarning("npc_parsesrcfile", w2, "trader", filepath, strline(buffer, p-buffer)) // TODO
+ else if( strncasecmp(w2, "duplicate", 9) == 0 ) {
+ char temp[10];
+ safestrncpy(temp, w2, 10);
+ DeprecationWarning("npc_parsesrcfile", temp, "duplicate", filepath, strline(buffer, p-buffer)); // TODO
+ }
+ else if( strcasecmp(w2,"monster") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "monster", filepath, strline(buffer, p-buffer)); } // TODO:
+ else if( strcasecmp(w2,"boss_monster") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "boss_monster", filepath, strline(buffer, p-buffer)); } // TODO
+ else if( strcasecmp(w2, "mapflag") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "mapflag", filepath, strline(buffer, p-buffer)); } // TODO
+ else
+#endif // ENABLE_CASE_CHECK
ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4);
p = strchr(p,'\n');// skip and continue
+ success = EXIT_FAILURE;
}
}
aFree(buffer);
- return;
+ return success;
}
int npc_script_event(struct map_session_data* sd, enum npce_event type)
@@ -3693,7 +4238,7 @@ int npc_script_event(struct map_session_data* sd, enum npce_event type)
return 0;
}
for (i = 0; i<script_event[type].event_count; i++)
- npc_event_sub(sd,script_event[type].event[i],script_event[type].event_name[i]);
+ npc->event_sub(sd,script_event[type].event[i],script_event[type].event_name[i]);
return i;
}
@@ -3704,14 +4249,14 @@ void npc_read_event_script(void)
char *name;
const char *event_name;
} config[] = {
- {"Login Event",script_config.login_event_name},
- {"Logout Event",script_config.logout_event_name},
- {"Load Map Event",script_config.loadmap_event_name},
- {"Base LV Up Event",script_config.baselvup_event_name},
- {"Job LV Up Event",script_config.joblvup_event_name},
- {"Die Event",script_config.die_event_name},
- {"Kill PC Event",script_config.kill_pc_event_name},
- {"Kill NPC Event",script_config.kill_mob_event_name},
+ {"Login Event",script->config.login_event_name},
+ {"Logout Event",script->config.logout_event_name},
+ {"Load Map Event",script->config.loadmap_event_name},
+ {"Base LV Up Event",script->config.baselvup_event_name},
+ {"Job LV Up Event",script->config.joblvup_event_name},
+ {"Die Event",script->config.die_event_name},
+ {"Kill PC Event",script->config.kill_pc_event_name},
+ {"Kill NPC Event",script->config.kill_mob_event_name},
};
for (i = 0; i < NPCE_MAX; i++)
@@ -3724,7 +4269,7 @@ void npc_read_event_script(void)
safestrncpy(name+2,config[i].event_name,62);
script_event[i].event_count = 0;
- iter = db_iterator(ev_db);
+ iter = db_iterator(npc->ev_db);
for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) )
{
const char* p = key.str;
@@ -3737,11 +4282,15 @@ void npc_read_event_script(void)
break;
}
- if( (p=strchr(p,':')) && p && strcmpi(name,p)==0 )
+ if( (p=strchr(p,':')) && strcmp(name,p) == 0 )
{
script_event[i].event[count] = ed;
script_event[i].event_name[count] = key.str;
script_event[i].event_count++;
+#ifdef ENABLE_CASE_CHECK
+ } else if( p && strcasecmp(name, p) == 0 ) {
+ DeprecationWarning2("npc_read_event_script", p, name, config[i].event_name); // TODO
+#endif // ENABLE_CASE_CHECK
}
}
dbi_destroy(iter);
@@ -3754,211 +4303,236 @@ void npc_read_event_script(void)
}
}
-void npc_clear_pathlist(void) {
- struct npc_path_data *npd = NULL;
- DBIterator *path_list = db_iterator(npc_path_db);
+/**
+ * @see DBApply
+ */
+int npc_path_db_clear_sub(DBKey key, DBData *data, va_list args)
+{
+ struct npc_path_data *npd = DB->data2ptr(data);
+ if (npd->path)
+ aFree(npd->path);
+ return 0;
+}
- /* free all npc_path_data filepaths */
- for( npd = dbi_first(path_list); dbi_exists(path_list); npd = dbi_next(path_list) ) {
- if( npd->path )
- aFree(npd->path);
- }
+/**
+ * @see DBApply
+ */
+int npc_ev_label_db_clear_sub(DBKey key, DBData *data, va_list args)
+{
+ struct linkdb_node **label_linkdb = DB->data2ptr(data);
+ linkdb_final(label_linkdb); // linked data (struct event_data*) is freed when clearing ev_db
+ return 0;
+}
- dbi_destroy(path_list);
+/**
+ * Main npc file processing
+ * @param npc_min Minimum npc id - used to know how many NPCs were loaded
+ **/
+void npc_process_files( int npc_min ) {
+ struct npc_src_list *file; // Current file
+
+ ShowStatus("Loading NPCs...\r");
+ for( file = npc->src_files; file != NULL; file = file->next ) {
+ ShowStatus("Loading NPC file: %s"CL_CLL"\r", file->name);
+ if (npc->parsesrcfile(file->name, false) != EXIT_SUCCESS)
+ map->retval = EXIT_FAILURE;
+ }
+ ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Warps\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Shops\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
+ npc_id - npc_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
}
//Clear then reload npcs files
int npc_reload(void) {
- struct npc_src_list *nsl;
int16 m, i;
int npc_new_min = npc_id;
struct s_mapiterator* iter;
struct block_list* bl;
+ if (map->retval == EXIT_FAILURE)
+ map->retval = EXIT_SUCCESS; // Clear return status in case something failed before.
+
/* clear guild flag cache */
guild->flags_clear();
- npc_clear_pathlist();
+ npc->path_db->clear(npc->path_db, npc->path_db_clear_sub);
- db_clear(npc_path_db);
-
- db_clear(npcname_db);
- db_clear(ev_db);
+ db_clear(npc->name_db);
+ db_clear(npc->ev_db);
+ npc->ev_label_db->clear(npc->ev_label_db, npc->ev_label_db_clear_sub);
+ npc_last_npd = NULL;
+ npc_last_path = NULL;
+ npc_last_ref = NULL;
+
//Remove all npcs/mobs. [Skotlex]
iter = mapit_geteachiddb();
for( bl = (struct block_list*)mapit->first(iter); mapit->exists(iter); bl = (struct block_list*)mapit->next(iter) ) {
switch(bl->type) {
- case BL_NPC:
- if( bl->id != fake_nd->bl.id )// don't remove fake_nd
- npc_unload((struct npc_data *)bl, false);
- break;
- case BL_MOB:
- unit_free(bl,CLR_OUTSIGHT);
- break;
+ case BL_NPC:
+ if( bl->id != npc->fake_nd->bl.id )// don't remove fake_nd
+ npc->unload((struct npc_data *)bl, false);
+ break;
+ case BL_MOB:
+ unit->free(bl,CLR_OUTSIGHT);
+ break;
}
}
mapit->free(iter);
- if(battle_config.dynamic_mobs)
- {// dynamic check by [random]
- for (m = 0; m < iMap->map_num; m++) {
+ if(battle_config.dynamic_mobs) {// dynamic check by [random]
+ for (m = 0; m < map->count; m++) {
for (i = 0; i < MAX_MOB_LIST_PER_MAP; i++) {
- if (map[m].moblist[i] != NULL) {
- aFree(map[m].moblist[i]);
- map[m].moblist[i] = NULL;
+ if (map->list[m].moblist[i] != NULL) {
+ aFree(map->list[m].moblist[i]);
+ map->list[m].moblist[i] = NULL;
}
- if( map[m].mob_delete_timer != INVALID_TIMER )
+ if( map->list[m].mob_delete_timer != INVALID_TIMER )
{ // Mobs were removed anyway,so delete the timer [Inkfish]
- iTimer->delete_timer(map[m].mob_delete_timer, iMap->removemobs_timer);
- map[m].mob_delete_timer = INVALID_TIMER;
+ timer->delete(map->list[m].mob_delete_timer, map->removemobs_timer);
+ map->list[m].mob_delete_timer = INVALID_TIMER;
}
}
+ if (map->list[m].npc_num > 0)
+ ShowWarning("npc_reload: %d npcs weren't removed at map %s!\n", map->list[m].npc_num, map->list[m].name);
}
- if (map[m].npc_num > 0)
- ShowWarning("npc_reload: %d npcs weren't removed at map %s!\n", map[m].npc_num, map[m].name);
}
// clear mob spawn lookup index
- mob_clear_spawninfo();
+ mob->clear_spawninfo();
npc_warp = npc_shop = npc_script = 0;
npc_mob = npc_cache_mob = npc_delay_mob = 0;
// reset mapflags
- iMap->flags_init();
+ map->flags_init();
- //TODO: the following code is copy-pasted from do_init_npc(); clean it up
- // Reloading npcs now
- for (nsl = npc_src_files; nsl; nsl = nsl->next) {
- ShowStatus("Loading NPC file: %s"CL_CLL"\r", nsl->name);
- npc_parsesrcfile(nsl->name,false);
- }
- ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Warps\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Shops\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
- npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
-
- instance->final();
+ // Reprocess npc files and reload constants
+ itemdb->name_constants();
+ npc_process_files( npc_new_min );
- iMap->zone_init();
-
- npc->motd = npc_name2id("HerculesMOTD"); /* [Ind/Hercules] */
-
- //Re-read the NPC Script Events cache.
- npc_read_event_script();
+ instance->reload();
+
+ map->zone_init();
- /* refresh guild castle flags on both woe setups */
- npc_event_doall("OnAgitInit");
- npc_event_doall("OnAgitInit2");
+ npc->motd = npc->name2id("HerculesMOTD"); /* [Ind/Hercules] */
- //Execute the OnInit event for freshly loaded npcs. [Skotlex]
- ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit"));
+ //Re-read the NPC Script Events cache.
+ npc->read_event_script();
+ // Execute main initialisation events
+ // The correct initialisation order is:
+ // OnInit -> OnInterIfInit -> OnInterIfInitOnce -> OnAgitInit -> OnAgitInit2
+ npc->event_do_oninit( true );
+ npc->market_fromsql();
// Execute rest of the startup events if connected to char-server. [Lance]
- if(!CheckForCharServer()){
- ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit"));
- ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce"));
+ // Executed when connection is established with char-server in chrif_connectack
+ if( !intif->CheckForCharServer() ) {
+ ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc->event_doall("OnInterIfInit"));
+ ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc->event_doall("OnInterIfInitOnce"));
}
+ // Refresh guild castle flags on both woe setups
+ // These events are only executed after receiving castle information from char-server
+ npc->event_doall("OnAgitInit");
+ npc->event_doall("OnAgitInit2");
+
return 0;
}
//Unload all npc in the given file
-bool npc_unloadfile( const char* path ) {
- DBIterator * iter = db_iterator(npcname_db);
+bool npc_unloadfile( const char* filepath ) {
+ DBIterator * iter = db_iterator(npc->name_db);
struct npc_data* nd = NULL;
bool found = false;
for( nd = dbi_first(iter); dbi_exists(iter); nd = dbi_next(iter) ) {
- if( nd->path && strcasecmp(nd->path,path) == 0 ) {
+ if( nd->path && strcasecmp(nd->path,filepath) == 0 ) { // FIXME: This can break in case-sensitive file systems
found = true;
- npc_unload_duplicates(nd);/* unload any npcs which could duplicate this but be in a different file */
- npc_unload(nd, true);
+ npc->unload_duplicates(nd);/* unload any npcs which could duplicate this but be in a different file */
+ npc->unload(nd, true);
}
}
dbi_destroy(iter);
if( found ) /* refresh event cache */
- npc_read_event_script();
+ npc->read_event_script();
return found;
}
void do_clear_npc(void) {
- db_clear(npcname_db);
- db_clear(ev_db);
+ db_clear(npc->name_db);
+ db_clear(npc->ev_db);
+ npc->ev_label_db->clear(npc->ev_label_db, npc->ev_label_db_clear_sub);
}
/*==========================================
* Destructor
*------------------------------------------*/
int do_final_npc(void) {
- npc_clear_pathlist();
- ev_db->destroy(ev_db, NULL);
- npcname_db->destroy(npcname_db, NULL);
- npc_path_db->destroy(npc_path_db, NULL);
- ers_destroy(timer_event_ers);
- npc_clearsrcfile();
+ db_destroy(npc->ev_db);
+ npc->ev_label_db->destroy(npc->ev_label_db, npc->ev_label_db_clear_sub);
+ db_destroy(npc->name_db);
+ npc->path_db->destroy(npc->path_db, npc->path_db_clear_sub);
+ ers_destroy(npc->timer_event_ers);
+ npc->clearsrcfile();
return 0;
}
-static void npc_debug_warps_sub(struct npc_data* nd)
-{
+void npc_debug_warps_sub(struct npc_data* nd) {
int16 m;
if (nd->bl.type != BL_NPC || nd->subtype != WARP || nd->bl.m < 0)
return;
- m = iMap->mapindex2mapid(nd->u.warp.mapindex);
+ m = map->mapindex2mapid(nd->u.warp.mapindex);
if (m < 0) return; //Warps to another map, nothing to do about it.
if (nd->u.warp.x == 0 && nd->u.warp.y == 0) return; // random warp
- if (iMap->getcell(m, nd->u.warp.x, nd->u.warp.y, CELL_CHKNPC)) {
+ if (map->getcell(m, nd->u.warp.x, nd->u.warp.y, CELL_CHKNPC)) {
ShowWarning("Warp %s at %s(%d,%d) warps directly on top of an area npc at %s(%d,%d)\n",
nd->name,
- map[nd->bl.m].name, nd->bl.x, nd->bl.y,
- map[m].name, nd->u.warp.x, nd->u.warp.y
+ map->list[nd->bl.m].name, nd->bl.x, nd->bl.y,
+ map->list[m].name, nd->u.warp.x, nd->u.warp.y
);
}
- if (iMap->getcell(m, nd->u.warp.x, nd->u.warp.y, CELL_CHKNOPASS)) {
+ if (map->getcell(m, nd->u.warp.x, nd->u.warp.y, CELL_CHKNOPASS)) {
ShowWarning("Warp %s at %s(%d,%d) warps to a non-walkable tile at %s(%d,%d)\n",
nd->name,
- map[nd->bl.m].name, nd->bl.x, nd->bl.y,
- map[m].name, nd->u.warp.x, nd->u.warp.y
+ map->list[nd->bl.m].name, nd->bl.x, nd->bl.y,
+ map->list[m].name, nd->u.warp.x, nd->u.warp.y
);
}
}
-static void npc_debug_warps(void)
-{
+static void npc_debug_warps(void) {
int16 m, i;
- for (m = 0; m < iMap->map_num; m++)
- for (i = 0; i < map[m].npc_num; i++)
- npc_debug_warps_sub(map[m].npc[i]);
+ for (m = 0; m < map->count; m++)
+ for (i = 0; i < map->list[m].npc_num; i++)
+ npc->debug_warps_sub(map->list[m].npc[i]);
}
/*==========================================
* npc initialization
*------------------------------------------*/
-int do_init_npc(void)
-{
- struct npc_src_list *file;
+int do_init_npc(bool minimal) {
int i;
- memset(&npc_base_ud, 0, sizeof( struct unit_data) );
- npc_base_ud.bl = NULL;
- npc_base_ud.walktimer = INVALID_TIMER;
- npc_base_ud.skilltimer = INVALID_TIMER;
- npc_base_ud.attacktimer = INVALID_TIMER;
- npc_base_ud.attackabletime =
- npc_base_ud.canact_tick =
- npc_base_ud.canmove_tick = iTimer->gettick();
+ memset(&npc->base_ud, 0, sizeof( struct unit_data) );
+ npc->base_ud.bl = NULL;
+ npc->base_ud.walktimer = INVALID_TIMER;
+ npc->base_ud.skilltimer = INVALID_TIMER;
+ npc->base_ud.attacktimer = INVALID_TIMER;
+ npc->base_ud.attackabletime =
+ npc->base_ud.canact_tick =
+ npc->base_ud.canmove_tick = timer->gettick();
//Stock view data for normal npcs.
memset(&npc_viewdb, 0, sizeof(npc_viewdb));
@@ -3969,58 +4543,58 @@ int do_init_npc(void)
for( i = MAX_NPC_CLASS2_START; i < MAX_NPC_CLASS2_END; i++ )
npc_viewdb2[i - MAX_NPC_CLASS2_START].class_ = i;
- ev_db = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),2*NAME_LENGTH+2+1);
- npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH);
- npc_path_db = strdb_alloc(DB_OPT_BASE|DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,80);
+ npc->ev_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, EVENT_NAME_LENGTH);
+ npc->ev_label_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, NAME_LENGTH);
+ npc->name_db = strdb_alloc(DB_OPT_BASE, NAME_LENGTH);
+ npc->path_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 0);
- timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE);
+ npc_last_npd = NULL;
+ npc_last_path = NULL;
+ npc_last_ref = NULL;
- // process all npc files
- ShowStatus("Loading NPCs...\r");
- for( file = npc_src_files; file != NULL; file = file->next ) {
- ShowStatus("Loading NPC file: %s"CL_CLL"\r", file->name);
- npc_parsesrcfile(file->name,false);
+ // Should be loaded before npc processing, otherwise labels could overwrite constant values
+ // and lead to undefined behavior [Panikon]
+ itemdb->name_constants();
+
+ if (!minimal) {
+ npc->timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE);
+
+ npc_process_files(START_NPC_NUM);
}
- ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Warps\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Shops\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
- npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
- iMap->zone_init();
+ if (!minimal) {
+ map->zone_init();
- npc->motd = npc_name2id("HerculesMOTD"); /* [Ind/Hercules] */
+ npc->motd = npc->name2id("HerculesMOTD"); /* [Ind/Hercules] */
- // set up the events cache
- memset(script_event, 0, sizeof(script_event));
- npc_read_event_script();
+ // set up the events cache
+ memset(script_event, 0, sizeof(script_event));
+ npc->read_event_script();
- //Debug function to locate all endless loop warps.
- if (battle_config.warp_point_debug)
- npc_debug_warps();
+ //Debug function to locate all endless loop warps.
+ if (battle_config.warp_point_debug)
+ npc->debug_warps();
- iTimer->add_timer_func_list(npc_event_do_clock,"npc_event_do_clock");
- iTimer->add_timer_func_list(npc_timerevent,"npc_timerevent");
+ timer->add_func_list(npc->event_do_clock,"npc_event_do_clock");
+ timer->add_func_list(npc->timerevent,"npc_timerevent");
+ }
// Init dummy NPC
- fake_nd = (struct npc_data *)aCalloc(1,sizeof(struct npc_data));
- fake_nd->bl.m = -1;
- fake_nd->bl.id = npc_get_new_npc_id();
- fake_nd->class_ = -1;
- fake_nd->speed = 200;
- strcpy(fake_nd->name,"FAKE_NPC");
- memcpy(fake_nd->exname, fake_nd->name, 9);
+ npc->fake_nd = (struct npc_data *)aCalloc(1,sizeof(struct npc_data));
+ npc->fake_nd->bl.m = -1;
+ npc->fake_nd->bl.id = npc->get_new_npc_id();
+ npc->fake_nd->class_ = -1;
+ npc->fake_nd->speed = 200;
+ strcpy(npc->fake_nd->name,"FAKE_NPC");
+ memcpy(npc->fake_nd->exname, npc->fake_nd->name, 9);
npc_script++;
- fake_nd->bl.type = BL_NPC;
- fake_nd->subtype = SCRIPT;
+ npc->fake_nd->bl.type = BL_NPC;
+ npc->fake_nd->subtype = SCRIPT;
- strdb_put(npcname_db, fake_nd->exname, fake_nd);
- fake_nd->u.scr.timerid = INVALID_TIMER;
- iMap->addiddb(&fake_nd->bl);
+ strdb_put(npc->name_db, npc->fake_nd->exname, npc->fake_nd);
+ npc->fake_nd->u.scr.timerid = INVALID_TIMER;
+ map->addiddb(&npc->fake_nd->bl);
// End of initialization
return 0;
@@ -4029,4 +4603,114 @@ void npc_defaults(void) {
npc = &npc_s;
npc->motd = NULL;
+ npc->ev_db = NULL;
+ npc->ev_label_db = NULL;
+ npc->name_db = NULL;
+ npc->path_db = NULL;
+ npc->timer_event_ers = NULL;
+ npc->fake_nd = NULL;
+ npc->src_files = NULL;
+ /* */
+ npc->trader_ok = false;
+ npc->trader_funds[0] = npc->trader_funds[1] = 0;
+ /* */
+ npc->init = do_init_npc;
+ npc->final = do_final_npc;
+ /* */
+ npc->get_new_npc_id = npc_get_new_npc_id;
+ npc->get_viewdata = npc_get_viewdata;
+ npc->isnear_sub = npc_isnear_sub;
+ npc->isnear = npc_isnear;
+ npc->ontouch_event = npc_ontouch_event;
+ npc->ontouch2_event = npc_ontouch2_event;
+ npc->enable_sub = npc_enable_sub;
+ npc->enable = npc_enable;
+ npc->name2id = npc_name2id;
+ npc->event_dequeue = npc_event_dequeue;
+ npc->event_export_create = npc_event_export_create;
+ npc->event_export = npc_event_export;
+ npc->event_sub = npc_event_sub;
+ npc->event_doall_sub = npc_event_doall_sub;
+ npc->event_do = npc_event_do;
+ npc->event_doall_id = npc_event_doall_id;
+ npc->event_doall = npc_event_doall;
+ npc->event_do_clock = npc_event_do_clock;
+ npc->event_do_oninit = npc_event_do_oninit;
+ npc->timerevent_export = npc_timerevent_export;
+ npc->timerevent = npc_timerevent;
+ npc->timerevent_start = npc_timerevent_start;
+ npc->timerevent_stop = npc_timerevent_stop;
+ npc->timerevent_quit = npc_timerevent_quit;
+ npc->gettimerevent_tick = npc_gettimerevent_tick;
+ npc->settimerevent_tick = npc_settimerevent_tick;
+ npc->event = npc_event;
+ npc->touch_areanpc_sub = npc_touch_areanpc_sub;
+ npc->touchnext_areanpc = npc_touchnext_areanpc;
+ npc->touch_areanpc = npc_touch_areanpc;
+ npc->touch_areanpc2 = npc_touch_areanpc2;
+ npc->check_areanpc = npc_check_areanpc;
+ npc->checknear = npc_checknear;
+ npc->globalmessage = npc_globalmessage;
+ npc->run_tomb = run_tomb;
+ npc->click = npc_click;
+ npc->scriptcont = npc_scriptcont;
+ npc->buysellsel = npc_buysellsel;
+ npc->cashshop_buylist = npc_cashshop_buylist;
+ npc->buylist_sub = npc_buylist_sub;
+ npc->cashshop_buy = npc_cashshop_buy;
+ npc->buylist = npc_buylist;
+ npc->selllist_sub = npc_selllist_sub;
+ npc->selllist = npc_selllist;
+ npc->remove_map = npc_remove_map;
+ npc->unload_ev = npc_unload_ev;
+ npc->unload_ev_label = npc_unload_ev_label;
+ npc->unload_dup_sub = npc_unload_dup_sub;
+ npc->unload_duplicates = npc_unload_duplicates;
+ npc->unload = npc_unload;
+ npc->clearsrcfile = npc_clearsrcfile;
+ npc->addsrcfile = npc_addsrcfile;
+ npc->delsrcfile = npc_delsrcfile;
+ npc->parsename = npc_parsename;
+ npc->parseview = npc_parseview;
+ npc->viewisid = npc_viewisid;
+ npc->add_warp = npc_add_warp;
+ npc->parse_warp = npc_parse_warp;
+ npc->parse_shop = npc_parse_shop;
+ npc->convertlabel_db = npc_convertlabel_db;
+ npc->skip_script = npc_skip_script;
+ npc->parse_script = npc_parse_script;
+ npc->parse_duplicate = npc_parse_duplicate;
+ npc->duplicate4instance = npc_duplicate4instance;
+ npc->setcells = npc_setcells;
+ npc->unsetcells_sub = npc_unsetcells_sub;
+ npc->unsetcells = npc_unsetcells;
+ npc->movenpc = npc_movenpc;
+ npc->setdisplayname = npc_setdisplayname;
+ npc->setclass = npc_setclass;
+ npc->do_atcmd_event = npc_do_atcmd_event;
+ npc->parse_function = npc_parse_function;
+ npc->parse_mob2 = npc_parse_mob2;
+ npc->parse_mob = npc_parse_mob;
+ npc->parse_mapflag = npc_parse_mapflag;
+ npc->parsesrcfile = npc_parsesrcfile;
+ npc->script_event = npc_script_event;
+ npc->read_event_script = npc_read_event_script;
+ npc->path_db_clear_sub = npc_path_db_clear_sub;
+ npc->ev_label_db_clear_sub = npc_ev_label_db_clear_sub;
+ npc->reload = npc_reload;
+ npc->unloadfile = npc_unloadfile;
+ npc->do_clear_npc = do_clear_npc;
+ npc->debug_warps_sub = npc_debug_warps_sub;
+ npc->debug_warps = npc_debug_warps;
+ npc->secure_timeout_timer = npc_rr_secure_timeout_timer;
+ /* */
+ npc->trader_count_funds = npc_trader_count_funds;
+ npc->trader_pay = npc_trader_pay;
+ npc->trader_update = npc_trader_update;
+ npc->market_buylist = npc_market_buylist;
+ npc->trader_open = npc_trader_open;
+ npc->market_fromsql = npc_market_fromsql;
+ npc->market_tosql = npc_market_tosql;
+ npc->market_delfromsql = npc_market_delfromsql;
+ npc->market_delfromsql_sub = npc_market_delfromsql_sub;
}
diff --git a/src/map/npc.h b/src/map/npc.h
index 16e6fe74c..4c904e1ac 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -2,17 +2,32 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _NPC_H_
-#define _NPC_H_
+#ifndef MAP_NPC_H
+#define MAP_NPC_H
#include "map.h" // struct block_list
#include "status.h" // struct status_change
#include "unit.h" // struct unit_data
-struct block_list;
-struct npc_data;
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+
+struct HPluginData;
struct view_data;
-struct unit_data npc_base_ud;
+enum npc_parse_options {
+ NPO_NONE = 0x0,
+ NPO_ONINIT = 0x1,
+ NPO_TRADER = 0x2,
+};
+
+enum npc_shop_types {
+ NST_ZENY,/* default */
+ NST_CASH,/* official npc cash shop */
+ NST_MARKET,/* official npc market type */
+ NST_CUSTOM,
+ /* */
+ NST_MAX,
+};
struct npc_timerevent_list {
int timer,pos;
@@ -22,9 +37,16 @@ struct npc_label_list {
int pos;
};
struct npc_item_list {
- unsigned int nameid,value;
+ unsigned short nameid;
+ unsigned int value;
+ unsigned int qty;
};
-
+struct npc_shop_data {
+ unsigned char type;/* what am i */
+ struct npc_item_list *item;/* list */
+ unsigned short items;/* total */
+};
+struct npc_parse;
struct npc_data {
struct block_list bl;
struct unit_data *ud;
@@ -37,7 +59,7 @@ struct npc_data {
char exname[NAME_LENGTH+1];// unique npc name
int chat_id;
int touching_id;
- unsigned int next_walktime;
+ int64 next_walktime;
uint8 dir;
unsigned size : 2;
@@ -46,7 +68,7 @@ struct npc_data {
unsigned short level;
unsigned short stat_point;
- void* chatdb; // pointer to a npc_parse struct (see npc_chat.c)
+ struct npc_parse *chatdb;
char* path;/* path dir */
enum npc_subtype subtype;
int src_id;
@@ -56,14 +78,17 @@ struct npc_data {
short xs,ys; // OnTouch area radius
int guild_id;
int timer,timerid,timeramount,rid;
- unsigned int timertick;
+ int64 timertick;
struct npc_timerevent_list *timer_event;
int label_list_num;
struct npc_label_list *label_list;
+ /* */
+ struct npc_shop_data *shop;
+ bool trader;
} scr;
- struct {
+ struct { /* TODO duck this as soon as the new shop formatting is deemed stable */
struct npc_item_list* shop_item;
- int count;
+ unsigned short count;
} shop;
struct {
short xs,ys; // OnTouch area radius
@@ -76,14 +101,15 @@ struct npc_data {
char killer_name[NAME_LENGTH];
} tomb;
} u;
+ /* HPData Support for npc_data */
+ struct HPluginData **hdata;
+ unsigned int hdatac;
};
-
#define START_NPC_NUM 110000000
-enum actor_classes
-{
+enum actor_classes {
WARP_CLASS = 45,
HIDDEN_WARP_CLASS = 139,
WARP_DEBUG_CLASS = 722,
@@ -95,15 +121,11 @@ enum actor_classes
#define MAX_NPC_CLASS 1000
// New NPC range
#define MAX_NPC_CLASS2_START 10000
-#define MAX_NPC_CLASS2_END 10049
+#define MAX_NPC_CLASS2_END 10110
//Checks if a given id is a valid npc id. [Skotlex]
//Since new npcs are added all the time, the max valid value is the one before the first mob (Scorpion = 1001)
-#define npcdb_checkid(id) ( ( (id) >= 46 && (id) <= 125) || (id) == HIDDEN_WARP_CLASS || ( (id) > 400 && (id) < MAX_NPC_CLASS ) || (id) == INVISIBLE_CLASS || ( (id) > 10000 && (id) < 10049 ) )
-
-#ifdef PCRE_SUPPORT
-void npc_chat_finalize(struct npc_data* nd);
-#endif
+#define npcdb_checkid(id) ( ( (id) >= 46 && (id) <= 125) || (id) == HIDDEN_WARP_CLASS || ( (id) > 400 && (id) < MAX_NPC_CLASS ) || (id) == INVISIBLE_CLASS || ( (id) > MAX_NPC_CLASS2_START && (id) < MAX_NPC_CLASS2_END ) )
//Script NPC events.
enum npce_event {
@@ -117,89 +139,212 @@ enum npce_event {
NPCE_KILLNPC,
NPCE_MAX
};
-struct view_data* npc_get_viewdata(int class_);
-int npc_chat_sub(struct block_list* bl, va_list ap);
-int npc_event_dequeue(struct map_session_data* sd);
-int npc_event(struct map_session_data* sd, const char* eventname, int ontouch);
-int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y);
-int npc_touch_areanpc2(struct mob_data *md); // [Skotlex]
-int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range);
-int npc_touchnext_areanpc(struct map_session_data* sd,bool leavemap);
-int npc_click(struct map_session_data* sd, struct npc_data* nd);
-int npc_scriptcont(struct map_session_data* sd, int id, bool closing);
-struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* bl);
-int npc_buysellsel(struct map_session_data* sd, int id, int type);
-int npc_buylist(struct map_session_data* sd,int n, unsigned short* item_list);
-int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list);
-void npc_parse_mob2(struct spawn_data* mob);
-const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath);
-struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y);
-int npc_globalmessage(const char* name,const char* mes);
-
-void npc_setcells(struct npc_data* nd);
-void npc_unsetcells(struct npc_data* nd);
-void npc_movenpc(struct npc_data* nd, int16 x, int16 y);
-int npc_enable(const char* name, int flag);
-void npc_setdisplayname(struct npc_data* nd, const char* newname);
-void npc_setclass(struct npc_data* nd, short class_);
-struct npc_data* npc_name2id(const char* name);
-bool npc_isnear(struct block_list * bl);
-
-int npc_get_new_npc_id(void);
-
-void npc_addsrcfile(const char* name);
-void npc_delsrcfile(const char* name);
-void npc_parsesrcfile(const char* filepath, bool runOnInit);
-void do_clear_npc(void);
-int do_final_npc(void);
-int do_init_npc(void);
-void npc_event_do_oninit(void);
-int npc_do_ontimer(int npc_id, int option);
-
-int npc_event_do(const char* name);
-int npc_event_doall(const char* name);
-int npc_event_doall_id(const char* name, int rid);
-
-int npc_timerevent_start(struct npc_data* nd, int rid);
-int npc_timerevent_stop(struct npc_data* nd);
-void npc_timerevent_quit(struct map_session_data* sd);
-int npc_gettimerevent_tick(struct npc_data* nd);
-int npc_settimerevent_tick(struct npc_data* nd, int newtimer);
-int npc_remove_map(struct npc_data* nd);
-void npc_unload_duplicates (struct npc_data* nd);
-int npc_unload(struct npc_data* nd, bool single);
-int npc_reload(void);
-void npc_read_event_script(void);
-int npc_script_event(struct map_session_data* sd, enum npce_event type);
-
-int npc_duplicate4instance(struct npc_data *snd, int16 m);
-int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points);
-
-extern struct npc_data* fake_nd;
-
-int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short* item_list);
-/**
- * For the Secure NPC Timeout option (check config/Secure.h) [RR]
- **/
-#ifdef SECURE_NPCTIMEOUT
- int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data);
-#endif
+// linked list of npc source files
+struct npc_src_list {
+ struct npc_src_list* next;
+ char name[4]; // dynamic array, the structure is allocated with extra bytes (string length)
+};
-// @commands (script-based)
-int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const char* message, const char* eventname);
+struct event_data {
+ struct npc_data *nd;
+ int pos;
+};
-bool npc_unloadfile( const char* path );
+struct npc_path_data {
+ char* path;
+ unsigned short references;
+};
-/* npc.c interface (barely started/WIP) */
+/* npc.c interface */
struct npc_interface {
/* */
struct npc_data *motd;
+ DBMap *ev_db; // const char* event_name -> struct event_data*
+ DBMap *ev_label_db; // const char* label_name (without leading "::") -> struct linkdb_node** (key: struct npc_data*; data: struct event_data*)
+ DBMap *name_db; // const char* npc_name -> struct npc_data*
+ DBMap *path_db;
+ struct eri *timer_event_ers; //For the npc timer data. [Skotlex]
+ struct npc_data *fake_nd;
+ struct npc_src_list *src_files;
+ struct unit_data base_ud;
+ /* npc trader global data, for ease of transition between the script, cleared on every usage */
+ bool trader_ok;
+ int trader_funds[2];
+ /* */
+ int (*init) (bool minimal);
+ int (*final) (void);
+ /* */
+ int (*get_new_npc_id) (void);
+ struct view_data* (*get_viewdata) (int class_);
+ int (*isnear_sub) (struct block_list *bl, va_list args);
+ bool (*isnear) (struct block_list *bl);
+ int (*ontouch_event) (struct map_session_data *sd, struct npc_data *nd);
+ int (*ontouch2_event) (struct map_session_data *sd, struct npc_data *nd);
+ int (*enable_sub) (struct block_list *bl, va_list ap);
+ int (*enable) (const char *name, int flag);
+ struct npc_data* (*name2id) (const char *name);
+ int (*event_dequeue) (struct map_session_data *sd);
+ DBData (*event_export_create) (DBKey key, va_list args);
+ int (*event_export) (struct npc_data *nd, int i);
+ int (*event_sub) (struct map_session_data *sd, struct event_data *ev, const char *eventname);
+ void (*event_doall_sub) (void *key, void *data, va_list ap);
+ int (*event_do) (const char *name);
+ int (*event_doall_id) (const char *name, int rid);
+ int (*event_doall) (const char *name);
+ int (*event_do_clock) (int tid, int64 tick, int id, intptr_t data);
+ void (*event_do_oninit) ( bool reload );
+ int (*timerevent_export) (struct npc_data *nd, int i);
+ int (*timerevent) (int tid, int64 tick, int id, intptr_t data);
+ int (*timerevent_start) (struct npc_data *nd, int rid);
+ int (*timerevent_stop) (struct npc_data *nd);
+ void (*timerevent_quit) (struct map_session_data *sd);
+ int64 (*gettimerevent_tick) (struct npc_data *nd);
+ int (*settimerevent_tick) (struct npc_data *nd, int newtimer);
+ int (*event) (struct map_session_data *sd, const char *eventname, int ontouch);
+ int (*touch_areanpc_sub) (struct block_list *bl, va_list ap);
+ int (*touchnext_areanpc) (struct map_session_data *sd, bool leavemap);
+ int (*touch_areanpc) (struct map_session_data *sd, int16 m, int16 x, int16 y);
+ int (*touch_areanpc2) (struct mob_data *md);
+ int (*check_areanpc) (int flag, int16 m, int16 x, int16 y, int16 range);
+ struct npc_data* (*checknear) (struct map_session_data *sd, struct block_list *bl);
+ int (*globalmessage) (const char *name, const char *mes);
+ void (*run_tomb) (struct map_session_data *sd, struct npc_data *nd);
+ int (*click) (struct map_session_data *sd, struct npc_data *nd);
+ int (*scriptcont) (struct map_session_data *sd, int id, bool closing);
+ int (*buysellsel) (struct map_session_data *sd, int id, int type);
+ int (*cashshop_buylist) (struct map_session_data *sd, int points, int count, unsigned short *item_list);
+ int (*buylist_sub) (struct map_session_data *sd, int n, unsigned short *item_list, struct npc_data *nd);
+ int (*cashshop_buy) (struct map_session_data *sd, int nameid, int amount, int points);
+ int (*buylist) (struct map_session_data *sd, int n, unsigned short *item_list);
+ int (*selllist_sub) (struct map_session_data *sd, int n, unsigned short *item_list, struct npc_data *nd);
+ int (*selllist) (struct map_session_data *sd, int n, unsigned short *item_list);
+ int (*remove_map) (struct npc_data *nd);
+ int (*unload_ev) (DBKey key, DBData *data, va_list ap);
+ int (*unload_ev_label) (DBKey key, DBData *data, va_list ap);
+ int (*unload_dup_sub) (struct npc_data *nd, va_list args);
+ void (*unload_duplicates) (struct npc_data *nd);
+ int (*unload) (struct npc_data *nd, bool single);
+ void (*clearsrcfile) (void);
+ void (*addsrcfile) (const char *name);
+ void (*delsrcfile) (const char *name);
+ void (*parsename) (struct npc_data *nd, const char *name, const char *start, const char *buffer, const char *filepath);
+ int (*parseview) (const char *w4, const char *start, const char *buffer, const char *filepath);
+ bool (*viewisid) (const char *viewid);
+ struct npc_data* (*add_warp) (char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y);
+ const char* (*parse_warp) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ const char* (*parse_shop) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ void (*convertlabel_db) (struct npc_label_list *label_list, const char *filepath);
+ const char* (*skip_script) (const char *start, const char *buffer, const char *filepath, int *retval);
+ const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options, int *retval);
+ const char* (*parse_duplicate) (char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval);
+ int (*duplicate4instance) (struct npc_data *snd, int16 m);
+ void (*setcells) (struct npc_data *nd);
+ int (*unsetcells_sub) (struct block_list *bl, va_list ap);
+ void (*unsetcells) (struct npc_data *nd);
+ void (*movenpc) (struct npc_data *nd, int16 x, int16 y);
+ void (*setdisplayname) (struct npc_data *nd, const char *newname);
+ void (*setclass) (struct npc_data *nd, short class_);
+ int (*do_atcmd_event) (struct map_session_data *sd, const char *command, const char *message, const char *eventname);
+ const char* (*parse_function) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ void (*parse_mob2) (struct spawn_data *mobspawn);
+ const char* (*parse_mob) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ const char* (*parse_mapflag) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ int (*parsesrcfile) (const char *filepath, bool runOnInit);
+ int (*script_event) (struct map_session_data *sd, enum npce_event type);
+ void (*read_event_script) (void);
+ int (*path_db_clear_sub) (DBKey key, DBData *data, va_list args);
+ int (*ev_label_db_clear_sub) (DBKey key, DBData *data, va_list args);
+ int (*reload) (void);
+ bool (*unloadfile) (const char *filepath);
+ void (*do_clear_npc) (void);
+ void (*debug_warps_sub) (struct npc_data *nd);
+ void (*debug_warps) (void);
/* */
-} npc_s;
+ void (*trader_count_funds) (struct npc_data *nd, struct map_session_data *sd);
+ bool (*trader_pay) (struct npc_data *nd, struct map_session_data *sd, int price, int points);
+ void (*trader_update) (int master);
+ int (*market_buylist) (struct map_session_data* sd, unsigned short list_size, struct packet_npc_market_purchase *p);
+ bool (*trader_open) (struct map_session_data *sd, struct npc_data *nd);
+ void (*market_fromsql) (void);
+ void (*market_tosql) (struct npc_data *nd, unsigned short index);
+ void (*market_delfromsql) (struct npc_data *nd, unsigned short index);
+ void (*market_delfromsql_sub) (const char *npcname, unsigned short index);
+ /**
+ * For the Secure NPC Timeout option (check config/Secure.h) [RR]
+ **/
+ int (*secure_timeout_timer) (int tid, int64 tick, int id, intptr_t data);
+};
struct npc_interface *npc;
void npc_defaults(void);
-#endif /* _NPC_H_ */
+
+/* comes from npc_chat.c */
+#ifdef PCRE_SUPPORT
+#include "../../3rdparty/pcre/include/pcre.h"
+/* Structure containing all info associated with a single pattern block */
+struct pcrematch_entry {
+ struct pcrematch_entry* next;
+ char* pattern;
+ pcre* pcre_;
+ pcre_extra* pcre_extra_;
+ char* label;
+};
+
+/* A set of patterns that can be activated and deactived with a single command */
+struct pcrematch_set {
+ struct pcrematch_set* prev;
+ struct pcrematch_set* next;
+ struct pcrematch_entry* head;
+ int setid;
+};
+
+/*
+ * Entire data structure hung off a NPC
+ */
+struct npc_parse {
+ struct pcrematch_set* active;
+ struct pcrematch_set* inactive;
+};
+
+struct npc_chat_interface {
+ int (*sub) (struct block_list* bl, va_list ap);
+ void (*finalize) (struct npc_data* nd);
+ void (*def_pattern) (struct npc_data* nd, int setid, const char* pattern, const char* label);
+ struct pcrematch_entry* (*create_pcrematch_entry) (struct pcrematch_set* set);
+ void (*delete_pcreset) (struct npc_data* nd, int setid);
+ void (*deactivate_pcreset) (struct npc_data* nd, int setid);
+ void (*activate_pcreset) (struct npc_data* nd, int setid);
+ struct pcrematch_set* (*lookup_pcreset) (struct npc_data* nd, int setid);
+ void (*finalize_pcrematch_entry) (struct pcrematch_entry* e);
+};
+
+struct npc_chat_interface *npc_chat;
+
+/**
+ * pcre interface (libpcre)
+ * so that plugins may share and take advantage of the core's pcre
+ * should be moved into core/perhaps its own file once hpm is enhanced for login/char
+ **/
+struct pcre_interface {
+ pcre *(*compile) (const char *pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr);
+ pcre_extra *(*study) (const pcre *code, int options, const char **errptr);
+ int (*exec) (const pcre *code, const pcre_extra *extra, PCRE_SPTR subject, int length, int startoffset, int options, int *ovector, int ovecsize);
+ void (*free) (void *ptr);
+ int (*copy_substring) (const char *subject, int *ovector, int stringcount, int stringnumber, char *buffer, int buffersize);
+ void (*free_substring) (const char *stringptr);
+ int (*copy_named_substring) (const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, char *buffer, int buffersize);
+ int (*get_substring) (const char *subject, int *ovector, int stringcount, int stringnumber, const char **stringptr);
+};
+
+struct pcre_interface *libpcre;
+
+/**
+ * Also defaults libpcre
+ **/
+void npc_chat_defaults(void);
+#endif
+
+#endif /* MAP_NPC_H */
diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c
index c7faa2df6..8bc246819 100644
--- a/src/map/npc_chat.c
+++ b/src/map/npc_chat.c
@@ -2,25 +2,33 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifdef PCRE_SUPPORT
+#define HERCULES_CORE
-#include "../common/timer.h"
-#include "../common/malloc.h"
-#include "../common/nullpo.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
+#ifdef PCRE_SUPPORT
-#include "mob.h" // struct mob_data
#include "npc.h" // struct npc_data
-#include "pc.h" // struct map_session_data
-#include "script.h" // set_var()
-
-#include "../../3rdparty/pcre/include/pcre.h"
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdarg.h>
+
+#include "../../3rdparty/pcre/include/pcre.h"
+
+#include "mob.h" // struct mob_data
+#include "pc.h" // struct map_session_data
+#include "script.h" // set_var()
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+
+/**
+ * interface sources
+ **/
+struct npc_chat_interface npc_chat_s;
+struct pcre_interface libpcre_s;
/**
@@ -41,7 +49,7 @@
*
* defpattern 1, "[^:]+: (.*) loves (.*)", "label";
*
- * this defines a new pattern in set 1 using perl syntax
+ * this defines a new pattern in set 1 using perl syntax
* (http://www.troubleshooters.com/codecorn/littperl/perlreg.htm)
* and tells it to jump to the supplied label when the pattern
* is matched.
@@ -51,7 +59,7 @@
* before the script gets executed.
*
* activatepset 1;
- *
+ *
* This activates a set of patterns.. You can have many pattern
* sets defined and many active all at once. This feature allows
* you to set up "conversations" and ever changing expectations of
@@ -70,47 +78,16 @@
* deletes a pset
*/
-/* Structure containing all info associated with a single pattern block */
-struct pcrematch_entry {
- struct pcrematch_entry* next;
- char* pattern;
- pcre* pcre_;
- pcre_extra* pcre_extra_;
- char* label;
-};
-
-/* A set of patterns that can be activated and deactived with a single command */
-struct pcrematch_set {
- struct pcrematch_set* prev;
- struct pcrematch_set* next;
- struct pcrematch_entry* head;
- int setid;
-};
-
-/*
- * Entire data structure hung off a NPC
- *
- * The reason I have done it this way (a void * in npc_data and then
- * this) was to reduce the number of patches that needed to be applied
- * to a ragnarok distribution to bring this code online. I
- * also wanted people to be able to grab this one file to get updates
- * without having to do a large number of changes.
- */
-struct npc_parse {
- struct pcrematch_set* active;
- struct pcrematch_set* inactive;
-};
-
/**
- * delete everythign associated with a entry
+ * delete everything associated with a entry
*
* This does NOT do the list management
*/
void finalize_pcrematch_entry(struct pcrematch_entry* e)
{
- pcre_free(e->pcre_);
- pcre_free(e->pcre_extra_);
+ libpcre->free(e->pcre_);
+ libpcre->free(e->pcre_extra_);
aFree(e->pattern);
aFree(e->label);
}
@@ -118,12 +95,11 @@ void finalize_pcrematch_entry(struct pcrematch_entry* e)
/**
* Lookup (and possibly create) a new set of patterns by the set id
*/
-static struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid)
-{
+struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid) {
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
- if (npcParse == NULL)
- nd->chatdb = npcParse = (struct npc_parse *) aCalloc(sizeof(struct npc_parse), 1);
+ struct npc_parse *npcParse = nd->chatdb;
+ if (npcParse == NULL)
+ nd->chatdb = npcParse = (struct npc_parse *)aCalloc(sizeof(struct npc_parse), 1);
pcreset = npcParse->active;
@@ -132,7 +108,7 @@ static struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid)
break;
pcreset = pcreset->next;
}
- if (pcreset == NULL)
+ if (pcreset == NULL)
pcreset = npcParse->inactive;
while (pcreset != NULL) {
@@ -142,7 +118,7 @@ static struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid)
}
if (pcreset == NULL) {
- pcreset = (struct pcrematch_set *) aCalloc(sizeof(struct pcrematch_set), 1);
+ pcreset = (struct pcrematch_set *)aCalloc(sizeof(struct pcrematch_set), 1);
pcreset->next = npcParse->inactive;
if (pcreset->next != NULL)
pcreset->next->prev = pcreset;
@@ -159,11 +135,11 @@ static struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid)
*
* if the setid does not exist, this will silently return
*/
-static void activate_pcreset(struct npc_data* nd, int setid)
+void activate_pcreset(struct npc_data* nd, int setid)
{
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
- if (npcParse == NULL)
+ struct npc_parse *npcParse = nd->chatdb;
+ if (npcParse == NULL)
return; // Nothing to activate...
pcreset = npcParse->inactive;
while (pcreset != NULL) {
@@ -177,7 +153,7 @@ static void activate_pcreset(struct npc_data* nd, int setid)
pcreset->next->prev = pcreset->prev;
if (pcreset->prev != NULL)
pcreset->prev->next = pcreset->next;
- else
+ else
npcParse->inactive = pcreset->next;
pcreset->prev = NULL;
@@ -192,15 +168,15 @@ static void activate_pcreset(struct npc_data* nd, int setid)
*
* if the setid does not exist, this will silently return
*/
-static void deactivate_pcreset(struct npc_data* nd, int setid)
+void deactivate_pcreset(struct npc_data* nd, int setid)
{
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
- if (npcParse == NULL)
+ struct npc_parse *npcParse = nd->chatdb;
+ if (npcParse == NULL)
return; // Nothing to deactivate...
if (setid == -1) {
while(npcParse->active != NULL)
- deactivate_pcreset(nd, npcParse->active->setid);
+ npc_chat->deactivate_pcreset(nd, npcParse->active->setid);
return;
}
pcreset = npcParse->active;
@@ -215,7 +191,7 @@ static void deactivate_pcreset(struct npc_data* nd, int setid)
pcreset->next->prev = pcreset->prev;
if (pcreset->prev != NULL)
pcreset->prev->next = pcreset->next;
- else
+ else
npcParse->active = pcreset->next;
pcreset->prev = NULL;
@@ -228,12 +204,12 @@ static void deactivate_pcreset(struct npc_data* nd, int setid)
/**
* delete a set of patterns.
*/
-static void delete_pcreset(struct npc_data* nd, int setid)
+void delete_pcreset(struct npc_data* nd, int setid)
{
int active = 1;
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
- if (npcParse == NULL)
+ struct npc_parse *npcParse = nd->chatdb;
+ if (npcParse == NULL)
return; // Nothing to deactivate...
pcreset = npcParse->active;
while (pcreset != NULL) {
@@ -250,7 +226,7 @@ static void delete_pcreset(struct npc_data* nd, int setid)
pcreset = pcreset->next;
}
}
- if (pcreset == NULL)
+ if (pcreset == NULL)
return;
if (pcreset->next != NULL)
@@ -268,8 +244,8 @@ static void delete_pcreset(struct npc_data* nd, int setid)
while (pcreset->head) {
struct pcrematch_entry* n = pcreset->head->next;
- finalize_pcrematch_entry(pcreset->head);
- aFree(pcreset->head); // Cleanin' the last ones.. [Lance]
+ npc_chat->finalize_pcrematch_entry(pcreset->head);
+ aFree(pcreset->head); // Cleaning the last ones.. [Lance]
pcreset->head = n;
}
@@ -277,9 +253,9 @@ static void delete_pcreset(struct npc_data* nd, int setid)
}
/**
- * create a new pattern entry
+ * create a new pattern entry
*/
-static struct pcrematch_entry* create_pcrematch_entry(struct pcrematch_set* set)
+struct pcrematch_entry* create_pcrematch_entry(struct pcrematch_set* set)
{
struct pcrematch_entry * e = (struct pcrematch_entry *) aCalloc(sizeof(struct pcrematch_entry), 1);
struct pcrematch_entry * last = set->head;
@@ -313,31 +289,31 @@ void npc_chat_def_pattern(struct npc_data* nd, int setid, const char* pattern, c
const char *err;
int erroff;
- struct pcrematch_set * s = lookup_pcreset(nd, setid);
- struct pcrematch_entry *e = create_pcrematch_entry(s);
+ struct pcrematch_set * s = npc_chat->lookup_pcreset(nd, setid);
+ struct pcrematch_entry *e = npc_chat->create_pcrematch_entry(s);
e->pattern = aStrdup(pattern);
e->label = aStrdup(label);
- e->pcre_ = pcre_compile(pattern, PCRE_CASELESS, &err, &erroff, NULL);
- e->pcre_extra_ = pcre_study(e->pcre_, 0, &err);
+ e->pcre_ = libpcre->compile(pattern, PCRE_CASELESS, &err, &erroff, NULL);
+ e->pcre_extra_ = libpcre->study(e->pcre_, 0, &err);
}
/**
* Delete everything associated with a NPC concerning the pattern
- * matching code
+ * matching code
*
- * this could be more efficent but.. how often do you do this?
+ * this could be more efficient but.. how often do you do this?
*/
void npc_chat_finalize(struct npc_data* nd)
{
- struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb;
+ struct npc_parse *npcParse = nd->chatdb;
if (npcParse == NULL)
return;
while(npcParse->active)
- delete_pcreset(nd, npcParse->active->setid);
+ npc_chat->delete_pcreset(nd, npcParse->active->setid);
while(npcParse->inactive)
- delete_pcreset(nd, npcParse->inactive->setid);
+ npc_chat->delete_pcreset(nd, npcParse->inactive->setid);
// Additional cleaning up [Lance]
aFree(npcParse);
@@ -348,8 +324,8 @@ void npc_chat_finalize(struct npc_data* nd)
*/
int npc_chat_sub(struct block_list* bl, va_list ap)
{
- struct npc_data* nd = (struct npc_data *) bl;
- struct npc_parse* npcParse = (struct npc_parse *) nd->chatdb;
+ struct npc_data *nd = (struct npc_data *) bl;
+ struct npc_parse *npcParse = nd->chatdb;
char* msg;
int len, i;
struct map_session_data* sd;
@@ -368,13 +344,13 @@ int npc_chat_sub(struct block_list* bl, va_list ap)
// iterate across all active sets
for (pcreset = npcParse->active; pcreset != NULL; pcreset = pcreset->next)
{
- // interate across all patterns in that set
+ // n across all patterns in that set
for (e = pcreset->head; e != NULL; e = e->next)
{
- int offsets[2*10 + 10]; // 1/3 reserved for temp space requred by pcre_exec
+ int offsets[2*10 + 10]; // 1/3 reserved for temp space required by pcre_exec
// perform pattern match
- int r = pcre_exec(e->pcre_, e->pcre_extra_, msg, len, 0, 0, offsets, ARRAYLENGTH(offsets));
+ int r = libpcre->exec(e->pcre_, e->pcre_extra_, msg, len, 0, 0, offsets, ARRAYLENGTH(offsets));
if (r > 0)
{
// save out the matched strings
@@ -382,20 +358,20 @@ int npc_chat_sub(struct block_list* bl, va_list ap)
{
char var[6], val[255];
snprintf(var, sizeof(var), "$@p%i$", i);
- pcre_copy_substring(msg, offsets, r, i, val, sizeof(val));
- set_var(sd, var, val);
+ libpcre->copy_substring(msg, offsets, r, i, val, sizeof(val));
+ script->set_var(sd, var, val);
}
// find the target label.. this sucks..
lst = nd->u.scr.label_list;
ARR_FIND(0, nd->u.scr.label_list_num, i, strncmp(lst[i].name, e->label, sizeof(lst[i].name)) == 0);
if (i == nd->u.scr.label_list_num) {
- ShowWarning("Unable to find label: %s\n", e->label);
+ ShowWarning("npc_chat_sub: Unable to find label: %s\n", e->label);
return 0;
}
// run the npc script
- run_script(nd->u.scr.script,lst[i].pos,sd->bl.id,nd->bl.id);
+ script->run(nd->u.scr.script,lst[i].pos,sd->bl.id,nd->bl.id);
return 0;
}
}
@@ -404,48 +380,68 @@ int npc_chat_sub(struct block_list* bl, va_list ap)
return 0;
}
-// Various script builtins used to support these functions
+// Various script built-ins used to support these functions
+BUILDIN(defpattern) {
+ int setid = script_getnum(st,2);
+ const char* pattern = script_getstr(st,3);
+ const char* label = script_getstr(st,4);
+ struct npc_data* nd = (struct npc_data *)map->id2bl(st->oid);
+
+ npc_chat->def_pattern(nd, setid, pattern, label);
-int buildin_defpattern(struct script_state* st)
-{
- int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2]));
- const char* pattern = script->conv_str(st,& (st->stack->stack_data[st->start+3]));
- const char* label = script->conv_str(st,& (st->stack->stack_data[st->start+4]));
- struct npc_data* nd = (struct npc_data *)iMap->id2bl(st->oid);
-
- npc_chat_def_pattern(nd, setid, pattern, label);
-
- return 1;
+ return true;
}
-int buildin_activatepset(struct script_state* st)
-{
- int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2]));
- struct npc_data* nd = (struct npc_data *)iMap->id2bl(st->oid);
-
- activate_pcreset(nd, setid);
+BUILDIN(activatepset) {
+ int setid = script_getnum(st,2);
+ struct npc_data* nd = (struct npc_data *)map->id2bl(st->oid);
- return 1;
+ npc_chat->activate_pcreset(nd, setid);
+
+ return true;
}
-int buildin_deactivatepset(struct script_state* st)
-{
- int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2]));
- struct npc_data* nd = (struct npc_data *)iMap->id2bl(st->oid);
+BUILDIN(deactivatepset) {
+ int setid = script_getnum(st,2);
+ struct npc_data* nd = (struct npc_data *)map->id2bl(st->oid);
- deactivate_pcreset(nd, setid);
+ npc_chat->deactivate_pcreset(nd, setid);
- return 1;
+ return true;
}
-int buildin_deletepset(struct script_state* st)
-{
- int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2]));
- struct npc_data* nd = (struct npc_data *)iMap->id2bl(st->oid);
-
- delete_pcreset(nd, setid);
+BUILDIN(deletepset) {
+ int setid = script_getnum(st,2);
+ struct npc_data* nd = (struct npc_data *)map->id2bl(st->oid);
- return 1;
+ npc_chat->delete_pcreset(nd, setid);
+
+ return true;
+}
+
+void npc_chat_defaults(void) {
+ npc_chat = &npc_chat_s;
+
+ npc_chat->sub = npc_chat_sub;
+ npc_chat->finalize = npc_chat_finalize;
+ npc_chat->def_pattern = npc_chat_def_pattern;
+ npc_chat->create_pcrematch_entry = create_pcrematch_entry;
+ npc_chat->delete_pcreset = delete_pcreset;
+ npc_chat->deactivate_pcreset = deactivate_pcreset;
+ npc_chat->activate_pcreset = activate_pcreset;
+ npc_chat->lookup_pcreset = lookup_pcreset;
+ npc_chat->finalize_pcrematch_entry = finalize_pcrematch_entry;
+
+ libpcre = &libpcre_s;
+
+ libpcre->compile = pcre_compile;
+ libpcre->study = pcre_study;
+ libpcre->exec = pcre_exec;
+ libpcre->free = pcre_free;
+ libpcre->copy_substring = pcre_copy_substring;
+ libpcre->free_substring = pcre_free_substring;
+ libpcre->copy_named_substring = pcre_copy_named_substring;
+ libpcre->get_substring = pcre_get_substring;
}
#endif //PCRE_SUPPORT
diff --git a/src/map/packets.h b/src/map/packets.h
index c467090dd..810f341d4 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -3,8 +3,8 @@
//Included directly by clif.h in packet_loaddb()
-#ifndef _PACKETS_H_
-#define _PACKETS_H_
+#ifndef MAP_PACKETS_H
+#define MAP_PACKETS_H
#ifndef packet
#define packet(a,b,...)
@@ -1613,7 +1613,7 @@ packet(0x020d,-1);
//2009-10-27aRagexeRE
#if PACKETVER >= 20091027
- packet(0x07f5,6,clif->pGMReqAccountName,2);
+ packet(0x07f5,6,clif->pGMFullStrip,2);
packet(0x07f6,14);
#endif
@@ -1971,14 +1971,14 @@ packet(0x020d,-1);
#ifndef PACKETVER_RE
packet(0x091D,18,clif->pPartyBookingRegisterReq,2,4,6);
#else
- packet(0x08E5,41,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x08E5,41,clif->pPartyRecruitRegisterReq,2,4);
#endif
packet(0x08E6,4);
- packet(0x08E7,10,clif->pPartyBookingSearchReq,2);
+ packet(0x08E7,10,clif->pPartyRecruitSearchReq,2);
packet(0x08E8,-1);
- packet(0x08E9,2,clif->pPartyBookingDeleteReq,2);
+ packet(0x08E9,2,clif->pPartyRecruitDeleteReq,2);
packet(0x08EA,4);
- packet(0x08EB,39,clif->pPartyBookingUpdateReq,2);
+ packet(0x08EB,39,clif->pPartyRecruitUpdateReq,2);
packet(0x08EC,73);
packet(0x08ED,43);
packet(0x08EE,6);
@@ -2022,16 +2022,14 @@ packet(0x020d,-1);
packet(0x0364,8,clif->pMoveFromKafra,2,4);
packet(0x096A,6,clif->pGetCharNameRequest,2);
packet(0x0368,6,clif->pSolveCharName,2);
- packet(0x08E5,41,clif->pPartyBookingRegisterReq,2,4);
+ packet(0x08E5,41,clif->pPartyRecruitRegisterReq,2,4);
packet(0x08d2,10);
packet(0x0916,26,clif->pGuildInvite2,2);
- packetKeys(0x1540e48,0x13041224,0x31247924);
-
#endif
#ifndef PACKETVER_RE
#if PACKETVER >= 20120604
- packet(0x0861,18,clif->pPartyBookingRegisterReq,2,4,6);
+ packet(0x0861,18,clif->pPartyRecruitRegisterReq,2,4,6);
#endif
#endif
@@ -2065,10 +2063,36 @@ packet(0x020d,-1);
packet(0x0886,2,clif->pReqCloseBuyingStore,0);
#endif
-//2012-07-16aRagExe (special thanks to Yommy!)
+//2012-07-16aRagExe (special thanks to Yommy/Frost!)
#if PACKETVER >= 20120716
+ packet(0x0879,18,clif->pPartyBookingRegisterReq,2,4,6);
+ packet(0x023B,26,clif->pFriendsListAdd,2);
+ packet(0x0361,5,clif->pHomMenu,2,4);
+ packet(0x0819,36,clif->pStoragePassword,0);
+ packet(0x0802,26,clif->pPartyInvite2,2);
+ packet(0x022D,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0439,8,clif->pUseItem,2,4);
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0360,6,clif->pReqClickBuyingStore,2);
+ packet(0x0940,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0811,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x0202,5,clif->pChangeDir,2,4);
+ packet(0x07E4,6,clif->pTakeItem,2);
+ packet(0x0362,6,clif->pDropItem,2,4);
+ packet(0x07EC,8,clif->pMoveToKafra,2,4);
packet(0x0364,8,clif->pMoveFromKafra,2,4);
- packetKeys(0x76052205, 0x22052205, 0x22052205);
+ packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x096A,6,clif->pGetCharNameRequest,2);
+ packet(0x0368,6,clif->pSolveCharName,2);
#endif
//2013-03-20Ragexe (Judas + Yommy)
@@ -2094,7 +2118,11 @@ packet(0x020d,-1);
packet(0x035F,6,clif->pReqClickBuyingStore,2);
packet(0x0886,2,clif->pReqCloseBuyingStore,0);
packet(0x0938,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- packet(0x085D,41,clif->pPartyBookingRegisterReq,2,4);
+#ifdef PACKETVER_RE
+ packet(0x085D,41,clif->pPartyRecruitRegisterReq,2,4);
+#else // not PACKETVER_RE
+ packet(0x085D,18,clif->pPartyBookingRegisterReq,2,4);
+#endif // PACKETVER_RE
//packet(0x095A,8); // unknown usage
packet(0x0868,-1,clif->pItemListWindowSelected,2,4,8);
packet(0x0888,19,clif->pWantToConnection,2,6,10,14,18);
@@ -2103,7 +2131,6 @@ packet(0x020d,-1);
packet(0x086F,26,clif->pFriendsListAdd,2);
packet(0x093F,5,clif->pHomMenu,2,4);
packet(0x0947,36,clif->pStoragePassword,0);
- packetKeys(0x3F094C49, 0x55F86C1E, 0x58AA359A);
// Shuffle End
// New Packets
@@ -2136,7 +2163,11 @@ packet(0x020d,-1);
packet(0x0360,6,clif->pReqClickBuyingStore,2);
packet(0x0817,2,clif->pReqCloseBuyingStore,0);
packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- packet(0x092D,41,clif->pPartyBookingRegisterReq,2,4);
+#ifdef PACKETVER_RE
+ packet(0x092D,41,clif->pPartyRecruitRegisterReq,2,4);
+#else // not PACKETVER_RE
+ packet(0x092D,18,clif->pPartyBookingRegisterReq,2,4);
+#endif // PACKETVER_RE
//packet(0x08AA,8); // CZ_JOIN_BATTLE_FIELD
packet(0x0963,-1,clif->pItemListWindowSelected,2,4,8);
packet(0x0943,19,clif->pWantToConnection,2,6,10,14,18);
@@ -2171,7 +2202,11 @@ packet(0x020d,-1);
packet(0x0368,6,clif->pReqClickBuyingStore,2);
packet(0x086E,2,clif->pReqCloseBuyingStore,0);
packet(0x0874,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- packet(0x089B,41,clif->pPartyBookingRegisterReq,2,4);
+#ifdef PACKETVER_RE
+ packet(0x089B,41,clif->pPartyRecruitRegisterReq,2,4);
+#else // not PACKETVER_RE
+ packet(0x089B,18,clif->pPartyBookingRegisterReq,2,4);
+#endif // PACKETVER_RE
//packet(0x0965,8); // CZ_JOIN_BATTLE_FIELD
packet(0x086A,-1,clif->pItemListWindowSelected,2,4,8);
packet(0x08A9,19,clif->pWantToConnection,2,6,10,14,18);
@@ -2205,7 +2240,11 @@ packet(0x020d,-1);
packet(0x0892,6,clif->pReqClickBuyingStore,2);
packet(0x0964,2,clif->pReqCloseBuyingStore,0);
packet(0x0869,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- packet(0x0874,41,clif->pPartyBookingRegisterReq,2,4);
+#ifdef PACKETVER_RE
+ packet(0x0874,41,clif->pPartyRecruitRegisterReq,2,4);
+#else // not PACKETVER_RE
+ packet(0x0874,18,clif->pPartyBookingRegisterReq,2,4);
+#endif // PACKETVER_RE
// packet(0x088E,8); // CZ_JOIN_BATTLE_FIELD
packet(0x0958,-1,clif->pItemListWindowSelected,2,4,8);
packet(0x0919,19,clif->pWantToConnection,2,6,10,14,18);
@@ -2238,7 +2277,11 @@ packet(0x020d,-1);
packet(0x0360,6,clif->pReqClickBuyingStore,2);
packet(0x0817,2,clif->pReqCloseBuyingStore,0);
packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- packet(0x0365,41,clif->pPartyBookingRegisterReq,2,4);
+#ifdef PACKETVER_RE
+ packet(0x0365,41,clif->pPartyRecruitRegisterReq,2,4);
+#else // not PACKETVER_RE
+ packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+#endif // PACKETVER_RE
// packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD
packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
packet(0x022D,19,clif->pWantToConnection,2,6,10,14,18);
@@ -2249,8 +2292,714 @@ packet(0x020d,-1);
packet(0x0883,36,clif->pStoragePassword,0);
#endif
+//2013-06-12Ragexe (Shakto)
+#if PACKETVER >= 20130612
+ packet(0x087E,5,clif->pChangeDir,2,4);
+ packet(0x0919,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0940,26,clif->pFriendsListAdd,2);
+ packet(0x093A,5,clif->pHomMenu,2,4);
+ packet(0x0964,36,clif->pStoragePassword,0);
+#endif
+
+//2013-06-18Ragexe (Shakto)
+#if PACKETVER >= 20130618
+ packet(0x0889,7,clif->pActionRequest,2,6);
+ packet(0x0951,10,clif->pUseSkillToId,2,4,6);
+ packet(0x088E,5,clif->pWalkToXY,2);
+ packet(0x0930,6,clif->pTickSend,2);
+ packet(0x08A6,5,clif->pChangeDir,2,4);
+ packet(0x0962,6,clif->pTakeItem,2);
+ packet(0x0917,6,clif->pDropItem,2,4);
+ packet(0x0885,8,clif->pMoveToKafra,2,4);
+ packet(0x0936,8,clif->pMoveFromKafra,2,4);
+ packet(0x096A,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x094F,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x0944,6,clif->pGetCharNameRequest,2);
+ packet(0x0945,6,clif->pSolveCharName,2);
+ packet(0x0890,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0363,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0281,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0891,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0862,6,clif->pReqClickBuyingStore,2);
+ packet(0x085A,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0932,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+#ifdef PACKETVER_RE
+ packet(0x08A7,41,clif->pPartyRecruitRegisterReq,2,4);
+#else // not PACKETVER_RE
+ packet(0x08A7,18,clif->pPartyBookingRegisterReq,2,4);
+#endif // PACKETVER_RE
+ // packet(0x087A,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0942,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x095B,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0887,26,clif->pPartyInvite2,2);
+ // packet(0x0878,4); // CZ_GANGSI_RANK
+ packet(0x0953,26,clif->pFriendsListAdd,2);
+ packet(0x02C4,5,clif->pHomMenu,2,4);
+ packet(0x0864,36,clif->pStoragePassword,0);
+#endif
+
+//2013-06-26Ragexe (Shakto)
+#if PACKETVER >= 20130626
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x094D,5,clif->pChangeDir,2,4);
+ packet(0x088B,6,clif->pTakeItem,2);
+ packet(0x0952,6,clif->pDropItem,2,4);
+ packet(0x0921,8,clif->pMoveToKafra,2,4);
+ packet(0x0817,8,clif->pMoveFromKafra,2,4);
+ packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x096A,6,clif->pGetCharNameRequest,2);
+ packet(0x0368,6,clif->pSolveCharName,2);
+ packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0360,6,clif->pReqClickBuyingStore,2);
+ packet(0x0365,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+#ifdef PACKETVER_RE
+ packet(0x0894,41,clif->pPartyRecruitRegisterReq,2,4);
+#else // not PACKETVER_RE
+ packet(0x0894,18,clif->pPartyBookingRegisterReq,2,4);
+#endif // PACKETVER_RE
+ // packet(0x0860,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x08A5,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x088C,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0895,26,clif->pPartyInvite2,2);
+ // packet(0x088F,4); // CZ_GANGSI_RANK
+ packet(0x08AB,26,clif->pFriendsListAdd,2);
+ packet(0x0960,5,clif->pHomMenu,2,4);
+ packet(0x0930,36,clif->pStoragePassword,0);
+#endif
+
+/* Bank System [Yommy/Hercules] */
+#if PACKETVER >= 20130724
+ packet(0x09A6,12); // ZC_BANKING_CHECK
+ packet(0x09A7,10,clif->pBankDeposit,2,4,6);
+ packet(0x09A8,16); // ZC_ACK_BANKING_DEPOSIT
+ packet(0x09A9,10,clif->pBankWithdraw,2,4,6);
+ packet(0x09AA,16); // ZC_ACK_BANKING_WITHDRAW
+ packet(0x09AB,6,clif->pBankCheck,2,4);
+ ////
+ packet(0x09B6,6,clif->pBankOpen,2,4);
+ packet(0x09B7,4); // ZC_ACK_OPEN_BANKING
+ packet(0x09B8,6,clif->pBankClose,2,4);
+ packet(0x09B9,4); // ZC_ACK_CLOSE_BANKING
+#endif
+
+//2013-07-03Ragexe (Shakto)
+#if PACKETVER >= 20130703
+ packet(0x0930,5,clif->pChangeDir,2,4);
+ packet(0x07E4,6,clif->pTakeItem,2);
+ packet(0x0362,6,clif->pDropItem,2,4);
+ packet(0x07EC,8,clif->pMoveToKafra,2,4);
+ packet(0x0364,8,clif->pMoveFromKafra,2,4);
+ packet(0x0202,6,clif->pReqClickBuyingStore,2);
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+#ifdef PACKETVER_RE
+ packet(0x0365,41,clif->pPartyRecruitRegisterReq,2,4);
+#else // not PACKETVER_RE
+ packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+#endif // PACKETVER_RE
+ // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x022D,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0802,26,clif->pPartyInvite2,2);
+ // packet(0x0436,4); // CZ_GANGSI_RANK
+ packet(0x0360,26,clif->pFriendsListAdd,2);
+ packet(0x094A,5,clif->pHomMenu,2,4);
+ packet(0x0873,36,clif->pStoragePassword,0);
+ packet(0x097C,4,clif->pRanklist);
+#endif
+
+//2013-08-07Ragexe (Shakto)
+#if PACKETVER >= 20130807
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x0202,5,clif->pChangeDir,2,4);
+ packet(0x07E4,6,clif->pTakeItem,2);
+ packet(0x0362,6,clif->pDropItem,2,4);
+ packet(0x07EC,8,clif->pMoveToKafra,2,4);
+ packet(0x0364,8,clif->pMoveFromKafra,2,4);
+ packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x096A,6,clif->pGetCharNameRequest,2);
+ packet(0x0368,6,clif->pSolveCharName,2);
+ packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0360,6,clif->pReqClickBuyingStore,2);
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+#ifdef PACKETVER_RE
+ packet(0x0365,41,clif->pPartyRecruitRegisterReq,2,4);
+#else // not PACKETVER_RE
+ packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+#endif // PACKETVER_RE
+ // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x022D,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0802,26,clif->pPartyInvite2,2);
+ // packet(0x0436,4); // CZ_GANGSI_RANK
+ packet(0x023B,26,clif->pFriendsListAdd,2);
+ packet(0x0361,5,clif->pHomMenu,2,4);
+ packet(0x0887,36,clif->pStoragePassword,0);
+#endif
+
+//2013-08-14aRagexe - Themon
+#if PACKETVER >= 20130814
+ packet(0x0874,7,clif->pActionRequest,2,6);
+ packet(0x0947,10,clif->pUseSkillToId,2,4,6);
+ packet(0x093A,5,clif->pWalkToXY,2);
+ packet(0x088A,6,clif->pTickSend,2);
+ packet(0x088C,5,clif->pChangeDir,2,4);
+ packet(0x0926,6,clif->pTakeItem,2);
+ packet(0x095F,6,clif->pDropItem,2,4);
+ packet(0x0202,8,clif->pMoveToKafra,2,4);
+ packet(0x0873,8,clif->pMoveFromKafra,2,4);
+ packet(0x0887,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x0962,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x0937,6,clif->pGetCharNameRequest,2);
+ packet(0x0923,6,clif->pSolveCharName,2);
+ packet(0x0868,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0941,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0889,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0835,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0895,6,clif->pReqClickBuyingStore,2);
+ packet(0x094E,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0936,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+#ifdef PACKETVER_RE
+ packet(0x0365,41,clif->pPartyRecruitRegisterReq,2,4);
+#else // not PACKETVER_RE
+ packet(0x0959,18,clif->pPartyBookingRegisterReq,2,4);
+#endif // PACKETVER_RE
+ // packet(0x0896,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x08A4,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x0368,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0927,26,clif->pPartyInvite2,2);
+ // packet(0x0815,4); // CZ_GANGSI_RANK
+ packet(0x0281,26,clif->pFriendsListAdd,2);
+ packet(0x0958,5,clif->pHomMenu,2,4);
+ packet(0x0885,36,clif->pStoragePassword,0);
+#endif
+
+// 2013-12-18bRagexe - Yommy
+#if PACKETVER >= 20131218
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x0947,5,clif->pChangeDir,2,4);
+ packet(0x07E4,6,clif->pTakeItem,2);
+ packet(0x0362,6,clif->pDropItem,2,4);
+ packet(0x07EC,8,clif->pMoveToKafra,2,4);
+ packet(0x0364,8,clif->pMoveFromKafra,2,4);
+ packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x096A,6,clif->pGetCharNameRequest,2);
+ packet(0x0368,6,clif->pSolveCharName,2);
+ packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x022D,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0360,6,clif->pReqClickBuyingStore,2);
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+ // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x092F,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0802,26,clif->pPartyInvite2,2);
+ // packet(0x087B,4); // CZ_GANGSI_RANK
+ packet(0x08AB,26,clif->pFriendsListAdd,2);
+ packet(0x0811,5,clif->pHomMenu,2,4);
+ packet(0x085C,36,clif->pStoragePassword,0);
+ /* New */
+ packet(0x09d4,2,clif->pNPCShopClosed);
+ packet(0x09ce,102,clif->pGM_Monster_Item,2);
+ /* NPC Market */
+ packet(0x09d8,2,clif->pNPCMarketClosed);
+ packet(0x09d6,-1,clif->pNPCMarketPurchase);
+#endif
+
+// 2013-12-23cRagexe - Yommy
+#if PACKETVER >= 20131223
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x0202,5,clif->pChangeDir,2,4);
+ packet(0x07E4,6,clif->pTakeItem,2);
+ packet(0x0362,6,clif->pDropItem,2,4);
+ packet(0x07EC,8,clif->pMoveToKafra,2,4);
+ packet(0x0364,8,clif->pMoveFromKafra,2,4);
+ packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x096A,6,clif->pGetCharNameRequest,2);
+ packet(0x0368,6,clif->pSolveCharName,2);
+ packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0360,6,clif->pReqClickBuyingStore,2);
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+ // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x022d,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0802,26,clif->pPartyInvite2,2);
+ // packet(0x0436,4); // CZ_GANGSI_RANK
+ packet(0x023B,26,clif->pFriendsListAdd,2);
+ packet(0x0361,5,clif->pHomMenu,2,4);
+ packet(0x08A4,36,clif->pStoragePassword,0);
+ packet(0x09df,7);
+#endif
+
+// 2013-12-30aRagexe - Yommy
+#if PACKETVER >= 20131230
+ packet(0x0871,7,clif->pActionRequest,2,6);
+ packet(0x02C4,10,clif->pUseSkillToId,2,4,6);
+ packet(0x035F,5,clif->pWalkToXY,2);
+ packet(0x0438,6,clif->pTickSend,2);
+ packet(0x094A,5,clif->pChangeDir,2,4);
+ packet(0x092A,6,clif->pTakeItem,2);
+ packet(0x0860,6,clif->pDropItem,2,4);
+ packet(0x0968,8,clif->pMoveToKafra,2,4);
+ packet(0x0895,8,clif->pMoveFromKafra,2,4);
+ packet(0x091E,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x096A,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x0926,6,clif->pGetCharNameRequest,2);
+ packet(0x0898,6,clif->pSolveCharName,2);
+ packet(0x087B,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0369,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x093D,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x087F,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0969,6,clif->pReqClickBuyingStore,2);
+ packet(0x094C,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0365,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x091F,18,clif->pPartyBookingRegisterReq,2,4);
+ // packet(0x093E,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x022D,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x089C,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x08A9,26,clif->pPartyInvite2,2);
+ // packet(0x087E,4); // CZ_GANGSI_RANK
+ packet(0x0943,26,clif->pFriendsListAdd,2);
+ packet(0x0949,5,clif->pHomMenu,2,4);
+ packet(0x091D,36,clif->pStoragePassword,0);
+#endif
+
+// 2014 Packet Data
+
+// 2014-01-15eRagexe - YomRawr
+#if PACKETVER >= 20140115
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x08A7,5,clif->pChangeDir,2,4);
+ packet(0x0940,6,clif->pTakeItem,2);
+ packet(0x0361,6,clif->pDropItem,2,4);
+ packet(0x088E,8,clif->pMoveToKafra,2,4);
+ packet(0x0367,8,clif->pMoveFromKafra,2,4);
+ packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x0802,6,clif->pGetCharNameRequest,2);
+ packet(0x0368,6,clif->pSolveCharName,2);
+ packet(0x0360,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0817,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0815,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x096A,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x088A,6,clif->pReqClickBuyingStore,2);
+ packet(0x0965,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x096A,18,clif->pPartyBookingRegisterReq,2,4);
+ // packet(0x088A,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0965,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x0966,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x095D,26,clif->pPartyInvite2,2);
+ // packet(0x095B,4); // CZ_GANGSI_RANK
+ packet(0x089B,26,clif->pFriendsListAdd,2);
+ packet(0x092D,5,clif->pHomMenu,2,4);
+ packet(0x0865,36,clif->pStoragePassword,0);
+#endif
+
+// 2014-02-05bRagexe - Themon
+#if PACKETVER >= 20140205
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x0202,5,clif->pChangeDir,2,4);
+ packet(0x07E4,6,clif->pTakeItem,2);
+ packet(0x0362,6,clif->pDropItem,2,4);
+ packet(0x07EC,8,clif->pMoveToKafra,2,4);
+ packet(0x0364,8,clif->pMoveFromKafra,2,4);
+ packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x096A,6,clif->pGetCharNameRequest,2);
+ packet(0x0368,6,clif->pSolveCharName,2);
+ packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0360,6,clif->pReqClickBuyingStore,2);
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+ // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x022D,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0802,26,clif->pPartyInvite2,2);
+ // packet(0x0436,4); // CZ_GANGSI_RANK
+ packet(0x023B,26,clif->pFriendsListAdd,2);
+ packet(0x0361,5,clif->pHomMenu,2,4);
+ packet(0x0938,36,clif->pStoragePassword,0);
+ packet(0x09DF,7);
+#endif
+
+// 2014-03-05bRagexe - Themon
+#if PACKETVER >= 20140305
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x0815,5,clif->pChangeDir,2,4);
+ packet(0x0202,6,clif->pTakeItem,2);
+ packet(0x0362,6,clif->pDropItem,2,4);
+ packet(0x07EC,8,clif->pMoveToKafra,2,4);
+ packet(0x0364,8,clif->pMoveFromKafra,2,4);
+ packet(0x0436,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x096A,6,clif->pGetCharNameRequest,2);
+ packet(0x0368,6,clif->pSolveCharName,2);
+ packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0360,6,clif->pReqClickBuyingStore,2);
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0361,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+ // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x0438,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0802,26,clif->pPartyInvite2,2);
+ // packet(0x0878,4); // CZ_GANGSI_RANK
+ packet(0x07E4,26,clif->pFriendsListAdd,2);
+ packet(0x0934,5,clif->pHomMenu,2,4);
+ packet(0x095e,36,clif->pStoragePassword,0);
+ packet(0x09DF,7);
+#endif
+
+// 2014-04-02gRagexe - Themon
+#if PACKETVER >= 20140402
+ packet(0x0946,7,clif->pActionRequest,2,6);
+ packet(0x0868,10,clif->pUseSkillToId,2,4,6);
+ packet(0x093F,5,clif->pWalkToXY,2);
+ packet(0x0950,6,clif->pTickSend,2);
+ packet(0x0360,5,clif->pChangeDir,2,4);
+ packet(0x0958,6,clif->pTakeItem,2);
+ packet(0x0882,6,clif->pDropItem,2,4);
+ packet(0x095C,8,clif->pMoveToKafra,2,4);
+ packet(0x085B,8,clif->pMoveFromKafra,2,4);
+ packet(0x0364,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x092D,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x088A,6,clif->pGetCharNameRequest,2);
+ packet(0x07EC,6,clif->pSolveCharName,2);
+ packet(0x0965,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x085D,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0933,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x091F,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x023B,6,clif->pReqClickBuyingStore,2);
+ packet(0x0867,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0944,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x08AC,18,clif->pPartyBookingRegisterReq,2,4);
+ // packet(0x094C,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0883,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x0920,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0890,26,clif->pPartyInvite2,2);
+ // packet(0x088C,4); // CZ_GANGSI_RANK
+ packet(0x089A,26,clif->pFriendsListAdd,2);
+ packet(0x0896,5,clif->pHomMenu,2,4);
+ packet(0x0926,36,clif->pStoragePassword,0);
+ packet(0x09DF,7);
+#endif
+
+// 2014-04-16aRagexe - Themon
+#if PACKETVER >= 20140416
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x0202,5,clif->pChangeDir,2,4);
+ packet(0x07E4,6,clif->pTakeItem,2);
+ packet(0x0362,6,clif->pDropItem,2,4);
+ packet(0x07EC,8,clif->pMoveToKafra,2,4);
+ packet(0x0364,8,clif->pMoveFromKafra,2,4);
+ packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8);
+ packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10);
+ packet(0x096A,6,clif->pGetCharNameRequest,2);
+ packet(0x0368,6,clif->pSolveCharName,2);
+ packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0360,6,clif->pReqClickBuyingStore,2);
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+ // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x022D,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0802,26,clif->pPartyInvite2,2);
+ // packet(0x0436,4); // CZ_GANGSI_RANK
+ packet(0x023B,26,clif->pFriendsListAdd,2);
+ packet(0x0361,5,clif->pHomMenu,2,4);
+ packet(0x095C,36,clif->pStoragePassword,0);
+ packet(0x09DF,7);
+#endif
+
+/* PacketKeys: http://hercules.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */
+#if PACKETVER >= 20110817
+ packetKeys(0x053D5CED,0x3DED6DED,0x6DED6DED); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20110824
+ packetKeys(0x35C91401,0x262A5556,0x28FA03AA); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20110831
+ packetKeys(0x3AD67ED0,0x44703C69,0x6F876809); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20110906
+ packetKeys(0x3AD67ED0,0x44703C69,0x6F876809); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20111005
+ packetKeys(0x291E6762,0x77CD391A,0x60AC2F16); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20111012
+ packetKeys(0x7F3C2D29,0x59B01DE6,0x1DBB44CA); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20111021
+ packetKeys(0x357D55DC,0x5A8D759F,0x245C30F5); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20111025
+ packetKeys(0x50AE1A63,0x3CE579B5,0x29C10406); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20111102
+ packetKeys(0x5324329D,0x5D545D52,0x06137269); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20111109
+ packetKeys(0x0B642BDA,0x6ECB1D1C,0x61C7454B); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20111122
+ packetKeys(0x3B550F07,0x1F666C7C,0x60304EF5); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20111207
+ packetKeys(0x2A610886,0x3E09165E,0x57C11888); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20111214
+ packetKeys(0x5151306B,0x7AE32886,0x53060628); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20111220
+ packetKeys(0x05D53871,0x7D0027B4,0x29975333); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20111228
+ packetKeys(0x0FF87E93,0x6CFF7860,0x3A3D1DEC); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120104
+ packetKeys(0x262034A1,0x674542A5,0x73A50BA5); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120111
+ packetKeys(0x2B412AFC,0x4FF94487,0x6705339D); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120120
+ packetKeys(0x504345D0,0x3D427B1B,0x794C2DCC); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120202
+ packetKeys(0x2CFC0A71,0x2BA91D8D,0x087E39E0); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120207
+ packetKeys(0x1D373F5D,0x5ACD604D,0x1C4D7C4D); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120214
+ packetKeys(0x7A255EFA,0x30977276,0x2D4A0448); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120229
+ packetKeys(0x520B4C64,0x2800407D,0x47651458); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120307
+ packetKeys(0x382A6DEF,0x5CBE7202,0x61F46637); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120314
+ packetKeys(0x689C1729,0x11812639,0x60F82967); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120321
+ packetKeys(0x21F9683F,0x710C5CA5,0x1FD910E9); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120328
+ packetKeys(0x75B8553B,0x37F20B12,0x385C2B40); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120404
+ packetKeys(0x0036310C,0x2DCD0BED,0x1EE62A78); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120410
+ packetKeys(0x01581359,0x452D6FFA,0x6AFB6E2E); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120418
+ packetKeys(0x01540E48,0x13041224,0x31247924); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120424
+ packetKeys(0x411D1DBB,0x4CBA4848,0x1A432FC4); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120509
+ packetKeys(0x16CF3301,0x1F472B9B,0x0B4A3CD2); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120515
+ packetKeys(0x4A715EF9,0x79103E4F,0x405C1238); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120525
+ packetKeys(0x70EB4CCB,0x0487713C,0x398D4B08); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120605
+ packetKeys(0x68CA3080,0x31B74BDD,0x505208F1); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120612
+ packetKeys(0x32E45D64,0x35643564,0x35643564); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120618
+ packetKeys(0x261F261F,0x261F261F,0x261F261F); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120702
+ packetKeys(0x25733B31,0x53486CFD,0x398649BD); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20120716
+ packetKeys(0x76052205,0x22052205,0x22052205); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20130320
+ packetKeys(0x3F094C49,0x55F86C1E,0x58AA359A); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20130514
+ packetKeys(0x75794A38,0x58A96BC1,0x296E6FB8); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20130522
+ packetKeys(0x6948050B,0x06511D9D,0x725D4DF1); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20130529
+ packetKeys(0x023A6C87,0x14BF1F1E,0x5CC70CC9); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20130605
+ packetKeys(0x646E08D9,0x5F153AB5,0x61B509B5); /* Thanks to Shakto */
+#endif
+
#if PACKETVER >= 20130612
- packetKeys(0x6D166F66, 0x3C000FCF, 0x295B0FCB); /* Thanks to Shakto */
+ packetKeys(0x6D166F66,0x3C000FCF,0x295B0FCB); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20130618
+ packetKeys(0x434115DE,0x34A10FE9,0x6791428E); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20130626
+ packetKeys(0x38F453EF,0x6A040FD8,0X65BD6668); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20130703
+ packetKeys(0x4FF90E23,0x0F1432F2,0x4CFA1EDA); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20130807
+ packetKeys(0x7E241DE0,0x5E805580,0x3D807D80); /* Thanks to Shakto */
+#endif
+
+#if PACKETVER >= 20130814
+ packetKeys(0x23A23148,0x0C41420E,0x53785AD7); /* Themon */
+#endif
+
+#if PACKETVER >= 20131218
+ packetKeys(0x6A596301,0x76866D0E,0x32294A45);
+#endif
+
+#if PACKETVER >= 20131223
+ packetKeys(0x631C511C,0x111C111C,0x111C111C);
+#endif
+
+#if PACKETVER >= 20131230
+ packetKeys(0x611B7097,0x01F957A1,0x768A0FCB);
+#endif
+
+// 2014 Packet Keys
+
+#if PACKETVER >= 20140115
+ packetKeys(0x63224335,0x0F3A1F27,0x6D217B24); /* Thanks to Yommy */
+#endif
+
+#if PACKETVER >= 20140205
+ packetKeys(0x63DC7BDC,0x7BDC7BDC,0x7BDC7BDC); /* Themon */
+#endif
+
+#if PACKETVER >= 20140305
+ packetKeys(0x116763F2,0x41117DAC,0x7FD13C45); /* Themon */
+#endif
+
+#if PACKETVER >= 20140402
+ packetKeys(0x15D3271C,0x004D725B,0x111A3A37); /* Themon */
+#endif
+
+#if PACKETVER >= 20140416
+ packetKeys(0x04810281,0x42814281,0x42814281); /* Themon */
+#endif
+
+#if defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3)
+ packetKeys(OBFUSCATIONKEY1,OBFUSCATIONKEY2,OBFUSCATIONKEY3);
#endif
-#endif /* _PACKETS_H_ */
+#endif /* MAP_PACKETS_H */
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index 083c00e31..b32baf53a 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -3,21 +3,20 @@
/* Hercules Renewal: Phase Two http://hercules.ws/board/topic/383-hercules-renewal-phase-two/ */
-#ifndef _PACKETS_STRUCT_H_
-#define _PACKETS_STRUCT_H_
+#ifndef MAP_PACKETS_STRUCT_H
+#define MAP_PACKETS_STRUCT_H
+#include "../common/cbasetypes.h"
#include "../common/mmo.h"
/**
- * structs for data
- */
-struct EQUIPSLOTINFO {
- unsigned short card[4];
-};
-/**
*
**/
enum packet_headers {
+ banking_withdraw_ackType = 0x9aa,
+ banking_deposit_ackType = 0x9a8,
+ banking_checkType = 0x9a6,
+ cart_additem_ackType = 0x12c,
sc_notickType = 0x196,
#if PACKETVER < 20061218
additemType = 0xa0,
@@ -38,7 +37,7 @@ enum packet_headers {
idle_unitType = 0x2ee,
#elif PACKETVER < 20101124
idle_unitType = 0x7f9,
-#elif PACKETVER < 20140000 //actual 20120221
+#elif PACKETVER < 20150000 //actual 20120221
idle_unitType = 0x857,
#else
idle_unitType = 0x915,
@@ -52,6 +51,15 @@ enum packet_headers {
#endif
status_change2Type = 0x43f,
status_change_endType = 0x196,
+#if PACKETVER < 20091103
+ spawn_unit2Type = 0x7c,
+ idle_unit2Type = 0x78,
+#endif
+#if PACKETVER < 20071113
+ damageType = 0x8a,
+#else
+ damageType = 0x2e1,
+#endif
#if PACKETVER < 4
spawn_unitType = 0x79,
#elif PACKETVER < 7
@@ -62,7 +70,7 @@ enum packet_headers {
spawn_unitType = 0x2ed,
#elif PACKETVER < 20101124
spawn_unitType = 0x7f8,
-#elif PACKETVER < 20140000 //actual 20120221
+#elif PACKETVER < 20150000 //actual 20120221
spawn_unitType = 0x858,
#else
spawn_unitType = 0x90f,
@@ -73,6 +81,8 @@ enum packet_headers {
authokType = 0x2eb,
#endif
script_clearType = 0x8d6,
+ package_item_announceType = 0x7fd,
+ item_drop_announceType = 0x7fd,
#if PACKETVER < 4
unit_walkingType = 0x7b,
#elif PACKETVER < 7
@@ -83,7 +93,7 @@ enum packet_headers {
unit_walkingType = 0x2ec,
#elif PACKETVER < 20101124
unit_walkingType = 0x7f7,
-#elif PACKETVER < 20140000 //actual 20120221
+#elif PACKETVER < 20150000 //actual 20120221
unit_walkingType = 0x856,
#else
unit_walkingType = 0x914,
@@ -96,22 +106,192 @@ enum packet_headers {
bgqueue_revokereqType = 0x8da,
bgqueue_battlebeginackType = 0x8e0,
bgqueue_notify_entryType = 0x8d9,
- bgqueue_battlebegins = 0x8df,
+ bgqueue_battlebeginsType = 0x8df,
+ notify_bounditemType = 0x2d3,
+#if PACKETVER < 20110718
+ skill_entryType = 0x11f,
+#elif PACKETVER < 20121212
+ skill_entryType = 0x8c7,
+#elif PACKETVER < 20130731
+ skill_entryType = 0x99f,
+#else
+ skill_entryType = 0x9ca,
+#endif
+ graffiti_entryType = 0x1c9,
#if PACKETVER > 20130000 /* not sure date */
dropflooritemType = 0x84b,
#else
dropflooritemType = 0x9e,
#endif
+#if PACKETVER >= 20120925
+ inventorylistnormalType = 0x991,
+#elif PACKETVER >= 20080102
+ inventorylistnormalType = 0x2e8,
+#elif PACKETVER >= 20071002
+ inventorylistnormalType = 0x1ee,
+#else
+ inventorylistnormalType = 0xa3,
+#endif
+#if PACKETVER >= 20120925
+ inventorylistequipType = 0x992,
+#elif PACKETVER >= 20080102
+ inventorylistequipType = 0x2d0,
+#elif PACKETVER >= 20071002
+ inventorylistequipType = 0x295,
+#else
+ inventorylistequipType = 0xa4,
+#endif
+#if PACKETVER >= 20120925
+ storagelistnormalType = 0x995,
+#elif PACKETVER >= 20080102
+ storagelistnormalType = 0x2ea,
+#elif PACKETVER >= 20071002
+ storagelistnormalType = 0x295,
+#else
+ storagelistnormalType = 0xa5,
+#endif
+#if PACKETVER >= 20120925
+ storagelistequipType = 0x996,
+#elif PACKETVER >= 20080102
+ storagelistequipType = 0x2d1,
+#elif PACKETVER >= 20071002
+ storagelistequipType = 0x296,
+#else
+ storagelistequipType = 0xa6,
+#endif
+#if PACKETVER >= 20120925
+ cartlistnormalType = 0x993,
+#elif PACKETVER >= 20080102
+ cartlistnormalType = 0x2e9,
+#elif PACKETVER >= 20071002
+ cartlistnormalType = 0x1ef,
+#else
+ cartlistnormalType = 0x123,
+#endif
+#if PACKETVER >= 20120925
+ cartlistequipType = 0x994,
+#elif PACKETVER >= 20080102
+ cartlistequipType = 0x2d2,
+#elif PACKETVER >= 20071002
+ cartlistequipType = 0x297,
+#else
+ cartlistequipType = 0x122,
+#endif
+#if PACKETVER >= 20120925
+ equipitemType = 0x998,
+#else
+ equipitemType = 0xa9,
+#endif
+#if PACKETVER >= 20120925
+ equipitemackType = 0x999,
+#else
+ equipitemackType = 0xaa,
+#endif
+#if PACKETVER >= 20120925
+ unequipitemackType = 0x99a,
+#else
+ unequipitemackType = 0xac,
+#endif
+#if PACKETVER >= 20120925
+ viewequipackType = 0x997,
+#elif PACKETVER >= 20101124
+ viewequipackType = 0x859,
+#else
+ viewequipackType = 0x2d7,
+#endif
+ notifybindonequip = 0x2d3,
monsterhpType = 0x977,
maptypeproperty2Type = 0x99b,
+ npcmarketresultackType = 0x9d7,
+ npcmarketopenType = 0x9d5,
+#if PACKETVER >= 20131223
+ wisendType = 0x9df,
+#else
+ wisendType = 0x98,
+#endif
};
+#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(push, 1)
+#endif // not NetBSD < 6 / Solaris
+
+/**
+ * structs for data
+ */
+struct EQUIPSLOTINFO {
+ unsigned short card[4];
+} __attribute__((packed));
+
+struct NORMALITEM_INFO {
+ short index;
+ unsigned short ITID;
+ unsigned char type;
+#if PACKETVER < 20120925
+ uint8 IsIdentified;
+#endif
+ short count;
+#if PACKETVER >= 20120925
+ unsigned int WearState;
+#else
+ unsigned short WearState;
+#endif
+#if PACKETVER >= 5
+ struct EQUIPSLOTINFO slot;
+#endif
+#if PACKETVER >= 20080102
+ int HireExpireDate;
+#endif
+#if PACKETVER >= 20120925
+ struct {
+ unsigned char IsIdentified : 1;
+ unsigned char PlaceETCTab : 1;
+ unsigned char SpareBits : 6;
+ } Flag;
+#endif
+} __attribute__((packed));
+
+struct EQUIPITEM_INFO {
+ short index;
+ unsigned short ITID;
+ unsigned char type;
+#if PACKETVER < 20120925
+ uint8 IsIdentified;
+#endif
+#if PACKETVER >= 20120925
+ unsigned int location;
+ unsigned int WearState;
+#else
+ unsigned short location;
+ unsigned short WearState;
+#endif
+#if PACKETVER < 20120925
+ uint8 IsDamaged;
+#endif
+ unsigned char RefiningLevel;
+ struct EQUIPSLOTINFO slot;
+#if PACKETVER >= 20071002
+ int HireExpireDate;
+#endif
+#if PACKETVER >= 20080102
+ unsigned short bindOnEquipType;
+#endif
+#if PACKETVER >= 20100629
+ unsigned short wItemSpriteNumber;
+#endif
+#if PACKETVER >= 20120925
+ struct {
+ unsigned char IsIdentified : 1;
+ unsigned char IsDamaged : 1;
+ unsigned char PlaceETCTab : 1;
+ unsigned char SpareBits : 5;
+ } Flag;
+#endif
+} __attribute__((packed));
struct packet_authok {
short PacketType;
unsigned int startTime;
- char PosDir[3];
+ unsigned char PosDir[3];
unsigned char xSize;
unsigned char ySize;
#if PACKETVER >= 20080102
@@ -138,8 +318,8 @@ struct packet_additem {
unsigned short Index;
unsigned short count;
unsigned short nameid;
- bool IsIdentified;
- bool IsDamaged;
+ uint8 IsIdentified;
+ uint8 IsDamaged;
unsigned char refiningLevel;
struct EQUIPSLOTINFO slot;
#if PACKETVER >= 20120925
@@ -164,14 +344,73 @@ struct packet_dropflooritem {
#if PACKETVER >= 20130000 /* not sure date */
unsigned short type;
#endif
- bool IsIdentified;
+ uint8 IsIdentified;
short xPos;
short yPos;
unsigned char subX;
unsigned char subY;
short count;
} __attribute__((packed));
-
+#if PACKETVER < 20091103
+struct packet_idle_unit2 {
+ short PacketType;
+#if PACKETVER >= 20071106
+ unsigned char objecttype;
+#endif
+ unsigned int GID;
+ short speed;
+ short bodyState;
+ short healthState;
+ short effectState;
+ short job;
+ short head;
+ short weapon;
+ short accessory;
+ short shield;
+ short accessory2;
+ short accessory3;
+ short headpalette;
+ short bodypalette;
+ short headDir;
+ unsigned int GUID;
+ short GEmblemVer;
+ short honor;
+ short virtue;
+ uint8 isPKModeON;
+ unsigned char sex;
+ unsigned char PosDir[3];
+ unsigned char xSize;
+ unsigned char ySize;
+ unsigned char state;
+ short clevel;
+} __attribute__((packed));
+struct packet_spawn_unit2 {
+ short PacketType;
+#if PACKETVER >= 20071106
+ unsigned char objecttype;
+#endif
+ unsigned int GID;
+ short speed;
+ short bodyState;
+ short healthState;
+ short effectState;
+ short head;
+ short weapon;
+ short accessory;
+ short job;
+ short shield;
+ short accessory2;
+ short accessory3;
+ short headpalette;
+ short bodypalette;
+ short headDir;
+ uint8 isPKModeON;
+ unsigned char sex;
+ unsigned char PosDir[3];
+ unsigned char xSize;
+ unsigned char ySize;
+} __attribute__((packed));
+#endif
struct packet_spawn_unit {
short PacketType;
#if PACKETVER >= 20091103
@@ -209,21 +448,21 @@ struct packet_spawn_unit {
unsigned int GUID;
short GEmblemVer;
short honor;
-#if PACKETVER >= 20091103
+#if PACKETVER > 7
int virtue;
#else
short virtue;
#endif
- bool isPKModeON;
+ uint8 isPKModeON;
unsigned char sex;
- char PosDir[3];
+ unsigned char PosDir[3];
unsigned char xSize;
unsigned char ySize;
short clevel;
#if PACKETVER >= 20080102
short font;
#endif
-#if PACKETVER >= 20140000 //actual 20120221
+#if PACKETVER >= 20150000 //actual 20120221
int maxHP;
int HP;
unsigned char isBoss;
@@ -234,13 +473,15 @@ struct packet_unit_walking {
short PacketType;
#if PACKETVER >= 20091103
short PacketLength;
+#endif
+#if PACKETVER > 20071106
unsigned char objecttype;
#endif
unsigned int GID;
short speed;
short bodyState;
short healthState;
-#if PACKETVER < 20080102
+#if PACKETVER < 7
short effectState;
#else
int effectState;
@@ -268,21 +509,21 @@ struct packet_unit_walking {
unsigned int GUID;
short GEmblemVer;
short honor;
-#if PACKETVER >= 20091103
+#if PACKETVER > 7
int virtue;
#else
short virtue;
#endif
- bool isPKModeON;
+ uint8 isPKModeON;
unsigned char sex;
- char MoveData[6];
+ unsigned char MoveData[6];
unsigned char xSize;
unsigned char ySize;
short clevel;
#if PACKETVER >= 20080102
short font;
#endif
-#if PACKETVER >= 20140000 //actual 20120221
+#if PACKETVER >= 20150000 //actual 20120221
int maxHP;
int HP;
unsigned char isBoss;
@@ -326,14 +567,14 @@ struct packet_idle_unit {
unsigned int GUID;
short GEmblemVer;
short honor;
-#if PACKETVER >= 20091103
+#if PACKETVER > 7
int virtue;
#else
short virtue;
#endif
- bool isPKModeON;
+ uint8 isPKModeON;
unsigned char sex;
- char PosDir[3];
+ unsigned char PosDir[3];
unsigned char xSize;
unsigned char ySize;
unsigned char state;
@@ -341,7 +582,7 @@ struct packet_idle_unit {
#if PACKETVER >= 20080102
short font;
#endif
-#if PACKETVER >= 20140000 //actual 20120221
+#if PACKETVER >= 20150000 //actual 20120221
int maxHP;
int HP;
unsigned char isBoss;
@@ -356,7 +597,7 @@ struct packet_status_change {
#if PACKETVER >= 20120618
unsigned int Total;
#endif
-#if PACKETVER >= 20090121
+#if PACKETVER >= 20090121
unsigned int Left;
int val1;
int val2;
@@ -386,30 +627,30 @@ struct packet_maptypeproperty2 {
short PacketType;
short type;
struct {
- unsigned int party : 1;
- unsigned int guild : 1;
- unsigned int siege : 1;
- unsigned int mineffect : 1;
- unsigned int nolockon : 1;
- unsigned int countpk : 1;
- unsigned int nopartyformation : 1;
- unsigned int bg : 1;
- unsigned int noitemconsumption : 1;
- unsigned int usecart : 1;
- unsigned int summonstarmiracle : 1;
- unsigned int SpareBits : 15;
+ unsigned int party : 1; // Show attack cursor on non-party members (PvP)
+ unsigned int guild : 1; // Show attack cursor on non-guild members (GvG)
+ unsigned int siege : 1; // Show emblem over characters' heads when in GvG (WoE castle)
+ unsigned int mineffect : 1; // Automatically enable /mineffect
+ unsigned int nolockon : 1; // TODO: What does this do? (shows attack cursor on non-party members)
+ unsigned int countpk : 1; /// Show the PvP counter
+ unsigned int nopartyformation : 1; /// Prevent party creation/modification
+ unsigned int bg : 1; // TODO: What does this do? Probably related to Battlegrounds, but I'm not sure on the effect
+ unsigned int noitemconsumption : 1; // TODO: What does this do? (shows a "Nothing found in the selected map" message when set)
+ unsigned int usecart : 1; /// Allow opening cart inventory
+ unsigned int summonstarmiracle : 1; // TODO: What does this do? Related to Taekwon Masters, but I have no idea.
+ unsigned int SpareBits : 15; /// Currently ignored, reserved for future updates
} flag;
} __attribute__((packed));
struct packet_bgqueue_ack {
short PacketType;
- short type;
+ unsigned char type;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_notice_delete {
short PacketType;
- short type;
+ unsigned char type;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
@@ -437,7 +678,7 @@ struct packet_bgqueue_revoke_req {
struct packet_bgqueue_battlebegin_ack {
short PacketType;
- short result;
+ unsigned char result;
char bg_name[NAME_LENGTH];
char game_name[NAME_LENGTH];
} __attribute__((packed));
@@ -459,7 +700,267 @@ struct packet_script_clear {
unsigned int NpcID;
} __attribute__((packed));
+/* made possible thanks to Yommy!! */
+struct packet_package_item_announce {
+ short PacketType;
+ short PacketLength;
+ unsigned char type;
+ unsigned short ItemID;
+ char len;
+ char Name[NAME_LENGTH];
+ char unknown;
+ unsigned short BoxItemID;
+} __attribute__((packed));
+
+/* made possible thanks to Yommy!! */
+struct packet_item_drop_announce {
+ short PacketType;
+ short PacketLength;
+ unsigned char type;
+ unsigned short ItemID;
+ char len;
+ char Name[NAME_LENGTH];
+ char monsterNameLen;
+ char monsterName[NAME_LENGTH];
+} __attribute__((packed));
+
+struct packet_cart_additem_ack {
+ short PacketType;
+ char result;
+} __attribute__((packed));
+
+struct packet_banking_check {
+ short PacketType;
+ int64 Money;
+ short Reason;
+} __attribute__((packed));
+
+struct packet_banking_deposit_req {
+ short PacketType;
+ unsigned int AID;
+ int Money;
+} __attribute__((packed));
+
+struct packet_banking_withdraw_req {
+ short PacketType;
+ unsigned int AID;
+ int Money;
+} __attribute__((packed));
+
+struct packet_banking_deposit_ack {
+ short PacketType;
+ short Reason;
+ int64 Money;
+ int Balance;
+} __attribute__((packed));
+
+struct packet_banking_withdraw_ack {
+ short PacketType;
+ short Reason;
+ int64 Money;
+ int Balance;
+} __attribute__((packed));
+
+struct packet_itemlist_normal {
+ short PacketType;
+ short PacketLength;
+ struct NORMALITEM_INFO list[MAX_ITEMLIST];
+} __attribute__((packed));
+
+struct packet_itemlist_equip {
+ short PacketType;
+ short PacketLength;
+ struct EQUIPITEM_INFO list[MAX_ITEMLIST];
+} __attribute__((packed));
+
+struct packet_storelist_normal {
+ short PacketType;
+ short PacketLength;
+#if PACKETVER >= 20120925
+ char name[NAME_LENGTH];
+#endif
+ struct NORMALITEM_INFO list[MAX_ITEMLIST];
+} __attribute__((packed));
+
+struct packet_storelist_equip {
+ short PacketType;
+ short PacketLength;
+#if PACKETVER >= 20120925
+ char name[NAME_LENGTH];
+#endif
+ struct EQUIPITEM_INFO list[MAX_ITEMLIST];
+} __attribute__((packed));
+
+struct packet_equip_item {
+ short PacketType;
+ unsigned short index;
+#if PACKETVER >= 20120925
+ unsigned int wearLocation;
+#else
+ unsigned short wearLocation;
+#endif
+} __attribute__((packed));
+
+struct packet_equipitem_ack {
+ short PacketType;
+ unsigned short index;
+#if PACKETVER >= 20120925
+ unsigned int wearLocation;
+#else
+ unsigned short wearLocation;
+#endif
+#if PACKETVER >= 20100629
+ unsigned short wItemSpriteNumber;
+#endif
+ unsigned char result;
+} __attribute__((packed));
+
+struct packet_unequipitem_ack {
+ short PacketType;
+ unsigned short index;
+#if PACKETVER >= 20120925
+ unsigned int wearLocation;
+#else
+ unsigned short wearLocation;
+#endif
+ unsigned char result;
+} __attribute__((packed));
+
+struct packet_viewequip_ack {
+ short PacketType;
+ short PacketLength;
+ char characterName[NAME_LENGTH];
+ short job;
+ short head;
+ short accessory;
+ short accessory2;
+ short accessory3;
+#if PACKETVER >= 20101124
+ short robe;
+#endif
+ short headpalette;
+ short bodypalette;
+ unsigned char sex;
+ struct EQUIPITEM_INFO list[MAX_INVENTORY];
+} __attribute__((packed));
+
+struct packet_notify_bounditem {
+ short PacketType;
+ unsigned short index;
+} __attribute__((packed));
+
+struct packet_skill_entry {
+ short PacketType;
+#if PACKETVER >= 20110718
+ short PacketLength;
+#endif
+ unsigned int AID;
+ unsigned int creatorAID;
+ short xPos;
+ short yPos;
+#if PACKETVER >= 20121212
+ int job;
+#else
+ unsigned char job;
+#endif
+#if PACKETVER >= 20110718
+ char RadiusRange;
+#endif
+ unsigned char isVisible;
+#if PACKETVER >= 20130731
+ unsigned char level;
+#endif
+} __attribute__((packed));
+
+struct packet_graffiti_entry {
+ short PacketType;
+ unsigned int AID;
+ unsigned int creatorAID;
+ short xPos;
+ short yPos;
+ unsigned char job;
+ unsigned char isVisible;
+ unsigned char isContens;
+ char msg[80];
+} __attribute__((packed));
+
+struct packet_damage {
+ short PacketType;
+ unsigned int GID;
+ unsigned int targetGID;
+ unsigned int startTime;
+ int attackMT;
+ int attackedMT;
+#if PACKETVER < 20071113
+ short damage;
+#else
+ int damage;
+#endif
+ short count;
+ unsigned char action;
+#if PACKETVER < 20071113
+ short leftDamage;
+#else
+ int leftDamage;
+#endif
+} __attribute__((packed));
+
+struct packet_gm_monster_item {
+ short PacketType;
+#if PACKETVER >= 20131218
+ char str[100];
+#else
+ char str[24];
+#endif
+} __attribute__((packed));
+
+struct packet_npc_market_purchase {
+ short PacketType;
+ short PacketLength;
+ struct {
+ unsigned short ITID;
+ int qty;
+ } list[MAX_INVENTORY];/* assuming MAX_INVENTORY is max since you can't hold more than MAX_INVENTORY items thus cant buy that many at once. */
+} __attribute__((packed));
+
+struct packet_npc_market_result_ack {
+ short PacketType;
+ short PacketLength;
+ unsigned char result;
+ struct {
+ unsigned short ITID;
+ unsigned short qty;
+ unsigned int price;
+ } list[MAX_INVENTORY];/* assuming MAX_INVENTORY is max since you can't hold more than MAX_INVENTORY items thus cant buy that many at once. */
+} __attribute__((packed));
+
+struct packet_npc_market_open {
+ short PacketType;
+ short PacketLength;
+ /* inner struct figured by Ind after some annoying hour of debugging (data Thanks to Yommy) */
+ struct {
+ unsigned short nameid;
+ unsigned char type;
+ unsigned int price;
+ unsigned int qty;
+ unsigned short view;
+ // It seems that the client doesn't have any hard-coded limit for this list
+ // it's possible to send up to 1890 items without dropping a packet that's
+ // too large [Panikon]
+ } list[1000];/* TODO: whats the actual max of this? */
+} __attribute__((packed));
+
+struct packet_wis_end {
+ short PacketType;
+ char result;
+#if PACKETVER >= 20131223
+ unsigned int unknown;/* maybe AID, not sure what for (works sending as 0) */
+#endif
+} __attribute__((packed));
+
+#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(pop)
+#endif // not NetBSD < 6 / Solaris
-#endif /* _PACKETS_STRUCT_H_ */
+#endif /* MAP_PACKETS_STRUCT_H */
diff --git a/src/map/party.c b/src/map/party.c
index adcb35c5a..7cf340edb 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -1,46 +1,46 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/timer.h"
-#include "../common/socket.h" // last_tick
-#include "../common/nullpo.h"
-#include "../common/malloc.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/utils.h"
-#include "../common/strlib.h"
+#define HERCULES_CORE
+#include "../config/core.h" // GP_BOUND_ITEMS, RENEWAL_EXP
#include "party.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
#include "atcommand.h" //msg_txt()
-#include "pc.h"
-#include "map.h"
-#include "instance.h"
#include "battle.h"
-#include "intif.h"
#include "clif.h"
+#include "instance.h"
+#include "intif.h"
+#include "itemdb.h"
#include "log.h"
+#include "map.h"
+#include "mob.h" // struct mob_data
+#include "pc.h"
#include "skill.h"
#include "status.h"
-#include "itemdb.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-static DBMap* party_db; // int party_id -> struct party_data* (releases data)
-static DBMap* party_booking_db; // int char_id -> struct party_booking_ad_info* (releases data) // Party Booking [Spiria]
-static unsigned long party_booking_nextid = 1;
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h" // last_tick
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data);
+struct party_interface party_s;
/*==========================================
* Fills the given party_member structure according to the sd provided.
* Used when creating/adding people to a party. [Skotlex]
*------------------------------------------*/
-static void party_fill_member(struct party_member* member, struct map_session_data* sd, unsigned int leader)
-{
+void party_fill_member(struct party_member* member, struct map_session_data* sd, unsigned int leader) {
member->account_id = sd->status.account_id;
member->char_id = sd->status.char_id;
safestrncpy(member->name, sd->status.name, NAME_LENGTH);
@@ -52,8 +52,7 @@ static void party_fill_member(struct party_member* member, struct map_session_da
}
/// Get the member_id of a party member.
/// Return -1 if not in party.
-int party_getmemberid(struct party_data* p, struct map_session_data* sd)
-{
+int party_getmemberid(struct party_data* p, struct map_session_data* sd) {
int member_id;
nullpo_retr(-1, p);
if( sd == NULL )
@@ -66,7 +65,6 @@ int party_getmemberid(struct party_data* p, struct map_session_data* sd)
return member_id;
}
-
/*==========================================
* Request an available sd of this party
*------------------------------------------*/
@@ -81,10 +79,8 @@ struct map_session_data* party_getavailablesd(struct party_data *p)
/*==========================================
* Retrieves and validates the sd pointer for this party member [Skotlex]
*------------------------------------------*/
-
-static TBL_PC* party_sd_check(int party_id, int account_id, int char_id)
-{
- TBL_PC* sd = iMap->id2sd(account_id);
+TBL_PC* party_sd_check(int party_id, int account_id, int char_id) {
+ TBL_PC* sd = map->id2sd(account_id);
if (!(sd && sd->status.char_id == char_id))
return NULL;
@@ -93,7 +89,7 @@ static TBL_PC* party_sd_check(int party_id, int account_id, int char_id)
sd->status.party_id = party_id;// auto-join if not in a party
if (sd->status.party_id != party_id)
{ //If player belongs to a different party, kick him out.
- intif_party_leave(party_id,account_id,char_id);
+ intif->party_leave(party_id,account_id,char_id);
return NULL;
}
@@ -102,35 +98,30 @@ static TBL_PC* party_sd_check(int party_id, int account_id, int char_id)
int party_db_final(DBKey key, DBData *data, va_list ap) {
struct party_data *p;
- if( ( p = DB->data2ptr(data) ) && p->instance )
- aFree(p->instance);
+ if( ( p = DB->data2ptr(data) ) ) {
+ int j;
+
+ if( p->instance )
+ aFree(p->instance);
+
+ for( j = 0; j < p->hdatac; j++ ) {
+ if( p->hdata[j]->flag.free ) {
+ aFree(p->hdata[j]->data);
+ }
+ aFree(p->hdata[j]);
+ }
+ if( p->hdata )
+ aFree(p->hdata);
+ }
return 0;
}
-/*==========================================
- * Destructor
- * Called in map shutdown, cleanup var
- *------------------------------------------*/
-void do_final_party(void)
-{
- party_db->destroy(party_db,party_db_final);
- party_booking_db->destroy(party_booking_db,NULL); // Party Booking [Spiria]
-}
-// Constructor, init vars
-void do_init_party(void)
-{
- party_db = idb_alloc(DB_OPT_RELEASE_DATA);
- party_booking_db = idb_alloc(DB_OPT_RELEASE_DATA); // Party Booking [Spiria]
- iTimer->add_timer_func_list(party_send_xy_timer, "party_send_xy_timer");
- iTimer->add_timer_interval(iTimer->gettick()+battle_config.party_update_interval, party_send_xy_timer, 0, 0, battle_config.party_update_interval);
-}
-
/// Party data lookup using party id.
struct party_data* party_search(int party_id)
{
if(!party_id)
return NULL;
- return (struct party_data*)idb_get(party_db,party_id);
+ return (struct party_data*)idb_get(party->db,party_id);
}
/// Party data lookup using party name.
@@ -138,7 +129,7 @@ struct party_data* party_searchname(const char* str)
{
struct party_data* p;
- DBIterator *iter = db_iterator(party_db);
+ DBIterator *iter = db_iterator(party->db);
for( p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter) )
{
if( strncmpi(p->party.name,str,NAME_LENGTH) == 0 )
@@ -170,22 +161,21 @@ int party_create(struct map_session_data *sd,char *name,int item,int item2)
sd->party_creating = true;
- party_fill_member(&leader, sd, 1);
+ party->fill_member(&leader, sd, 1);
- intif_create_party(&leader,name,item,item2);
+ intif->create_party(&leader,name,item,item2);
return 0;
}
-void party_created(int account_id,int char_id,int fail,int party_id,char *name)
-{
+void party_created(int account_id,int char_id,int fail,int party_id,char *name) {
struct map_session_data *sd;
- sd=iMap->id2sd(account_id);
+ sd=map->id2sd(account_id);
- if (!sd || sd->status.char_id != char_id || !sd->party_creating )
- { //Character logged off before creation ack?
+ if (!sd || sd->status.char_id != char_id || !sd->party_creating ) {
+ //Character logged off before creation ack?
if (!fail) //break up party since player could not be added to it.
- intif_party_leave(party_id,account_id,char_id);
+ intif->party_leave(party_id,account_id,char_id);
return;
}
@@ -203,46 +193,43 @@ void party_created(int account_id,int char_id,int fail,int party_id,char *name)
int party_request_info(int party_id, int char_id)
{
- return intif_request_partyinfo(party_id, char_id);
+ return intif->request_partyinfo(party_id, char_id);
}
/// Invoked (from char-server) when the party info is not found.
-int party_recv_noinfo(int party_id, int char_id)
-{
+int party_recv_noinfo(int party_id, int char_id) {
party->broken(party_id);
- if( char_id != 0 )// requester
- {
+ if( char_id != 0 ) {
+ // requester
struct map_session_data* sd;
- sd = iMap->charid2sd(char_id);
+ sd = map->charid2sd(char_id);
if( sd && sd->status.party_id == party_id )
sd->status.party_id = 0;
}
return 0;
}
-static void party_check_state(struct party_data *p)
-{
+void party_check_state(struct party_data *p) {
int i;
memset(&p->state, 0, sizeof(p->state));
- for (i = 0; i < MAX_PARTY; i ++)
- {
- if (!p->party.member[i].online) continue; //Those not online shouldn't aport to skill usage and all that.
+ for (i = 0; i < MAX_PARTY; i ++) {
+ if (!p->party.member[i].online) continue; //Those not online shouldn't apart to skill usage and all that.
switch (p->party.member[i].class_) {
- case JOB_MONK:
- case JOB_BABY_MONK:
- case JOB_CHAMPION:
- p->state.monk = 1;
- break;
- case JOB_STAR_GLADIATOR:
- p->state.sg = 1;
- break;
- case JOB_SUPER_NOVICE:
- case JOB_SUPER_BABY:
- p->state.snovice = 1;
- break;
- case JOB_TAEKWON:
- p->state.tk = 1;
- break;
+ case JOB_MONK:
+ case JOB_BABY_MONK:
+ case JOB_CHAMPION:
+ p->state.monk = 1;
+ break;
+ case JOB_STAR_GLADIATOR:
+ p->state.sg = 1;
+ break;
+ case JOB_SUPER_NOVICE:
+ case JOB_SUPER_BABY:
+ p->state.snovice = 1;
+ break;
+ case JOB_TAEKWON:
+ p->state.tk = 1;
+ break;
}
}
}
@@ -261,7 +248,7 @@ int party_recv_info(struct party* sp, int char_id)
nullpo_ret(sp);
- p = (struct party_data*)idb_get(party_db, sp->party_id);
+ p = (struct party_data*)idb_get(party->db, sp->party_id);
if( p != NULL ) {// diff members
for( member_id = 0; member_id < MAX_PARTY; ++member_id ) {
member = &p->party.member[member_id];
@@ -290,7 +277,7 @@ int party_recv_info(struct party* sp, int char_id)
CREATE(p, struct party_data, 1);
p->instance = NULL;
p->instances = 0;
- idb_put(party_db, sp->party_id, p);
+ idb_put(party->db, sp->party_id, p);
}
while( removed_count > 0 ) {// no longer in party
member_id = removed[--removed_count];
@@ -306,9 +293,9 @@ int party_recv_info(struct party* sp, int char_id)
member = &p->party.member[member_id];
if ( member->char_id == 0 )
continue;// empty
- p->data[member_id].sd = party_sd_check(sp->party_id, member->account_id, member->char_id);
+ p->data[member_id].sd = party->sd_check(sp->party_id, member->account_id, member->char_id);
}
- party_check_state(p);
+ party->check_state(p);
while( added_count > 0 ) { // new in party
member_id = added[--added_count];
sd = p->data[member_id].sd;
@@ -319,15 +306,17 @@ int party_recv_info(struct party* sp, int char_id)
clif->party_option(p,sd,0x100);
clif->party_info(p,NULL);
for( j = 0; j < p->instances; j++ ) {
- if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER )
- continue;
- clif->instance_join(sd->fd, p->instance[j]);
- break;
+ if( p->instance[j] >= 0 ) {
+ if( instance->list[p->instance[j]].idle_timer == INVALID_TIMER && instance->list[p->instance[j]].progress_timer == INVALID_TIMER )
+ continue;
+ clif->instance_join(sd->fd, p->instance[j]);
+ break;
+ }
}
}
- if( char_id != 0 )// requester
- {
- sd = iMap->charid2sd(char_id);
+ if( char_id != 0 ) {
+ // requester
+ sd = map->charid2sd(char_id);
if( sd && sd->status.party_id == sp->party_id && party->getmemberid(p,sd) == -1 )
sd->status.party_id = 0;// was not in the party
}
@@ -396,8 +385,7 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
return 1;
}
-void party_reply_invite(struct map_session_data *sd,int party_id,int flag)
-{
+void party_reply_invite(struct map_session_data *sd,int party_id,int flag) {
struct map_session_data* tsd;
struct party_member member;
@@ -407,13 +395,13 @@ void party_reply_invite(struct map_session_data *sd,int party_id,int flag)
sd->party_invite_account = 0;
return;
}
- tsd = iMap->id2sd(sd->party_invite_account);
+ tsd = map->id2sd(sd->party_invite_account);
if( flag == 1 && !sd->party_creating && !sd->party_joining )
{// accepted and allowed
sd->party_joining = true;
- party_fill_member(&member, sd, 0);
- intif_party_addmember(sd->party_invite, &member);
+ party->fill_member(&member, sd, 0);
+ intif->party_addmember(sd->party_invite, &member);
}
else
{// rejected or failure
@@ -441,10 +429,12 @@ void party_member_joined(struct map_session_data *sd)
int j;
p->data[i].sd = sd;
for( j = 0; j < p->instances; j++ ) {
- if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER )
- continue;
- clif->instance_join(sd->fd, p->instance[j]);
- break;
+ if( p->instance[j] >= 0 ) {
+ if( instance->list[p->instance[j]].idle_timer == INVALID_TIMER && instance->list[p->instance[j]].progress_timer == INVALID_TIMER )
+ continue;
+ clif->instance_join(sd->fd, p->instance[j]);
+ break;
+ }
}
} else
sd->status.party_id = 0; //He does not belongs to the party really?
@@ -452,19 +442,18 @@ void party_member_joined(struct map_session_data *sd)
/// Invoked (from char-server) when a new member is added to the party.
/// flag: 0-success, 1-failure
-int party_member_added(int party_id,int account_id,int char_id, int flag)
-{
- struct map_session_data *sd = iMap->id2sd(account_id),*sd2;
+int party_member_added(int party_id,int account_id,int char_id, int flag) {
+ struct map_session_data *sd = map->id2sd(account_id),*sd2;
struct party_data *p = party->search(party_id);
int i, j;
if(sd == NULL || sd->status.char_id != char_id || !sd->party_joining ) {
if (!flag) //Char logged off before being accepted into party.
- intif_party_leave(party_id,account_id,char_id);
+ intif->party_leave(party_id,account_id,char_id);
return 0;
}
- sd2 = iMap->id2sd(sd->party_invite_account);
+ sd2 = map->id2sd(sd->party_invite_account);
sd->party_joining = false;
sd->party_invite = 0;
@@ -472,7 +461,7 @@ int party_member_added(int party_id,int account_id,int char_id, int flag)
if (!p) {
ShowError("party_member_added: party %d not found.\n",party_id);
- intif_party_leave(party_id,account_id,char_id);
+ intif->party_leave(party_id,account_id,char_id);
return 0;
}
@@ -502,10 +491,12 @@ int party_member_added(int party_id,int account_id,int char_id, int flag)
clif->charnameupdate(sd); //Update char name's display [Skotlex]
for( j = 0; j < p->instances; j++ ) {
- if( instances[p->instance[j]].idle_timer == INVALID_TIMER && instances[p->instance[j]].progress_timer == INVALID_TIMER )
- continue;
- clif->instance_join(sd->fd, p->instance[j]);
- break;
+ if( p->instance[j] >= 0 ) {
+ if( instance->list[p->instance[j]].idle_timer == INVALID_TIMER && instance->list[p->instance[j]].progress_timer == INVALID_TIMER )
+ continue;
+ clif->instance_join(sd->fd, p->instance[j]);
+ break;
+ }
}
return 0;
@@ -532,7 +523,7 @@ int party_removemember(struct map_session_data* sd, int account_id, char* name)
if( i == MAX_PARTY )
return 0; // no such char in party
- intif_party_leave(p->party.party_id,account_id,p->party.member[i].char_id);
+ intif->party_leave(p->party.party_id,account_id,p->party.member[i].char_id);
return 1;
}
@@ -550,14 +541,14 @@ int party_leave(struct map_session_data *sd)
if( i == MAX_PARTY )
return 0;
- intif_party_leave(p->party.party_id,sd->status.account_id,sd->status.char_id);
+ intif->party_leave(p->party.party_id,sd->status.account_id,sd->status.char_id);
return 1;
}
/// Invoked (from char-server) when a party member leaves the party.
int party_member_withdraw(int party_id, int account_id, int char_id)
{
- struct map_session_data* sd = iMap->id2sd(account_id);
+ struct map_session_data* sd = map->id2sd(account_id);
struct party_data* p = party->search(party_id);
if( p ) {
@@ -568,18 +559,26 @@ int party_member_withdraw(int party_id, int account_id, int char_id)
memset(&p->party.member[i], 0, sizeof(p->party.member[0]));
memset(&p->data[i], 0, sizeof(p->data[0]));
p->party.count--;
- party_check_state(p);
+ party->check_state(p);
}
}
if( sd && sd->status.party_id == party_id && sd->status.char_id == char_id ) {
+#ifdef GP_BOUND_ITEMS
+ pc->bound_clear(sd,IBT_PARTY);
+#endif
sd->status.party_id = 0;
clif->charnameupdate(sd); //Update name display [Skotlex]
//TODO: hp bars should be cleared too
- if( p->instances )
+ if( p && p->instances )
instance->check_kick(sd);
}
-
+ if (sd && sd->sc.data[SC_DANCING]) {
+ status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_DRUMBATTLE, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_NIBELUNGEN, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_SIEGFRIED, INVALID_TIMER);
+ }
return 0;
}
@@ -594,8 +593,10 @@ int party_broken(int party_id)
return 0;
for( j = 0; j < p->instances; j++ ) {
- instance->destroy( p->instance[j] );
- instances[p->instance[j]].owner_id = 0;
+ if( p->instance[j] >= 0 ) {
+ instance->destroy( p->instance[j] );
+ instance->list[p->instance[j]].owner_id = 0;
+ }
}
for( i = 0; i < MAX_PARTY; i++ ) {
@@ -605,7 +606,19 @@ int party_broken(int party_id)
}
}
- idb_remove(party_db,party_id);
+ if( p->instance )
+ aFree(p->instance);
+
+ for( j = 0; j < p->hdatac; j++ ) {
+ if( p->hdata[j]->flag.free ) {
+ aFree(p->hdata[j]->data);
+ }
+ aFree(p->hdata[j]);
+ }
+ if( p->hdata )
+ aFree(p->hdata);
+
+ idb_remove(party->db,party_id);
return 0;
}
@@ -615,14 +628,13 @@ int party_changeoption(struct map_session_data *sd,int exp,int item)
if( sd->status.party_id==0)
return 0;
- intif_party_changeoption(sd->status.party_id,sd->status.account_id,exp,item);
+ intif->party_changeoption(sd->status.party_id,sd->status.account_id,exp,item);
return 0;
}
-int party_optionchanged(int party_id,int account_id,int exp,int item,int flag)
-{
+int party_optionchanged(int party_id,int account_id,int exp,int item,int flag) {
struct party_data *p;
- struct map_session_data *sd=iMap->id2sd(account_id);
+ struct map_session_data *sd=map->id2sd(account_id);
if( (p=party->search(party_id))==NULL)
return 0;
@@ -650,8 +662,7 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts
return false;
}
- if( map[sd->bl.m].flag.partylock )
- {
+ if( map->list[sd->bl.m].flag.partylock ) {
clif->message(sd->fd, msg_txt(287));
return false;
}
@@ -683,7 +694,7 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts
clif->message(p->data[tmi].sd->fd, msg_txt(285));
//Update info.
- intif_party_leaderchange(p->party.party_id,p->party.member[tmi].account_id,p->party.member[tmi].char_id);
+ intif->party_leaderchange(p->party.party_id,p->party.member[tmi].account_id,p->party.member[tmi].char_id);
clif->party_info(p,NULL);
return true;
}
@@ -692,7 +703,7 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts
/// - changes maps
/// - logs in or out
/// - gains a level (disabled)
-int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short map,int online,int lv)
+int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short mapid,int online,int lv)
{
struct party_member* m;
struct party_data* p;
@@ -710,11 +721,11 @@ int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short m
}
m = &p->party.member[i];
- m->map = map;
+ m->map = mapid;
m->online = online;
m->lv = lv;
//Check if they still exist on this map server
- p->data[i].sd = party_sd_check(party_id, account_id, char_id);
+ p->data[i].sd = party->sd_check(party_id, account_id, char_id);
clif->party_info(p,NULL);
return 0;
@@ -727,7 +738,7 @@ void party_send_movemap(struct map_session_data *sd)
if( sd->status.party_id==0 )
return;
- intif_party_changemap(sd,1);
+ intif->party_changemap(sd,1);
p=party->search(sd->status.party_id);
if (!p) return;
@@ -755,7 +766,7 @@ void party_send_movemap(struct map_session_data *sd)
void party_send_levelup(struct map_session_data *sd)
{
- intif_party_changemap(sd,1);
+ intif->party_changemap(sd,1);
}
int party_send_logout(struct map_session_data *sd)
@@ -766,7 +777,7 @@ int party_send_logout(struct map_session_data *sd)
if(!sd->status.party_id)
return 0;
- intif_party_changemap(sd,0);
+ intif->party_changemap(sd,0);
p=party->search(sd->status.party_id);
if(!p) return 0;
@@ -783,7 +794,7 @@ int party_send_message(struct map_session_data *sd,const char *mes,int len)
{
if(sd->status.party_id==0)
return 0;
- intif_party_message(sd->status.party_id,sd->status.account_id,mes,len);
+ intif->party_message(sd->status.party_id,sd->status.account_id,mes,len);
party->recv_message(sd->status.party_id,sd->status.account_id,mes,len);
// Chat logging type 'P' / Party Chat
@@ -833,7 +844,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id
case TK_COUNTER: //Increase Triple Attack rate of Monks.
if((p_sd->class_&MAPID_UPPERMASK) == MAPID_MONK
&& pc->checkskill(p_sd,MO_TRIPLEATTACK)) {
- sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,MO_TRIPLEATTACK,
+ sc_start4(&p_sd->bl,&p_sd->bl,SC_SKILLRATE_UP,100,MO_TRIPLEATTACK,
50+50*skill_lv, //+100/150/200% rate
0,0,skill->get_time(SG_FRIEND, 1));
}
@@ -842,7 +853,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id
if((p_sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
&& sd->sc.data[SC_COUNTERKICK_READY]
&& pc->checkskill(p_sd,SG_FRIEND)) {
- sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER,
+ sc_start4(&p_sd->bl,&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER,
50+50*pc->checkskill(p_sd,SG_FRIEND), //+100/150/200% rate
0,0,skill->get_time(SG_FRIEND, 1));
}
@@ -852,11 +863,10 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id
return 0;
}
-int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+int party_send_xy_timer(int tid, int64 tick, int id, intptr_t data) {
struct party_data* p;
- DBIterator *iter = db_iterator(party_db);
+ DBIterator *iter = db_iterator(party->db);
// for each existing party,
for( p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter) )
{
@@ -871,7 +881,7 @@ int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data)
for( i = 0; i < MAX_PARTY; i++ )
{
struct map_session_data* sd = p->data[i].sd;
- if( !sd ) continue;
+ if( !sd || sd->bg_id ) continue;
if( p->data[i].x != sd->bl.x || p->data[i].y != sd->bl.y )
{// perform position update
@@ -948,7 +958,9 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b
for (i = 0; i < c; i++) {
#ifdef RENEWAL_EXP
if( !(src && src->type == BL_MOB && ((TBL_MOB*)src)->db->mexp) ){
- int rate = pc->level_penalty_mod(sd[i], (TBL_MOB*)src, 1);
+ struct mob_data *md = (TBL_MOB*)src;
+ int rate = pc->level_penalty_mod(md->level - (sd[i])->status.base_level, md->status.race, md->status.mode, 1);
+
base_exp = (unsigned int)cap_value(base_exp_bonus * rate / 100, 1, UINT_MAX);
job_exp = (unsigned int)cap_value(job_exp_bonus * rate / 100, 1, UINT_MAX);
}
@@ -1050,9 +1062,11 @@ int party_sub_count(struct block_list *bl, va_list ap)
return 1;
}
-/// Executes 'func' for each party member on the same map and in range (0:whole map)
-int party_foreachsamemap(int (*func)(struct block_list*,va_list),struct map_session_data *sd,int range,...)
-{
+/**
+ * Arglist-based version of party_foreachsamemap
+ * @see party_foreachsamemap
+ */
+int party_vforeachsamemap(int (*func)(struct block_list*,va_list), struct map_session_data *sd, int range, va_list ap) {
struct party_data *p;
int i;
int x0,y0,x1,y1;
@@ -1083,138 +1097,220 @@ int party_foreachsamemap(int (*func)(struct block_list*,va_list),struct map_sess
list[blockcount++]=&psd->bl;
}
- iMap->freeblock_lock();
+ map->freeblock_lock();
- for(i=0;i<blockcount;i++)
- {
- va_list ap;
- va_start(ap, range);
- total += func(list[i], ap);
- va_end(ap);
+ for(i=0;i<blockcount;i++) {
+ va_list ap_copy;
+ va_copy(ap_copy, ap);
+ total += func(list[i], ap_copy);
+ va_end(ap_copy);
}
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return total;
}
+// Special check for Minstrel's and Wanderer's chorus skills.
+int party_sub_count_chorus(struct block_list *bl, va_list ap) {
+ struct map_session_data *sd = (TBL_PC *)bl;
+
+ if (sd->state.autotrade)
+ return 0;
+
+ if (battle_config.idle_no_share && pc_isidle(sd))
+ return 0;
+
+ if ( (sd->class_&MAPID_THIRDMASK) != MAPID_MINSTRELWANDERER )
+ return 0;
+
+ return 1;
+}
+
+/**
+ * Executes 'func' for each party member on the same map and within a 'range' cells area
+ * @param func Function to execute
+ * @param sd Reference character for party, map, area center
+ * @param range Area size (0 = whole map)
+ * @param ... Additional parameters to pass to func()
+ * @return Sum of the return values from func()
+ */
+int party_foreachsamemap(int (*func)(struct block_list*,va_list), struct map_session_data *sd, int range, ...) {
+ va_list ap;
+ int ret;
+ va_start(ap, range);
+ ret = party->vforeachsamemap(func, sd, range, ap);
+ va_end(ap);
+ return ret;
+}
+
/*==========================================
* Party Booking in KRO [Spiria]
*------------------------------------------*/
-static struct party_booking_ad_info* create_party_booking_data(void)
-{
+struct party_booking_ad_info* create_party_booking_data(void) {
struct party_booking_ad_info *pb_ad;
CREATE(pb_ad, struct party_booking_ad_info, 1);
- pb_ad->index = party_booking_nextid++;
+ pb_ad->index = party->booking_nextid++;
return pb_ad;
}
-#ifndef PARTY_RECRUIT
-void party_booking_register(struct map_session_data *sd, short level, short mapid, short* job)
-#else
-void party_booking_register(struct map_session_data *sd, short level, const char *notice)
-#endif
-{
+void party_recruit_register(struct map_session_data *sd, short level, const char *notice) {
+#ifdef PARTY_RECRUIT
struct party_booking_ad_info *pb_ad;
-#ifndef PARTY_RECRUIT
- int i;
-#endif
- pb_ad = (struct party_booking_ad_info*)idb_get(party_booking_db, sd->status.char_id);
+ pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
if( pb_ad == NULL )
{
- pb_ad = create_party_booking_data();
- idb_put(party_booking_db, sd->status.char_id, pb_ad);
+ pb_ad = party->create_booking_data();
+ idb_put(party->booking_db, sd->status.char_id, pb_ad);
}
else
{// already registered
- clif->PartyBookingRegisterAck(sd, 2);
+ clif->PartyRecruitRegisterAck(sd, 2);
return;
}
memcpy(pb_ad->charname,sd->status.name,NAME_LENGTH);
pb_ad->expiretime = (int)time(NULL);
pb_ad->p_detail.level = level;
+ safestrncpy(pb_ad->p_detail.notice, notice, PB_NOTICE_LENGTH);
+
+ clif->PartyRecruitRegisterAck(sd, 0);
+ clif->PartyRecruitInsertNotify(sd, pb_ad); // Notice
+#else
+ return;
+#endif
+}
+
+void party_booking_register(struct map_session_data *sd, short level, short mapid, short* job) {
#ifndef PARTY_RECRUIT
+ struct party_booking_ad_info *pb_ad;
+ int i;
+
+ pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
+
+ if( pb_ad == NULL )
+ {
+ pb_ad = party->create_booking_data();
+ idb_put(party->booking_db, sd->status.char_id, pb_ad);
+ }
+ else
+ {// already registered
+ clif->PartyBookingRegisterAck(sd, 2);
+ return;
+ }
+
+ memcpy(pb_ad->charname,sd->status.name,NAME_LENGTH);
+ pb_ad->expiretime = (int)time(NULL);
+ pb_ad->p_detail.level = level;
pb_ad->p_detail.mapid = mapid;
-
+
for(i=0;i<PARTY_BOOKING_JOBS;i++)
if(job[i] != 0xFF)
pb_ad->p_detail.job[i] = job[i];
else pb_ad->p_detail.job[i] = -1;
-#else
- safestrncpy(pb_ad->p_detail.notice, notice, PB_NOTICE_LENGTH);
-#endif
-
+
clif->PartyBookingRegisterAck(sd, 0);
clif->PartyBookingInsertNotify(sd, pb_ad); // Notice
-}
-
-#ifndef PARTY_RECRUIT
-void party_booking_update(struct map_session_data *sd, short* job)
#else
-void party_booking_update(struct map_session_data *sd, const char *notice)
-#endif
-{
-#ifndef PARTY_RECRUIT
- int i;
+ return;
#endif
+}
+
+void party_recruit_update(struct map_session_data *sd, const char *notice) {
+#ifdef PARTY_RECRUIT
struct party_booking_ad_info *pb_ad;
- pb_ad = (struct party_booking_ad_info*)idb_get(party_booking_db, sd->status.char_id);
+ pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
if( pb_ad == NULL )
return;
pb_ad->expiretime = (int)time(NULL);// Update time.
+ if (notice != NULL) {
+ safestrncpy(pb_ad->p_detail.notice, notice, PB_NOTICE_LENGTH);
+ }
+
+ clif->PartyRecruitUpdateNotify(sd, pb_ad);
+#else
+ return;
+#endif
+}
+void party_booking_update(struct map_session_data *sd, short* job) {
#ifndef PARTY_RECRUIT
+ int i;
+ struct party_booking_ad_info *pb_ad;
+
+ pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
+
+ if( pb_ad == NULL )
+ return;
+
+ pb_ad->expiretime = (int)time(NULL);// Update time.
+
for(i=0;i<PARTY_BOOKING_JOBS;i++)
if(job[i] != 0xFF)
pb_ad->p_detail.job[i] = job[i];
else pb_ad->p_detail.job[i] = -1;
+
+ clif->PartyBookingUpdateNotify(sd, pb_ad);
#else
- if (notice != NULL) {
- safestrncpy(pb_ad->p_detail.notice, notice, PB_NOTICE_LENGTH);
- }
+ return;
#endif
-
- clif->PartyBookingUpdateNotify(sd, pb_ad);
}
-#ifndef PARTY_RECRUIT
-void party_booking_search(struct map_session_data *sd, short level, short mapid, short job, unsigned long lastindex, short resultcount)
-#else
-void party_booking_search(struct map_session_data *sd, short level, short mapid, unsigned long lastindex, short resultcount)
-#endif
-{
+
+void party_recruit_search(struct map_session_data *sd, short level, short mapid, unsigned long lastindex, short resultcount) {
+#ifdef PARTY_RECRUIT
struct party_booking_ad_info *pb_ad;
-#ifndef PARTY_RECRUIT
- int i;
-#endif
int count = 0;
struct party_booking_ad_info* result_list[PARTY_BOOKING_RESULTS];
bool more_result = false;
- DBIterator* iter = db_iterator(party_booking_db);
+ DBIterator* iter = db_iterator(party->booking_db);
memset(result_list, 0, sizeof(result_list));
for( pb_ad = dbi_first(iter); dbi_exists(iter); pb_ad = dbi_next(iter) )
{
-#ifndef PARTY_RECRUIT
- if (pb_ad->index < lastindex || (level && (pb_ad->p_detail.level < level-15 || pb_ad->p_detail.level > level)))
- continue;
-#else
if ((level && (pb_ad->p_detail.level < level-15 || pb_ad->p_detail.level > level)))
continue;
-#endif
if (count >= PARTY_BOOKING_RESULTS){
more_result = true;
break;
}
+ result_list[count] = pb_ad;
+ if( result_list[count] )
+ {
+ count++;
+ }
+ }
+ dbi_destroy(iter);
+ clif->PartyRecruitSearchAck(sd->fd, result_list, count, more_result);
+#else
+ return;
+#endif
+}
+void party_booking_search(struct map_session_data *sd, short level, short mapid, short job, unsigned long lastindex, short resultcount) {
#ifndef PARTY_RECRUIT
+ struct party_booking_ad_info *pb_ad;
+ int i;
+ int count = 0;
+ struct party_booking_ad_info* result_list[PARTY_BOOKING_RESULTS];
+ bool more_result = false;
+ DBIterator* iter = db_iterator(party->booking_db);
+
+ memset(result_list, 0, sizeof(result_list));
+
+ for( pb_ad = dbi_first(iter); dbi_exists(iter); pb_ad = dbi_next(iter) ) {
+ if (pb_ad->index < lastindex || (level && (pb_ad->p_detail.level < level-15 || pb_ad->p_detail.level > level)))
+ continue;
+ if (count >= PARTY_BOOKING_RESULTS){
+ more_result = true;
+ break;
+ }
if (mapid == 0 && job == -1)
result_list[count] = pb_ad;
else if (mapid == 0) {
@@ -1225,9 +1321,6 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid,
if (pb_ad->p_detail.mapid == mapid)
result_list[count] = pb_ad;
}
-#else
- result_list[count] = pb_ad;
-#endif
if( result_list[count] )
{
count++;
@@ -1235,32 +1328,57 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid,
}
dbi_destroy(iter);
clif->PartyBookingSearchAck(sd->fd, result_list, count, more_result);
+#else
+ return;
+#endif
}
+
bool party_booking_delete(struct map_session_data *sd)
{
struct party_booking_ad_info* pb_ad;
- if((pb_ad = (struct party_booking_ad_info*)idb_get(party_booking_db, sd->status.char_id))!=NULL)
+ if((pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id))!=NULL)
{
+#ifdef PARTY_RECRUIT
+ clif->PartyRecruitDeleteNotify(sd, pb_ad->index);
+#else
clif->PartyBookingDeleteNotify(sd, pb_ad->index);
- idb_remove(party_booking_db,sd->status.char_id);
+#endif
+ idb_remove(party->booking_db,sd->status.char_id);
}
return true;
}
+void do_final_party(void) {
+ party->db->destroy(party->db,party->db_final);
+ db_destroy(party->booking_db); // Party Booking [Spiria]
+}
+// Constructor, init vars
+void do_init_party(bool minimal) {
+ if (minimal)
+ return;
+ party->db = idb_alloc(DB_OPT_RELEASE_DATA);
+ party->booking_db = idb_alloc(DB_OPT_RELEASE_DATA); // Party Booking [Spiria]
+ timer->add_func_list(party->send_xy_timer, "party_send_xy_timer");
+ timer->add_interval(timer->gettick()+battle_config.party_update_interval, party->send_xy_timer, 0, 0, battle_config.party_update_interval);
+}
/*=====================================
-* Default Functions : party.h
+* Default Functions : party.h
* Generated by HerculesInterfaceMaker
* created by Susu
*-------------------------------------*/
void party_defaults(void) {
party = &party_s;
+ /* */
+ party->db = NULL;
+ party->booking_db = NULL;
+ party->booking_nextid = 1;
/* funcs */
-
- party->do_init_party = do_init_party;
- party->do_final_party = do_final_party;
+ party->init = do_init_party;
+ party->final = do_final_party;
+ /* */
party->search = party_search;
party->searchname = party_searchname;
party->getmemberid = party_getmemberid;
@@ -1294,8 +1412,20 @@ void party_defaults(void) {
party->share_loot = party_share_loot;
party->send_dot_remove = party_send_dot_remove;
party->sub_count = party_sub_count;
+ party->sub_count_chorus = party_sub_count_chorus;
party->booking_register = party_booking_register;
party->booking_update = party_booking_update;
party->booking_search = party_booking_search;
+ party->recruit_register = party_recruit_register;
+ party->recruit_update = party_recruit_update;
+ party->recruit_search = party_recruit_search;
party->booking_delete = party_booking_delete;
+ party->vforeachsamemap = party_vforeachsamemap;
+ party->foreachsamemap = party_foreachsamemap;
+ party->send_xy_timer = party_send_xy_timer;
+ party->fill_member = party_fill_member;
+ party->sd_check = party_sd_check;
+ party->check_state = party_check_state;
+ party->create_booking_data = create_party_booking_data;
+ party->db_final = party_db_final;
}
diff --git a/src/map/party.h b/src/map/party.h
index e1f2d3a3b..d62db23a7 100644
--- a/src/map/party.h
+++ b/src/map/party.h
@@ -1,19 +1,22 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-#ifndef _PARTY_H_
-#define _PARTY_H_
-#include "../common/mmo.h" // struct party
-#include "../config/core.h"
-struct block_list;
-struct map_session_data;
-struct party;
-struct item;
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
+
+#ifndef MAP_PARTY_H
+#define MAP_PARTY_H
#include <stdarg.h>
+#include "map.h" // TBL_PC
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/mmo.h" // struct party
+
#define PARTY_BOOKING_JOBS 6
#define PARTY_BOOKING_RESULTS 10
+struct HPluginData;
+
struct party_member_data {
struct map_session_data *sd;
unsigned int hp; //For HP,x,y refreshing.
@@ -24,7 +27,7 @@ struct party_data {
struct party party;
struct party_member_data data[MAX_PARTY];
uint8 itemc; //For item distribution, position of last picker in party
- unsigned short *instance;
+ short *instance;
unsigned short instances;
struct {
unsigned monk : 1; //There's at least one monk in party?
@@ -32,8 +35,14 @@ struct party_data {
unsigned snovice :1; //There's a Super Novice
unsigned tk : 1; //There's a taekwon
} state;
+
+ /* HPM Custom Struct */
+ struct HPluginData **hdata;
+ unsigned int hdatac;
};
+#define PB_NOTICE_LENGTH (36 + 1)
+
#ifndef PARTY_RECRUIT
struct party_booking_detail {
short level;
@@ -42,44 +51,38 @@ struct party_booking_detail {
};
struct party_booking_ad_info {
- unsigned long index;
+ unsigned int index;
char charname[NAME_LENGTH];
- long expiretime;
+ int expiretime;
struct party_booking_detail p_detail;
};
-#else
-#define PB_NOTICE_LENGTH (36 + 1)
+#else /* PARTY_RECRUIT */
struct party_booking_detail {
short level;
char notice[PB_NOTICE_LENGTH];
};
struct party_booking_ad_info {
- unsigned long index;
- long expiretime;
+ unsigned int index;
+ int expiretime;
char charname[NAME_LENGTH];
struct party_booking_detail p_detail;
};
-#endif
-
-
-int party_foreachsamemap(int (*func)(struct block_list *,va_list),struct map_session_data *sd,int range,...);
-
-/*==========================================
- * Party Booking in KRO [Spiria]
- *------------------------------------------*/
+#endif /* PARTY_RECRUIT */
/*=====================================
-* Interface : party.h
+* Interface : party.h
* Generated by HerculesInterfaceMaker
* created by Susu
*-------------------------------------*/
struct party_interface {
-
+ DBMap* db; // int party_id -> struct party_data* (releases data)
+ DBMap* booking_db; // int char_id -> struct party_booking_ad_info* (releases data) // Party Booking [Spiria]
+ unsigned int booking_nextid;
/* funcs */
-
- void (*do_init_party) (void);
- void (*do_final_party) (void);
+ void (*init) (bool minimal);
+ void (*final) (void);
+ /* */
struct party_data* (*search) (int party_id);
struct party_data* (*searchname) (const char* str);
int (*getmemberid) (struct party_data* p, struct map_session_data* sd);
@@ -97,7 +100,7 @@ struct party_interface {
void (*reply_invite) (struct map_session_data *sd,int party_id,int flag);
int (*recv_noinfo) (int party_id, int char_id);
int (*recv_info) (struct party* sp, int char_id);
- int (*recv_movemap) (int party_id,int account_id,int char_id, unsigned short map,int online,int lv);
+ int (*recv_movemap) (int party_id,int account_id,int char_id, unsigned short mapid,int online,int lv);
int (*broken) (int party_id);
int (*optionchanged) (int party_id,int account_id,int exp,int item,int flag);
int (*changeoption) (struct map_session_data *sd,int exp,int item);
@@ -113,20 +116,31 @@ struct party_interface {
int (*share_loot) (struct party_data* p, struct map_session_data* sd, struct item* item_data, int first_charid);
int (*send_dot_remove) (struct map_session_data *sd);
int (*sub_count) (struct block_list *bl, va_list ap);
-#ifndef PARTY_RECRUIT
+ int (*sub_count_chorus) (struct block_list *bl, va_list ap);
+ /*==========================================
+ * Party Booking in KRO [Spiria]
+ *------------------------------------------*/
void (*booking_register) (struct map_session_data *sd, short level, short mapid, short* job);
void (*booking_update) (struct map_session_data *sd, short* job);
void (*booking_search) (struct map_session_data *sd, short level, short mapid, short job, unsigned long lastindex, short resultcount);
-#else
- void (*booking_register) (struct map_session_data *sd, short level, const char *notice);
- void (*booking_update) (struct map_session_data *sd, const char *notice);
- void (*booking_search) (struct map_session_data *sd, short level, short mapid, unsigned long lastindex, short resultcount);
-#endif
+ /* PARTY_RECRUIT */
+ void (*recruit_register) (struct map_session_data *sd, short level, const char *notice);
+ void (*recruit_update) (struct map_session_data *sd, const char *notice);
+ void (*recruit_search) (struct map_session_data *sd, short level, short mapid, unsigned long lastindex, short resultcount);
bool (*booking_delete) (struct map_session_data *sd);
-} party_s;
+ /* */
+ int (*vforeachsamemap) (int (*func)(struct block_list *,va_list),struct map_session_data *sd,int range, va_list ap);
+ int (*foreachsamemap) (int (*func)(struct block_list *,va_list),struct map_session_data *sd,int range,...);
+ int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data);
+ void (*fill_member) (struct party_member* member, struct map_session_data* sd, unsigned int leader);
+ TBL_PC* (*sd_check) (int party_id, int account_id, int char_id);
+ void (*check_state) (struct party_data *p);
+ struct party_booking_ad_info* (*create_booking_data) (void);
+ int (*db_final) (DBKey key, DBData *data, va_list ap);
+};
struct party_interface *party;
void party_defaults(void);
-#endif /* _PARTY_H_ */
+#endif /* MAP_PARTY_H */
diff --git a/src/map/path.c b/src/map/path.c
index 95895cb2a..5a9ddf9c7 100644
--- a/src/map/path.c
+++ b/src/map/path.c
@@ -1,149 +1,67 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/nullpo.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/malloc.h"
-#include "map.h"
-#include "battle.h"
+#define HERCULES_CORE
+
+#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA
#include "path.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "map.h"
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
-#define MAX_HEAP 150
-
-struct tmp_path { short x,y,dist,before,cost,flag;};
-#define calc_index(x,y) (((x)+(y)*MAX_WALKPATH) & (MAX_WALKPATH*MAX_WALKPATH-1))
-
-const char walk_choices [3][3] =
-{
- {1,0,7},
- {2,-1,6},
- {3,4,5},
-};
-
-/*==========================================
- * heap push (helper function)
- *------------------------------------------*/
-static void push_heap_path(int *heap,struct tmp_path *tp,int index)
-{
- int i,h;
-
- h = heap[0];
- heap[0]++;
-
- for( i = (h-1)/2; h > 0 && tp[index].cost < tp[heap[i+1]].cost; i = (h-1)/2 )
- heap[h+1] = heap[i+1], h = i;
-
- heap[h+1] = index;
-}
-
-/*==========================================
- * heap update (helper function)
- * Move toward the root because cost has decreased.
- *------------------------------------------*/
-static void update_heap_path(int *heap,struct tmp_path *tp,int index)
-{
- int i,h;
-
- ARR_FIND( 0, heap[0], h, heap[h+1] == index );
- if( h == heap[0] )
- {
- ShowError("update_heap_path bug\n");
- exit(EXIT_FAILURE);
- }
-
- for( i = (h-1)/2; h > 0 && tp[index].cost < tp[heap[i+1]].cost; i = (h-1)/2 )
- heap[h+1] = heap[i+1], h = i;
-
- heap[h+1] = index;
-}
+#define SET_OPEN 0
+#define SET_CLOSED 1
-/*==========================================
- * heap pop (helper function)
- *------------------------------------------*/
-static int pop_heap_path(int *heap,struct tmp_path *tp)
-{
- int i,h,k;
- int ret,last;
+#define DIR_NORTH 1
+#define DIR_WEST 2
+#define DIR_SOUTH 4
+#define DIR_EAST 8
- if( heap[0] <= 0 )
- return -1;
- ret = heap[1];
- last = heap[heap[0]];
- heap[0]--;
+struct path_interface path_s;
- for( h = 0, k = 2; k < heap[0]; k = k*2+2 )
- {
- if( tp[heap[k+1]].cost > tp[heap[k]].cost )
- k--;
- heap[h+1] = heap[k+1], h = k;
- }
+/// @name Structures and defines for A* pathfinding
+/// @{
- if( k == heap[0] )
- heap[h+1] = heap[k], h = k-1;
+/// Path node
+struct path_node {
+ struct path_node *parent; ///< pointer to parent (for path reconstruction)
+ short x; ///< X-coordinate
+ short y; ///< Y-coordinate
+ short g_cost; ///< Actual cost from start to this node
+ short f_cost; ///< g_cost + heuristic(this, goal)
+ short flag; ///< SET_OPEN / SET_CLOSED
+};
- for( i = (h-1)/2; h > 0 && tp[heap[i+1]].cost > tp[last].cost; i = (h-1)/2 )
- heap[h+1] = heap[i+1], h = i;
+/// Binary heap of path nodes
+BHEAP_STRUCT_DECL(node_heap, struct path_node*);
- heap[h+1]=last;
+/// Comparator for binary heap of path nodes (minimum cost at top)
+#define NODE_MINTOPCMP(i,j) ((i)->f_cost - (j)->f_cost)
- return ret;
-}
+#define calc_index(x,y) (((x)+(y)*MAX_WALKPATH) & (MAX_WALKPATH*MAX_WALKPATH-1))
-/*==========================================
- * calculate cost for the specified position
- *------------------------------------------*/
-static int calc_cost(struct tmp_path *p,int16 x1,int16 y1)
-{
- int xd = abs(x1 - p->x);
- int yd = abs(y1 - p->y);
- return (xd + yd)*10 + p->dist;
-}
+/// Estimates the cost from (x0,y0) to (x1,y1).
+/// This is inadmissible (overestimating) heuristic used by game client.
+#define heuristic(x0, y0, x1, y1) (MOVE_COST * (abs((x1) - (x0)) + abs((y1) - (y0)))) // Manhattan distance
+/// @}
-/*==========================================
- * attach/adjust path if neccessary
- *------------------------------------------*/
-static int add_path(int *heap,struct tmp_path *tp,int16 x,int16 y,int dist,int before,int cost)
+// Translates dx,dy into walking direction
+static const unsigned char walk_choices [3][3] =
{
- int i;
-
- i = calc_index(x,y);
-
- if( tp[i].x == x && tp[i].y == y )
- {
- if( tp[i].dist > dist )
- {
- tp[i].dist = dist;
- tp[i].before = before;
- tp[i].cost = cost;
- if( tp[i].flag )
- push_heap_path(heap,tp,i);
- else
- update_heap_path(heap,tp,i);
- tp[i].flag = 0;
- }
- return 0;
- }
-
- if( tp[i].x || tp[i].y )
- return 1;
-
- tp[i].x = x;
- tp[i].y = y;
- tp[i].dist = dist;
- tp[i].before = before;
- tp[i].cost = cost;
- tp[i].flag = 0;
- push_heap_path(heap,tp,i);
-
- return 0;
-}
+ {1,0,7},
+ {2,-1,6},
+ {3,4,5},
+};
/*==========================================
* Find the closest reachable cell, 'count' cells away from (x0,y0) in direction (dx,dy).
@@ -153,9 +71,9 @@ int path_blownpos(int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count)
{
struct map_data *md;
- if( !map[m].cell )
+ if( !map->list[m].cell )
return -1;
- md = &map[m];
+ md = &map->list[m];
if( count>25 ){ //Cap to prevent too much processing...?
ShowWarning("path_blownpos: count too many %d !\n",count);
@@ -168,21 +86,8 @@ int path_blownpos(int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count)
}
while( count > 0 && (dx != 0 || dy != 0) ) {
- if( !md->getcellp(md,x0+dx,y0+dy,CELL_CHKPASS) ) {// attempt partial movement
- int fx = ( dx != 0 && md->getcellp(md,x0+dx,y0,CELL_CHKPASS) );
- int fy = ( dy != 0 && md->getcellp(md,x0,y0+dy,CELL_CHKPASS) );
- if( fx && fy )
- {
- if(rnd()&1)
- dx=0;
- else
- dy=0;
- }
- if( !fx )
- dx=0;
- if( !fy )
- dy=0;
- }
+ if( !md->getcellp(md,x0+dx,y0+dy,CELL_CHKPASS) )
+ break;
x0 += dx;
y0 += dy;
@@ -206,9 +111,9 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16
if( spd == NULL )
spd = &s_spd; // use dummy output variable
- if (!map[m].cell)
+ if (!map->list[m].cell)
return false;
- md = &map[m];
+ md = &map->list[m];
dx = (x1 - x0);
if (dx < 0) {
@@ -262,164 +167,252 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16
return true;
}
+/// @name A* pathfinding related functions
+/// @{
+
+/// Pushes path_node to the binary node_heap.
+/// Ensures there is enough space in array to store new element.
+static void heap_push_node(struct node_heap *heap, struct path_node *node)
+{
+#ifndef __clang_analyzer__ // TODO: Figure out why clang's static analyzer doesn't like this
+ BHEAP_ENSURE(*heap, 1, 256);
+ BHEAP_PUSH(*heap, node, NODE_MINTOPCMP, swap_ptr);
+#endif // __clang_analyzer__
+}
+
+/// Updates path_node in the binary node_heap.
+static int heap_update_node(struct node_heap *heap, struct path_node *node)
+{
+ int i;
+ ARR_FIND(0, BHEAP_LENGTH(*heap), i, BHEAP_DATA(*heap)[i] == node);
+ if (i == BHEAP_LENGTH(*heap)) {
+ ShowError("heap_update_node: node not found\n");
+ return 1;
+ }
+ BHEAP_POPINDEX(*heap, i, NODE_MINTOPCMP, swap_ptr);
+ BHEAP_PUSH(*heap, node, NODE_MINTOPCMP, swap_ptr);
+ return 0;
+}
+
+/// Path_node processing in A* pathfinding.
+/// Adds new node to heap and updates/re-adds old ones if necessary.
+static int add_path(struct node_heap *heap, struct path_node *tp, int16 x, int16 y, int g_cost, struct path_node *parent, int h_cost)
+{
+ int i = calc_index(x, y);
+
+ if (tp[i].x == x && tp[i].y == y) { // We processed this node before
+ if (g_cost < tp[i].g_cost) { // New path to this node is better than old one
+ // Update costs and parent
+ tp[i].g_cost = g_cost;
+ tp[i].parent = parent;
+ tp[i].f_cost = g_cost + h_cost;
+ if (tp[i].flag == SET_CLOSED) {
+ heap_push_node(heap, &tp[i]); // Put it in open set again
+ }
+ else if (heap_update_node(heap, &tp[i])) {
+ return 1;
+ }
+ tp[i].flag = SET_OPEN;
+ }
+ return 0;
+ }
+
+ if (tp[i].x || tp[i].y) // Index is already taken; see `tp` array FIXME for details
+ return 1;
+
+ // New node
+ tp[i].x = x;
+ tp[i].y = y;
+ tp[i].g_cost = g_cost;
+ tp[i].parent = parent;
+ tp[i].f_cost = g_cost + h_cost;
+ tp[i].flag = SET_OPEN;
+ heap_push_node(heap, &tp[i]);
+ return 0;
+}
+///@}
+
/*==========================================
* path search (x0,y0)->(x1,y1)
* wpd: path info will be written here
* flag: &1 = easy path search only
* cell: type of obstruction to check for
*------------------------------------------*/
-bool path_search(struct walkpath_data *wpd,int16 m,int16 x0,int16 y0,int16 x1,int16 y1,int flag,cell_chk cell)
+bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell)
{
- int heap[MAX_HEAP+1];
- struct tmp_path tp[MAX_WALKPATH*MAX_WALKPATH];
- register int i,j,len,x,y,dx,dy;
- int rp,xs,ys;
+ register int i, j, x, y, dx, dy;
struct map_data *md;
struct walkpath_data s_wpd;
- if( wpd == NULL )
+ if (wpd == NULL)
wpd = &s_wpd; // use dummy output variable
- if( !map[m].cell )
+ if (!map->list[m].cell)
return false;
- md = &map[m];
+ md = &map->list[m];
#ifdef CELL_NOSTACK
//Do not check starting cell as that would get you stuck.
- if( x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys )
+ if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys)
#else
- if( x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| md->getcellp(md,x0,y0,cell)*/ )
+ if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| md->getcellp(md,x0,y0,cell)*/)
#endif
return false;
- if( x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || md->getcellp(md,x1,y1,cell) )
+
+ // Check destination cell
+ if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || md->getcellp(md,x1,y1,cell))
return false;
- // calculate (sgn(x1-x0), sgn(y1-y0))
- dx = ((dx = x1-x0)) ? ((dx<0) ? -1 : 1) : 0;
- dy = ((dy = y1-y0)) ? ((dy<0) ? -1 : 1) : 0;
+ if (flag&1) {
+ // Try finding direct path to target
+ // Direct path goes diagonally first, then in straight line.
- // try finding direct path to target
- x = x0;
- y = y0;
- i = 0;
- while( i < ARRAYLENGTH(wpd->path) )
- {
- wpd->path[i] = walk_choices[-dy + 1][dx + 1];
- i++;
+ // calculate (sgn(x1-x0), sgn(y1-y0))
+ dx = ((dx = x1-x0)) ? ((dx<0) ? -1 : 1) : 0;
+ dy = ((dy = y1-y0)) ? ((dy<0) ? -1 : 1) : 0;
- x += dx;
- y += dy;
+ x = x0; // Current position = starting cell
+ y = y0;
+ i = 0;
+ while( i < ARRAYLENGTH(wpd->path) )
+ {
+ wpd->path[i] = walk_choices[-dy + 1][dx + 1];
+ i++;
- if( x == x1 ) dx = 0;
- if( y == y1 ) dy = 0;
+ x += dx; // Advance current position
+ y += dy;
- if( dx == 0 && dy == 0 )
- break; // success
- if( md->getcellp(md,x,y,cell) )
- break; // obstacle = failure
- }
+ if( x == x1 ) dx = 0; // destination x reached, no longer move along x-axis
+ if( y == y1 ) dy = 0; // destination y reached, no longer move along y-axis
- if( x == x1 && y == y1 )
- { //easy path successful.
- wpd->path_len = i;
- wpd->path_pos = 0;
- return true;
+ if( dx == 0 && dy == 0 )
+ break; // success
+ if( md->getcellp(md,x,y,cell) )
+ break; // obstacle = failure
+ }
+
+ if( x == x1 && y == y1 )
+ { // easy path successful.
+ wpd->path_len = i;
+ wpd->path_pos = 0;
+ return true;
+ }
+
+ return false; // easy path unsuccessful
}
+ else { // !(flag&1)
+ // A* (A-star) pathfinding
+ // We always use A* for finding walkpaths because it is what game client uses.
+ // Easy pathfinding cuts corners of non-walkable cells, but client always walks around it.
+
+ BHEAP_STRUCT_VAR(node_heap, open_set); // 'Open' set
+
+ // FIXME: This array is too small to ensure all paths shorter than MAX_WALKPATH
+ // can be found without node collision: calc_index(node1) = calc_index(node2).
+ // Figure out more proper size or another way to keep track of known nodes.
+ struct path_node tp[MAX_WALKPATH * MAX_WALKPATH];
+ struct path_node *current, *it;
+ int xs = md->xs - 1;
+ int ys = md->ys - 1;
+ int len = 0;
+ memset(tp, 0, sizeof(tp));
+
+ // Start node
+ i = calc_index(x0, y0);
+ tp[i].parent = NULL;
+ tp[i].x = x0;
+ tp[i].y = y0;
+ tp[i].g_cost = 0;
+ tp[i].f_cost = heuristic(x0, y0, x1, y1);
+ tp[i].flag = SET_OPEN;
+
+ heap_push_node(&open_set, &tp[i]); // Put start node to 'open' set
+ for(;;)
+ {
+ int e = 0; // error flag
- if( flag&1 )
- return false;
+ // Saves allowed directions for the current cell. Diagonal directions
+ // are only allowed if both directions around it are allowed. This is
+ // to prevent cutting corner of nearby wall.
+ // For example, you can only go NW from the current cell, if you can
+ // go N *and* you can go W. Otherwise you need to walk around the
+ // (corner of the) non-walkable cell.
+ int allowed_dirs = 0;
- memset(tp,0,sizeof(tp));
-
- i=calc_index(x0,y0);
- tp[i].x=x0;
- tp[i].y=y0;
- tp[i].dist=0;
- tp[i].before=0;
- tp[i].cost=calc_cost(&tp[i],x1,y1);
- tp[i].flag=0;
- heap[0]=0;
- push_heap_path(heap,tp,calc_index(x0,y0));
- xs = md->xs - 1; // Place by subtracting a pre-
- ys = md->ys-1;
-
- for(;;)
- {
- int e=0,f=0,dist,cost,dc[4]={0,0,0,0};
+ int g_cost;
- if(heap[0]==0)
- return false;
- rp = pop_heap_path(heap,tp);
- x = tp[rp].x;
- y = tp[rp].y;
- dist = tp[rp].dist + 10;
- cost = tp[rp].cost;
+ if (BHEAP_LENGTH(open_set) == 0) {
+ BHEAP_CLEAR(open_set);
+ return false;
+ }
- if(x==x1 && y==y1)
- break;
+ current = BHEAP_PEEK(open_set); // Look for the lowest f_cost node in the 'open' set
+ BHEAP_POP(open_set, NODE_MINTOPCMP, swap_ptr); // Remove it from 'open' set
- // dc[0] : y++ Incremental cost at the time
- // dc[1] : x--
- // dc[2] : y--
- // dc[3] : x++
+ x = current->x;
+ y = current->y;
+ g_cost = current->g_cost;
- if(y < ys && !md->getcellp(md,x ,y+1,cell)) {
- f |= 1; dc[0] = (y >= y1 ? 20 : 0);
- e+=add_path(heap,tp,x ,y+1,dist,rp,cost+dc[0]); // (x, y+1)
- }
- if(x > 0 && !md->getcellp(md,x-1,y ,cell)) {
- f |= 2; dc[1] = (x <= x1 ? 20 : 0);
- e+=add_path(heap,tp,x-1,y ,dist,rp,cost+dc[1]); // (x-1, y )
- }
- if(y > 0 && !md->getcellp(md,x ,y-1,cell)) {
- f |= 4; dc[2] = (y <= y1 ? 20 : 0);
- e+=add_path(heap,tp,x ,y-1,dist,rp,cost+dc[2]); // (x , y-1)
- }
- if(x < xs && !md->getcellp(md,x+1,y ,cell)) {
- f |= 8; dc[3] = (x >= x1 ? 20 : 0);
- e+=add_path(heap,tp,x+1,y ,dist,rp,cost+dc[3]); // (x+1, y )
- }
- if( (f & (2+1)) == (2+1) && !md->getcellp(md,x-1,y+1,cell))
- e+=add_path(heap,tp,x-1,y+1,dist+4,rp,cost+dc[1]+dc[0]-6); // (x-1, y+1)
- if( (f & (2+4)) == (2+4) && !md->getcellp(md,x-1,y-1,cell))
- e+=add_path(heap,tp,x-1,y-1,dist+4,rp,cost+dc[1]+dc[2]-6); // (x-1, y-1)
- if( (f & (8+4)) == (8+4) && !md->getcellp(md,x+1,y-1,cell))
- e+=add_path(heap,tp,x+1,y-1,dist+4,rp,cost+dc[3]+dc[2]-6); // (x+1, y-1)
- if( (f & (8+1)) == (8+1) && !md->getcellp(md,x+1,y+1,cell))
- e+=add_path(heap,tp,x+1,y+1,dist+4,rp,cost+dc[3]+dc[0]-6); // (x+1, y+1)
- tp[rp].flag=1;
- if(e || heap[0]>=MAX_HEAP-5)
- return false;
- }
+ current->flag = SET_CLOSED; // Add current node to 'closed' set
- if( !(x==x1 && y==y1) ) // will never happen...
- return false;
+ if (x == x1 && y == y1) {
+ BHEAP_CLEAR(open_set);
+ break;
+ }
- for(len=0,i=rp;len<100 && i!=calc_index(x0,y0);i=tp[i].before,len++);
- if(len==100 || len>=sizeof(wpd->path))
- return false;
+ if (y < ys && !md->getcellp(md, x, y+1, cell)) allowed_dirs |= DIR_NORTH;
+ if (y > 0 && !md->getcellp(md, x, y-1, cell)) allowed_dirs |= DIR_SOUTH;
+ if (x < xs && !md->getcellp(md, x+1, y, cell)) allowed_dirs |= DIR_EAST;
+ if (x > 0 && !md->getcellp(md, x-1, y, cell)) allowed_dirs |= DIR_WEST;
+
+#define chk_dir(d) ((allowed_dirs & (d)) == (d))
+ // Process neighbors of current node
+ // TODO: Processing order affects chosen path if there is more than one path with same cost.
+ // In few cases path found by server will be different than path found by game client.
+ if (chk_dir(DIR_SOUTH))
+ e += add_path(&open_set, tp, x, y-1, g_cost + MOVE_COST, current, heuristic(x, y-1, x1, y1)); // (x, y-1) 4
+ if (chk_dir(DIR_SOUTH|DIR_WEST) && !md->getcellp(md, x-1, y-1, cell))
+ e += add_path(&open_set, tp, x-1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y-1, x1, y1)); // (x-1, y-1) 3
+ if (chk_dir(DIR_WEST))
+ e += add_path(&open_set, tp, x-1, y, g_cost + MOVE_COST, current, heuristic(x-1, y, x1, y1)); // (x-1, y) 2
+ if (chk_dir(DIR_NORTH|DIR_WEST) && !md->getcellp(md, x-1, y+1, cell))
+ e += add_path(&open_set, tp, x-1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y+1, x1, y1)); // (x-1, y+1) 1
+ if (chk_dir(DIR_NORTH))
+ e += add_path(&open_set, tp, x, y+1, g_cost + MOVE_COST, current, heuristic(x, y+1, x1, y1)); // (x, y+1) 0
+ if (chk_dir(DIR_NORTH|DIR_EAST) && !md->getcellp(md, x+1, y+1, cell))
+ e += add_path(&open_set, tp, x+1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y+1, x1, y1)); // (x+1, y+1) 7
+ if (chk_dir(DIR_EAST))
+ e += add_path(&open_set, tp, x+1, y, g_cost + MOVE_COST, current, heuristic(x+1, y, x1, y1)); // (x+1, y) 6
+ if (chk_dir(DIR_SOUTH|DIR_EAST) && !md->getcellp(md, x+1, y-1, cell))
+ e += add_path(&open_set, tp, x+1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y-1, x1, y1)); // (x+1, y-1) 5
+#undef chk_dir
+ if (e) {
+ BHEAP_CLEAR(open_set);
+ return false;
+ }
+ }
- wpd->path_len = len;
- wpd->path_pos = 0;
- for(i=rp,j=len-1;j>=0;i=tp[i].before,j--) {
- int dx = tp[i].x - tp[tp[i].before].x;
- int dy = tp[i].y - tp[tp[i].before].y;
- uint8 dir;
- if( dx == 0 ) {
- dir = (dy > 0 ? 0 : 4);
- } else if( dx > 0 ) {
- dir = (dy == 0 ? 6 : (dy < 0 ? 5 : 7) );
- } else {
- dir = (dy == 0 ? 2 : (dy > 0 ? 1 : 3) );
+ for (it = current; it->parent != NULL; it = it->parent, len++);
+ if (len > sizeof(wpd->path)) {
+ return false;
}
- wpd->path[j] = dir;
- }
- return true;
+ // Recreate path
+ wpd->path_len = len;
+ wpd->path_pos = 0;
+ for (it = current, j = len-1; j >= 0; it = it->parent, j--) {
+ dx = it->x - it->parent->x;
+ dy = it->y - it->parent->y;
+ wpd->path[j] = walk_choices[-dy + 1][dx + 1];
+ }
+ return true;
+ } // A* end
+
+ return false;
}
-//Distance functions, taken from http://www.flpcode.com/articles/article_fastdistance.shtml
+//Distance functions, taken from http://www.flipcode.com/articles/article_fastdistance.shtml
int check_distance(int dx, int dy, int distance)
{
#ifdef CIRCULAR_AREA
@@ -439,7 +432,7 @@ unsigned int distance(int dx, int dy)
if ( dx < 0 ) dx = -dx;
if ( dy < 0 ) dy = -dy;
- //There appears to be something wrong with the aproximation below when either dx/dy is 0! [Skotlex]
+ //There appears to be something wrong with the approximation below when either dx/dy is 0! [Skotlex]
if ( dx == 0 ) return dy;
if ( dy == 0 ) return dx;
@@ -460,3 +453,12 @@ unsigned int distance(int dx, int dy)
return (dx<dy?dy:dx);
#endif
}
+void path_defaults(void) {
+ path = &path_s;
+
+ path->blownpos = path_blownpos;
+ path->search_long = path_search_long;
+ path->search = path_search;
+ path->check_distance = check_distance;
+ path->distance = distance;
+}
diff --git a/src/map/path.h b/src/map/path.h
index b1ca71955..8d02e6558 100644
--- a/src/map/path.h
+++ b/src/map/path.h
@@ -1,10 +1,15 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _PATH_H_
-#define _PATH_H_
+#ifndef MAP_PATH_H
+#define MAP_PATH_H
#include "map.h" // enum cell_chk
+#include "../common/cbasetypes.h"
+
+#define MOVE_COST 10
+#define MOVE_DIAGONAL_COST 14
#define MAX_WALKPATH 32
@@ -19,25 +24,27 @@ struct shootpath_data {
int y[MAX_WALKPATH];
};
-// calculates destination cell for knockback
-int path_blownpos(int16 m,int16 x0,int16 y0,int16 dx,int16 dy,int count);
-
-// tries to find a walkable path
-bool path_search(struct walkpath_data *wpd,int16 m,int16 x0,int16 y0,int16 x1,int16 y1,int flag,cell_chk cell);
-
-// tries to find a shootable path
-bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16 x1,int16 y1,cell_chk cell);
-
+#define check_distance_bl(bl1, bl2, distance) (path->check_distance((bl1)->x - (bl2)->x, (bl1)->y - (bl2)->y, distance))
+#define check_distance_blxy(bl, x1, y1, distance) (path->check_distance((bl)->x - (x1), (bl)->y - (y1), distance))
+#define check_distance_xy(x0, y0, x1, y1, distance) (path->check_distance((x0) - (x1), (y0) - (y1), distance))
+
+#define distance_bl(bl1, bl2) (path->distance((bl1)->x - (bl2)->x, (bl1)->y - (bl2)->y))
+#define distance_blxy(bl, x1, y1) (path->distance((bl)->x - (x1), (bl)->y - (y1)))
+#define distance_xy(x0, y0, x1, y1) (path->distance((x0) - (x1), (y0) - (y1)))
+
+struct path_interface {
+ // calculates destination cell for knockback
+ int (*blownpos) (int16 m, int16 x0, int16 y0, int16 dx, int16 dy, int count);
+ // tries to find a walkable path
+ bool (*search) (struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell);
+ // tries to find a shootable path
+ bool (*search_long) (struct shootpath_data *spd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, cell_chk cell);
+ int (*check_distance) (int dx, int dy, int distance);
+ unsigned int (*distance) (int dx, int dy);
+};
-// distance related functions
-int check_distance(int dx, int dy, int distance);
-#define check_distance_bl(bl1, bl2, distance) check_distance((bl1)->x - (bl2)->x, (bl1)->y - (bl2)->y, distance)
-#define check_distance_blxy(bl, x1, y1, distance) check_distance((bl)->x-(x1), (bl)->y-(y1), distance)
-#define check_distance_xy(x0, y0, x1, y1, distance) check_distance((x0)-(x1), (y0)-(y1), distance)
+struct path_interface *path;
-unsigned int distance(int dx, int dy);
-#define distance_bl(bl1, bl2) distance((bl1)->x - (bl2)->x, (bl1)->y - (bl2)->y)
-#define distance_blxy(bl, x1, y1) distance((bl)->x-(x1), (bl)->y-(y1))
-#define distance_xy(x0, y0, x1, y1) distance((x0)-(x1), (y0)-(y1))
+void path_defaults(void);
-#endif /* _PATH_H_ */
+#endif /* MAP_PATH_H */
diff --git a/src/map/pc.c b/src/map/pc.c
index b7644f2fb..a6619fad2 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -2,90 +2,60 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/core.h" // get_svn_revision()
-#include "../common/malloc.h"
-#include "../common/nullpo.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/socket.h" // session[]
-#include "../common/strlib.h" // safestrncpy()
-#include "../common/timer.h"
-#include "../common/utils.h"
-#include "../common/mmo.h" //NAME_LENGTH
+#define HERCULES_CORE
+
+#include "../config/core.h" // DBPATH, GP_BOUND_ITEMS, MAX_SPIRITBALL, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EXP, SECURE_NPCTIMEOUT
+#include "pc.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
#include "atcommand.h" // get_atcommand_level()
#include "battle.h" // battle_config
#include "battleground.h"
+#include "chat.h"
#include "chrif.h"
#include "clif.h"
#include "date.h" // is_day_of_*()
#include "duel.h"
+#include "elemental.h"
+#include "guild.h" // guild->search(), guild_request_info()
+#include "homunculus.h"
+#include "instance.h"
#include "intif.h"
#include "itemdb.h"
#include "log.h"
#include "mail.h"
#include "map.h"
-#include "path.h"
-#include "homunculus.h"
-#include "instance.h"
#include "mercenary.h"
-#include "elemental.h"
+#include "mob.h" // struct mob_data
#include "npc.h" // fake_nd
-#include "pet.h" // pet_unlocktarget()
#include "party.h" // party->search()
-#include "guild.h" // guild->search(), guild_request_info()
+#include "path.h"
+#include "pc_groups.h"
+#include "pet.h" // pet_unlocktarget()
+#include "quest.h"
#include "script.h" // script_config
#include "skill.h"
#include "status.h" // struct status_data
-#include "pc.h"
-#include "pc_groups.h"
-#include "quest.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-
-#define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval
-static unsigned int exp_table[CLASS_COUNT][2][MAX_LEVEL];
-static unsigned int max_level[CLASS_COUNT][2];
-static unsigned int statp[MAX_LEVEL+1];
-#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
-static unsigned int level_penalty[3][RC_MAX][MAX_LEVEL*2+1];
-#endif
-
-// h-files are for declarations, not for implementations... [Shinomori]
-struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE];
-// timer for night.day implementation
-int day_timer_tid;
-int night_timer_tid;
-
-struct fame_list smith_fame_list[MAX_FAME_LIST];
-struct fame_list chemist_fame_list[MAX_FAME_LIST];
-struct fame_list taekwon_fame_list[MAX_FAME_LIST];
-
-static unsigned short equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_GARMENT,EQP_AMMO};
-
-//Links related info to the sd->hate_mob[]/sd->feel_map[] entries
-const struct sg_data sg_info[MAX_PC_FEELHATE] = {
- { SG_SUN_ANGER, SG_SUN_BLESS, SG_SUN_COMFORT, "PC_FEEL_SUN", "PC_HATE_MOB_SUN", is_day_of_sun },
- { SG_MOON_ANGER, SG_MOON_BLESS, SG_MOON_COMFORT, "PC_FEEL_MOON", "PC_HATE_MOB_MOON", is_day_of_moon },
- { SG_STAR_ANGER, SG_STAR_BLESS, SG_STAR_COMFORT, "PC_FEEL_STAR", "PC_HATE_MOB_STAR", is_day_of_star }
- };
+#include "storage.h"
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/core.h" // get_svn_revision()
+#include "../common/malloc.h"
+#include "../common/mmo.h" // NAME_LENGTH, MAX_CARTS, NEW_CARTS
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h" // session[]
+#include "../common/strlib.h" // safestrncpy()
+#include "../common/sysinfo.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-/**
- * Item Cool Down Delay Saving
- * Struct item_cd is not a member of struct map_session_data
- * to keep cooldowns in memory between player log-ins.
- * All cooldowns are reset when server is restarted.
- **/
-DBMap* itemcd_db = NULL; // char_id -> struct skill_cd
-struct item_cd {
- unsigned int tick[MAX_ITEMDELAYS];//tick
- short nameid[MAX_ITEMDELAYS];//skill id
-};
+struct pc_interface pc_s;
//Converts a class to its array index for CLASS_COUNT defined arrays.
//Note that it does not do a validity check for speed purposes, where parsing
@@ -96,15 +66,48 @@ int pc_class2idx(int class_) {
return class_;
}
-int pc_get_group_level(struct map_session_data *sd) {
- return sd->group_level;
+/**
+ * Creates a new dummy map session data.
+ * Used when there is no real player attached, but it is
+ * required to provide a session.
+ * Caller must release dummy on its own when it's no longer needed.
+ */
+struct map_session_data* pc_get_dummy_sd(void)
+{
+ struct map_session_data *dummy_sd;
+ CREATE(dummy_sd, struct map_session_data, 1);
+ dummy_sd->group = pcg->get_dummy_group(); // map_session_data.group is expected to be non-NULL at all times
+ return dummy_sd;
}
-static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data)
+/**
+ * Sets player's group.
+ * Caller should handle error (preferably display message and disconnect).
+ * @param group_id Group ID
+ * @return 1 on error, 0 on success
+ */
+int pc_set_group(struct map_session_data *sd, int group_id)
{
+ GroupSettings *group = pcg->id2group(group_id);
+ if (group == NULL)
+ return 1;
+ sd->group_id = group_id;
+ sd->group = group;
+ return 0;
+}
+
+/**
+ * Checks if commands used by player should be logged.
+ */
+bool pc_should_log_commands(struct map_session_data *sd)
+{
+ return pcg->should_log_commands(sd->group);
+}
+
+int pc_invincible_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
- if( (sd=(struct map_session_data *)iMap->id2sd(id)) == NULL || sd->bl.type!=BL_PC )
+ if( (sd=(struct map_session_data *)map->id2sd(id)) == NULL || sd->bl.type!=BL_PC )
return 1;
if(sd->invincible_timer != tid){
@@ -120,11 +123,11 @@ static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data
void pc_setinvincibletimer(struct map_session_data* sd, int val) {
nullpo_retv(sd);
- val += map[sd->bl.m].invincible_time_inc;
+ val += map->list[sd->bl.m].invincible_time_inc;
if( sd->invincible_timer != INVALID_TIMER )
- iTimer->delete_timer(sd->invincible_timer,pc_invincible_timer);
- sd->invincible_timer = iTimer->add_timer(iTimer->gettick()+val,pc_invincible_timer,sd->bl.id,0);
+ timer->delete(sd->invincible_timer,pc->invincible_timer);
+ sd->invincible_timer = timer->add(timer->gettick()+val,pc->invincible_timer,sd->bl.id,0);
}
void pc_delinvincibletimer(struct map_session_data* sd)
@@ -133,18 +136,17 @@ void pc_delinvincibletimer(struct map_session_data* sd)
if( sd->invincible_timer != INVALID_TIMER )
{
- iTimer->delete_timer(sd->invincible_timer,pc_invincible_timer);
+ timer->delete(sd->invincible_timer,pc->invincible_timer);
sd->invincible_timer = INVALID_TIMER;
- skill->unit_move(&sd->bl,iTimer->gettick(),1);
+ skill->unit_move(&sd->bl,timer->gettick(),1);
}
}
-static int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+int pc_spiritball_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
int i;
- if( (sd=(struct map_session_data *)iMap->id2sd(id)) == NULL || sd->bl.type!=BL_PC )
+ if( (sd=(struct map_session_data *)map->id2sd(id)) == NULL || sd->bl.type!=BL_PC )
return 1;
if( sd->spiritball <= 0 )
@@ -184,21 +186,21 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max)
if( sd->spiritball && sd->spiritball >= max ) {
if(sd->spirit_timer[0] != INVALID_TIMER)
- iTimer->delete_timer(sd->spirit_timer[0],pc_spiritball_timer);
+ timer->delete(sd->spirit_timer[0],pc->spiritball_timer);
sd->spiritball--;
if( sd->spiritball != 0 )
memmove(sd->spirit_timer+0, sd->spirit_timer+1, (sd->spiritball)*sizeof(int));
sd->spirit_timer[sd->spiritball] = INVALID_TIMER;
}
- tid = iTimer->add_timer(iTimer->gettick()+interval, pc_spiritball_timer, sd->bl.id, 0);
- ARR_FIND(0, sd->spiritball, i, sd->spirit_timer[i] == INVALID_TIMER || DIFF_TICK(iTimer->get_timer(tid)->tick, iTimer->get_timer(sd->spirit_timer[i])->tick) < 0);
+ tid = timer->add(timer->gettick()+interval, pc->spiritball_timer, sd->bl.id, 0);
+ ARR_FIND(0, sd->spiritball, i, sd->spirit_timer[i] == INVALID_TIMER || DIFF_TICK(timer->get(tid)->tick, timer->get(sd->spirit_timer[i])->tick) < 0);
if( i != sd->spiritball )
memmove(sd->spirit_timer+i+1, sd->spirit_timer+i, (sd->spiritball-i)*sizeof(int));
sd->spirit_timer[i] = tid;
sd->spiritball++;
if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
- clif->millenniumshield(sd,sd->spiritball);
+ clif->millenniumshield(&sd->bl,sd->spiritball);
else
clif->spiritball(&sd->bl);
@@ -226,7 +228,7 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type)
for(i=0;i<count;i++) {
if(sd->spirit_timer[i] != INVALID_TIMER) {
- iTimer->delete_timer(sd->spirit_timer[i],pc_spiritball_timer);
+ timer->delete(sd->spirit_timer[i],pc->spiritball_timer);
sd->spirit_timer[i] = INVALID_TIMER;
}
}
@@ -237,13 +239,13 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type)
if(!type) {
if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
- clif->millenniumshield(sd,sd->spiritball);
+ clif->millenniumshield(&sd->bl,sd->spiritball);
else
clif->spiritball(&sd->bl);
}
return 0;
}
-static int pc_check_banding( struct block_list *bl, va_list ap ) {
+int pc_check_banding( struct block_list *bl, va_list ap ) {
int *c, *b_sd;
struct block_list *src;
struct map_session_data *tsd;
@@ -258,7 +260,7 @@ static int pc_check_banding( struct block_list *bl, va_list ap ) {
if(pc_isdead(tsd))
return 0;
- sc = status_get_sc(bl);
+ sc = status->get_sc(bl);
if( bl == src )
return 0;
@@ -283,14 +285,14 @@ int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
c = 0;
memset(b_sd, 0, sizeof(b_sd));
- i = party_foreachsamemap(pc_check_banding,sd,range,&sd->bl,&c,&b_sd);
+ i = party->foreachsamemap(pc->check_banding,sd,range,&sd->bl,&c,&b_sd);
- if( c < 1 ) //just recalc status no need to recalc hp
- { // No more Royal Guards in Banding found.
- if( (sc = status_get_sc(&sd->bl)) != NULL && sc->data[SC_BANDING] )
- {
+ if( c < 1 ) {
+ //just recalc status no need to recalc hp
+ if( (sc = status->get_sc(&sd->bl)) != NULL && sc->data[SC_BANDING] ) {
+ // No more Royal Guards in Banding found.
sc->data[SC_BANDING]->val2 = 0; // Reset the counter
- status_calc_bl(&sd->bl, status_sc2scb_flag(SC_BANDING));
+ status_calc_bl(&sd->bl, status->sc2scb_flag(SC_BANDING));
}
return 0;
}
@@ -300,9 +302,8 @@ int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
i++;
// Get total HP of all Royal Guards in party.
- for( j = 0; j < i; j++ )
- {
- bsd = iMap->id2sd(b_sd[j]);
+ for( j = 0; j < i; j++ ) {
+ bsd = map->id2sd(b_sd[j]);
if( bsd != NULL )
hp += status_get_hp(&bsd->bl);
}
@@ -311,9 +312,8 @@ int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
hp = hp / i;
// If a Royal Guard have full HP, give more HP to others that haven't full HP.
- for( j = 0; j < i; j++ )
- {
- bsd = iMap->id2sd(b_sd[j]);
+ for( j = 0; j < i; j++ ) {
+ bsd = map->id2sd(b_sd[j]);
if( bsd != NULL && (tmp_hp = hp - status_get_max_hp(&bsd->bl)) > 0 )
{
extra_hp += tmp_hp;
@@ -324,16 +324,13 @@ int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
if( extra_hp > 0 && tmp_qty > 0 )
hp += extra_hp / tmp_qty;
- for( j = 0; j < i; j++ )
- {
- bsd = iMap->id2sd(b_sd[j]);
- if( bsd != NULL )
- {
- status_set_hp(&bsd->bl,hp,0); // Set hp
- if( (sc = status_get_sc(&bsd->bl)) != NULL && sc->data[SC_BANDING] )
- {
+ for( j = 0; j < i; j++ ) {
+ bsd = map->id2sd(b_sd[j]);
+ if( bsd != NULL ) {
+ status->set_hp(&bsd->bl,hp,0); // Set hp
+ if( (sc = status->get_sc(&bsd->bl)) != NULL && sc->data[SC_BANDING] ) {
sc->data[SC_BANDING]->val2 = c; // Set the counter. It doesn't count your self.
- status_calc_bl(&bsd->bl, status_sc2scb_flag(SC_BANDING)); // Set atk and def.
+ status_calc_bl(&bsd->bl, status->sc2scb_flag(SC_BANDING)); // Set atk and def.
}
}
}
@@ -344,22 +341,18 @@ int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
// Increases a player's fame points and displays a notice to him
void pc_addfame(struct map_session_data *sd,int count)
{
+ int ranktype = -1;
nullpo_retv(sd);
sd->status.fame += count;
if(sd->status.fame > MAX_FAME)
sd->status.fame = MAX_FAME;
switch(sd->class_&MAPID_UPPERMASK){
- case MAPID_BLACKSMITH: // Blacksmith
- clif->fame_blacksmith(sd,count);
- break;
- case MAPID_ALCHEMIST: // Alchemist
- clif->fame_alchemist(sd,count);
- break;
- case MAPID_TAEKWON: // Taekwon
- clif->fame_taekwon(sd,count);
- break;
+ case MAPID_BLACKSMITH: ranktype = RANKTYPE_BLACKSMITH; break;
+ case MAPID_ALCHEMIST: ranktype = RANKTYPE_ALCHEMIST; break;
+ case MAPID_TAEKWON: ranktype = RANKTYPE_TAEKWON; break;
}
- chrif_updatefamelist(sd);
+ clif->update_rankingpoint(sd, ranktype, count);
+ chrif->updatefamelist(sd);
}
// Check whether a player ID is in the fame rankers' list of its job, returns his/her position if so, 0 else
@@ -370,19 +363,19 @@ unsigned char pc_famerank(int char_id, int job)
switch(job){
case MAPID_BLACKSMITH: // Blacksmith
for(i = 0; i < MAX_FAME_LIST; i++){
- if(smith_fame_list[i].id == char_id)
+ if(pc->smith_fame_list[i].id == char_id)
return i + 1;
}
break;
case MAPID_ALCHEMIST: // Alchemist
for(i = 0; i < MAX_FAME_LIST; i++){
- if(chemist_fame_list[i].id == char_id)
+ if(pc->chemist_fame_list[i].id == char_id)
return i + 1;
}
break;
case MAPID_TAEKWON: // Taekwon
for(i = 0; i < MAX_FAME_LIST; i++){
- if(taekwon_fame_list[i].id == char_id)
+ if(pc->taekwon_fame_list[i].id == char_id)
return i + 1;
}
break;
@@ -392,20 +385,20 @@ unsigned char pc_famerank(int char_id, int job)
}
int pc_setrestartvalue(struct map_session_data *sd,int type) {
- struct status_data *status, *b_status;
+ struct status_data *st, *bst;
nullpo_ret(sd);
- b_status = &sd->base_status;
- status = &sd->battle_status;
+ bst = &sd->base_status;
+ st = &sd->battle_status;
if (type&1) { //Normal resurrection
- status->hp = 1; //Otherwise status_heal may fail if dead.
- status_heal(&sd->bl, b_status->hp, 0, 1);
- if( status->sp < b_status->sp )
- status_set_sp(&sd->bl, b_status->sp, 1);
+ st->hp = 1; //Otherwise status->heal may fail if dead.
+ status->heal(&sd->bl, bst->hp, 0, 1);
+ if( st->sp < bst->sp )
+ status->set_sp(&sd->bl, bst->sp, 1);
} else { //Just for saving on the char-server (with values as if respawned)
- sd->status.hp = b_status->hp;
- sd->status.sp = (status->sp < b_status->sp)?b_status->sp:status->sp;
+ sd->status.hp = bst->hp;
+ sd->status.sp = (st->sp < bst->sp) ? bst->sp : st->sp;
}
return 0;
}
@@ -413,9 +406,8 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) {
/*==========================================
Rental System
*------------------------------------------*/
-static int pc_inventory_rental_end(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct map_session_data *sd = iMap->id2sd(id);
+int pc_inventory_rental_end(int tid, int64 tick, int id, intptr_t data) {
+ struct map_session_data *sd = map->id2sd(id);
if( sd == NULL )
return 0;
if( tid != sd->rental_timer )
@@ -432,17 +424,84 @@ int pc_inventory_rental_clear(struct map_session_data *sd)
{
if( sd->rental_timer != INVALID_TIMER )
{
- iTimer->delete_timer(sd->rental_timer, pc_inventory_rental_end);
+ timer->delete(sd->rental_timer, pc->inventory_rental_end);
sd->rental_timer = INVALID_TIMER;
}
return 1;
}
+/* assumes i is valid (from default areas where it is called, it is) */
+void pc_rental_expire(struct map_session_data *sd, int i) {
+ short nameid = sd->status.inventory[i].nameid;
+ /* Soon to be dropped, we got plans to integrate it with item db */
+ switch( nameid ) {
+ case ITEMID_REINS_OF_MOUNT:
+ status_change_end(&sd->bl,SC_ALL_RIDING,INVALID_TIMER);
+ break;
+ case ITEMID_LOVE_ANGEL:
+ if( sd->status.font == 1 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_SQUIRREL:
+ if( sd->status.font == 2 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_GOGO:
+ if( sd->status.font == 3 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_PICTURE_DIARY:
+ if( sd->status.font == 4 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_MINI_HEART:
+ if( sd->status.font == 5 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_NEWCOMER:
+ if( sd->status.font == 6 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_KID:
+ if( sd->status.font == 7 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_MAGIC_CASTLE:
+ if( sd->status.font == 8 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_BULGING_HEAD:
+ if( sd->status.font == 9 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ }
+
+ clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid);
+ pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER);
+}
void pc_inventory_rentals(struct map_session_data *sd)
{
int i, c = 0;
- unsigned int expire_tick, next_tick = UINT_MAX;
+ int64 expire_tick, next_tick = INT64_MAX;
for( i = 0; i < MAX_INVENTORY; i++ )
{ // Check for Rentals on Inventory
@@ -452,14 +511,9 @@ void pc_inventory_rentals(struct map_session_data *sd)
continue;
if( sd->status.inventory[i].expire_time <= time(NULL) ) {
- if( sd->status.inventory[i].nameid == ITEMID_REINS_OF_MOUNT
- && sd->sc.data[SC_ALL_RIDING] ) {
- status_change_end(&sd->bl,SC_ALL_RIDING,INVALID_TIMER);
- }
- clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid);
- pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER);
+ pc->rental_expire(sd,i);
} else {
- expire_tick = (unsigned int)(sd->status.inventory[i].expire_time - time(NULL)) * 1000;
+ expire_tick = (int64)(sd->status.inventory[i].expire_time - time(NULL)) * 1000;
clif->rental_time(sd->fd, sd->status.inventory[i].nameid, (int)(expire_tick / 1000));
next_tick = min(expire_tick, next_tick);
c++;
@@ -467,7 +521,7 @@ void pc_inventory_rentals(struct map_session_data *sd)
}
if( c > 0 ) // min(next_tick,3600000) 1 hour each timer to keep announcing to the owner, and to avoid a but with rental time > 15 days
- sd->rental_timer = iTimer->add_timer(iTimer->gettick() + min(next_tick,3600000), pc_inventory_rental_end, sd->bl.id, 0);
+ sd->rental_timer = timer->add(timer->gettick() + min(next_tick,3600000), pc->inventory_rental_end, sd->bl.id, 0);
else
sd->rental_timer = INVALID_TIMER;
}
@@ -482,23 +536,15 @@ void pc_inventory_rental_add(struct map_session_data *sd, int seconds)
if( sd->rental_timer != INVALID_TIMER )
{
const struct TimerData * td;
- td = iTimer->get_timer(sd->rental_timer);
- if( DIFF_TICK(td->tick, iTimer->gettick()) > tick )
+ td = timer->get(sd->rental_timer);
+ if( DIFF_TICK(td->tick, timer->gettick()) > tick )
{ // Update Timer as this one ends first than the current one
pc->inventory_rental_clear(sd);
- sd->rental_timer = iTimer->add_timer(iTimer->gettick() + tick, pc_inventory_rental_end, sd->bl.id, 0);
+ sd->rental_timer = timer->add(timer->gettick() + tick, pc->inventory_rental_end, sd->bl.id, 0);
}
}
else
- sd->rental_timer = iTimer->add_timer(iTimer->gettick() + min(tick,3600000), pc_inventory_rental_end, sd->bl.id, 0);
-}
-
-/**
- * Determines if player can give / drop / trade / vend items
- */
-bool pc_can_give_items(struct map_session_data *sd)
-{
- return pc_has_permission(sd, PC_PERM_TRADE);
+ sd->rental_timer = timer->add(timer->gettick() + min(tick,3600000), pc->inventory_rental_end, sd->bl.id, 0);
}
/*==========================================
@@ -542,8 +588,8 @@ int pc_makesavestatus(struct map_session_data *sd)
sd->status.last_point.y = sd->bl.y;
}
- if(map[sd->bl.m].flag.nosave || map[sd->bl.m].instance_id >= 0){
- struct map_data *m=&map[sd->bl.m];
+ if(map->list[sd->bl.m].flag.nosave || map->list[sd->bl.m].instance_id >= 0) {
+ struct map_data *m=&map->list[sd->bl.m];
if(m->save.map)
memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point));
else
@@ -581,7 +627,7 @@ int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int lo
sd->client_tick = client_tick;
sd->state.active = 0; //to be set to 1 after player is fully authed and loaded.
sd->bl.type = BL_PC;
- sd->canlog_tick = iTimer->gettick();
+ sd->canlog_tick = timer->gettick();
//Required to prevent homunculus copuing a base speed of 0.
sd->battle_status.speed = sd->base_status.speed = DEFAULT_WALK_SPEED;
return 0;
@@ -596,16 +642,21 @@ int pc_equippoint(struct map_session_data *sd,int n)
if(!sd->inventory_data[n])
return 0;
- if (!itemdb_isequip2(sd->inventory_data[n]))
+ if (!itemdb->isequip2(sd->inventory_data[n]))
return 0; //Not equippable by players.
ep = sd->inventory_data[n]->equip;
if(sd->inventory_data[n]->look == W_DAGGER ||
sd->inventory_data[n]->look == W_1HSWORD ||
sd->inventory_data[n]->look == W_1HAXE) {
- if(ep == EQP_HAND_R && (pc->checkskill(sd,AS_LEFT) > 0 || (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN ||
- (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO))//Kagerou and Oboro can dual wield daggers. [Rytech]
- return EQP_ARMS;
+ if( (pc->checkskill(sd,AS_LEFT) > 0 ||
+ (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN ||
+ (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO) ) { //Kagerou and Oboro can dual wield daggers. [Rytech]
+ if( ep == EQP_HAND_R )
+ return EQP_ARMS;
+ if( ep == EQP_SHADOW_WEAPON )
+ return EQP_SHADOW_ARMS;
+ }
}
return ep;
}
@@ -618,7 +669,7 @@ int pc_setinventorydata(struct map_session_data *sd)
for(i=0;i<MAX_INVENTORY;i++) {
id = sd->status.inventory[i].nameid;
- sd->inventory_data[i] = id?itemdb_search(id):NULL;
+ sd->inventory_data[i] = id?itemdb->search(id):NULL;
}
return 0;
}
@@ -639,26 +690,26 @@ int pc_calcweapontype(struct map_session_data *sd)
// dual-wield
sd->status.weapon = 0;
switch (sd->weapontype1){
- case W_DAGGER:
- switch (sd->weapontype2) {
- case W_DAGGER: sd->status.weapon = W_DOUBLE_DD; break;
- case W_1HSWORD: sd->status.weapon = W_DOUBLE_DS; break;
- case W_1HAXE: sd->status.weapon = W_DOUBLE_DA; break;
- }
- break;
- case W_1HSWORD:
- switch (sd->weapontype2) {
- case W_DAGGER: sd->status.weapon = W_DOUBLE_DS; break;
- case W_1HSWORD: sd->status.weapon = W_DOUBLE_SS; break;
- case W_1HAXE: sd->status.weapon = W_DOUBLE_SA; break;
- }
- break;
- case W_1HAXE:
- switch (sd->weapontype2) {
- case W_DAGGER: sd->status.weapon = W_DOUBLE_DA; break;
- case W_1HSWORD: sd->status.weapon = W_DOUBLE_SA; break;
- case W_1HAXE: sd->status.weapon = W_DOUBLE_AA; break;
- }
+ case W_DAGGER:
+ switch (sd->weapontype2) {
+ case W_DAGGER: sd->status.weapon = W_DOUBLE_DD; break;
+ case W_1HSWORD: sd->status.weapon = W_DOUBLE_DS; break;
+ case W_1HAXE: sd->status.weapon = W_DOUBLE_DA; break;
+ }
+ break;
+ case W_1HSWORD:
+ switch (sd->weapontype2) {
+ case W_DAGGER: sd->status.weapon = W_DOUBLE_DS; break;
+ case W_1HSWORD: sd->status.weapon = W_DOUBLE_SS; break;
+ case W_1HAXE: sd->status.weapon = W_DOUBLE_SA; break;
+ }
+ break;
+ case W_1HAXE:
+ switch (sd->weapontype2) {
+ case W_DAGGER: sd->status.weapon = W_DOUBLE_DA; break;
+ case W_1HSWORD: sd->status.weapon = W_DOUBLE_SA; break;
+ case W_1HAXE: sd->status.weapon = W_DOUBLE_AA; break;
+ }
}
// unknown, default to right hand type
if (!sd->status.weapon)
@@ -681,7 +732,7 @@ int pc_setequipindex(struct map_session_data *sd)
continue;
if(sd->status.inventory[i].equip) {
for(j=0;j<EQI_MAX;j++)
- if(sd->status.inventory[i].equip & equip_pos[j])
+ if(sd->status.inventory[i].equip & pc->equip_pos[j])
sd->equip_index[j] = i;
if(sd->status.inventory[i].equip & EQP_HAND_R)
@@ -701,7 +752,7 @@ int pc_setequipindex(struct map_session_data *sd)
}
}
}
- pc_calcweapontype(sd);
+ pc->calcweapontype(sd);
return 0;
}
@@ -719,7 +770,7 @@ int pc_setequipindex(struct map_session_data *sd)
// if( item->card[MAX_SLOTS - 1] && s < MAX_SLOTS - 1 )
// s = MAX_SLOTS - 1;
//
-// ARR_FIND( 0, s, i, item->card[i] && (data = itemdb_exists(item->card[i])) != NULL && data->flag.no_equip&flag );
+// ARR_FIND( 0, s, i, item->card[i] && (data = itemdb->exists(item->card[i])) != NULL && data->flag.no_equip&flag );
// return( i < s ) ? 0 : 1;
//}
@@ -857,12 +908,14 @@ int pc_isequip(struct map_session_data *sd,int n)
if(item == NULL)
return 0;
- if(item->elv && sd->status.base_level < (unsigned int)item->elv)
+ if(item->elv && sd->status.base_level < (unsigned int)item->elv){
+ clif->msg(sd, 0x6ED);
return 0;
-#ifdef RENEWAL
- if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax)
+ }
+ if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax){
+ clif->msg(sd, 0x6ED);
return 0;
-#endif
+ }
if(item->sex != 2 && sd->status.sex != item->sex)
return 0;
@@ -902,10 +955,10 @@ int pc_isequip(struct map_session_data *sd,int n)
return 0;
//Not usable by upper class. [Inkfish]
while( 1 ) {
- if( item->class_upper&1 && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
- if( item->class_upper&2 && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
- if( item->class_upper&4 && sd->class_&JOBL_BABY ) break;
- if( item->class_upper&8 && sd->class_&JOBL_THIRD ) break;
+ if( item->class_upper&ITEMUPPER_NORMAL && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
+ if( item->class_upper&ITEMUPPER_UPPER && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
+ if( item->class_upper&ITEMUPPER_BABY && sd->class_&JOBL_BABY ) break;
+ if( item->class_upper&ITEMUPPER_THIRD && sd->class_&JOBL_THIRD ) break;
return 0;
}
@@ -918,14 +971,17 @@ int pc_isequip(struct map_session_data *sd,int n)
*------------------------------------------*/
bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers) {
int i;
- unsigned long tick = iTimer->gettick();
+ int64 tick = timer->gettick();
uint32 ip = session[sd->fd]->client_addr;
sd->login_id2 = login_id2;
- sd->group_id = group_id;
- /* load user permissions */
- pc_group_pc_load(sd);
+ if (pc->set_group(sd, group_id) != 0) {
+ ShowWarning("pc_authok: %s (AID:%d) logged in with unknown group id (%d)! kicking...\n",
+ st->name, sd->status.account_id, group_id);
+ clif->authfail_fd(sd->fd, 0);
+ return false;
+ }
memcpy(&sd->status, st, sizeof(*st));
@@ -965,6 +1021,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
sd->npc_timer_id = INVALID_TIMER;
sd->pvp_timer = INVALID_TIMER;
sd->fontcolor_tid = INVALID_TIMER;
+ sd->expiration_tid = INVALID_TIMER;
/**
* For the Secure NPC Timeout option (check config/Secure.h) [RR]
**/
@@ -985,6 +1042,8 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
sd->cansendmail_tick = tick;
sd->hchsysch_tick = tick;
+ sd->idletime = sockt->last_tick;
+
for(i = 0; i < MAX_SPIRITBALL; i++)
sd->spirit_timer[i] = INVALID_TIMER;
for(i = 0; i < ARRAYLENGTH(sd->autobonus); i++)
@@ -1011,13 +1070,13 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
if( sd->status.option & OPTION_INVISIBLE && !pc->can_use_command(sd, "@hide") )
sd->status.option &=~ OPTION_INVISIBLE;
- status_change_init(&sd->bl);
+ status->change_init(&sd->bl);
sd->sc.option = sd->status.option; //This is the actual option used in battle.
//Set here because we need the inventory data for weapon sprite parsing.
- status_set_viewdata(&sd->bl, sd->status.class_);
- unit_dataset(&sd->bl);
+ status->set_viewdata(&sd->bl, sd->status.class_);
+ unit->dataset(&sd->bl);
sd->guild_x = -1;
sd->guild_y = -1;
@@ -1037,6 +1096,11 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
sd->state.dialog = 0;
+ sd->delayed_damage = 0;
+
+ if( battle_config.item_check )
+ sd->state.itemcheck = 1;
+
// Event Timers
for( i = 0; i < MAX_EVENTTIMER; i++ )
sd->eventtimer[i] = INVALID_TIMER;
@@ -1046,12 +1110,23 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
for( i = 0; i < 3; i++ )
sd->hate_mob[i] = -1;
- //warp player
+ sd->quest_log = NULL;
+ sd->num_quests = 0;
+ sd->avail_quests = 0;
+ sd->save_quest = false;
+
+ sd->regs.vars = i64db_alloc(DB_OPT_BASE);
+ sd->regs.arrays = NULL;
+ sd->vars_dirty = false;
+ sd->vars_ok = false;
+ sd->vars_received = 0x0;
+
+ //warp player
if ((i=pc->setpos(sd,sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, CLR_OUTSIGHT)) != 0) {
ShowError ("Last_point_map %s - id %d not found (error code %d)\n", mapindex_id2name(sd->status.last_point.map), sd->status.last_point.map, i);
// try warping to a default map instead (church graveyard)
- if (pc->setpos(sd, mapindex_name2id(MAP_PRONTERA), 273, 354, CLR_OUTSIGHT) != 0) {
+ if (pc->setpos(sd, mapindex->name2id(MAP_PRONTERA), 273, 354, CLR_OUTSIGHT) != 0) {
// if we fail again
clif->authfail_fd(sd->fd, 0);
return false;
@@ -1076,23 +1151,13 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
if( !changing_mapservers ) {
if (battle_config.display_version == 1) {
- const char* svn = get_svn_revision();
- const char* git = get_git_hash();
char buf[256];
- if( git[0] != HERC_UNKNOWN_VER )
- sprintf(buf,"Git Hash: %s", git);
- else if( svn[0] != HERC_UNKNOWN_VER )
- sprintf(buf,"SVN Revision: %s", svn);
- else
- sprintf(buf,"Unknown Version");
+ sprintf(buf, msg_txt(1295), sysinfo->vcstype(), sysinfo->vcsrevision_src(), sysinfo->vcsrevision_scripts()); // %s revision '%s' (src) / '%s' (scripts)
clif->message(sd->fd, buf);
}
- // message of the limited time of the account
- if (expiration_time != 0) { // don't display if it's unlimited or unknow value
- char tmpstr[1024];
- strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(501), localtime(&expiration_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S."
- clif->wis_message(sd->fd, iMap->wisp_server_name, tmpstr, strlen(tmpstr)+1);
+ if (expiration_time != 0) {
+ sd->expiration_time = expiration_time;
}
/**
@@ -1110,13 +1175,18 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
* Check if player have any item cooldowns on
**/
pc->itemcd_do(sd,true);
-
+
+#ifdef GP_BOUND_ITEMS
+ if( sd->status.party_id == 0 )
+ pc->bound_clear(sd,IBT_PARTY);
+#endif
+
/* [Ind/Hercules] */
sd->sc_display = NULL;
sd->sc_display_count = 0;
// Request all registries (auth is considered completed whence they arrive)
- intif_request_registry(sd,7);
+ intif->request_registry(sd,7);
return true;
}
@@ -1141,7 +1211,7 @@ int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl)
return 0;
}
- class_ = status_get_class(bl);
+ class_ = status->get_class(bl);
if (!pcdb_checkid(class_)) {
unsigned int max_hp = status_get_max_hp(bl);
if ((pos == 1 && max_hp < 6000) || (pos == 2 && max_hp < 20000))
@@ -1150,7 +1220,7 @@ int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl)
return 0; //Wrong size
}
sd->hate_mob[pos] = class_;
- pc_setglobalreg(sd,sg_info[pos].hate_var,class_+1);
+ pc_setglobalreg(sd,script->add_str(pc->sg_info[pos].hate_var),class_+1);
clif->hate_info(sd, pos, class_, 1);
return 1;
}
@@ -1162,55 +1232,58 @@ int pc_reg_received(struct map_session_data *sd)
{
int i,j, idx = 0;
- sd->change_level_2nd = pc_readglobalreg(sd,"jobchange_level");
- sd->change_level_3rd = pc_readglobalreg(sd,"jobchange_level_3rd");
- sd->die_counter = pc_readglobalreg(sd,"PC_DIE_COUNTER");
+ sd->vars_ok = true;
+
+ sd->change_level_2nd = pc_readglobalreg(sd,script->add_str("jobchange_level"));
+ sd->change_level_3rd = pc_readglobalreg(sd,script->add_str("jobchange_level_3rd"));
+ sd->die_counter = pc_readglobalreg(sd,script->add_str("PC_DIE_COUNTER"));
// Cash shop
- sd->cashPoints = pc_readaccountreg(sd,"#CASHPOINTS");
- sd->kafraPoints = pc_readaccountreg(sd,"#KAFRAPOINTS");
+ sd->cashPoints = pc_readaccountreg(sd,script->add_str("#CASHPOINTS"));
+ sd->kafraPoints = pc_readaccountreg(sd,script->add_str("#KAFRAPOINTS"));
// Cooking Exp
- sd->cook_mastery = pc_readglobalreg(sd,"COOK_MASTERY");
+ sd->cook_mastery = pc_readglobalreg(sd,script->add_str("COOK_MASTERY"));
if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) {
// Better check for class rather than skill to prevent "skill resets" from unsetting this
- sd->mission_mobid = pc_readglobalreg(sd,"TK_MISSION_ID");
- sd->mission_count = pc_readglobalreg(sd,"TK_MISSION_COUNT");
+ sd->mission_mobid = pc_readglobalreg(sd,script->add_str("TK_MISSION_ID"));
+ sd->mission_count = pc_readglobalreg(sd,script->add_str("TK_MISSION_COUNT"));
}
//SG map and mob read [Komurka]
for(i=0;i<MAX_PC_FEELHATE;i++) { //for now - someone need to make reading from txt/sql
- if ((j = pc_readglobalreg(sd,sg_info[i].feel_var))!=0) {
+ if ((j = pc_readglobalreg(sd,script->add_str(pc->sg_info[i].feel_var)))!=0) {
sd->feel_map[i].index = j;
- sd->feel_map[i].m = iMap->mapindex2mapid(j);
+ sd->feel_map[i].m = map->mapindex2mapid(j);
} else {
sd->feel_map[i].index = 0;
sd->feel_map[i].m = -1;
}
- sd->hate_mob[i] = pc_readglobalreg(sd,sg_info[i].hate_var)-1;
+ sd->hate_mob[i] = pc_readglobalreg(sd,script->add_str(pc->sg_info[i].hate_var))-1;
}
if ((i = pc->checkskill(sd,RG_PLAGIARISM)) > 0) {
- sd->cloneskill_id = pc_readglobalreg(sd,"CLONE_SKILL");
+ sd->cloneskill_id = pc_readglobalreg(sd,script->add_str("CLONE_SKILL"));
if (sd->cloneskill_id > 0 && (idx = skill->get_index(sd->cloneskill_id))) {
sd->status.skill[idx].id = sd->cloneskill_id;
- sd->status.skill[idx].lv = pc_readglobalreg(sd,"CLONE_SKILL_LV");
+ sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_str("CLONE_SKILL_LV"));
if (sd->status.skill[idx].lv > i)
sd->status.skill[idx].lv = i;
sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
}
}
if ((i = pc->checkskill(sd,SC_REPRODUCE)) > 0) {
- sd->reproduceskill_id = pc_readglobalreg(sd,"REPRODUCE_SKILL");
+ sd->reproduceskill_id = pc_readglobalreg(sd,script->add_str("REPRODUCE_SKILL"));
if( sd->reproduceskill_id > 0 && (idx = skill->get_index(sd->reproduceskill_id))) {
sd->status.skill[idx].id = sd->reproduceskill_id;
- sd->status.skill[idx].lv = pc_readglobalreg(sd,"REPRODUCE_SKILL_LV");
+ sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_str("REPRODUCE_SKILL_LV"));
if( i < sd->status.skill[idx].lv)
sd->status.skill[idx].lv = i;
sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
}
}
+
//Weird... maybe registries were reloaded?
if (sd->state.active)
return 0;
@@ -1223,70 +1296,67 @@ int pc_reg_received(struct map_session_data *sd)
// pet
if (sd->status.pet_id > 0)
- intif_request_petdata(sd->status.account_id, sd->status.char_id, sd->status.pet_id);
+ intif->request_petdata(sd->status.account_id, sd->status.char_id, sd->status.pet_id);
// Homunculus [albator]
if( sd->status.hom_id > 0 )
- intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id);
+ intif->homunculus_requestload(sd->status.account_id, sd->status.hom_id);
if( sd->status.mer_id > 0 )
- intif_mercenary_request(sd->status.mer_id, sd->status.char_id);
+ intif->mercenary_request(sd->status.mer_id, sd->status.char_id);
if( sd->status.ele_id > 0 )
- intif_elemental_request(sd->status.ele_id, sd->status.char_id);
+ intif->elemental_request(sd->status.ele_id, sd->status.char_id);
- iMap->addiddb(&sd->bl);
- iMap->delnickdb(sd->status.char_id, sd->status.name);
- if (!chrif_auth_finished(sd))
+ map->addiddb(&sd->bl);
+ map->delnickdb(sd->status.char_id, sd->status.name);
+ if (!chrif->auth_finished(sd))
ShowError("pc_reg_received: Failed to properly remove player %d:%d from logging db!\n", sd->status.account_id, sd->status.char_id);
pc->load_combo(sd);
- status_calc_pc(sd,1);
- chrif_scdata_request(sd->status.account_id, sd->status.char_id);
+ status_calc_pc(sd,SCO_FIRST|SCO_FORCE);
+ chrif->scdata_request(sd->status.account_id, sd->status.char_id);
- intif_Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox
- intif_request_questlog(sd);
+ intif->Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox
+ intif->request_questlog(sd);
if (sd->state.connect_new == 0 && sd->fd) { //Character already loaded map! Gotta trigger LoadEndAck manually.
sd->state.connect_new = 1;
clif->pLoadEndAck(sd->fd, sd);
}
- pc->inventory_rentals(sd);
-
if( sd->sc.option & OPTION_INVISIBLE ) {
sd->vd.class_ = INVISIBLE_CLASS;
clif->message(sd->fd, msg_txt(11)); // Invisible: On
// decrement the number of pvp players on the map
- map[sd->bl.m].users_pvp--;
+ map->list[sd->bl.m].users_pvp--;
- if( map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ) {// unregister the player for ranking
- iTimer->delete_timer( sd->pvp_timer, pc->calc_pvprank_timer );
+ if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ) {// unregister the player for ranking
+ timer->delete( sd->pvp_timer, pc->calc_pvprank_timer );
sd->pvp_timer = INVALID_TIMER;
}
clif->changeoption(&sd->bl);
}
if( npc->motd ) /* [Ind/Hercules] */
- run_script(npc->motd->u.scr.script, 0, sd->bl.id, fake_nd->bl.id);
-
+ script->run(npc->motd->u.scr.script, 0, sd->bl.id, npc->fake_nd->bl.id);
+
return 1;
}
-static int pc_calc_skillpoint(struct map_session_data* sd)
-{
+int pc_calc_skillpoint(struct map_session_data* sd) {
int i,skill_lv,inf2,skill_point=0;
nullpo_ret(sd);
for(i=1;i<MAX_SKILL;i++){
if( (skill_lv = pc->checkskill2(sd,i)) > 0) {
- inf2 = skill_db[i].inf2;
+ inf2 = skill->db[i].inf2;
if((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) &&
- !(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex]
+ !(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL|INF2_GUILD_SKILL)) //Do not count wedding/link skills. [Skotlex]
) {
if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
skill_point += skill_lv;
- else if(sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0)
+ else if(sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0)
skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
}
}
@@ -1318,10 +1388,10 @@ int pc_calc_skilltree(struct map_session_data *sd)
if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these
sd->status.skill[i].id = 0; //First clear skills.
/* permanent skills that must be re-checked */
- if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) {
- switch( skill_db[i].nameid ) {
+ if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT ) {
+ switch( skill->db[i].nameid ) {
case NV_TRICKDEAD:
- if( (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) {
+ if( (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) {
sd->status.skill[i].id = 0;
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = 0;
@@ -1338,19 +1408,19 @@ int pc_calc_skilltree(struct map_session_data *sd)
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
}
- if( sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER && skill_db[i].nameid >= DC_HUMMING && skill_db[i].nameid <= DC_SERVICEFORYOU )
+ if( sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER && skill->db[i].nameid >= DC_HUMMING && skill->db[i].nameid <= DC_SERVICEFORYOU )
{ //Enable Bard/Dancer spirit linked skills.
if( sd->status.sex )
{ //Link dancer skills to bard.
if( sd->status.skill[i-8].lv < 10 )
continue;
- sd->status.skill[i].id = skill_db[i].nameid;
+ sd->status.skill[i].id = skill->db[i].nameid;
sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill
sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
} else { //Link bard skills to dancer.
if( sd->status.skill[i].lv < 10 )
continue;
- sd->status.skill[i-8].id = skill_db[i-8].nameid;
+ sd->status.skill[i-8].id = skill->db[i-8].nameid;
sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill
sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
}
@@ -1359,7 +1429,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) {
for( i = 0; i < MAX_SKILL; i++ ) {
- switch(skill_db[i].nameid) {
+ switch(skill->db[i].nameid) {
/**
* Dummy skills must be added here otherwise they'll be displayed in the,
* skill tree and since they have no icons they'll give resource errors
@@ -1378,23 +1448,22 @@ int pc_calc_skilltree(struct map_session_data *sd)
case WL_SUMMON_ATK_GROUND:
case LG_OVERBRAND_BRANDISH:
case LG_OVERBRAND_PLUSATK:
- case WM_SEVERE_RAINSTORM_MELEE:
continue;
default:
break;
}
- if( skill_db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL) )
+ if( skill->db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL) )
continue; //Only skills you can't have are npc/guild ones
- if( skill_db[i].max > 0 )
- sd->status.skill[i].id = skill_db[i].nameid;
+ if( skill->db[i].max > 0 )
+ sd->status.skill[i].id = skill->db[i].nameid;
}
return 0;
}
do {
flag = 0;
- for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ ) {
- int f, idx = skill_tree[c][i].idx;
+ for( i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[c][i].id) > 0; i++ ) {
+ int f, idx = pc->skill_tree[c][i].idx;
if( sd->status.skill[idx].id )
continue; //Skill already known.
@@ -1403,26 +1472,26 @@ int pc_calc_skilltree(struct map_session_data *sd)
int j;
for(j = 0; j < MAX_PC_SKILL_REQUIRE; j++) {
int k;
- if((k=skill_tree[c][i].need[j].id)) {
- int idx2 = skill_tree[c][i].need[j].idx;
+ if((k=pc->skill_tree[c][i].need[j].id)) {
+ int idx2 = pc->skill_tree[c][i].need[j].idx;
if (sd->status.skill[idx2].id == 0 || sd->status.skill[idx2].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[idx2].flag == SKILL_FLAG_PLAGIARIZED)
k = 0; //Not learned.
else if (sd->status.skill[idx2].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level
k = sd->status.skill[idx2].flag - SKILL_FLAG_REPLACED_LV_0;
else
k = pc->checkskill2(sd,idx2);
- if (k < skill_tree[c][i].need[j].lv) {
+ if (k < pc->skill_tree[c][i].need[j].lv) {
f = 0;
break;
}
}
}
- if( sd->status.job_level < skill_tree[c][i].joblv )
+ if( sd->status.job_level < pc->skill_tree[c][i].joblv )
f = 0; // job level requirement wasn't satisfied
}
if( f ) {
int inf2;
- inf2 = skill_db[idx].inf2;
+ inf2 = skill->db[idx].inf2;
if(!sd->status.skill[idx].lv && (
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
@@ -1432,7 +1501,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills.
sd->status.skill[idx].id = id;
-
+
if(inf2&INF2_SPIRIT_SKILL) { //Spirit skills cannot be learned, they will only show up on your tree when you get buffed.
sd->status.skill[idx].lv = 1; // need to manually specify a skill level
sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill.
@@ -1451,9 +1520,9 @@ int pc_calc_skilltree(struct map_session_data *sd)
- (c > 0) to avoid grant Novice Skill Tree in case of Skill Reset (need more logic)
- (sd->status.skill_point == 0) to wait until all skill points are asigned to avoid problems with Job Change quest. */
- for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ ) {
- int idx = skill_tree[c][i].idx;
- if( (skill_db[idx].inf2&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) )
+ for( i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[c][i].id) > 0; i++ ) {
+ int idx = pc->skill_tree[c][i].idx;
+ if( (skill->db[idx].inf2&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) )
continue; //Do not include Quest/Wedding skills.
if( sd->status.skill[idx].id == 0 ) {
@@ -1471,7 +1540,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
}
//Checks if you can learn a new skill after having leveled up a skill.
-static void pc_check_skilltree(struct map_session_data *sd, int skill_id)
+void pc_check_skilltree(struct map_session_data *sd, int skill_id)
{
int i,id=0,flag;
int c=0;
@@ -1488,22 +1557,22 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill_id)
c = pc->class2idx(c);
do {
flag = 0;
- for( i = 0; i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0; i++ ) {
- int j, f = 1, k, idx = skill_tree[c][i].idx;
+ for( i = 0; i < MAX_SKILL_TREE && (id=pc->skill_tree[c][i].id)>0; i++ ) {
+ int j, f = 1, k, idx = pc->skill_tree[c][i].idx;
if( sd->status.skill[idx].id ) //Already learned
continue;
for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) {
- if( (k = skill_tree[c][i].need[j].id) ) {
- int idx2 = skill_tree[c][i].need[j].idx;
+ if( (k = pc->skill_tree[c][i].need[j].id) ) {
+ int idx2 = pc->skill_tree[c][i].need[j].idx;
if( sd->status.skill[idx2].id == 0 || sd->status.skill[idx2].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[idx2].flag == SKILL_FLAG_PLAGIARIZED )
k = 0; //Not learned.
else if( sd->status.skill[idx2].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level
k = sd->status.skill[idx2].flag - SKILL_FLAG_REPLACED_LV_0;
else
k = pc->checkskill2(sd,idx2);
- if( k < skill_tree[c][i].need[j].lv ) {
+ if( k < pc->skill_tree[c][i].need[j].lv ) {
f = 0;
break;
}
@@ -1511,10 +1580,10 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill_id)
}
if( !f )
continue;
- if( sd->status.job_level < skill_tree[c][i].joblv )
+ if( sd->status.job_level < pc->skill_tree[c][i].joblv )
continue;
- j = skill_db[idx].inf2;
+ j = skill->db[idx].inf2;
if( !sd->status.skill[idx].lv && (
(j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
j&INF2_WEDDING_SKILL ||
@@ -1523,6 +1592,7 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill_id)
continue; //Cannot be learned via normal means.
sd->status.skill[idx].id = id;
+
flag = 1;
}
} while(flag);
@@ -1538,7 +1608,7 @@ int pc_clean_skilltree(struct map_session_data *sd)
sd->status.skill[i].id = 0;
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = 0;
- } else if (sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0) {
+ } else if (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) {
sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = 0;
}
@@ -1555,13 +1625,14 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
if (!battle_config.skillup_limit || pc_has_permission(sd, PC_PERM_ALL_SKILL))
return c;
- skill_point = pc_calc_skillpoint(sd);
+ skill_point = pc->calc_skillpoint(sd);
- novice_skills = max_level[pc->class2idx(JOB_NOVICE)][1] - 1;
+ novice_skills = pc->max_level[pc->class2idx(JOB_NOVICE)][1] - 1;
+ sd->sktree.second = sd->sktree.third = 0;
+
// limit 1st class and above to novice job levels
- if(skill_point < novice_skills)
- {
+ if(skill_point < novice_skills) {
c = MAPID_NOVICE;
}
// limit 2nd class and above to first class job levels (super novices are exempt)
@@ -1574,7 +1645,7 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
{
// if neither 2nd nor 3rd jobchange levels are known, we have to assume a default for 2nd
if (!sd->change_level_3rd)
- sd->change_level_2nd = max_level[pc->class2idx(pc->mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex))][1];
+ sd->change_level_2nd = pc->max_level[pc->class2idx(pc->mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex))][1];
else
sd->change_level_2nd = 1 + skill_point + sd->status.skill_point
- (sd->status.job_level - 1)
@@ -1589,11 +1660,12 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
}
- pc_setglobalreg (sd, "jobchange_level", sd->change_level_2nd);
+ pc_setglobalreg (sd, script->add_str("jobchange_level"), sd->change_level_2nd);
}
if (skill_point < novice_skills + (sd->change_level_2nd - 1)) {
c &= MAPID_BASEMASK;
+ sd->sktree.second = ( novice_skills + (sd->change_level_2nd - 1) ) - skill_point;
} else if(sd->class_&JOBL_THIRD) { // limit 3rd class to 2nd class/trans job levels
// regenerate change_level_3rd
if (!sd->change_level_3rd) {
@@ -1601,17 +1673,19 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
- (sd->status.job_level - 1)
- (sd->change_level_2nd - 1)
- novice_skills;
- pc_setglobalreg (sd, "jobchange_level_3rd", sd->change_level_3rd);
+ pc_setglobalreg (sd, script->add_str("jobchange_level_3rd"), sd->change_level_3rd);
}
- if (skill_point < novice_skills + (sd->change_level_2nd - 1) + (sd->change_level_3rd - 1))
+ if (skill_point < novice_skills + (sd->change_level_2nd - 1) + (sd->change_level_3rd - 1)) {
c &= MAPID_UPPERMASK;
+ sd->sktree.third = (novice_skills + (sd->change_level_2nd - 1) + (sd->change_level_3rd - 1)) - skill_point;
+ }
}
}
// restore non-limiting flags
c |= sd->class_&(JOBL_UPPER|JOBL_BABY);
-
+
return c;
}
@@ -1643,9 +1717,9 @@ int pc_updateweightstatus(struct map_session_data *sd)
// start new status change
if( new_overweight == 1 )
- sc_start(&sd->bl, SC_WEIGHTOVER50, 100, 0, 0);
+ sc_start(NULL,&sd->bl, SC_WEIGHTOVER50, 100, 0, 0);
else if( new_overweight == 2 )
- sc_start(&sd->bl, SC_WEIGHTOVER90, 100, 0, 0);
+ sc_start(NULL,&sd->bl, SC_WEIGHTOVER90, 100, 0, 0);
// update overweight status
sd->regen.state.overweight = new_overweight;
@@ -1679,8 +1753,15 @@ int pc_disguise(struct map_session_data *sd, int class_) {
} else
sd->disguise = class_;
- status_set_viewdata(&sd->bl, class_);
+ status->set_viewdata(&sd->bl, class_);
clif->changeoption(&sd->bl);
+ // We need to update the client so it knows that a costume is being used
+ if( sd->sc.option&OPTION_COSTUME ) {
+ clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_);
+ clif->changelook(&sd->bl,LOOK_WEAPON,0);
+ clif->changelook(&sd->bl,LOOK_SHIELD,0);
+ clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
+ }
if (sd->bl.prev != NULL) {
clif->spawn(&sd->bl);
@@ -1689,11 +1770,17 @@ int pc_disguise(struct map_session_data *sd, int class_) {
clif->cartlist(sd);
clif->updatestatus(sd,SP_CARTINFO);
}
+ if (sd->chatID) {
+ struct chat_data* cd;
+
+ if( (cd = (struct chat_data*)map->id2bl(sd->chatID)) )
+ clif->dispchat(cd,0);
+ }
}
return 1;
}
-static int pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, short rate, short flag, short card_id)
+int pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, short rate, short flag, short card_id)
{
int i;
@@ -1729,7 +1816,7 @@ static int pc_bonus_autospell(struct s_autospell *spell, int max, short id, shor
return 1;
}
-static int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, short card_id)
+int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, short card_id)
{
int i;
@@ -1755,7 +1842,7 @@ static int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short
return 1;
}
-static int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, short rate, short arrow_rate, unsigned char flag)
+int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, short rate, short arrow_rate, unsigned char flag)
{
int i;
if (!(flag&(ATF_SHORT|ATF_LONG)))
@@ -1784,13 +1871,10 @@ static int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id,
return 1;
}
-static int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill, unsigned char target)
-{
+int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill_id, unsigned char target) {
int i;
- for( i = 0; i < max && effect[i].skill; i++ )
- {
- if( effect[i].id == id && effect[i].skill == skill && effect[i].target == target )
- {
+ for( i = 0; i < max && effect[i].skill; i++ ) {
+ if( effect[i].id == id && effect[i].skill == skill_id && effect[i].target == target ) {
effect[i].rate += rate;
return 1;
}
@@ -1801,14 +1885,14 @@ static int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, e
}
effect[i].id = id;
effect[i].rate = rate;
- effect[i].skill = skill;
+ effect[i].skill = skill_id;
effect[i].target = target;
return 1;
}
-static int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short group, int race, int rate)
-{
+int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short group, int race, int rate) {
int i;
+
//Apply config rate adjustment settings.
if (rate >= 0) { //Absolute drop.
if (battle_config.item_rate_adddrop != 100)
@@ -1855,8 +1939,7 @@ static int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id
return 1;
}
-int pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short flag,const char *other_script,unsigned short pos,bool onskill)
-{
+int pc_addautobonus(struct s_autobonus *bonus,char max,const char *bonus_script,short rate,unsigned int dur,short flag,const char *other_script,unsigned short pos,bool onskill) {
int i;
ARR_FIND(0, max, i, bonus[i].rate == 0);
@@ -1886,7 +1969,7 @@ int pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short
bonus[i].active = INVALID_TIMER;
bonus[i].atk_type = flag;
bonus[i].pos = pos;
- bonus[i].bonus_script = aStrdup(script);
+ bonus[i].bonus_script = aStrdup(bonus_script);
bonus[i].other_script = other_script?aStrdup(other_script):NULL;
return 1;
}
@@ -1905,15 +1988,15 @@ int pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus,c
if( autobonus[i].bonus_script )
{
int j;
- ARR_FIND( 0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus[i].pos );
- if( j < EQI_MAX-1 )
- script_run_autobonus(autobonus[i].bonus_script,sd->bl.id,sd->equip_index[j]);
+ ARR_FIND( 0, EQI_MAX, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus[i].pos );
+ if( j < EQI_MAX )
+ script->run_autobonus(autobonus[i].bonus_script,sd->bl.id,sd->equip_index[j]);
}
continue;
}
else
{ // Logout / Unequipped an item with an activated bonus
- iTimer->delete_timer(autobonus[i].active,pc->endautobonus);
+ timer->delete(autobonus[i].active,pc->endautobonus);
autobonus[i].active = INVALID_TIMER;
}
}
@@ -1936,21 +2019,20 @@ int pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus)
if( autobonus->other_script )
{
int j;
- ARR_FIND( 0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus->pos );
- if( j < EQI_MAX-1 )
- script_run_autobonus(autobonus->other_script,sd->bl.id,sd->equip_index[j]);
+ ARR_FIND( 0, EQI_MAX, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus->pos );
+ if( j < EQI_MAX )
+ script->run_autobonus(autobonus->other_script,sd->bl.id,sd->equip_index[j]);
}
- autobonus->active = iTimer->add_timer(iTimer->gettick()+autobonus->duration, pc->endautobonus, sd->bl.id, (intptr_t)autobonus);
+ autobonus->active = timer->add(timer->gettick()+autobonus->duration, pc->endautobonus, sd->bl.id, (intptr_t)autobonus);
sd->state.autobonus |= autobonus->pos;
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
return 0;
}
-int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct map_session_data *sd = iMap->id2sd(id);
+int pc_endautobonus(int tid, int64 tick, int id, intptr_t data) {
+ struct map_session_data *sd = map->id2sd(id);
struct s_autobonus *autobonus = (struct s_autobonus *)data;
nullpo_ret(sd);
@@ -1958,7 +2040,7 @@ int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data)
autobonus->active = INVALID_TIMER;
sd->state.autobonus &= ~autobonus->pos;
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
return 0;
}
@@ -2030,13 +2112,12 @@ int pc_bonus_subele(struct map_session_data* sd, unsigned char ele, short rate,
/*==========================================
* Add a bonus(type) to player sd
*------------------------------------------*/
-int pc_bonus(struct map_session_data *sd,int type,int val)
-{
- struct status_data *status;
+int pc_bonus(struct map_session_data *sd,int type,int val) {
+ struct status_data *bst;
int bonus;
nullpo_ret(sd);
- status = &sd->base_status;
+ bst = &sd->base_status;
switch(type){
case SP_STR:
@@ -2050,58 +2131,57 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
break;
case SP_ATK1:
if(!sd->state.lr_flag) {
- bonus = status->rhw.atk + val;
- status->rhw.atk = cap_value(bonus, 0, USHRT_MAX);
+ bonus = bst->rhw.atk + val;
+ bst->rhw.atk = cap_value(bonus, 0, USHRT_MAX);
}
else if(sd->state.lr_flag == 1) {
- bonus = status->lhw.atk + val;
- status->lhw.atk = cap_value(bonus, 0, USHRT_MAX);
+ bonus = bst->lhw.atk + val;
+ bst->lhw.atk = cap_value(bonus, 0, USHRT_MAX);
}
break;
case SP_ATK2:
if(!sd->state.lr_flag) {
- bonus = status->rhw.atk2 + val;
- status->rhw.atk2 = cap_value(bonus, 0, USHRT_MAX);
+ bonus = bst->rhw.atk2 + val;
+ bst->rhw.atk2 = cap_value(bonus, 0, USHRT_MAX);
}
else if(sd->state.lr_flag == 1) {
- bonus = status->lhw.atk2 + val;
- status->lhw.atk2 = cap_value(bonus, 0, USHRT_MAX);
+ bonus = bst->lhw.atk2 + val;
+ bst->lhw.atk2 = cap_value(bonus, 0, USHRT_MAX);
}
break;
case SP_BASE_ATK:
if(sd->state.lr_flag != 2) {
#ifdef RENEWAL
- sd->bonus.eatk += val;
- clif->updatestatus(sd,SP_ATK2);
+ bst->equip_atk += val;
#else
- bonus = status->batk + val;
- status->batk = cap_value(bonus, 0, USHRT_MAX);
+ bonus = bst->batk + val;
+ bst->batk = cap_value(bonus, 0, USHRT_MAX);
#endif
}
break;
case SP_DEF1:
if(sd->state.lr_flag != 2) {
- bonus = status->def + val;
+ bonus = bst->def + val;
#ifdef RENEWAL
- status->def = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ bst->def = cap_value(bonus, SHRT_MIN, SHRT_MAX);
#else
- status->def = cap_value(bonus, CHAR_MIN, CHAR_MAX);
+ bst->def = cap_value(bonus, CHAR_MIN, CHAR_MAX);
#endif
}
break;
case SP_DEF2:
if(sd->state.lr_flag != 2) {
- bonus = status->def2 + val;
- status->def2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ bonus = bst->def2 + val;
+ bst->def2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
}
break;
case SP_MDEF1:
if(sd->state.lr_flag != 2) {
- bonus = status->mdef + val;
+ bonus = bst->mdef + val;
#ifdef RENEWAL
- status->mdef = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ bst->mdef = cap_value(bonus, SHRT_MIN, SHRT_MAX);
#else
- status->mdef = cap_value(bonus, CHAR_MIN, CHAR_MAX);
+ bst->mdef = cap_value(bonus, CHAR_MIN, CHAR_MAX);
#endif
if( sd->state.lr_flag == 3 ) {//Shield, used for royal guard
sd->bonus.shieldmdef += bonus;
@@ -2110,33 +2190,33 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
break;
case SP_MDEF2:
if(sd->state.lr_flag != 2) {
- bonus = status->mdef2 + val;
- status->mdef2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ bonus = bst->mdef2 + val;
+ bst->mdef2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
}
break;
case SP_HIT:
if(sd->state.lr_flag != 2) {
- bonus = status->hit + val;
- status->hit = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ bonus = bst->hit + val;
+ bst->hit = cap_value(bonus, SHRT_MIN, SHRT_MAX);
} else
sd->bonus.arrow_hit+=val;
break;
case SP_FLEE1:
if(sd->state.lr_flag != 2) {
- bonus = status->flee + val;
- status->flee = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ bonus = bst->flee + val;
+ bst->flee = cap_value(bonus, SHRT_MIN, SHRT_MAX);
}
break;
case SP_FLEE2:
if(sd->state.lr_flag != 2) {
- bonus = status->flee2 + val*10;
- status->flee2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ bonus = bst->flee2 + val*10;
+ bst->flee2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
}
break;
case SP_CRITICAL:
if(sd->state.lr_flag != 2) {
- bonus = status->cri + val*10;
- status->cri = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ bonus = bst->cri + val*10;
+ bst->cri = cap_value(bonus, SHRT_MIN, SHRT_MAX);
} else
sd->bonus.arrow_cri += val*10;
break;
@@ -2145,8 +2225,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
ShowError("pc_bonus: SP_ATKELE: Invalid element %d\n", val);
break;
}
- switch (sd->state.lr_flag)
- {
+ switch (sd->state.lr_flag) {
case 2:
switch (sd->status.weapon) {
case W_BOW:
@@ -2156,7 +2235,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
case W_SHOTGUN:
case W_GRENADE:
//Become weapon element.
- status->rhw.ele=val;
+ bst->rhw.ele=val;
break;
default: //Become arrow element.
sd->bonus.arrow_ele=val;
@@ -2164,10 +2243,10 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
}
break;
case 1:
- status->lhw.ele=val;
+ bst->lhw.ele=val;
break;
default:
- status->rhw.ele=val;
+ bst->rhw.ele=val;
break;
}
break;
@@ -2177,21 +2256,21 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
break;
}
if(sd->state.lr_flag != 2)
- status->def_ele=val;
+ bst->def_ele=val;
break;
case SP_MAXHP:
if(sd->state.lr_flag == 2)
break;
- val += (int)status->max_hp;
+ val += (int)bst->max_hp;
//Negative bonuses will underflow, this will be handled in status_calc_pc through casting
//If this is called outside of status_calc_pc, you'd better pray they do not underflow and end with UINT_MAX max_hp.
- status->max_hp = (unsigned int)val;
+ bst->max_hp = (unsigned int)val;
break;
case SP_MAXSP:
if(sd->state.lr_flag == 2)
break;
- val += (int)status->max_sp;
- status->max_sp = (unsigned int)val;
+ val += (int)bst->max_sp;
+ bst->max_sp = (unsigned int)val;
break;
#ifndef RENEWAL_CAST
case SP_VARCASTRATE:
@@ -2222,14 +2301,14 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
case W_GATLING:
case W_SHOTGUN:
case W_GRENADE:
- status->rhw.range += val;
+ bst->rhw.range += val;
}
break;
case 1:
- status->lhw.range += val;
+ bst->lhw.range += val;
break;
default:
- status->rhw.range += val;
+ bst->rhw.range += val;
break;
}
break;
@@ -2248,9 +2327,9 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
case SP_ASPD_RATE: //Stackable increase - Made it linear as per rodatazone
if(sd->state.lr_flag != 2)
#ifndef RENEWAL_ASPD
- status->aspd_rate -= 10*val;
+ bst->aspd_rate -= 10*val;
#else
- status->aspd_rate2 += val;
+ bst->aspd_rate2 += val;
#endif
break;
case SP_HP_RECOV_RATE:
@@ -2630,11 +2709,13 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
break;
case SP_ADD_VARIABLECAST:
if(sd->state.lr_flag != 2)
-
sd->bonus.add_varcast += val;
-
break;
#endif
+ case SP_ADD_MONSTER_DROP_CHAINITEM:
+ if (sd->state.lr_flag != 2)
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, val, (1<<RC_BOSS)|(1<<RC_NONBOSS), 10000);
+ break;
default:
ShowWarning("pc_bonus: unknown type %d %d !\n",type,val);
break;
@@ -2652,593 +2733,591 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
nullpo_ret(sd);
switch(type){
- case SP_ADDELE:
- if(type2 >= ELE_MAX) {
- ShowError("pc_bonus2: SP_ADDELE: Invalid element %d\n", type2);
+ case SP_ADDELE:
+ if(type2 >= ELE_MAX) {
+ ShowError("pc_bonus2: SP_ADDELE: Invalid element %d\n", type2);
+ break;
+ }
+ if(!sd->state.lr_flag)
+ sd->right_weapon.addele[type2]+=val;
+ else if(sd->state.lr_flag == 1)
+ sd->left_weapon.addele[type2]+=val;
+ else if(sd->state.lr_flag == 2)
+ sd->arrow_addele[type2]+=val;
break;
- }
- if(!sd->state.lr_flag)
- sd->right_weapon.addele[type2]+=val;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.addele[type2]+=val;
- else if(sd->state.lr_flag == 2)
- sd->arrow_addele[type2]+=val;
- break;
- case SP_ADDRACE:
- if(!sd->state.lr_flag)
- sd->right_weapon.addrace[type2]+=val;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.addrace[type2]+=val;
- else if(sd->state.lr_flag == 2)
- sd->arrow_addrace[type2]+=val;
- break;
- case SP_ADDSIZE:
- if(!sd->state.lr_flag)
- sd->right_weapon.addsize[type2]+=val;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.addsize[type2]+=val;
- else if(sd->state.lr_flag == 2)
- sd->arrow_addsize[type2]+=val;
- break;
- case SP_SUBELE:
- if(type2 >= ELE_MAX) {
- ShowError("pc_bonus2: SP_SUBELE: Invalid element %d\n", type2);
+ case SP_ADDRACE:
+ if(!sd->state.lr_flag)
+ sd->right_weapon.addrace[type2]+=val;
+ else if(sd->state.lr_flag == 1)
+ sd->left_weapon.addrace[type2]+=val;
+ else if(sd->state.lr_flag == 2)
+ sd->arrow_addrace[type2]+=val;
break;
- }
- if(sd->state.lr_flag != 2)
- sd->subele[type2]+=val;
- break;
- case SP_SUBRACE:
- if(sd->state.lr_flag != 2)
- sd->subrace[type2]+=val;
- break;
- case SP_ADDEFF:
- if (type2 > SC_MAX) {
- ShowWarning("pc_bonus2 (Add Effect): %d is not supported.\n", type2);
+ case SP_ADDSIZE:
+ if(!sd->state.lr_flag)
+ sd->right_weapon.addsize[type2]+=val;
+ else if(sd->state.lr_flag == 1)
+ sd->left_weapon.addsize[type2]+=val;
+ else if(sd->state.lr_flag == 2)
+ sd->arrow_addsize[type2]+=val;
break;
- }
- pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2,
- sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, 0);
- break;
- case SP_ADDEFF2:
- if (type2 > SC_MAX) {
- ShowWarning("pc_bonus2 (Add Effect2): %d is not supported.\n", type2);
+ case SP_SUBELE:
+ if(type2 >= ELE_MAX) {
+ ShowError("pc_bonus2: SP_SUBELE: Invalid element %d\n", type2);
+ break;
+ }
+ if(sd->state.lr_flag != 2)
+ sd->subele[type2]+=val;
break;
- }
- pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2,
- sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, ATF_SELF);
- break;
- case SP_RESEFF:
- if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) {
- ShowWarning("pc_bonus2 (Resist Effect): %d is not supported.\n", type2);
+ case SP_SUBRACE:
+ if(sd->state.lr_flag != 2)
+ sd->subrace[type2]+=val;
break;
- }
- if(sd->state.lr_flag == 2)
+ case SP_ADDEFF:
+ if (type2 > SC_MAX) {
+ ShowWarning("pc_bonus2 (Add Effect): %d is not supported.\n", type2);
+ break;
+ }
+ pc->bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2,
+ sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, 0);
break;
- i = sd->reseff[type2-SC_COMMON_MIN]+val;
- sd->reseff[type2-SC_COMMON_MIN]= cap_value(i, 0, 10000);
- break;
- case SP_MAGIC_ADDELE:
- if(type2 >= ELE_MAX) {
- ShowError("pc_bonus2: SP_MAGIC_ADDELE: Invalid element %d\n", type2);
+ case SP_ADDEFF2:
+ if (type2 > SC_MAX) {
+ ShowWarning("pc_bonus2 (Add Effect2): %d is not supported.\n", type2);
+ break;
+ }
+ pc->bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2,
+ sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, ATF_SELF);
break;
- }
- if(sd->state.lr_flag != 2)
- sd->magic_addele[type2]+=val;
- break;
- case SP_MAGIC_ADDRACE:
- if(sd->state.lr_flag != 2)
- sd->magic_addrace[type2]+=val;
- break;
- case SP_MAGIC_ADDSIZE:
- if(sd->state.lr_flag != 2)
- sd->magic_addsize[type2]+=val;
- break;
- case SP_MAGIC_ATK_ELE:
- if(sd->state.lr_flag != 2)
- sd->magic_atk_ele[type2]+=val;
- break;
- case SP_ADD_DAMAGE_CLASS:
- switch (sd->state.lr_flag) {
- case 0: //Right hand
- ARR_FIND(0, ARRAYLENGTH(sd->right_weapon.add_dmg), i, sd->right_weapon.add_dmg[i].rate == 0 || sd->right_weapon.add_dmg[i].class_ == type2);
- if (i == ARRAYLENGTH(sd->right_weapon.add_dmg))
- {
- ShowWarning("pc_bonus2: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->right_weapon.add_dmg));
+ case SP_RESEFF:
+ if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) {
+ ShowWarning("pc_bonus2 (Resist Effect): %d is not supported.\n", type2);
break;
}
- sd->right_weapon.add_dmg[i].class_ = type2;
- sd->right_weapon.add_dmg[i].rate += val;
- if (!sd->right_weapon.add_dmg[i].rate) //Shift the rest of elements up.
- memmove(&sd->right_weapon.add_dmg[i], &sd->right_weapon.add_dmg[i+1], sizeof(sd->right_weapon.add_dmg) - (i+1)*sizeof(sd->right_weapon.add_dmg[0]));
+ if(sd->state.lr_flag == 2)
+ break;
+ i = sd->reseff[type2-SC_COMMON_MIN]+val;
+ sd->reseff[type2-SC_COMMON_MIN]= cap_value(i, 0, 10000);
break;
- case 1: //Left hand
- ARR_FIND(0, ARRAYLENGTH(sd->left_weapon.add_dmg), i, sd->left_weapon.add_dmg[i].rate == 0 || sd->left_weapon.add_dmg[i].class_ == type2);
- if (i == ARRAYLENGTH(sd->left_weapon.add_dmg))
- {
- ShowWarning("pc_bonus2: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->left_weapon.add_dmg));
+ case SP_MAGIC_ADDELE:
+ if(type2 >= ELE_MAX) {
+ ShowError("pc_bonus2: SP_MAGIC_ADDELE: Invalid element %d\n", type2);
break;
}
- sd->left_weapon.add_dmg[i].class_ = type2;
- sd->left_weapon.add_dmg[i].rate += val;
- if (!sd->left_weapon.add_dmg[i].rate) //Shift the rest of elements up.
- memmove(&sd->left_weapon.add_dmg[i], &sd->left_weapon.add_dmg[i+1], sizeof(sd->left_weapon.add_dmg) - (i+1)*sizeof(sd->left_weapon.add_dmg[0]));
+ if(sd->state.lr_flag != 2)
+ sd->magic_addele[type2]+=val;
break;
- }
- break;
- case SP_ADD_MAGIC_DAMAGE_CLASS:
- if(sd->state.lr_flag == 2)
+ case SP_MAGIC_ADDRACE:
+ if(sd->state.lr_flag != 2)
+ sd->magic_addrace[type2]+=val;
break;
- ARR_FIND(0, ARRAYLENGTH(sd->add_mdmg), i, sd->add_mdmg[i].rate == 0 || sd->add_mdmg[i].class_ == type2);
- if (i == ARRAYLENGTH(sd->add_mdmg))
- {
- ShowWarning("pc_bonus2: Reached max (%d) number of add Class magic dmg bonuses per character!\n", ARRAYLENGTH(sd->add_mdmg));
+ case SP_MAGIC_ADDSIZE:
+ if(sd->state.lr_flag != 2)
+ sd->magic_addsize[type2]+=val;
break;
- }
- sd->add_mdmg[i].class_ = type2;
- sd->add_mdmg[i].rate += val;
- if (!sd->add_mdmg[i].rate) //Shift the rest of elements up.
- memmove(&sd->add_mdmg[i], &sd->add_mdmg[i+1], sizeof(sd->add_mdmg) - (i+1)*sizeof(sd->add_mdmg[0]));
- break;
- case SP_ADD_DEF_CLASS:
- if(sd->state.lr_flag == 2)
+ case SP_MAGIC_ATK_ELE:
+ if(sd->state.lr_flag != 2)
+ sd->magic_atk_ele[type2]+=val;
break;
- ARR_FIND(0, ARRAYLENGTH(sd->add_def), i, sd->add_def[i].rate == 0 || sd->add_def[i].class_ == type2);
- if (i == ARRAYLENGTH(sd->add_def))
- {
- ShowWarning("pc_bonus2: Reached max (%d) number of add Class def bonuses per character!\n", ARRAYLENGTH(sd->add_def));
+ case SP_ADD_DAMAGE_CLASS:
+ switch (sd->state.lr_flag) {
+ case 0: //Right hand
+ ARR_FIND(0, ARRAYLENGTH(sd->right_weapon.add_dmg), i, sd->right_weapon.add_dmg[i].rate == 0 || sd->right_weapon.add_dmg[i].class_ == type2);
+ if (i == ARRAYLENGTH(sd->right_weapon.add_dmg)) {
+ ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of add Class dmg bonuses per character!\n",
+ ARRAYLENGTH(sd->right_weapon.add_dmg));
+ break;
+ }
+ sd->right_weapon.add_dmg[i].class_ = type2;
+ sd->right_weapon.add_dmg[i].rate += val;
+ if (!sd->right_weapon.add_dmg[i].rate) //Shift the rest of elements up.
+ memmove(&sd->right_weapon.add_dmg[i], &sd->right_weapon.add_dmg[i+1], sizeof(sd->right_weapon.add_dmg) - (i+1)*sizeof(sd->right_weapon.add_dmg[0]));
+ break;
+ case 1: //Left hand
+ ARR_FIND(0, ARRAYLENGTH(sd->left_weapon.add_dmg), i, sd->left_weapon.add_dmg[i].rate == 0 || sd->left_weapon.add_dmg[i].class_ == type2);
+ if (i == ARRAYLENGTH(sd->left_weapon.add_dmg)) {
+ ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of add Class dmg bonuses per character!\n",
+ ARRAYLENGTH(sd->left_weapon.add_dmg));
+ break;
+ }
+ sd->left_weapon.add_dmg[i].class_ = type2;
+ sd->left_weapon.add_dmg[i].rate += val;
+ if (!sd->left_weapon.add_dmg[i].rate) //Shift the rest of elements up.
+ memmove(&sd->left_weapon.add_dmg[i], &sd->left_weapon.add_dmg[i+1], sizeof(sd->left_weapon.add_dmg) - (i+1)*sizeof(sd->left_weapon.add_dmg[0]));
+ break;
+ }
break;
- }
- sd->add_def[i].class_ = type2;
- sd->add_def[i].rate += val;
- if (!sd->add_def[i].rate) //Shift the rest of elements up.
- memmove(&sd->add_def[i], &sd->add_def[i+1], sizeof(sd->add_def) - (i+1)*sizeof(sd->add_def[0]));
- break;
- case SP_ADD_MDEF_CLASS:
- if(sd->state.lr_flag == 2)
+ case SP_ADD_MAGIC_DAMAGE_CLASS:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->add_mdmg), i, sd->add_mdmg[i].rate == 0 || sd->add_mdmg[i].class_ == type2);
+ if (i == ARRAYLENGTH(sd->add_mdmg)) {
+ ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of add Class magic dmg bonuses per character!\n", ARRAYLENGTH(sd->add_mdmg));
+ break;
+ }
+ sd->add_mdmg[i].class_ = type2;
+ sd->add_mdmg[i].rate += val;
+ if (!sd->add_mdmg[i].rate) //Shift the rest of elements up.
+ memmove(&sd->add_mdmg[i], &sd->add_mdmg[i+1], sizeof(sd->add_mdmg) - (i+1)*sizeof(sd->add_mdmg[0]));
break;
- ARR_FIND(0, ARRAYLENGTH(sd->add_mdef), i, sd->add_mdef[i].rate == 0 || sd->add_mdef[i].class_ == type2);
- if (i == ARRAYLENGTH(sd->add_mdef))
- {
- ShowWarning("pc_bonus2: Reached max (%d) number of add Class mdef bonuses per character!\n", ARRAYLENGTH(sd->add_mdef));
+ case SP_ADD_DEF_CLASS:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->add_def), i, sd->add_def[i].rate == 0 || sd->add_def[i].class_ == type2);
+ if (i == ARRAYLENGTH(sd->add_def)) {
+ ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of add Class def bonuses per character!\n", ARRAYLENGTH(sd->add_def));
+ break;
+ }
+ sd->add_def[i].class_ = type2;
+ sd->add_def[i].rate += val;
+ if (!sd->add_def[i].rate) //Shift the rest of elements up.
+ memmove(&sd->add_def[i], &sd->add_def[i+1], sizeof(sd->add_def) - (i+1)*sizeof(sd->add_def[0]));
break;
- }
- sd->add_mdef[i].class_ = type2;
- sd->add_mdef[i].rate += val;
- if (!sd->add_mdef[i].rate) //Shift the rest of elements up.
- memmove(&sd->add_mdef[i], &sd->add_mdef[i+1], sizeof(sd->add_mdef) - (i+1)*sizeof(sd->add_mdef[0]));
- break;
- case SP_HP_DRAIN_RATE:
- if(!sd->state.lr_flag) {
- sd->right_weapon.hp_drain[RC_NONBOSS].rate += type2;
- sd->right_weapon.hp_drain[RC_NONBOSS].per += val;
- sd->right_weapon.hp_drain[RC_BOSS].rate += type2;
- sd->right_weapon.hp_drain[RC_BOSS].per += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.hp_drain[RC_NONBOSS].rate += type2;
- sd->left_weapon.hp_drain[RC_NONBOSS].per += val;
- sd->left_weapon.hp_drain[RC_BOSS].rate += type2;
- sd->left_weapon.hp_drain[RC_BOSS].per += val;
- }
- break;
- case SP_HP_DRAIN_VALUE:
- if(!sd->state.lr_flag) {
- sd->right_weapon.hp_drain[RC_NONBOSS].value += type2;
- sd->right_weapon.hp_drain[RC_NONBOSS].type = val;
- sd->right_weapon.hp_drain[RC_BOSS].value += type2;
- sd->right_weapon.hp_drain[RC_BOSS].type = val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.hp_drain[RC_NONBOSS].value += type2;
- sd->left_weapon.hp_drain[RC_NONBOSS].type = val;
- sd->left_weapon.hp_drain[RC_BOSS].value += type2;
- sd->left_weapon.hp_drain[RC_BOSS].type = val;
- }
- break;
- case SP_SP_DRAIN_RATE:
- if(!sd->state.lr_flag) {
- sd->right_weapon.sp_drain[RC_NONBOSS].rate += type2;
- sd->right_weapon.sp_drain[RC_NONBOSS].per += val;
- sd->right_weapon.sp_drain[RC_BOSS].rate += type2;
- sd->right_weapon.sp_drain[RC_BOSS].per += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.sp_drain[RC_NONBOSS].rate += type2;
- sd->left_weapon.sp_drain[RC_NONBOSS].per += val;
- sd->left_weapon.sp_drain[RC_BOSS].rate += type2;
- sd->left_weapon.sp_drain[RC_BOSS].per += val;
- }
- break;
- case SP_SP_DRAIN_VALUE:
- if(!sd->state.lr_flag) {
- sd->right_weapon.sp_drain[RC_NONBOSS].value += type2;
- sd->right_weapon.sp_drain[RC_NONBOSS].type = val;
- sd->right_weapon.sp_drain[RC_BOSS].value += type2;
- sd->right_weapon.sp_drain[RC_BOSS].type = val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.sp_drain[RC_NONBOSS].value += type2;
- sd->left_weapon.sp_drain[RC_NONBOSS].type = val;
- sd->left_weapon.sp_drain[RC_BOSS].value += type2;
- sd->left_weapon.sp_drain[RC_BOSS].type = val;
- }
- break;
- case SP_SP_VANISH_RATE:
- if(sd->state.lr_flag != 2) {
- sd->bonus.sp_vanish_rate += type2;
- sd->bonus.sp_vanish_per += val;
- }
- break;
- case SP_GET_ZENY_NUM:
- if(sd->state.lr_flag != 2 && sd->bonus.get_zeny_rate < val) {
- sd->bonus.get_zeny_rate = val;
- sd->bonus.get_zeny_num = type2;
- }
- break;
- case SP_ADD_GET_ZENY_NUM:
- if(sd->state.lr_flag != 2) {
- sd->bonus.get_zeny_rate += val;
- sd->bonus.get_zeny_num += type2;
- }
- break;
- case SP_WEAPON_COMA_ELE:
- if(type2 >= ELE_MAX) {
- ShowError("pc_bonus2: SP_WEAPON_COMA_ELE: Invalid element %d\n", type2);
+ case SP_ADD_MDEF_CLASS:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->add_mdef), i, sd->add_mdef[i].rate == 0 || sd->add_mdef[i].class_ == type2);
+ if (i == ARRAYLENGTH(sd->add_mdef)) {
+ ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of add Class mdef bonuses per character!\n", ARRAYLENGTH(sd->add_mdef));
+ break;
+ }
+ sd->add_mdef[i].class_ = type2;
+ sd->add_mdef[i].rate += val;
+ if (!sd->add_mdef[i].rate) //Shift the rest of elements up.
+ memmove(&sd->add_mdef[i], &sd->add_mdef[i+1], sizeof(sd->add_mdef) - (i+1)*sizeof(sd->add_mdef[0]));
break;
- }
- if(sd->state.lr_flag == 2)
+ case SP_HP_DRAIN_RATE:
+ if(!sd->state.lr_flag) {
+ sd->right_weapon.hp_drain[RC_NONBOSS].rate += type2;
+ sd->right_weapon.hp_drain[RC_NONBOSS].per += val;
+ sd->right_weapon.hp_drain[RC_BOSS].rate += type2;
+ sd->right_weapon.hp_drain[RC_BOSS].per += val;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.hp_drain[RC_NONBOSS].rate += type2;
+ sd->left_weapon.hp_drain[RC_NONBOSS].per += val;
+ sd->left_weapon.hp_drain[RC_BOSS].rate += type2;
+ sd->left_weapon.hp_drain[RC_BOSS].per += val;
+ }
break;
- sd->weapon_coma_ele[type2] += val;
- sd->special_state.bonus_coma = 1;
- break;
- case SP_WEAPON_COMA_RACE:
- if(sd->state.lr_flag == 2)
+ case SP_HP_DRAIN_VALUE:
+ if(!sd->state.lr_flag) {
+ sd->right_weapon.hp_drain[RC_NONBOSS].value += type2;
+ sd->right_weapon.hp_drain[RC_NONBOSS].type = val;
+ sd->right_weapon.hp_drain[RC_BOSS].value += type2;
+ sd->right_weapon.hp_drain[RC_BOSS].type = val;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.hp_drain[RC_NONBOSS].value += type2;
+ sd->left_weapon.hp_drain[RC_NONBOSS].type = val;
+ sd->left_weapon.hp_drain[RC_BOSS].value += type2;
+ sd->left_weapon.hp_drain[RC_BOSS].type = val;
+ }
break;
- sd->weapon_coma_race[type2] += val;
- sd->special_state.bonus_coma = 1;
- break;
- case SP_WEAPON_ATK:
- if(sd->state.lr_flag != 2)
- sd->weapon_atk[type2]+=val;
- break;
- case SP_WEAPON_ATK_RATE:
- if(sd->state.lr_flag != 2)
- sd->weapon_atk_rate[type2]+=val;
- break;
- case SP_CRITICAL_ADDRACE:
- if(sd->state.lr_flag != 2)
- sd->critaddrace[type2] += val*10;
- break;
- case SP_ADDEFF_WHENHIT:
- if (type2 > SC_MAX) {
- ShowWarning("pc_bonus2 (Add Effect when hit): %d is not supported.\n", type2);
+ case SP_SP_DRAIN_RATE:
+ if(!sd->state.lr_flag) {
+ sd->right_weapon.sp_drain[RC_NONBOSS].rate += type2;
+ sd->right_weapon.sp_drain[RC_NONBOSS].per += val;
+ sd->right_weapon.sp_drain[RC_BOSS].rate += type2;
+ sd->right_weapon.sp_drain[RC_BOSS].per += val;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.sp_drain[RC_NONBOSS].rate += type2;
+ sd->left_weapon.sp_drain[RC_NONBOSS].per += val;
+ sd->left_weapon.sp_drain[RC_BOSS].rate += type2;
+ sd->left_weapon.sp_drain[RC_BOSS].per += val;
+ }
break;
- }
- if(sd->state.lr_flag != 2)
- pc_bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, val, 0, 0);
- break;
- case SP_SKILL_ATK:
- if(sd->state.lr_flag == 2)
+ case SP_SP_DRAIN_VALUE:
+ if(!sd->state.lr_flag) {
+ sd->right_weapon.sp_drain[RC_NONBOSS].value += type2;
+ sd->right_weapon.sp_drain[RC_NONBOSS].type = val;
+ sd->right_weapon.sp_drain[RC_BOSS].value += type2;
+ sd->right_weapon.sp_drain[RC_BOSS].type = val;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.sp_drain[RC_NONBOSS].value += type2;
+ sd->left_weapon.sp_drain[RC_NONBOSS].type = val;
+ sd->left_weapon.sp_drain[RC_BOSS].value += type2;
+ sd->left_weapon.sp_drain[RC_BOSS].type = val;
+ }
break;
- ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == 0 || sd->skillatk[i].id == type2);
- if (i == ARRAYLENGTH(sd->skillatk))
- { //Better mention this so the array length can be updated. [Skotlex]
- ShowDebug("run_script: bonus2 bSkillAtk reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillatk), type2, val);
+ case SP_SP_VANISH_RATE:
+ if(sd->state.lr_flag != 2) {
+ sd->bonus.sp_vanish_rate += type2;
+ sd->bonus.sp_vanish_per = max(sd->bonus.sp_vanish_per,val);
+ sd->bonus.sp_vanish_trigger=0;
+ }
break;
- }
- if (sd->skillatk[i].id == type2)
- sd->skillatk[i].val += val;
- else {
- sd->skillatk[i].id = type2;
- sd->skillatk[i].val = val;
- }
- break;
- case SP_SKILL_HEAL:
- if(sd->state.lr_flag == 2)
+ case SP_GET_ZENY_NUM:
+ if(sd->state.lr_flag != 2 && sd->bonus.get_zeny_rate < val) {
+ sd->bonus.get_zeny_rate = val;
+ sd->bonus.get_zeny_num = type2;
+ }
break;
- ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == 0 || sd->skillheal[i].id == type2);
- if (i == ARRAYLENGTH(sd->skillheal))
- { // Better mention this so the array length can be updated. [Skotlex]
- ShowDebug("run_script: bonus2 bSkillHeal reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal), type2, val);
+ case SP_ADD_GET_ZENY_NUM:
+ if(sd->state.lr_flag != 2) {
+ sd->bonus.get_zeny_rate += val;
+ sd->bonus.get_zeny_num += type2;
+ }
break;
- }
- if (sd->skillheal[i].id == type2)
- sd->skillheal[i].val += val;
- else {
- sd->skillheal[i].id = type2;
- sd->skillheal[i].val = val;
- }
- break;
- case SP_SKILL_HEAL2:
- if(sd->state.lr_flag == 2)
+ case SP_WEAPON_COMA_ELE:
+ if(type2 >= ELE_MAX) {
+ ShowError("pc_bonus2: SP_WEAPON_COMA_ELE: Invalid element %d\n", type2);
+ break;
+ }
+ if(sd->state.lr_flag == 2)
+ break;
+ sd->weapon_coma_ele[type2] += val;
+ sd->special_state.bonus_coma = 1;
break;
- ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == 0 || sd->skillheal2[i].id == type2);
- if (i == ARRAYLENGTH(sd->skillheal2))
- { // Better mention this so the array length can be updated. [Skotlex]
- ShowDebug("run_script: bonus2 bSkillHeal2 reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal2), type2, val);
+ case SP_WEAPON_COMA_RACE:
+ if(sd->state.lr_flag == 2)
+ break;
+ sd->weapon_coma_race[type2] += val;
+ sd->special_state.bonus_coma = 1;
break;
- }
- if (sd->skillheal2[i].id == type2)
- sd->skillheal2[i].val += val;
- else {
- sd->skillheal2[i].id = type2;
- sd->skillheal2[i].val = val;
- }
- break;
- case SP_ADD_SKILL_BLOW:
- if(sd->state.lr_flag == 2)
+ case SP_WEAPON_ATK:
+ if(sd->state.lr_flag != 2)
+ sd->weapon_atk[type2]+=val;
break;
- ARR_FIND(0, ARRAYLENGTH(sd->skillblown), i, sd->skillblown[i].id == 0 || sd->skillblown[i].id == type2);
- if (i == ARRAYLENGTH(sd->skillblown))
- { //Better mention this so the array length can be updated. [Skotlex]
- ShowDebug("run_script: bonus2 bSkillBlown reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillblown), type2, val);
+ case SP_WEAPON_ATK_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->weapon_atk_rate[type2]+=val;
break;
- }
- if(sd->skillblown[i].id == type2)
- sd->skillblown[i].val += val;
- else {
- sd->skillblown[i].id = type2;
- sd->skillblown[i].val = val;
- }
- break;
-#ifndef RENEWAL_CAST
- case SP_VARCASTRATE:
-#endif
- case SP_CASTRATE:
- if(sd->state.lr_flag == 2)
+ case SP_CRITICAL_ADDRACE:
+ if(sd->state.lr_flag != 2)
+ sd->critaddrace[type2] += val*10;
break;
- ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2);
- if (i == ARRAYLENGTH(sd->skillcast))
- { //Better mention this so the array length can be updated. [Skotlex]
- ShowDebug("run_script: bonus2 %s reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n",
-
-#ifndef RENEWAL_CAST
- "bCastRate",
-#else
- "bVariableCastrate",
-#endif
-
- ARRAYLENGTH(sd->skillcast), type2, val);
+ case SP_ADDEFF_WHENHIT:
+ if (type2 > SC_MAX) {
+ ShowWarning("pc_bonus2 (Add Effect when hit): %d is not supported.\n", type2);
+ break;
+ }
+ if(sd->state.lr_flag != 2)
+ pc->bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, val, 0, 0);
break;
- }
- if(sd->skillcast[i].id == type2)
- sd->skillcast[i].val += val;
- else {
- sd->skillcast[i].id = type2;
- sd->skillcast[i].val = val;
- }
- break;
-
- case SP_FIXCASTRATE:
- if(sd->state.lr_flag == 2)
+ case SP_SKILL_ATK:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == 0 || sd->skillatk[i].id == type2);
+ if (i == ARRAYLENGTH(sd->skillatk)) {
+ //Better mention this so the array length can be updated. [Skotlex]
+ ShowDebug("script->run: bonus2 bSkillAtk reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
+ ARRAYLENGTH(sd->skillatk), type2, val);
+ break;
+ }
+ if (sd->skillatk[i].id == type2)
+ sd->skillatk[i].val += val;
+ else {
+ sd->skillatk[i].id = type2;
+ sd->skillatk[i].val = val;
+ }
+ break;
+ case SP_SKILL_HEAL:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == 0 || sd->skillheal[i].id == type2);
+ if (i == ARRAYLENGTH(sd->skillheal)) {
+ // Better mention this so the array length can be updated. [Skotlex]
+ ShowDebug("script->run: bonus2 bSkillHeal reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
+ ARRAYLENGTH(sd->skillheal), type2, val);
+ break;
+ }
+ if (sd->skillheal[i].id == type2)
+ sd->skillheal[i].val += val;
+ else {
+ sd->skillheal[i].id = type2;
+ sd->skillheal[i].val = val;
+ }
+ break;
+ case SP_SKILL_HEAL2:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == 0 || sd->skillheal2[i].id == type2);
+ if (i == ARRAYLENGTH(sd->skillheal2)) {
+ // Better mention this so the array length can be updated. [Skotlex]
+ ShowDebug("script->run: bonus2 bSkillHeal2 reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
+ ARRAYLENGTH(sd->skillheal2), type2, val);
+ break;
+ }
+ if (sd->skillheal2[i].id == type2)
+ sd->skillheal2[i].val += val;
+ else {
+ sd->skillheal2[i].id = type2;
+ sd->skillheal2[i].val = val;
+ }
+ break;
+ case SP_ADD_SKILL_BLOW:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->skillblown), i, sd->skillblown[i].id == 0 || sd->skillblown[i].id == type2);
+ if (i == ARRAYLENGTH(sd->skillblown)) {
+ //Better mention this so the array length can be updated. [Skotlex]
+ ShowDebug("script->run: bonus2 bSkillBlown reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
+ ARRAYLENGTH(sd->skillblown), type2, val);
+ break;
+ }
+ if(sd->skillblown[i].id == type2)
+ sd->skillblown[i].val += val;
+ else {
+ sd->skillblown[i].id = type2;
+ sd->skillblown[i].val = val;
+ }
break;
+ #ifndef RENEWAL_CAST
+ case SP_VARCASTRATE:
+ #endif
+ case SP_CASTRATE:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2);
+ if (i == ARRAYLENGTH(sd->skillcast)) {
+ //Better mention this so the array length can be updated. [Skotlex]
+ ShowDebug("script->run: bonus2 %s reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
- ARR_FIND(0, ARRAYLENGTH(sd->skillfixcastrate), i, sd->skillfixcastrate[i].id == 0 || sd->skillfixcastrate[i].id == type2);
+ #ifndef RENEWAL_CAST
+ "bCastRate",
+ #else
+ "bVariableCastrate",
+ #endif
- if (i == ARRAYLENGTH(sd->skillfixcastrate))
+ ARRAYLENGTH(sd->skillcast), type2, val);
+ break;
+ }
+ if(sd->skillcast[i].id == type2)
+ sd->skillcast[i].val += val;
+ else {
+ sd->skillcast[i].id = type2;
+ sd->skillcast[i].val = val;
+ }
+ break;
- {
+ case SP_FIXCASTRATE:
+ if(sd->state.lr_flag == 2)
+ break;
- ShowDebug("run_script: bonus2 bFixedCastrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcastrate), type2, val);
- break;
- }
+ ARR_FIND(0, ARRAYLENGTH(sd->skillfixcastrate), i, sd->skillfixcastrate[i].id == 0 || sd->skillfixcastrate[i].id == type2);
- if(sd->skillfixcastrate[i].id == type2)
- sd->skillfixcastrate[i].val += val;
+ if (i == ARRAYLENGTH(sd->skillfixcastrate)) {
+ ShowDebug("script->run: bonus2 bFixedCastrate reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
+ ARRAYLENGTH(sd->skillfixcastrate), type2, val);
+ break;
+ }
- else {
- sd->skillfixcastrate[i].id = type2;
- sd->skillfixcastrate[i].val = val;
- }
+ if(sd->skillfixcastrate[i].id == type2)
+ sd->skillfixcastrate[i].val += val;
- break;
+ else {
+ sd->skillfixcastrate[i].id = type2;
+ sd->skillfixcastrate[i].val = val;
+ }
- case SP_HP_LOSS_RATE:
- if(sd->state.lr_flag != 2) {
- sd->hp_loss.value = type2;
- sd->hp_loss.rate = val;
- }
- break;
- case SP_HP_REGEN_RATE:
- if(sd->state.lr_flag != 2) {
- sd->hp_regen.value = type2;
- sd->hp_regen.rate = val;
- }
- break;
- case SP_ADDRACE2:
- if (!(type2 > RC2_NONE && type2 < RC2_MAX))
break;
- if(sd->state.lr_flag != 2)
- sd->right_weapon.addrace2[type2] += val;
- else
- sd->left_weapon.addrace2[type2] += val;
- break;
- case SP_SUBSIZE:
- if(sd->state.lr_flag != 2)
- sd->subsize[type2]+=val;
- break;
- case SP_SUBRACE2:
- if (!(type2 > RC2_NONE && type2 < RC2_MAX))
+
+ case SP_HP_LOSS_RATE:
+ if(sd->state.lr_flag != 2) {
+ sd->hp_loss.value = type2;
+ sd->hp_loss.rate = val;
+ }
break;
- if(sd->state.lr_flag != 2)
- sd->subrace2[type2]+=val;
- break;
- case SP_ADD_ITEM_HEAL_RATE:
- if(sd->state.lr_flag == 2)
+ case SP_HP_REGEN_RATE:
+ if(sd->state.lr_flag != 2) {
+ sd->hp_regen.value = type2;
+ sd->hp_regen.rate = val;
+ }
break;
- if (type2 < MAX_ITEMGROUP) { //Group bonus
- sd->itemgrouphealrate[type2] += val;
+ case SP_ADDRACE2:
+ if (!(type2 > RC2_NONE && type2 < RC2_MAX))
+ break;
+ if(sd->state.lr_flag != 2)
+ sd->right_weapon.addrace2[type2] += val;
+ else
+ sd->left_weapon.addrace2[type2] += val;
break;
- }
- //Standard item bonus.
- for(i=0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid && sd->itemhealrate[i].nameid != type2; i++);
- if(i == ARRAYLENGTH(sd->itemhealrate)) {
- ShowWarning("pc_bonus2: Reached max (%d) number of item heal bonuses per character!\n", ARRAYLENGTH(sd->itemhealrate));
+ case SP_SUBSIZE:
+ if(sd->state.lr_flag != 2)
+ sd->subsize[type2]+=val;
break;
- }
- sd->itemhealrate[i].nameid = type2;
- sd->itemhealrate[i].rate += val;
- break;
- case SP_EXP_ADDRACE:
- if(sd->state.lr_flag != 2)
- sd->expaddrace[type2]+=val;
- break;
- case SP_SP_GAIN_RACE:
- if(sd->state.lr_flag != 2)
- sd->sp_gain_race[type2]+=val;
- break;
- case SP_ADD_MONSTER_DROP_ITEM:
- if (sd->state.lr_flag != 2)
- pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, (1<<RC_BOSS)|(1<<RC_NONBOSS), val);
- break;
- case SP_ADD_MONSTER_DROP_ITEMGROUP:
- if (sd->state.lr_flag != 2)
- pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, (1<<RC_BOSS)|(1<<RC_NONBOSS), val);
- break;
- case SP_SP_LOSS_RATE:
- if(sd->state.lr_flag != 2) {
- sd->sp_loss.value = type2;
- sd->sp_loss.rate = val;
- }
- break;
- case SP_SP_REGEN_RATE:
- if(sd->state.lr_flag != 2) {
- sd->sp_regen.value = type2;
- sd->sp_regen.rate = val;
- }
- break;
- case SP_HP_DRAIN_VALUE_RACE:
- if(!sd->state.lr_flag) {
- sd->right_weapon.hp_drain[type2].value += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.hp_drain[type2].value += val;
- }
- break;
- case SP_SP_DRAIN_VALUE_RACE:
- if(!sd->state.lr_flag) {
- sd->right_weapon.sp_drain[type2].value += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.sp_drain[type2].value += val;
- }
- break;
- case SP_IGNORE_MDEF_RATE:
- if(sd->state.lr_flag != 2)
- sd->ignore_mdef[type2] += val;
- break;
- case SP_IGNORE_DEF_RATE:
- if(sd->state.lr_flag != 2)
- sd->ignore_def[type2] += val;
- break;
- case SP_SP_GAIN_RACE_ATTACK:
- if(sd->state.lr_flag != 2)
- sd->sp_gain_race_attack[type2] = cap_value(sd->sp_gain_race_attack[type2] + val, 0, INT16_MAX);
- break;
- case SP_HP_GAIN_RACE_ATTACK:
- if(sd->state.lr_flag != 2)
- sd->hp_gain_race_attack[type2] = cap_value(sd->hp_gain_race_attack[type2] + val, 0, INT16_MAX);
- break;
- case SP_SKILL_USE_SP_RATE: //bonus2 bSkillUseSPrate,n,x;
- if(sd->state.lr_flag == 2)
+ case SP_SUBRACE2:
+ if (!(type2 > RC2_NONE && type2 < RC2_MAX))
+ break;
+ if(sd->state.lr_flag != 2)
+ sd->subrace2[type2]+=val;
break;
- ARR_FIND(0, ARRAYLENGTH(sd->skillusesprate), i, sd->skillusesprate[i].id == 0 || sd->skillusesprate[i].id == type2);
- if (i == ARRAYLENGTH(sd->skillusesprate)) {
- ShowDebug("run_script: bonus2 bSkillUseSPrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesprate), type2, val);
+ case SP_ADD_ITEM_HEAL_RATE:
+ if(sd->state.lr_flag == 2)
+ break;
+ //Standard item bonus.
+ for(i=0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid && sd->itemhealrate[i].nameid != type2; i++);
+ if (i == ARRAYLENGTH(sd->itemhealrate)) {
+ ShowWarning("pc_bonus2: Reached max (%"PRIuS") number of item heal bonuses per character!\n", ARRAYLENGTH(sd->itemhealrate));
+ break;
+ }
+ sd->itemhealrate[i].nameid = type2;
+ sd->itemhealrate[i].rate += val;
break;
- }
- if (sd->skillusesprate[i].id == type2)
- sd->skillusesprate[i].val += val;
- else {
- sd->skillusesprate[i].id = type2;
- sd->skillusesprate[i].val = val;
- }
- break;
- case SP_SKILL_COOLDOWN:
- if(sd->state.lr_flag == 2)
+ case SP_EXP_ADDRACE:
+ if(sd->state.lr_flag != 2)
+ sd->expaddrace[type2]+=val;
break;
- ARR_FIND(0, ARRAYLENGTH(sd->skillcooldown), i, sd->skillcooldown[i].id == 0 || sd->skillcooldown[i].id == type2);
- if (i == ARRAYLENGTH(sd->skillcooldown))
- {
- ShowDebug("run_script: bonus2 bSkillCoolDown reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillcooldown), type2, val);
+ case SP_SP_GAIN_RACE:
+ if(sd->state.lr_flag != 2)
+ sd->sp_gain_race[type2]+=val;
break;
- }
- if (sd->skillcooldown[i].id == type2)
- sd->skillcooldown[i].val += val;
- else {
- sd->skillcooldown[i].id = type2;
- sd->skillcooldown[i].val = val;
- }
- break;
- case SP_SKILL_FIXEDCAST:
- if(sd->state.lr_flag == 2)
+ case SP_ADD_MONSTER_DROP_ITEM:
+ if (sd->state.lr_flag != 2)
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, (1<<RC_BOSS)|(1<<RC_NONBOSS), val);
break;
- ARR_FIND(0, ARRAYLENGTH(sd->skillfixcast), i, sd->skillfixcast[i].id == 0 || sd->skillfixcast[i].id == type2);
- if (i == ARRAYLENGTH(sd->skillfixcast))
- {
- ShowDebug("run_script: bonus2 bSkillFixedCast reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcast), type2, val);
+ case SP_SP_LOSS_RATE:
+ if(sd->state.lr_flag != 2) {
+ sd->sp_loss.value = type2;
+ sd->sp_loss.rate = val;
+ }
break;
- }
- if (sd->skillfixcast[i].id == type2)
- sd->skillfixcast[i].val += val;
- else {
- sd->skillfixcast[i].id = type2;
- sd->skillfixcast[i].val = val;
- }
- break;
- case SP_SKILL_VARIABLECAST:
- if(sd->state.lr_flag == 2)
+ case SP_SP_REGEN_RATE:
+ if(sd->state.lr_flag != 2) {
+ sd->sp_regen.value = type2;
+ sd->sp_regen.rate = val;
+ }
break;
- ARR_FIND(0, ARRAYLENGTH(sd->skillvarcast), i, sd->skillvarcast[i].id == 0 || sd->skillvarcast[i].id == type2);
- if (i == ARRAYLENGTH(sd->skillvarcast))
- {
- ShowDebug("run_script: bonus2 bSkillVariableCast reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillvarcast), type2, val);
+ case SP_HP_DRAIN_VALUE_RACE:
+ if(!sd->state.lr_flag) {
+ sd->right_weapon.hp_drain[type2].value += val;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.hp_drain[type2].value += val;
+ }
break;
- }
- if (sd->skillvarcast[i].id == type2)
- sd->skillvarcast[i].val += val;
- else {
- sd->skillvarcast[i].id = type2;
- sd->skillvarcast[i].val = val;
- }
- break;
-#ifdef RENEWAL_CAST
- case SP_VARCASTRATE:
- if(sd->state.lr_flag == 2)
+ case SP_SP_DRAIN_VALUE_RACE:
+ if(!sd->state.lr_flag) {
+ sd->right_weapon.sp_drain[type2].value += val;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.sp_drain[type2].value += val;
+ }
break;
- ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2);
- if (i == ARRAYLENGTH(sd->skillcast))
- {
- ShowDebug("run_script: bonus2 bVariableCastrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n",ARRAYLENGTH(sd->skillcast), type2, val);
+ case SP_IGNORE_MDEF_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->ignore_mdef[type2] += val;
break;
- }
- if(sd->skillcast[i].id == type2)
- sd->skillcast[i].val -= val;
- else {
- sd->skillcast[i].id = type2;
- sd->skillcast[i].val -= val;
- }
- break;
-#endif
- case SP_SKILL_USE_SP: //bonus2 bSkillUseSP,n,x;
- if(sd->state.lr_flag == 2)
+ case SP_IGNORE_DEF_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->ignore_def[type2] += val;
break;
- ARR_FIND(0, ARRAYLENGTH(sd->skillusesp), i, sd->skillusesp[i].id == 0 || sd->skillusesp[i].id == type2);
- if (i == ARRAYLENGTH(sd->skillusesp)) {
- ShowDebug("run_script: bonus2 bSkillUseSP reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesp), type2, val);
+ case SP_SP_GAIN_RACE_ATTACK:
+ if(sd->state.lr_flag != 2)
+ sd->sp_gain_race_attack[type2] = cap_value(sd->sp_gain_race_attack[type2] + val, 0, INT16_MAX);
+ break;
+ case SP_HP_GAIN_RACE_ATTACK:
+ if(sd->state.lr_flag != 2)
+ sd->hp_gain_race_attack[type2] = cap_value(sd->hp_gain_race_attack[type2] + val, 0, INT16_MAX);
+ break;
+ case SP_SKILL_USE_SP_RATE: //bonus2 bSkillUseSPrate,n,x;
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->skillusesprate), i, sd->skillusesprate[i].id == 0 || sd->skillusesprate[i].id == type2);
+ if (i == ARRAYLENGTH(sd->skillusesprate)) {
+ ShowDebug("script->run: bonus2 bSkillUseSPrate reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
+ ARRAYLENGTH(sd->skillusesprate), type2, val);
+ break;
+ }
+ if (sd->skillusesprate[i].id == type2)
+ sd->skillusesprate[i].val += val;
+ else {
+ sd->skillusesprate[i].id = type2;
+ sd->skillusesprate[i].val = val;
+ }
+ break;
+ case SP_SKILL_COOLDOWN:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->skillcooldown), i, sd->skillcooldown[i].id == 0 || sd->skillcooldown[i].id == type2);
+ if (i == ARRAYLENGTH(sd->skillcooldown)) {
+ ShowDebug("script->run: bonus2 bSkillCoolDown reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
+ ARRAYLENGTH(sd->skillcooldown), type2, val);
+ break;
+ }
+ if (sd->skillcooldown[i].id == type2)
+ sd->skillcooldown[i].val += val;
+ else {
+ sd->skillcooldown[i].id = type2;
+ sd->skillcooldown[i].val = val;
+ }
+ break;
+ case SP_SKILL_FIXEDCAST:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->skillfixcast), i, sd->skillfixcast[i].id == 0 || sd->skillfixcast[i].id == type2);
+ if (i == ARRAYLENGTH(sd->skillfixcast)) {
+ ShowDebug("script->run: bonus2 bSkillFixedCast reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
+ ARRAYLENGTH(sd->skillfixcast), type2, val);
+ break;
+ }
+ if (sd->skillfixcast[i].id == type2)
+ sd->skillfixcast[i].val += val;
+ else {
+ sd->skillfixcast[i].id = type2;
+ sd->skillfixcast[i].val = val;
+ }
+ break;
+ case SP_SKILL_VARIABLECAST:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->skillvarcast), i, sd->skillvarcast[i].id == 0 || sd->skillvarcast[i].id == type2);
+ if (i == ARRAYLENGTH(sd->skillvarcast)) {
+ ShowDebug("script->run: bonus2 bSkillVariableCast reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
+ ARRAYLENGTH(sd->skillvarcast), type2, val);
+ break;
+ }
+ if (sd->skillvarcast[i].id == type2)
+ sd->skillvarcast[i].val += val;
+ else {
+ sd->skillvarcast[i].id = type2;
+ sd->skillvarcast[i].val = val;
+ }
+ break;
+ #ifdef RENEWAL_CAST
+ case SP_VARCASTRATE:
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2);
+ if (i == ARRAYLENGTH(sd->skillcast)) {
+ ShowDebug("script->run: bonus2 bVariableCastrate reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
+ ARRAYLENGTH(sd->skillcast), type2, val);
+ break;
+ }
+ if(sd->skillcast[i].id == type2)
+ sd->skillcast[i].val -= val;
+ else {
+ sd->skillcast[i].id = type2;
+ sd->skillcast[i].val -= val;
+ }
+ break;
+ #endif
+ case SP_SKILL_USE_SP: //bonus2 bSkillUseSP,n,x;
+ if(sd->state.lr_flag == 2)
+ break;
+ ARR_FIND(0, ARRAYLENGTH(sd->skillusesp), i, sd->skillusesp[i].id == 0 || sd->skillusesp[i].id == type2);
+ if (i == ARRAYLENGTH(sd->skillusesp)) {
+ ShowDebug("script->run: bonus2 bSkillUseSP reached it's limit (%"PRIuS" skills per character), bonus skill %d (+%d%%) lost.\n",
+ ARRAYLENGTH(sd->skillusesp), type2, val);
+ break;
+ }
+ if (sd->skillusesp[i].id == type2)
+ sd->skillusesp[i].val += val;
+ else {
+ sd->skillusesp[i].id = type2;
+ sd->skillusesp[i].val = val;
+ }
+ break;
+ case SP_ADD_MONSTER_DROP_CHAINITEM:
+ if (sd->state.lr_flag != 2)
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, val, 1<<type2, 10000);
+ break;
+ default:
+ ShowWarning("pc_bonus2: unknown type %d %d %d!\n",type,type2,val);
break;
- }
- if (sd->skillusesp[i].id == type2)
- sd->skillusesp[i].val += val;
- else {
- sd->skillusesp[i].id = type2;
- sd->skillusesp[i].val = val;
- }
- break;
- default:
- ShowWarning("pc_bonus2: unknown type %d %d %d!\n",type,type2,val);
- break;
}
return 0;
}
@@ -3248,161 +3327,185 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
nullpo_ret(sd);
switch(type){
- case SP_ADD_MONSTER_DROP_ITEM:
- if(sd->state.lr_flag != 2)
- pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, 1<<type3, val);
- break;
- case SP_ADD_CLASS_DROP_ITEM:
- if(sd->state.lr_flag != 2)
- pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, -type3, val);
- break;
- case SP_AUTOSPELL:
- if(sd->state.lr_flag != 2)
- {
- int target = skill->get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
- target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill->get_inf2(type2)&INF2_NO_TARGET_SELF));
- pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell),
- target?-type2:type2, type3, val, 0, current_equip_card_id);
- }
- break;
- case SP_AUTOSPELL_WHENHIT:
- if(sd->state.lr_flag != 2)
- {
- int target = skill->get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
- target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill->get_inf2(type2)&INF2_NO_TARGET_SELF));
- pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2),
- target?-type2:type2, type3, val, BF_NORMAL|BF_SKILL, current_equip_card_id);
- }
- break;
- case SP_SP_DRAIN_RATE:
- if(!sd->state.lr_flag) {
- sd->right_weapon.sp_drain[RC_NONBOSS].rate += type2;
- sd->right_weapon.sp_drain[RC_NONBOSS].per += type3;
- sd->right_weapon.sp_drain[RC_NONBOSS].type = val;
- sd->right_weapon.sp_drain[RC_BOSS].rate += type2;
- sd->right_weapon.sp_drain[RC_BOSS].per += type3;
- sd->right_weapon.sp_drain[RC_BOSS].type = val;
-
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.sp_drain[RC_NONBOSS].rate += type2;
- sd->left_weapon.sp_drain[RC_NONBOSS].per += type3;
- sd->left_weapon.sp_drain[RC_NONBOSS].type = val;
- sd->left_weapon.sp_drain[RC_BOSS].rate += type2;
- sd->left_weapon.sp_drain[RC_BOSS].per += type3;
- sd->left_weapon.sp_drain[RC_BOSS].type = val;
- }
- break;
- case SP_HP_DRAIN_RATE_RACE:
- if(!sd->state.lr_flag) {
- sd->right_weapon.hp_drain[type2].rate += type3;
- sd->right_weapon.hp_drain[type2].per += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.hp_drain[type2].rate += type3;
- sd->left_weapon.hp_drain[type2].per += val;
- }
- break;
- case SP_SP_DRAIN_RATE_RACE:
- if(!sd->state.lr_flag) {
- sd->right_weapon.sp_drain[type2].rate += type3;
- sd->right_weapon.sp_drain[type2].per += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.sp_drain[type2].rate += type3;
- sd->left_weapon.sp_drain[type2].per += val;
- }
- break;
- case SP_ADD_MONSTER_DROP_ITEMGROUP:
- if (sd->state.lr_flag != 2)
- pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, 1<<type3, val);
- break;
+ case SP_ADD_MONSTER_DROP_ITEM:
+ if(sd->state.lr_flag != 2)
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, 1<<type3, val);
+ break;
+ case SP_ADD_CLASS_DROP_ITEM:
+ if(sd->state.lr_flag != 2)
+ pc->bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, -type3, val);
+ break;
+ case SP_AUTOSPELL:
+ if(sd->state.lr_flag != 2)
+ {
+ int target = skill->get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
+ target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill->get_inf2(type2)&INF2_NO_TARGET_SELF));
+ pc->bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell),
+ target?-type2:type2, type3, val, 0, status->current_equip_card_id);
+ }
+ break;
+ case SP_AUTOSPELL_WHENHIT:
+ if(sd->state.lr_flag != 2)
+ {
+ int target = skill->get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
+ target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill->get_inf2(type2)&INF2_NO_TARGET_SELF));
+ pc->bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2),
+ target?-type2:type2, type3, val, BF_NORMAL|BF_SKILL, status->current_equip_card_id);
+ }
+ break;
+ case SP_SP_DRAIN_RATE:
+ if(!sd->state.lr_flag) {
+ sd->right_weapon.sp_drain[RC_NONBOSS].rate += type2;
+ sd->right_weapon.sp_drain[RC_NONBOSS].per += type3;
+ sd->right_weapon.sp_drain[RC_NONBOSS].type = val;
+ sd->right_weapon.sp_drain[RC_BOSS].rate += type2;
+ sd->right_weapon.sp_drain[RC_BOSS].per += type3;
+ sd->right_weapon.sp_drain[RC_BOSS].type = val;
- case SP_ADDEFF:
- if (type2 > SC_MAX) {
- ShowWarning("pc_bonus3 (Add Effect): %d is not supported.\n", type2);
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.sp_drain[RC_NONBOSS].rate += type2;
+ sd->left_weapon.sp_drain[RC_NONBOSS].per += type3;
+ sd->left_weapon.sp_drain[RC_NONBOSS].type = val;
+ sd->left_weapon.sp_drain[RC_BOSS].rate += type2;
+ sd->left_weapon.sp_drain[RC_BOSS].per += type3;
+ sd->left_weapon.sp_drain[RC_BOSS].type = val;
+ }
+ break;
+ case SP_HP_DRAIN_RATE_RACE:
+ if(!sd->state.lr_flag) {
+ sd->right_weapon.hp_drain[type2].rate += type3;
+ sd->right_weapon.hp_drain[type2].per += val;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.hp_drain[type2].rate += type3;
+ sd->left_weapon.hp_drain[type2].per += val;
+ }
+ break;
+ case SP_SP_DRAIN_RATE_RACE:
+ if(!sd->state.lr_flag) {
+ sd->right_weapon.sp_drain[type2].rate += type3;
+ sd->right_weapon.sp_drain[type2].per += val;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.sp_drain[type2].rate += type3;
+ sd->left_weapon.sp_drain[type2].per += val;
+ }
+ break;
+ case SP_ADDEFF:
+ if (type2 > SC_MAX) {
+ ShowWarning("pc_bonus3 (Add Effect): %d is not supported.\n", type2);
+ break;
+ }
+ pc->bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2,
+ sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, val);
break;
- }
- pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2,
- sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, val);
- break;
- case SP_ADDEFF_WHENHIT:
- if (type2 > SC_MAX) {
- ShowWarning("pc_bonus3 (Add Effect when hit): %d is not supported.\n", type2);
+ case SP_ADDEFF_WHENHIT:
+ if (type2 > SC_MAX) {
+ ShowWarning("pc_bonus3 (Add Effect when hit): %d is not supported.\n", type2);
+ break;
+ }
+ if(sd->state.lr_flag != 2)
+ pc->bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, type3, 0, val);
break;
- }
- if(sd->state.lr_flag != 2)
- pc_bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, type3, 0, val);
- break;
- case SP_ADDEFF_ONSKILL:
- if( type3 > SC_MAX ) {
- ShowWarning("pc_bonus3 (Add Effect on skill): %d is not supported.\n", type3);
+ case SP_ADDEFF_ONSKILL:
+ if( type3 > SC_MAX ) {
+ ShowWarning("pc_bonus3 (Add Effect on skill): %d is not supported.\n", type3);
+ break;
+ }
+ if( sd->state.lr_flag != 2 )
+ pc->bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, val, type2, ATF_TARGET);
break;
- }
- if( sd->state.lr_flag != 2 )
- pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, val, type2, ATF_TARGET);
- break;
- case SP_ADDELE:
- if (type2 > ELE_MAX) {
- ShowWarning("pc_bonus3 (SP_ADDELE): element %d is out of range.\n", type2);
+ case SP_ADDELE:
+ if (type2 > ELE_MAX) {
+ ShowWarning("pc_bonus3 (SP_ADDELE): element %d is out of range.\n", type2);
+ break;
+ }
+ if (sd->state.lr_flag != 2)
+ pc_bonus_addele(sd, (unsigned char)type2, type3, val);
break;
- }
- if (sd->state.lr_flag != 2)
- pc_bonus_addele(sd, (unsigned char)type2, type3, val);
- break;
- case SP_SUBELE:
- if (type2 > ELE_MAX) {
- ShowWarning("pc_bonus3 (SP_SUBELE): element %d is out of range.\n", type2);
+ case SP_SUBELE:
+ if (type2 > ELE_MAX) {
+ ShowWarning("pc_bonus3 (SP_SUBELE): element %d is out of range.\n", type2);
+ break;
+ }
+ if (sd->state.lr_flag != 2)
+ pc_bonus_subele(sd, (unsigned char)type2, type3, val);
+ break;
+ case SP_SP_VANISH_RATE:
+ if(sd->state.lr_flag != 2) {
+ sd->bonus.sp_vanish_rate += type2;
+ sd->bonus.sp_vanish_per = max(sd->bonus.sp_vanish_per,type3);
+ sd->bonus.sp_vanish_trigger=val;
+ }
break;
- }
- if (sd->state.lr_flag != 2)
- pc_bonus_subele(sd, (unsigned char)type2, type3, val);
- break;
- default:
- ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val);
- break;
+ default:
+ ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val);
+ break;
}
return 0;
}
-int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val)
-{
+int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val) {
nullpo_ret(sd);
- switch(type){
+ switch(type) {
case SP_AUTOSPELL:
if(sd->state.lr_flag != 2)
- pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, 0, current_equip_card_id);
+ pc->bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, 0, status->current_equip_card_id);
break;
case SP_AUTOSPELL_WHENHIT:
if(sd->state.lr_flag != 2)
- pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, BF_NORMAL|BF_SKILL, current_equip_card_id);
+ pc->bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, BF_NORMAL|BF_SKILL, status->current_equip_card_id);
break;
case SP_AUTOSPELL_ONSKILL:
- if(sd->state.lr_flag != 2)
- {
+ if(sd->state.lr_flag != 2) {
int target = skill->get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill->get_inf2(type2)&INF2_NO_TARGET_SELF));
- pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, target?-type3:type3, type4, val, current_equip_card_id);
+ pc->bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, target?-type3:type3, type4, val, status->current_equip_card_id);
}
break;
case SP_ADDEFF_ONSKILL:
if( type2 > SC_MAX ) {
- ShowWarning("pc_bonus3 (Add Effect on skill): %d is not supported.\n", type2);
+ ShowWarning("pc_bonus4 (Add Effect on skill): %d is not supported.\n", type2);
break;
}
if( sd->state.lr_flag != 2 )
- pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, type4, type2, val);
+ pc->bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, type4, type2, val);
+ break;
+
+ case SP_SET_DEF_RACE: //bonus4 bSetDefRace,n,x,r,y;
+ if( type2 > RC_MAX ) {
+ ShowWarning("pc_bonus4 (DEF_SET): %d is not supported.\n", type2);
+ break;
+ }
+ if(sd->state.lr_flag == 2)
+ break;
+ sd->def_set_race[type2].rate = type3;
+ sd->def_set_race[type2].tick = type4;
+ sd->def_set_race[type2].value = val;
+ break;
+
+ case SP_SET_MDEF_RACE: //bonus4 bSetMDefRace,n,x,r,y;
+ if( type2 > RC_MAX ) {
+ ShowWarning("pc_bonus4 (MDEF_SET): %d is not supported.\n", type2);
+ break;
+ }
+ if(sd->state.lr_flag == 2)
+ break;
+ sd->mdef_set_race[type2].rate = type3;
+ sd->mdef_set_race[type2].tick = type4;
+ sd->mdef_set_race[type2].value = val;
break;
default:
@@ -3413,29 +3516,28 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4
return 0;
}
-int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4,int type5,int val)
-{
+int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4,int type5,int val) {
nullpo_ret(sd);
switch(type){
- case SP_AUTOSPELL:
- if(sd->state.lr_flag != 2)
- pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id);
- break;
+ case SP_AUTOSPELL:
+ if(sd->state.lr_flag != 2)
+ pc->bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, status->current_equip_card_id);
+ break;
- case SP_AUTOSPELL_WHENHIT:
- if(sd->state.lr_flag != 2)
- pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id);
- break;
+ case SP_AUTOSPELL_WHENHIT:
+ if(sd->state.lr_flag != 2)
+ pc->bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, status->current_equip_card_id);
+ break;
- case SP_AUTOSPELL_ONSKILL:
- if(sd->state.lr_flag != 2)
- pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, (val&1?-type3:type3), (val&2?-type4:type4), type5, current_equip_card_id);
- break;
+ case SP_AUTOSPELL_ONSKILL:
+ if(sd->state.lr_flag != 2)
+ pc->bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, (val&1?-type3:type3), (val&2?-type4:type4), type5, status->current_equip_card_id);
+ break;
- default:
- ShowWarning("pc_bonus5: unknown type %d %d %d %d %d %d!\n",type,type2,type3,type4,type5,val);
- break;
+ default:
+ ShowWarning("pc_bonus5: unknown type %d %d %d %d %d %d!\n",type,type2,type3,type4,type5,val);
+ break;
}
return 0;
@@ -3452,7 +3554,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) {
uint16 index = 0;
nullpo_ret(sd);
- if( !(index = skill->get_index(id)) || skill_db[index].name == NULL) {
+ if( !(index = skill->get_index(id)) || skill->db[index].name == NULL) {
ShowError("pc_skill: Skill with id %d does not exist in the skill database\n", id);
return 0;
}
@@ -3475,8 +3577,8 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) {
clif->deleteskill(sd,id);
} else
clif->addskill(sd,id);
- if( !skill_db[index].inf ) //Only recalculate for passive skills.
- status_calc_pc(sd, 0);
+ if( !skill->db[index].inf ) //Only recalculate for passive skills.
+ status_calc_pc(sd, SCO_NONE);
break;
case 1: //Item bonus skill.
if( sd->status.skill[index].id == id ) {
@@ -3509,8 +3611,8 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) {
clif->deleteskill(sd,id);
} else
clif->addskill(sd,id);
- if( !skill_db[index].inf ) //Only recalculate for passive skills.
- status_calc_pc(sd, 0);
+ if( !skill->db[index].inf ) //Only recalculate for passive skills.
+ status_calc_pc(sd, SCO_NONE);
break;
default: //Unknown flag?
return 0;
@@ -3579,13 +3681,12 @@ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip)
/*==========================================
* Update buying value by skills
*------------------------------------------*/
-int pc_modifybuyvalue(struct map_session_data *sd,int orig_value)
-{
- int skill,val = orig_value,rate1 = 0,rate2 = 0;
- if((skill=pc->checkskill(sd,MC_DISCOUNT))>0) // merchant discount
- rate1 = 5+skill*2-((skill==10)? 1:0);
- if((skill=pc->checkskill(sd,RG_COMPULSION))>0) // rogue discount
- rate2 = 5+skill*4;
+int pc_modifybuyvalue(struct map_session_data *sd,int orig_value) {
+ int skill_lv,val = orig_value,rate1 = 0,rate2 = 0;
+ if((skill_lv=pc->checkskill(sd,MC_DISCOUNT))>0) // merchant discount
+ rate1 = 5+skill_lv*2-((skill_lv==10)? 1:0);
+ if((skill_lv=pc->checkskill(sd,RG_COMPULSION))>0) // rogue discount
+ rate2 = 5+skill_lv*4;
if(rate1 < rate2) rate1 = rate2;
if(rate1)
val = (int)((double)orig_value*(double)(100-rate1)/100.);
@@ -3598,11 +3699,10 @@ int pc_modifybuyvalue(struct map_session_data *sd,int orig_value)
/*==========================================
* Update selling value by skills
*------------------------------------------*/
-int pc_modifysellvalue(struct map_session_data *sd,int orig_value)
-{
- int skill,val = orig_value,rate = 0;
- if((skill=pc->checkskill(sd,MC_OVERCHARGE))>0) //OverCharge
- rate = 5+skill*2-((skill==10)? 1:0);
+int pc_modifysellvalue(struct map_session_data *sd,int orig_value) {
+ int skill_lv,val = orig_value,rate = 0;
+ if((skill_lv=pc->checkskill(sd,MC_OVERCHARGE))>0) //OverCharge
+ rate = 5+skill_lv*2-((skill_lv==10)? 1:0);
if(rate)
val = (int)((double)orig_value*(double)(100+rate)/100.);
if(val < 0) val = 0;
@@ -3625,9 +3725,9 @@ int pc_checkadditem(struct map_session_data *sd,int nameid,int amount)
if(amount > MAX_AMOUNT)
return ADDITEM_OVERAMOUNT;
- data = itemdb_search(nameid);
+ data = itemdb->search(nameid);
- if(!itemdb_isstackable2(data))
+ if(!itemdb->isstackable2(data))
return ADDITEM_NEW;
if( data->stack.inventory && amount > data->stack.amount )
@@ -3688,7 +3788,7 @@ int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
if( zeny > 0 && sd->state.showzeny ) {
char output[255];
sprintf(output, "Removed %dz.", zeny);
- clif->disp_onlyself(sd,output,strlen(output));
+ clif_disp_onlyself(sd,output,strlen(output));
}
return 0;
@@ -3723,14 +3823,14 @@ int pc_paycash(struct map_session_data *sd, int price, int points)
return -1;
}
- pc_setaccountreg(sd, "#CASHPOINTS", sd->cashPoints-cash);
- pc_setaccountreg(sd, "#KAFRAPOINTS", sd->kafraPoints-points);
+ pc_setaccountreg(sd, script->add_str("#CASHPOINTS"), sd->cashPoints-cash);
+ pc_setaccountreg(sd, script->add_str("#KAFRAPOINTS"), sd->kafraPoints-points);
if( battle_config.cashshop_show_points )
{
char output[128];
sprintf(output, msg_txt(504), points, cash, sd->kafraPoints, sd->cashPoints);
- clif->disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
}
return cash+points;
}
@@ -3750,12 +3850,12 @@ int pc_getcash(struct map_session_data *sd, int cash, int points)
cash = MAX_ZENY-sd->cashPoints;
}
- pc_setaccountreg(sd, "#CASHPOINTS", sd->cashPoints+cash);
+ pc_setaccountreg(sd, script->add_str("#CASHPOINTS"), sd->cashPoints+cash);
if( battle_config.cashshop_show_points )
{
sprintf(output, msg_txt(505), cash, sd->cashPoints);
- clif->disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
}
return cash;
}
@@ -3773,12 +3873,12 @@ int pc_getcash(struct map_session_data *sd, int cash, int points)
points = MAX_ZENY-sd->kafraPoints;
}
- pc_setaccountreg(sd, "#KAFRAPOINTS", sd->kafraPoints+points);
+ pc_setaccountreg(sd, script->add_str("#KAFRAPOINTS"), sd->kafraPoints+points);
if( battle_config.cashshop_show_points )
{
sprintf(output, msg_txt(506), points, sd->kafraPoints);
- clif->disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
}
return points;
}
@@ -3816,22 +3916,29 @@ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
if( zeny > 0 && sd->state.showzeny ) {
char output[255];
sprintf(output, "Gained %dz.", zeny);
- clif->disp_onlyself(sd,output,strlen(output));
+ clif_disp_onlyself(sd,output,strlen(output));
}
return 0;
}
-/*==========================================
- * Searching a specified itemid in inventory and return his stored index
- *------------------------------------------*/
-int pc_search_inventory(struct map_session_data *sd,int item_id)
-{
+/**
+ * Searches for the specified item ID in inventory and return its inventory index.
+ *
+ * If the item is found, the returned value is guaranteed to be a valid index
+ * (non-negative, smaller than MAX_INVENTORY).
+ *
+ * @param sd Character to search on.
+ * @param item_id The item ID to search.
+ * @return the inventory index of the first instance of the requested item.
+ * @retval INDEX_NOT_FOUND if the item wasn't found.
+ */
+int pc_search_inventory(struct map_session_data *sd, int item_id) {
int i;
- nullpo_retr(-1, sd);
+ nullpo_retr(INDEX_NOT_FOUND, sd);
ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == item_id && (sd->status.inventory[i].amount > 0 || item_id == 0) );
- return ( i < MAX_INVENTORY ) ? i : -1;
+ return ( i < MAX_INVENTORY ) ? i : INDEX_NOT_FOUND;
}
/*==========================================
@@ -3840,11 +3947,11 @@ int pc_search_inventory(struct map_session_data *sd,int item_id)
0 = success
1 = invalid itemid not found or negative amount
2 = overweight
- 3 = ?
+ 3 = ?
4 = no free place found
5 = max amount reached
- 6 = ?
- 7 = stack limitation
+ 6 = ?
+ 7 = stack limitation
*------------------------------------------*/
int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type)
{
@@ -3860,7 +3967,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
if( amount > MAX_AMOUNT )
return 5;
- data = itemdb_search(item_data->nameid);
+ data = itemdb->search(item_data->nameid);
if( data->stack.inventory && amount > data->stack.amount )
{// item stack limitation
@@ -3871,14 +3978,37 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
if(sd->weight + w > sd->max_weight)
return 2;
+ if( item_data->bound ) {
+ switch( (enum e_item_bound_type)item_data->bound ) {
+ case IBT_CHARACTER:
+ case IBT_ACCOUNT:
+ break; /* no restrictions */
+ case IBT_PARTY:
+ if( !sd->status.party_id ) {
+ ShowError("pc_additem: can't add party_bound item to character without party!\n");
+ ShowError("pc_additem: %s - x%d %s (%d)\n",sd->status.name,amount,data->jname,data->nameid);
+ return 7;/* need proper code? */
+ }
+ break;
+ case IBT_GUILD:
+ if( !sd->status.guild_id ) {
+ ShowError("pc_additem: can't add guild_bound item to character without guild!\n");
+ ShowError("pc_additem: %s - x%d %s (%d)\n",sd->status.name,amount,data->jname,data->nameid);
+ return 7;/* need proper code? */
+ }
+ break;
+ }
+ }
+
i = MAX_INVENTORY;
- if( itemdb_isstackable2(data) && item_data->expire_time == 0 )
- { // Stackable | Non Rental
- for( i = 0; i < MAX_INVENTORY; i++ )
- {
- if( sd->status.inventory[i].nameid == item_data->nameid && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 )
- {
+ // Stackable | Non Rental
+ if( itemdb->isstackable2(data) && item_data->expire_time == 0 ) {
+ for( i = 0; i < MAX_INVENTORY; i++ ) {
+ if( sd->status.inventory[i].nameid == item_data->nameid &&
+ sd->status.inventory[i].bound == item_data->bound &&
+ sd->status.inventory[i].expire_time == 0 &&
+ memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 ) {
if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) )
return 5;
sd->status.inventory[i].amount += amount;
@@ -3888,25 +4018,26 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
}
}
- if( i >= MAX_INVENTORY )
- {
+ if ( i >= MAX_INVENTORY ) {
i = pc->search_inventory(sd,0);
- if( i < 0 )
+ if (i == INDEX_NOT_FOUND)
return 4;
memcpy(&sd->status.inventory[i], item_data, sizeof(sd->status.inventory[0]));
- // clear equips field first, just in case
+ // clear equip and favorite fields first, just in case
if( item_data->equip )
sd->status.inventory[i].equip = 0;
+ if( item_data->favorite )
+ sd->status.inventory[i].favorite = 0;
sd->status.inventory[i].amount = amount;
sd->inventory_data[i] = data;
clif->additem(sd,i,amount,0);
}
-#ifdef NSI_UNIQUE_ID
- if( !itemdb_isstackable2(data) && !item_data->unique_id )
- sd->status.inventory[i].unique_id = itemdb_unique_id(0,0);
-#endif
+
+ if( !itemdb->isstackable2(data) && !item_data->unique_id )
+ sd->status.inventory[i].unique_id = itemdb->unique_id(sd);
+
logs->pick_pc(sd, log_type, amount, &sd->status.inventory[i],sd->inventory_data[i]);
sd->weight += w;
@@ -3918,8 +4049,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
/* rental item check */
if( item_data->expire_time ) {
if( time(NULL) > item_data->expire_time ) {
- clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid);
- pc->delitem(sd, i, sd->status.inventory[i].amount, 1, 0, LOG_TYPE_OTHER);
+ pc->rental_expire(sd,i);
} else {
int seconds = (int)( item_data->expire_time - time(NULL) );
clif->rental_time(sd->fd, sd->status.inventory[i].nameid, seconds);
@@ -3989,8 +4119,7 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount)
)
return 0;
- if( map[sd->bl.m].flag.nodrop )
- {
+ if( map->list[sd->bl.m].flag.nodrop ) {
clif->message (sd->fd, msg_txt(271));
return 0; //Can't drop items in nodrop mapflag maps.
}
@@ -4001,7 +4130,7 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount)
return 0;
}
- if (!iMap->addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 2))
+ if (!map->addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 2))
return 0;
pc->delitem(sd, n, amount, 1, 0, LOG_TYPE_PICKDROP_PLAYER);
@@ -4018,7 +4147,7 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount)
int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
{
int flag=0;
- unsigned int tick = iTimer->gettick();
+ int64 tick = timer->gettick();
struct map_session_data *first_sd = NULL,*second_sd = NULL,*third_sd = NULL;
struct party_data *p=NULL;
@@ -4031,9 +4160,8 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
if (sd->status.party_id)
p = party->search(sd->status.party_id);
- if(fitem->first_get_charid > 0 && fitem->first_get_charid != sd->status.char_id)
- {
- first_sd = iMap->charid2sd(fitem->first_get_charid);
+ if(fitem->first_get_charid > 0 && fitem->first_get_charid != sd->status.char_id) {
+ first_sd = map->charid2sd(fitem->first_get_charid);
if(DIFF_TICK(tick,fitem->first_get_tick) < 0) {
if (!(p && p->party.item&1 &&
first_sd && first_sd->status.party_id == sd->status.party_id
@@ -4041,9 +4169,8 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
return 0;
}
else
- if(fitem->second_get_charid > 0 && fitem->second_get_charid != sd->status.char_id)
- {
- second_sd = iMap->charid2sd(fitem->second_get_charid);
+ if(fitem->second_get_charid > 0 && fitem->second_get_charid != sd->status.char_id) {
+ second_sd = map->charid2sd(fitem->second_get_charid);
if(DIFF_TICK(tick, fitem->second_get_tick) < 0) {
if(!(p && p->party.item&1 &&
((first_sd && first_sd->status.party_id == sd->status.party_id) ||
@@ -4052,9 +4179,8 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
return 0;
}
else
- if(fitem->third_get_charid > 0 && fitem->third_get_charid != sd->status.char_id)
- {
- third_sd = iMap->charid2sd(fitem->third_get_charid);
+ if(fitem->third_get_charid > 0 && fitem->third_get_charid != sd->status.char_id) {
+ third_sd = map->charid2sd(fitem->third_get_charid);
if(DIFF_TICK(tick,fitem->third_get_tick) < 0) {
if(!(p && p->party.item&1 &&
((first_sd && first_sd->status.party_id == sd->status.party_id) ||
@@ -4076,7 +4202,7 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
//Display pickup animation.
pc_stop_attack(sd);
clif->takeitem(&sd->bl,&fitem->bl);
- iMap->clearflooritem(&fitem->bl);
+ map->clearflooritem(&fitem->bl);
return 1;
}
@@ -4104,96 +4230,97 @@ int pc_isUseitem(struct map_session_data *sd,int n)
if( !item->script ) //if it has no script, you can't really consume it!
return 0;
- if( (item->item_usage.flag&NOUSE_SITTING) && (pc_issit(sd) == 1) && (pc->get_group_level(sd) < item->item_usage.override) ) {
- clif->msgtable(sd->fd,664);
+ if( (item->item_usage.flag&INR_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override) ) {
+ clif->msgtable(sd->fd,0x297);
//clif->colormes(sd->fd,COLOR_WHITE,msg_txt(1474));
return 0; // You cannot use this item while sitting.
}
- switch( nameid ) //@TODO, lot oh harcoded nameid here
- {
- case 605: // Anodyne
- if( map_flag_gvg(sd->bl.m) )
+ if (sd->state.storage_flag && item->type != IT_CASH) {
+ clif->colormes(sd->fd, COLOR_RED, msg_txt(1475));
+ return 0; // You cannot use this item while storage is open.
+ }
+
+ switch( nameid ) { // TODO: Is there no better way to handle this, other than hardcoding item IDs?
+ case ITEMID_ANODYNE:
+ if( map_flag_gvg2(sd->bl.m) )
return 0;
- case 606:
+ case ITEMID_ALOEBERA:
if( pc_issit(sd) )
return 0;
break;
- case 601: // Fly Wing
- case 12212: // Giant Fly Wing
- if( map[sd->bl.m].flag.noteleport || map_flag_gvg(sd->bl.m) )
- {
+ case ITEMID_WING_OF_FLY:
+ case ITEMID_GIANT_FLY_WING:
+ if( map->list[sd->bl.m].flag.noteleport || map_flag_gvg2(sd->bl.m) ) {
clif->skill_mapinfomessage(sd,0);
return 0;
}
- case 602: // ButterFly Wing
- case 14527: // Dungeon Teleport Scroll
- case 14581: // Dungeon Teleport Scroll
- case 14582: // Yellow Butterfly Wing
- case 14583: // Green Butterfly Wing
- case 14584: // Red Butterfly Wing
- case 14585: // Blue Butterfly Wing
- case 14591: // Siege Teleport Scroll
- if( sd->duel_group && !battle_config.duel_allow_teleport )
- {
- clif->message(sd->fd, msg_txt(663));
+ case ITEMID_WING_OF_BUTTERFLY:
+ case ITEMID_DUN_TELE_SCROLL1:
+ case ITEMID_DUN_TELE_SCROLL2:
+ case ITEMID_WOB_RUNE: // Yellow Butterfly Wing
+ case ITEMID_WOB_SCHWALTZ: // Green Butterfly Wing
+ case ITEMID_WOB_RACHEL: // Red Butterfly Wing
+ case ITEMID_WOB_LOCAL: // Blue Butterfly Wing
+ case ITEMID_SIEGE_TELEPORT_SCROLL:
+ if( sd->duel_group && !battle_config.duel_allow_teleport ) {
+ clif->message(sd->fd, msg_txt(863)); // "Duel: Can't use this item in duel."
return 0;
}
- if( nameid != 601 && nameid != 12212 && map[sd->bl.m].flag.noreturn )
+ if( nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && map->list[sd->bl.m].flag.noreturn )
return 0;
break;
- case 604: // Dead Branch
- case 12024: // Red Pouch
- case 12103: // Bloody Branch
- case 12109: // Poring Box
- if( map[sd->bl.m].flag.nobranch || map_flag_gvg(sd->bl.m) )
+ case ITEMID_BRANCH_OF_DEAD_TREE:
+ case ITEMID_RED_POUCH_OF_SURPRISE:
+ case ITEMID_BLOODY_DEAD_BRANCH:
+ case ITEMID_PORING_BOX:
+ if( map->list[sd->bl.m].flag.nobranch || map_flag_gvg2(sd->bl.m) )
return 0;
break;
- case 12210: // Bubble Gum
- case 12264: // Comp Bubble Gum
+ case ITEMID_BUBBLE_GUM:
+ case ITEMID_COMP_BUBBLE_GUM:
if( sd->sc.data[SC_CASH_RECEIVEITEM] )
return 0;
break;
- case 12208: // Battle Manual
- case 12263: // Comp Battle Manual
- case 12312: // Thick Battle Manual
- case 12705: // Noble Nameplate
- case 14532: // Battle_Manual25
- case 14533: // Battle_Manual100
- case 14545: // Battle_Manual300
+ case ITEMID_BATTLE_MANUAL:
+ case ITEMID_COMP_BATTLE_MANUAL:
+ case ITEMID_THICK_MANUAL50:
+ case ITEMID_NOBLE_NAMEPLATE:
+ case ITEMID_BATTLE_MANUAL25:
+ case ITEMIDBATTLE_MANUAL100:
+ case ITEMID_BATTLE_MANUAL_X3:
if( sd->sc.data[SC_CASH_PLUSEXP] )
return 0;
break;
- case 14592: // JOB_Battle_Manual
+ case ITEMID_JOB_MANUAL50:
if( sd->sc.data[SC_CASH_PLUSONLYJOBEXP] )
return 0;
break;
// Mercenary Items
-
- case 12184: // Mercenary's Red Potion
- case 12185: // Mercenary's Blue Potion
- case 12241: // Mercenary's Concentration Potion
- case 12242: // Mercenary's Awakening Potion
- case 12243: // Mercenary's Berserk Potion
+ case ITEMID_MERCENARY_RED_POTION:
+ case ITEMID_MERCENARY_BLUE_POTION:
+ case ITEMID_M_CENTER_POTION:
+ case ITEMID_M_AWAKENING_POTION:
+ case ITEMID_M_BERSERK_POTION:
if( sd->md == NULL || sd->md->db == NULL )
return 0;
- if (sd->md->sc.data[SC_BERSERK] || sd->md->sc.data[SC_SATURDAY_NIGHT_FEVER] || sd->md->sc.data[SC__BLOODYLUST])
+ if (sd->md->sc.data[SC_BERSERK])
return 0;
- if( nameid == 12242 && sd->md->db->lv < 40 )
+ if( nameid == ITEMID_M_AWAKENING_POTION && sd->md->db->lv < 40 )
return 0;
- if( nameid == 12243 && sd->md->db->lv < 80 )
+ if( nameid == ITEMID_M_BERSERK_POTION && sd->md->db->lv < 80 )
return 0;
break;
- case 12213: //Neuralizer
- if( !map[sd->bl.m].flag.reset )
+ case ITEMID_NEURALIZER:
+ if( !map->list[sd->bl.m].flag.reset )
return 0;
break;
}
- if( nameid >= 12153 && nameid <= 12182 && sd->md != NULL )
- return 0; // Mercenary Scrolls
+ if( nameid >= ITEMID_BOW_MERCENARY_SCROLL1 && nameid <= ITEMID_SPEARMERCENARY_SCROLL10 && sd->md != NULL ) // Mercenary Scrolls
+ return 0;
/**
* Only Rune Knights may use runes
@@ -4206,17 +4333,30 @@ int pc_isUseitem(struct map_session_data *sd,int n)
else if( itemdb_is_poison(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_GUILLOTINE_CROSS )
return 0;
+ if( item->package || item->group ) {
+ if( pc_is90overweight(sd) ) {
+ clif->msgtable(sd->fd,ITEM_CANT_OBTAIN_WEIGHT);
+ return 0;
+ }
+ if( !pc->inventoryblank(sd) ) {
+ clif->colormes(sd->fd,COLOR_RED,msg_txt(1477));
+ return 0;
+ }
+ }
+
//Gender check
if(item->sex != 2 && sd->status.sex != item->sex)
return 0;
//Required level check
- if(item->elv && sd->status.base_level < (unsigned int)item->elv)
+ if(item->elv && sd->status.base_level < (unsigned int)item->elv){
+ clif->msg(sd, 0x6EE);
return 0;
+ }
-#ifdef RENEWAL
- if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax)
+ if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax){
+ clif->msg(sd, 0x6EE);
return 0;
-#endif
+ }
//Not equipable by class. [Skotlex]
if (!(
@@ -4224,20 +4364,29 @@ int pc_isUseitem(struct map_session_data *sd,int n)
(item->class_base[sd->class_&JOBL_2_1?1:(sd->class_&JOBL_2_2?2:0)])
))
return 0;
- //Not usable by upper class. [Inkfish]
+
+ //Not usable by upper class. [Haru]
while( 1 ) {
- if( item->class_upper&1 && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
- if( item->class_upper&2 && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
- if( item->class_upper&4 && sd->class_&JOBL_BABY ) break;
- if( item->class_upper&8 && sd->class_&JOBL_THIRD ) break;
+ // Normal classes (no upper, no baby, no third classes)
+ if( item->class_upper&ITEMUPPER_NORMAL && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
+#ifdef RENEWAL
+ // Upper classes (no third classes)
+ if( item->class_upper&ITEMUPPER_UPPER && sd->class_&JOBL_UPPER && !(sd->class_&JOBL_THIRD) ) break;
+#else
+ //pre-re has no use for the extra, so we maintain the previous for backwards compatibility
+ if( item->class_upper&ITEMUPPER_UPPER && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
+#endif
+ // Baby classes (no third classes)
+ if( item->class_upper&ITEMUPPER_BABY && sd->class_&JOBL_BABY && !(sd->class_&JOBL_THIRD) ) break;
+ // Third classes (no upper, no baby classes)
+ if( item->class_upper&ITEMUPPER_THIRD && sd->class_&JOBL_THIRD && !(sd->class_&(JOBL_UPPER|JOBL_BABY)) ) break;
+ // Upper third classes
+ if( item->class_upper&ITEMUPPER_THURDUPPER && sd->class_&JOBL_THIRD && sd->class_&JOBL_UPPER ) break;
+ // Baby third classes
+ if( item->class_upper&ITEMUPPER_THIRDBABY && sd->class_&JOBL_THIRD && sd->class_&JOBL_BABY ) break;
return 0;
}
- //Dead Branch & Bloody Branch & Porings Box
- // FIXME: outdated, use constants or database
- if( nameid == 604 || nameid == 12103 || nameid == 12109 )
- logs->branch(sd);
-
return 1;
}
@@ -4247,11 +4396,10 @@ int pc_isUseitem(struct map_session_data *sd,int n)
* 0 = fail
* 1 = success
*------------------------------------------*/
-int pc_useitem(struct map_session_data *sd,int n)
-{
- unsigned int tick = iTimer->gettick();
+int pc_useitem(struct map_session_data *sd,int n) {
+ int64 tick = timer->gettick();
int amount, nameid, i;
- struct script_code *script;
+ struct script_code *item_script;
nullpo_ret(sd);
@@ -4266,7 +4414,7 @@ int pc_useitem(struct map_session_data *sd,int n)
if( sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0 )
return 0;
- if( !pc_isUseitem(sd,n) )
+ if( !pc->isUseitem(sd,n) )
return 0;
// Store information for later use before it is lost (via pc->delitem) [Paradox924X]
@@ -4275,15 +4423,20 @@ int pc_useitem(struct map_session_data *sd,int n)
if (nameid != ITEMID_NAUTHIZ && sd->sc.opt1 > 0 && sd->sc.opt1 != OPT1_STONEWAIT && sd->sc.opt1 != OPT1_BURNING)
return 0;
+ // Statuses that don't let the player use items
if (sd->sc.count && (
- sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] ||
+ sd->sc.data[SC_BERSERK] ||
(sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) ||
sd->sc.data[SC_TRICKDEAD] ||
sd->sc.data[SC_HIDING] ||
sd->sc.data[SC__SHADOWFORM] ||
+ sd->sc.data[SC__INVISIBILITY] ||
sd->sc.data[SC__MANHOLE] ||
sd->sc.data[SC_KG_KAGEHUMI] ||
sd->sc.data[SC_WHITEIMPRISON] ||
+ sd->sc.data[SC_DEEP_SLEEP] ||
+ sd->sc.data[SC_SATURDAY_NIGHT_FEVER] ||
+ sd->sc.data[SC_COLD] ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM)
))
return 0;
@@ -4305,18 +4458,17 @@ int pc_useitem(struct map_session_data *sd,int n)
//perform a skill-use check before going through. [Skotlex]
//resurrection was picked as testing skill, as a non-offensive, generic skill, it will do.
//FIXME: Is this really needed here? It'll be checked in unit.c after all and this prevents skill items using when silenced [Inkfish]
- if( sd->inventory_data[n]->flag.delay_consume && ( sd->ud.skilltimer != INVALID_TIMER /*|| !status_check_skilluse(&sd->bl, &sd->bl, ALL_RESURRECTION, 0)*/ ) )
+ if( sd->inventory_data[n]->flag.delay_consume && ( sd->ud.skilltimer != INVALID_TIMER /*|| !status->check_skilluse(&sd->bl, &sd->bl, ALL_RESURRECTION, 0)*/ ) )
return 0;
if( sd->inventory_data[n]->delay > 0 ) {
- int i;
ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == nameid );
if( i == MAX_ITEMDELAYS ) /* item not found. try first empty now */
ARR_FIND(0, MAX_ITEMDELAYS, i, !sd->item_delay[i].nameid );
if( i < MAX_ITEMDELAYS ) {
if( sd->item_delay[i].nameid ) {// found
if( DIFF_TICK(sd->item_delay[i].tick, tick) > 0 ) {
- int e_tick = DIFF_TICK(sd->item_delay[i].tick, tick)/1000;
+ int e_tick = (int)(DIFF_TICK(sd->item_delay[i].tick, tick)/1000);
clif->msgtable_num(sd->fd, 0x746, e_tick + 1); // [%d] seconds left until you can use
return 0; // Delay has not expired yet
}
@@ -4337,10 +4489,11 @@ int pc_useitem(struct map_session_data *sd,int n)
}
}
- /* on restricted maps the item is consumed but the effect is not used */
- for(i = 0; i < map[sd->bl.m].zone->disabled_items_count; i++) {
- if( map[sd->bl.m].zone->disabled_items[i] == nameid ) {
- if( battle_config.item_restricted_consumption_type ) {
+ /* on restricted maps the item is consumed but the effect is not used */
+ for(i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++) {
+ if( map->list[sd->bl.m].zone->disabled_items[i] == nameid ) {
+ clif->msg(sd, ITEM_CANT_USE_AREA); // This item cannot be used within this area
+ if( battle_config.item_restricted_consumption_type && sd->status.inventory[n].expire_time == 0 ) {
clif->useitemack(sd,n,sd->status.inventory[n].amount-1,true);
pc->delitem(sd,n,1,1,0,LOG_TYPE_CONSUME);
}
@@ -4348,13 +4501,17 @@ int pc_useitem(struct map_session_data *sd,int n)
}
}
+ //Dead Branch & Bloody Branch & Porings Box
+ if( nameid == ITEMID_BRANCH_OF_DEAD_TREE || nameid == ITEMID_BLOODY_DEAD_BRANCH || nameid == ITEMID_PORING_BOX )
+ logs->branch(sd);
+
sd->itemid = sd->status.inventory[n].nameid;
sd->itemindex = n;
if(sd->catch_target_class != -1) //Abort pet catching.
sd->catch_target_class = -1;
amount = sd->status.inventory[n].amount;
- script = sd->inventory_data[n]->script;
+ item_script = sd->inventory_data[n]->script;
//Check if the item is to be consumed immediately [Skotlex]
if( sd->inventory_data[n]->flag.delay_consume )
clif->useitemack(sd,n,amount,true);
@@ -4368,18 +4525,23 @@ int pc_useitem(struct map_session_data *sd,int n)
if(sd->status.inventory[n].card[0]==CARD0_CREATE &&
pc->famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST))
{
- potion_flag = 2; // Famous player's potions have 50% more efficiency
+ script->potion_flag = 2; // Famous player's potions have 50% more efficiency
if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_ROGUE)
- potion_flag = 3; //Even more effective potions.
+ script->potion_flag = 3; //Even more effective potions.
}
//Update item use time.
sd->canuseitem_tick = tick + battle_config.item_use_interval;
if( itemdb_iscashfood(nameid) )
sd->canusecashfood_tick = tick + battle_config.cashfood_use_interval;
-
- run_script(script,0,sd->bl.id,fake_nd->bl.id);
- potion_flag = 0;
+
+ script->current_item_id = nameid;
+
+ script->run(item_script,0,sd->bl.id,npc->fake_nd->bl.id);
+
+ script->current_item_id = 0;
+ script->potion_flag = 0;
+
return 1;
}
@@ -4399,35 +4561,35 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
if(item_data->nameid <= 0 || amount <= 0)
return 1;
- data = itemdb_search(item_data->nameid);
+ data = itemdb->search(item_data->nameid);
if( data->stack.cart && amount > data->stack.amount )
{// item stack limitation
return 1;
}
- if( !itemdb_cancartstore(item_data, pc->get_group_level(sd)) )
- { // Check item trade restrictions [Skotlex]
+ if( !itemdb_cancartstore(item_data, pc_get_group_level(sd)) || (item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd)))
+ { // Check item trade restrictions [Skotlex]
clif->message (sd->fd, msg_txt(264));
- return 1;
+ return 1;/* TODO: there is no official response to this? */
}
if( (w = data->weight*amount) + sd->cart_weight > sd->cart_weight_max )
return 1;
i = MAX_CART;
- if( itemdb_isstackable2(data) && !item_data->expire_time )
+ if( itemdb->isstackable2(data) && !item_data->expire_time )
{
ARR_FIND( 0, MAX_CART, i,
- sd->status.cart[i].nameid == item_data->nameid &&
- sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] &&
+ sd->status.cart[i].nameid == item_data->nameid && sd->status.cart[i].bound == item_data->bound &&
+ sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] &&
sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3] );
};
if( i < MAX_CART )
{// item already in cart, stack it
if( amount > MAX_AMOUNT - sd->status.cart[i].amount || ( data->stack.cart && amount > data->stack.amount - sd->status.cart[i].amount ) )
- return 1; // no room
+ return 2; // no room
sd->status.cart[i].amount+=amount;
clif->cart_additem(sd,i,amount,0);
@@ -4436,7 +4598,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
{// item not stackable or not present, add it
ARR_FIND( 0, MAX_CART, i, sd->status.cart[i].nameid == 0 );
if( i == MAX_CART )
- return 1; // no room
+ return 2; // no room
memcpy(&sd->status.cart[i],item_data,sizeof(sd->status.cart[0]));
sd->status.cart[i].amount=amount;
@@ -4462,7 +4624,7 @@ int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_
struct item_data * data;
nullpo_retr(1, sd);
- if( sd->status.cart[n].nameid == 0 || sd->status.cart[n].amount < amount || !(data = itemdb_exists(sd->status.cart[n].nameid)) )
+ if( sd->status.cart[n].nameid == 0 || sd->status.cart[n].amount < amount || !(data = itemdb->exists(sd->status.cart[n].nameid)) )
return 1;
logs->pick_pc(sd, log_type, -amount, &sd->status.cart[n],data);
@@ -4490,6 +4652,7 @@ int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_
int pc_putitemtocart(struct map_session_data *sd,int idx,int amount)
{
struct item *item_data;
+ int flag;
nullpo_ret(sd);
@@ -4501,10 +4664,10 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount)
if( item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending )
return 1;
- if( pc->cart_additem(sd,item_data,amount,LOG_TYPE_NONE) == 0 )
+ if( (flag = pc->cart_additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0 )
return pc->delitem(sd,idx,amount,0,5,LOG_TYPE_NONE);
- return 1;
+ return flag;
}
/*==========================================
@@ -4546,13 +4709,45 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
if(item_data->nameid==0 || amount < 1 || item_data->amount<amount || sd->state.vending )
return 1;
+
if((flag = pc->additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0)
return pc->cart_delitem(sd,idx,amount,0,LOG_TYPE_NONE);
- clif->additem(sd,0,0,flag);
- return 1;
+ return flag;
+}
+void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) {
+ int i;
+
+ switch( type ) {
+ /* both restricted to inventory */
+ case IBT_PARTY:
+ case IBT_CHARACTER:
+ for( i = 0; i < MAX_INVENTORY; i++ ){
+ if( sd->status.inventory[i].bound == type ) {
+ pc->delitem(sd,i,sd->status.inventory[i].amount,0,1,LOG_TYPE_OTHER);
+ }
+ }
+ break;
+ case IBT_ACCOUNT:
+ ShowError("Helllo! You reached pc_bound_clear for IBT_ACCOUNT, unfortunately no scenario was expected for this!\n");
+ break;
+ case IBT_GUILD: {
+ struct guild_storage *gstor = gstorage->id2storage(sd->status.guild_id);
+
+ for( i = 0; i < MAX_INVENTORY; i++ ){
+ if(sd->status.inventory[i].bound == type) {
+ if( gstor )
+ gstorage->additem(sd,gstor,&sd->status.inventory[i],sd->status.inventory[i].amount);
+ pc->delitem(sd,i,sd->status.inventory[i].amount,0,1,gstor?LOG_TYPE_GSTORAGE:LOG_TYPE_OTHER);
+ }
+ }
+ if( gstor )
+ gstorage->close(sd);
+ }
+ break;
+ }
+
}
-
/*==========================================
* Display item stolen msg to player sd
*------------------------------------------*/
@@ -4567,7 +4762,7 @@ int pc_show_steal(struct block_list *bl,va_list ap)
sd=va_arg(ap,struct map_session_data *);
itemid=va_arg(ap,int);
- if((item=itemdb_exists(itemid))==NULL)
+ if((item=itemdb->exists(itemid))==NULL)
sprintf(output,"%s stole an Unknown Item (id: %i).",sd->status.name, itemid);
else
sprintf(output,"%s stole %s.",sd->status.name,item->jname);
@@ -4598,11 +4793,11 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
if(md->state.steal_flag == UCHAR_MAX || ( md->sc.opt1 && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE ) ) //already stolen from / status change check
return 0;
- sd_status= status_get_status_data(&sd->bl);
- md_status= status_get_status_data(bl);
+ sd_status= status->get_status_data(&sd->bl);
+ md_status= status->get_status_data(bl);
if( md->master_id || md_status->mode&MD_BOSS || mob_is_treasure(md) ||
- map[bl->m].flag.nomobloot || // check noloot map flag [Lorky]
+ map->list[bl->m].flag.nomobloot || // check noloot map flag [Lorky]
(battle_config.skill_steal_max_tries && //Reached limit of steal attempts. [Lupus]
md->state.steal_flag++ >= battle_config.skill_steal_max_tries)
) { //Can't steal from
@@ -4620,7 +4815,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
// Try dropping one item, in the order from first to last possible slot.
// Droprate is affected by the skill success rate.
for( i = 0; i < MAX_STEAL_DROP; i++ )
- if( md->db->dropitem[i].nameid > 0 && (data = itemdb_exists(md->db->dropitem[i].nameid)) && rnd() % 10000 < md->db->dropitem[i].p * rate/100. )
+ if( md->db->dropitem[i].nameid > 0 && (data = itemdb->exists(md->db->dropitem[i].nameid)) && rnd() % 10000 < md->db->dropitem[i].p * rate/100. )
break;
if( i == MAX_STEAL_DROP )
return 0;
@@ -4629,7 +4824,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
memset(&tmp_item,0,sizeof(tmp_item));
tmp_item.nameid = itemid;
tmp_item.amount = 1;
- tmp_item.identify = itemdb_isidentified2(data);
+ tmp_item.identify = itemdb->isidentified2(data);
flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER);
//TODO: Should we disable stealing when the item you stole couldn't be added to your inventory? Perhaps players will figure out a way to exploit this behaviour otherwise?
@@ -4641,7 +4836,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
}
if(battle_config.show_steal_in_same_party)
- party_foreachsamemap(pc_show_steal,sd,AREA_SIZE,sd,tmp_item.nameid);
+ party->foreachsamemap(pc->show_steal,sd,AREA_SIZE,sd,tmp_item.nameid);
//Logs items, Stolen from mobs [Lupus]
logs->pick_mob(md, LOG_TYPE_STEAL, -1, &tmp_item, data);
@@ -4651,20 +4846,21 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
char message[128];
sprintf (message, msg_txt(542), (sd->status.name != NULL)?sd->status.name :"GM", md->db->jname, data->jname, (float)md->db->dropitem[i].p/100);
//MSG: "'%s' stole %s's %s (chance: %0.02f%%)"
- intif_broadcast(message,strlen(message)+1,0);
+ intif->broadcast(message, strlen(message)+1, BC_DEFAULT);
}
return 1;
}
-/*==========================================
- * Stole zeny from bl (mob)
- * return
- * 0 = fail
- * 1 = success
- *------------------------------------------*/
-int pc_steal_coin(struct map_session_data *sd,struct block_list *target)
-{
- int rate,skill;
+/**
+ * Steals zeny from a monster through the RG_STEALCOIN skill.
+ *
+ * @param sd Source character
+ * @param target Target monster
+ *
+ * @return Amount of stolen zeny (0 in case of failure)
+ **/
+int pc_steal_coin(struct map_session_data *sd, struct block_list *target) {
+ int rate, skill_lv;
struct mob_data *md;
if(!sd || !target || target->type != BL_MOB)
return 0;
@@ -4676,16 +4872,14 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *target)
if( mob_is_treasure(md) )
return 0;
- // FIXME: This formula is either custom or outdated.
- skill = pc->checkskill(sd,RG_STEALCOIN)*10;
- rate = skill + (sd->status.base_level - md->level)*3 + sd->battle_status.dex*2 + sd->battle_status.luk*2;
- if(rnd()%1000 < rate)
- {
- int amount = md->level*10 + rnd()%100;
+ skill_lv = pc->checkskill(sd, RG_STEALCOIN);
+ rate = skill_lv*10 + (sd->status.base_level - md->level)*2 + sd->battle_status.dex/2 + sd->battle_status.luk/2;
+ if(rnd()%1000 < rate) {
+ int amount = md->level * skill_lv / 10 + md->level*8 + rnd()%(md->level*2 + 1); // mob_lv * skill_lv / 10 + random [mob_lv*8; mob_lv*10]
pc->getzeny(sd, amount, LOG_TYPE_STEAL, NULL);
md->state.steal_coin_flag = 1;
- return 1;
+ return amount;
}
return 0;
}
@@ -4697,13 +4891,13 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *target)
* 1 - Invalid map index.
* 2 - Map not in this map-server, and failed to locate alternate map-server.
*------------------------------------------*/
-int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype) {
+int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int y, clr_type clrtype) {
int16 m;
nullpo_ret(sd);
- if( !mapindex || !mapindex_id2name(mapindex) ) {
- ShowDebug("pc_setpos: Passed mapindex(%d) is invalid!\n", mapindex);
+ if( !map_index || !mapindex_id2name(map_index) || ( m = map->mapindex2mapid(map_index) ) == -1 ) {
+ ShowDebug("pc_setpos: Passed mapindex(%d) is invalid!\n", map_index);
return 1;
}
@@ -4711,53 +4905,68 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
pc->setstand(sd);
pc->setrestartvalue(sd,1);
}
- m = iMap->mapindex2mapid(mapindex);
- if( map[m].flag.src4instance ) {
+ if( map->list[m].flag.src4instance ) {
struct party_data *p;
bool stop = false;
int i = 0, j = 0;
if( sd->instances ) {
for( i = 0; i < sd->instances; i++ ) {
- ARR_FIND(0, instances[sd->instance[i]].num_map, j, map[instances[sd->instance[i]].map[j]].instance_src_map == m && !map[instances[sd->instance[i]].map[j]].cName);
- if( j != instances[sd->instance[i]].num_map )
- break;
+ if( sd->instance[i] >= 0 ) {
+ ARR_FIND(0, instance->list[sd->instance[i]].num_map, j, map->list[instance->list[sd->instance[i]].map[j]].instance_src_map == m && !map->list[instance->list[sd->instance[i]].map[j]].custom_name);
+ if( j != instance->list[sd->instance[i]].num_map )
+ break;
+ }
}
if( i != sd->instances ) {
- m = instances[sd->instance[i]].map[j];
- mapindex = map[m].index;
+ m = instance->list[sd->instance[i]].map[j];
+ map_index = map_id2index(m);
stop = true;
}
}
if ( !stop && sd->status.party_id && (p = party->search(sd->status.party_id)) && p->instances ) {
for( i = 0; i < p->instances; i++ ) {
- ARR_FIND(0, instances[p->instance[i]].num_map, j, map[instances[p->instance[i]].map[j]].instance_src_map == m && !map[instances[p->instance[i]].map[j]].cName);
- if( j != instances[p->instance[i]].num_map )
- break;
+ if( p->instance[i] >= 0 ) {
+ ARR_FIND(0, instance->list[p->instance[i]].num_map, j, map->list[instance->list[p->instance[i]].map[j]].instance_src_map == m && !map->list[instance->list[p->instance[i]].map[j]].custom_name);
+ if( j != instance->list[p->instance[i]].num_map )
+ break;
+ }
}
if( i != p->instances ) {
- m = instances[p->instance[i]].map[j];
- mapindex = map[m].index;
+ m = instance->list[p->instance[i]].map[j];
+ map_index = map_id2index(m);
stop = true;
}
}
if ( !stop && sd->status.guild_id && sd->guild && sd->guild->instances ) {
for( i = 0; i < sd->guild->instances; i++ ) {
- ARR_FIND(0, instances[sd->guild->instance[i]].num_map, j, map[instances[sd->guild->instance[i]].map[j]].instance_src_map == m && !map[instances[sd->guild->instance[i]].map[j]].cName);
- if( j != instances[sd->guild->instance[i]].num_map )
- break;
+ if( sd->guild->instance[i] >= 0 ) {
+ ARR_FIND(0, instance->list[sd->guild->instance[i]].num_map, j, map->list[instance->list[sd->guild->instance[i]].map[j]].instance_src_map == m && !map->list[instance->list[sd->guild->instance[i]].map[j]].custom_name);
+ if( j != instance->list[sd->guild->instance[i]].num_map )
+ break;
+ }
}
if( i != sd->guild->instances ) {
- m = instances[sd->guild->instance[i]].map[j];
- mapindex = map[m].index;
- stop = true;
+ m = instance->list[sd->guild->instance[i]].map[j];
+ map_index = map_id2index(m);
+ //stop = true; Uncomment if adding new checks
}
}
+
+ /* we hit a instance, if empty we populate the spawn data */
+ if( map->list[m].instance_id >= 0 && instance->list[map->list[m].instance_id].respawn.map == 0 &&
+ instance->list[map->list[m].instance_id].respawn.x == 0 &&
+ instance->list[map->list[m].instance_id].respawn.y == 0) {
+ instance->list[map->list[m].instance_id].respawn.map = map_index;
+ instance->list[map->list[m].instance_id].respawn.x = x;
+ instance->list[map->list[m].instance_id].respawn.y = y;
+ }
}
- sd->state.changemap = (sd->mapindex != mapindex);
+ sd->state.changemap = (sd->mapindex != map_index);
sd->state.warping = 1;
+ sd->state.workinprogress = 0;
if( sd->state.changemap ) { // Misc map-changing settings
int i;
sd->state.pmap = sd->bl.m;
@@ -4765,13 +4974,13 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
for( i = 0; i < sd->queues_count; i++ ) {
struct hQueue *queue;
if( (queue = script->queue(sd->queues[i])) && queue->onMapChange[0] != '\0' ) {
- pc->setregstr(sd, add_str("QMapChangeTo"), map[m].name);
- npc_event(sd, queue->onMapChange, 0);
+ pc->setregstr(sd, script->add_str("QMapChangeTo"), map->list[m].name);
+ npc->event(sd, queue->onMapChange, 0);
}
}
- if( map[m].cell == (struct mapcell *)0xdeadbeaf )
- iMap->cellfromcache(&map[m]);
+ if( map->list[m].cell == (struct mapcell *)0xdeadbeaf )
+ map->cellfromcache(&map->list[m]);
if (sd->sc.count) { // Cancel some map related stuff.
if (sd->sc.data[SC_JAILED])
return 1; //You may not get out!
@@ -4781,11 +4990,15 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
status_change_end(&sd->bl, SC_MOON_COMFORT, INVALID_TIMER);
status_change_end(&sd->bl, SC_STAR_COMFORT, INVALID_TIMER);
status_change_end(&sd->bl, SC_MIRACLE, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_NEUTRALBARRIER_MASTER, INVALID_TIMER);//Will later check if this is needed. [Rytech]
+ status_change_end(&sd->bl, SC_NEUTRALBARRIER, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_STEALTHFIELD_MASTER, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_STEALTHFIELD, INVALID_TIMER);
if (sd->sc.data[SC_KNOWLEDGE]) {
struct status_change_entry *sce = sd->sc.data[SC_KNOWLEDGE];
if (sce->timer != INVALID_TIMER)
- iTimer->delete_timer(sce->timer, status_change_timer);
- sce->timer = iTimer->add_timer(iTimer->gettick() + skill->get_time(SG_KNOWLEDGE, sce->val1), status_change_timer, sd->bl.id, SC_KNOWLEDGE);
+ timer->delete(sce->timer, status->change_timer);
+ sce->timer = timer->add(timer->gettick() + skill->get_time(SG_KNOWLEDGE, sce->val1), status->change_timer, sd->bl.id, SC_KNOWLEDGE);
}
status_change_end(&sd->bl, SC_PROPERTYWALK, INVALID_TIMER);
status_change_end(&sd->bl, SC_CLOAKING, INVALID_TIMER);
@@ -4800,76 +5013,75 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
skill->clear_unitgroup(&sd->bl);
party->send_dot_remove(sd); //minimap dot fix [Kevin]
guild->send_dot_remove(sd);
- bg_send_dot_remove(sd);
+ bg->send_dot_remove(sd);
if (sd->regen.state.gc)
sd->regen.state.gc = 0;
// make sure vending is allowed here
- if (sd->state.vending && map[m].flag.novending) {
+ if (sd->state.vending && map->list[m].flag.novending) {
clif->message (sd->fd, msg_txt(276)); // "You can't open a shop on this map"
vending->close(sd);
}
- if( hChSys.local && map[sd->bl.m].channel && idb_exists(map[sd->bl.m].channel->users, sd->status.char_id) ) {
- clif->chsys_left(map[sd->bl.m].channel,sd);
+ if( hChSys.local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id) ) {
+ clif->chsys_left(map->list[sd->bl.m].channel,sd);
}
-
}
if( m < 0 ) {
uint32 ip;
uint16 port;
//if can't find any map-servers, just abort setting position.
- if(!sd->mapindex || iMap->mapname2ipport(mapindex,&ip,&port))
+ if(!sd->mapindex || map->mapname2ipport(map_index,&ip,&port))
return 2;
if (sd->npc_id)
- npc_event_dequeue(sd);
- npc_script_event(sd, NPCE_LOGOUT);
+ npc->event_dequeue(sd);
+ npc->script_event(sd, NPCE_LOGOUT);
//remove from map, THEN change x/y coordinates
- unit_remove_map_pc(sd,clrtype);
- sd->mapindex = mapindex;
+ unit->remove_map_pc(sd,clrtype);
+ sd->mapindex = map_index;
sd->bl.x=x;
sd->bl.y=y;
pc->clean_skilltree(sd);
- chrif_save(sd,2);
- chrif_changemapserver(sd, ip, (short)port);
+ chrif->save(sd,2);
+ chrif->changemapserver(sd, ip, (short)port);
//Free session data from this map server [Kevin]
- unit_free_pc(sd);
+ unit->free_pc(sd);
return 0;
}
- if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) {
- ShowError("pc_setpos: attempt to place player %s (%d:%d) on invalid coordinates (%s-%d,%d)\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(mapindex),x,y);
+ if( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) {
+ ShowError("pc_setpos: attempt to place player %s (%d:%d) on invalid coordinates (%s-%d,%d)\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(map_index),x,y);
x = y = 0; // make it random
}
if( x == 0 && y == 0 ) {// pick a random walkable cell
do {
- x=rnd()%(map[m].xs-2)+1;
- y=rnd()%(map[m].ys-2)+1;
- } while(iMap->getcell(m,x,y,CELL_CHKNOPASS));
+ x=rnd()%(map->list[m].xs-2)+1;
+ y=rnd()%(map->list[m].ys-2)+1;
+ } while(map->getcell(m,x,y,CELL_CHKNOPASS));
}
- if (sd->state.vending && iMap->getcell(m,x,y,CELL_CHKNOVENDING)) {
+ if (sd->state.vending && map->getcell(m,x,y,CELL_CHKNOVENDING)) {
clif->message (sd->fd, msg_txt(204)); // "You can't open a shop on this cell."
vending->close(sd);
}
if(sd->bl.prev != NULL){
- unit_remove_map_pc(sd,clrtype);
+ unit->remove_map_pc(sd,clrtype);
clif->changemap(sd,m,x,y); // [MouseJstr]
} else if(sd->state.active)
//Tag player for rewarping after map-loading is done. [Skotlex]
sd->state.rewarp = 1;
- sd->mapindex = mapindex;
+ sd->mapindex = map_index;
sd->bl.m = m;
sd->bl.x = sd->ud.to_x = x;
sd->bl.y = sd->ud.to_y = y;
- if( sd->status.guild_id > 0 && map[m].flag.gvg_castle ) { // Increased guild castle regen [Valaris]
+ if( sd->status.guild_id > 0 && map->list[m].flag.gvg_castle ) { // Increased guild castle regen [Valaris]
struct guild_castle *gc = guild->mapindex2gc(sd->mapindex);
if(gc && gc->guild_id == sd->status.guild_id)
sd->regen.state.gc = 1;
@@ -4895,6 +5107,10 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
sd->md->bl.y = sd->md->ud.to_y = y;
sd->md->ud.dir = sd->ud.dir;
}
+
+ /* given autotrades have no clients you have to trigger this manually otherwise they get stuck in memory limbo bugreport:7495 */
+ if( sd->state.autotrade )
+ clif->pLoadEndAck(0,sd);
return 0;
}
@@ -4906,8 +5122,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
* 0 = fail or FIXME success (from pc->setpos)
* x(1|2) = fail
*------------------------------------------*/
-int pc_randomwarp(struct map_session_data *sd, clr_type type)
-{
+int pc_randomwarp(struct map_session_data *sd, clr_type type) {
int x,y,i=0;
int16 m;
@@ -4915,16 +5130,16 @@ int pc_randomwarp(struct map_session_data *sd, clr_type type)
m=sd->bl.m;
- if (map[sd->bl.m].flag.noteleport) //Teleport forbidden
+ if (map->list[sd->bl.m].flag.noteleport) //Teleport forbidden
return 0;
- do{
- x=rnd()%(map[m].xs-2)+1;
- y=rnd()%(map[m].ys-2)+1;
- }while(iMap->getcell(m,x,y,CELL_CHKNOPASS) && (i++)<1000 );
+ do {
+ x=rnd()%(map->list[m].xs-2)+1;
+ y=rnd()%(map->list[m].ys-2)+1;
+ } while( map->getcell(m,x,y,CELL_CHKNOPASS) && (i++) < 1000 );
if (i < 1000)
- return pc->setpos(sd,map[sd->bl.m].index,x,y,type);
+ return pc->setpos(sd,map_id2index(sd->bl.m),x,y,type);
return 0;
}
@@ -4933,14 +5148,13 @@ int pc_randomwarp(struct map_session_data *sd, clr_type type)
* Records a memo point at sd's current position
* pos - entry to replace, (-1: shift oldest entry out)
*------------------------------------------*/
-int pc_memo(struct map_session_data* sd, int pos)
-{
- int skill;
+int pc_memo(struct map_session_data* sd, int pos) {
+ int skill_lv;
nullpo_ret(sd);
// check mapflags
- if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) {
+ if( sd->bl.m >= 0 && (map->list[sd->bl.m].flag.nomemo || map->list[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) {
clif->skill_mapinfomessage(sd, 1); // "Saved point cannot be memorized."
return 0;
}
@@ -4950,12 +5164,12 @@ int pc_memo(struct map_session_data* sd, int pos)
return 0; // invalid input
// check required skill level
- skill = pc->checkskill(sd, AL_WARP);
- if( skill < 1 ) {
+ skill_lv = pc->checkskill(sd, AL_WARP);
+ if( skill_lv < 1 ) {
clif->skill_memomessage(sd,2); // "You haven't learned Warp."
return 0;
}
- if( skill < 2 || skill - 2 < pos ) {
+ if( skill_lv < 2 || skill_lv - 2 < pos ) {
clif->skill_memomessage(sd,1); // "Skill Level is not high enough."
return 0;
}
@@ -5009,14 +5223,14 @@ int pc_checkskill2(struct map_session_data *sd,uint16 index) {
ShowError("pc_checkskill: Invalid skill index %d (char_id=%d).\n", index, sd->status.char_id);
return 0;
}
- if( skill_db[index].nameid >= GD_SKILLBASE && skill_db[index].nameid < GD_MAX ) {
+ if( skill->db[index].nameid >= GD_SKILLBASE && skill->db[index].nameid < GD_MAX ) {
struct guild *g;
if( sd->status.guild_id>0 && (g=sd->guild)!=NULL)
- return guild->checkskill(g,skill_db[index].nameid);
+ return guild->checkskill(g,skill->db[index].nameid);
return 0;
}
- if(sd->status.skill[index].id == skill_db[index].nameid)
+ if(sd->status.skill[index].id == skill->db[index].nameid)
return (sd->status.skill[index].lv);
return 0;
@@ -5041,9 +5255,11 @@ int pc_checkallowskill(struct map_session_data *sd)
SC_DANCING,
SC_GS_GATLINGFEVER,
#ifdef RENEWAL
+ SC_LKCONCENTRATION,
SC_EDP,
#endif
- SC_FEARBREEZE
+ SC_FEARBREEZE,
+ SC_EXEEDBREAK,
};
const enum sc_type scs_list[] = {
SC_AUTOGUARD,
@@ -5057,12 +5273,12 @@ int pc_checkallowskill(struct map_session_data *sd)
if(!sd->sc.count)
return 0;
- for (i = 0; i < ARRAYLENGTH(scw_list); i++)
- { // Skills requiring specific weapon types
+ for (i = 0; i < ARRAYLENGTH(scw_list); i++) {
+ // Skills requiring specific weapon types
if( scw_list[i] == SC_DANCING && !battle_config.dancing_weaponswitch_fix )
continue;
- if(sd->sc.data[scw_list[i]] &&
- !pc_check_weapontype(sd,skill->get_weapontype(status_sc2skill(scw_list[i]))))
+ if( sd->sc.data[scw_list[i]]
+ && !pc_check_weapontype(sd,skill->get_weapontype(status->sc2skill(scw_list[i]))))
status_change_end(&sd->bl, scw_list[i], INVALID_TIMER);
}
@@ -5091,7 +5307,7 @@ int pc_checkequip(struct map_session_data *sd,int pos)
nullpo_retr(-1, sd);
for(i=0;i<EQI_MAX;i++){
- if(pos & equip_pos[i])
+ if(pos & pc->equip_pos[i])
return sd->equip_index[i];
}
@@ -5132,6 +5348,7 @@ int pc_jobid2mapid(unsigned short b_class)
case JOB_STAR_GLADIATOR: return MAPID_STAR_GLADIATOR;
case JOB_KAGEROU:
case JOB_OBORO: return MAPID_KAGEROUOBORO;
+ case JOB_REBELLION: return MAPID_REBELLION;
case JOB_DEATH_KNIGHT: return MAPID_DEATH_KNIGHT;
//2-2 Jobs
case JOB_CRUSADER: return MAPID_CRUSADER;
@@ -5272,6 +5489,7 @@ int pc_mapid2jobid(unsigned short class_, int sex)
case MAPID_ASSASSIN: return JOB_ASSASSIN;
case MAPID_STAR_GLADIATOR: return JOB_STAR_GLADIATOR;
case MAPID_KAGEROUOBORO: return sex?JOB_KAGEROU:JOB_OBORO;
+ case MAPID_REBELLION: return JOB_REBELLION;
case MAPID_DEATH_KNIGHT: return JOB_DEATH_KNIGHT;
//2-2 Jobs
case MAPID_CRUSADER: return JOB_CRUSADER;
@@ -5382,107 +5600,107 @@ int pc_mapid2jobid(unsigned short class_, int sex)
const char* job_name(int class_)
{
switch (class_) {
- case JOB_NOVICE:
- case JOB_SWORDMAN:
- case JOB_MAGE:
- case JOB_ARCHER:
- case JOB_ACOLYTE:
- case JOB_MERCHANT:
- case JOB_THIEF:
+ case JOB_NOVICE: // 550
+ case JOB_SWORDMAN: // 551
+ case JOB_MAGE: // 552
+ case JOB_ARCHER: // 553
+ case JOB_ACOLYTE: // 554
+ case JOB_MERCHANT: // 555
+ case JOB_THIEF: // 556
return msg_txt(550 - JOB_NOVICE+class_);
- case JOB_KNIGHT:
- case JOB_PRIEST:
- case JOB_WIZARD:
- case JOB_BLACKSMITH:
- case JOB_HUNTER:
- case JOB_ASSASSIN:
+ case JOB_KNIGHT: // 557
+ case JOB_PRIEST: // 558
+ case JOB_WIZARD: // 559
+ case JOB_BLACKSMITH: // 560
+ case JOB_HUNTER: // 561
+ case JOB_ASSASSIN: // 562
return msg_txt(557 - JOB_KNIGHT+class_);
case JOB_KNIGHT2:
return msg_txt(557);
- case JOB_CRUSADER:
- case JOB_MONK:
- case JOB_SAGE:
- case JOB_ROGUE:
- case JOB_ALCHEMIST:
- case JOB_BARD:
- case JOB_DANCER:
+ case JOB_CRUSADER: // 563
+ case JOB_MONK: // 564
+ case JOB_SAGE: // 565
+ case JOB_ROGUE: // 566
+ case JOB_ALCHEMIST: // 567
+ case JOB_BARD: // 568
+ case JOB_DANCER: // 569
return msg_txt(563 - JOB_CRUSADER+class_);
case JOB_CRUSADER2:
return msg_txt(563);
- case JOB_WEDDING:
- case JOB_SUPER_NOVICE:
- case JOB_GUNSLINGER:
- case JOB_NINJA:
- case JOB_XMAS:
+ case JOB_WEDDING: // 570
+ case JOB_SUPER_NOVICE: // 571
+ case JOB_GUNSLINGER: // 572
+ case JOB_NINJA: // 573
+ case JOB_XMAS: // 574
return msg_txt(570 - JOB_WEDDING+class_);
case JOB_SUMMER:
return msg_txt(621);
- case JOB_NOVICE_HIGH:
- case JOB_SWORDMAN_HIGH:
- case JOB_MAGE_HIGH:
- case JOB_ARCHER_HIGH:
- case JOB_ACOLYTE_HIGH:
- case JOB_MERCHANT_HIGH:
- case JOB_THIEF_HIGH:
+ case JOB_NOVICE_HIGH: // 575
+ case JOB_SWORDMAN_HIGH: // 576
+ case JOB_MAGE_HIGH: // 577
+ case JOB_ARCHER_HIGH: // 578
+ case JOB_ACOLYTE_HIGH: // 579
+ case JOB_MERCHANT_HIGH: // 580
+ case JOB_THIEF_HIGH: // 581
return msg_txt(575 - JOB_NOVICE_HIGH+class_);
- case JOB_LORD_KNIGHT:
- case JOB_HIGH_PRIEST:
- case JOB_HIGH_WIZARD:
- case JOB_WHITESMITH:
- case JOB_SNIPER:
- case JOB_ASSASSIN_CROSS:
+ case JOB_LORD_KNIGHT: // 582
+ case JOB_HIGH_PRIEST: // 583
+ case JOB_HIGH_WIZARD: // 584
+ case JOB_WHITESMITH: // 585
+ case JOB_SNIPER: // 586
+ case JOB_ASSASSIN_CROSS: // 587
return msg_txt(582 - JOB_LORD_KNIGHT+class_);
case JOB_LORD_KNIGHT2:
return msg_txt(582);
- case JOB_PALADIN:
- case JOB_CHAMPION:
- case JOB_PROFESSOR:
- case JOB_STALKER:
- case JOB_CREATOR:
- case JOB_CLOWN:
- case JOB_GYPSY:
+ case JOB_PALADIN: // 588
+ case JOB_CHAMPION: // 589
+ case JOB_PROFESSOR: // 590
+ case JOB_STALKER: // 591
+ case JOB_CREATOR: // 592
+ case JOB_CLOWN: // 593
+ case JOB_GYPSY: // 594
return msg_txt(588 - JOB_PALADIN + class_);
case JOB_PALADIN2:
return msg_txt(588);
- case JOB_BABY:
- case JOB_BABY_SWORDMAN:
- case JOB_BABY_MAGE:
- case JOB_BABY_ARCHER:
- case JOB_BABY_ACOLYTE:
- case JOB_BABY_MERCHANT:
- case JOB_BABY_THIEF:
+ case JOB_BABY: // 595
+ case JOB_BABY_SWORDMAN: // 596
+ case JOB_BABY_MAGE: // 597
+ case JOB_BABY_ARCHER: // 598
+ case JOB_BABY_ACOLYTE: // 599
+ case JOB_BABY_MERCHANT: // 600
+ case JOB_BABY_THIEF: // 601
return msg_txt(595 - JOB_BABY + class_);
- case JOB_BABY_KNIGHT:
- case JOB_BABY_PRIEST:
- case JOB_BABY_WIZARD:
- case JOB_BABY_BLACKSMITH:
- case JOB_BABY_HUNTER:
- case JOB_BABY_ASSASSIN:
+ case JOB_BABY_KNIGHT: // 602
+ case JOB_BABY_PRIEST: // 603
+ case JOB_BABY_WIZARD: // 604
+ case JOB_BABY_BLACKSMITH: // 605
+ case JOB_BABY_HUNTER: // 606
+ case JOB_BABY_ASSASSIN: // 607
return msg_txt(602 - JOB_BABY_KNIGHT + class_);
case JOB_BABY_KNIGHT2:
return msg_txt(602);
- case JOB_BABY_CRUSADER:
- case JOB_BABY_MONK:
- case JOB_BABY_SAGE:
- case JOB_BABY_ROGUE:
- case JOB_BABY_ALCHEMIST:
- case JOB_BABY_BARD:
- case JOB_BABY_DANCER:
+ case JOB_BABY_CRUSADER: // 608
+ case JOB_BABY_MONK: // 609
+ case JOB_BABY_SAGE: // 610
+ case JOB_BABY_ROGUE: // 611
+ case JOB_BABY_ALCHEMIST: // 612
+ case JOB_BABY_BARD: // 613
+ case JOB_BABY_DANCER: // 614
return msg_txt(608 - JOB_BABY_CRUSADER + class_);
case JOB_BABY_CRUSADER2:
@@ -5499,74 +5717,82 @@ const char* job_name(int class_)
case JOB_SOUL_LINKER:
return msg_txt(618);
- case JOB_GANGSI:
- case JOB_DEATH_KNIGHT:
- case JOB_DARK_COLLECTOR:
+ case JOB_GANGSI: // 622
+ case JOB_DEATH_KNIGHT: // 623
+ case JOB_DARK_COLLECTOR: // 624
return msg_txt(622 - JOB_GANGSI+class_);
- case JOB_RUNE_KNIGHT:
- case JOB_WARLOCK:
- case JOB_RANGER:
- case JOB_ARCH_BISHOP:
- case JOB_MECHANIC:
- case JOB_GUILLOTINE_CROSS:
+ case JOB_RUNE_KNIGHT: // 625
+ case JOB_WARLOCK: // 626
+ case JOB_RANGER: // 627
+ case JOB_ARCH_BISHOP: // 628
+ case JOB_MECHANIC: // 629
+ case JOB_GUILLOTINE_CROSS: // 630
return msg_txt(625 - JOB_RUNE_KNIGHT+class_);
- case JOB_RUNE_KNIGHT_T:
- case JOB_WARLOCK_T:
- case JOB_RANGER_T:
- case JOB_ARCH_BISHOP_T:
- case JOB_MECHANIC_T:
- case JOB_GUILLOTINE_CROSS_T:
- return msg_txt(681 - JOB_RUNE_KNIGHT_T+class_);
-
- case JOB_ROYAL_GUARD:
- case JOB_SORCERER:
- case JOB_MINSTREL:
- case JOB_WANDERER:
- case JOB_SURA:
- case JOB_GENETIC:
- case JOB_SHADOW_CHASER:
+ case JOB_RUNE_KNIGHT_T: // 656
+ case JOB_WARLOCK_T: // 657
+ case JOB_RANGER_T: // 658
+ case JOB_ARCH_BISHOP_T: // 659
+ case JOB_MECHANIC_T: // 660
+ case JOB_GUILLOTINE_CROSS_T: // 661
+ return msg_txt(656 - JOB_RUNE_KNIGHT_T+class_);
+
+ case JOB_ROYAL_GUARD: // 631
+ case JOB_SORCERER: // 632
+ case JOB_MINSTREL: // 633
+ case JOB_WANDERER: // 634
+ case JOB_SURA: // 635
+ case JOB_GENETIC: // 636
+ case JOB_SHADOW_CHASER: // 637
return msg_txt(631 - JOB_ROYAL_GUARD+class_);
- case JOB_ROYAL_GUARD_T:
- case JOB_SORCERER_T:
- case JOB_MINSTREL_T:
- case JOB_WANDERER_T:
- case JOB_SURA_T:
- case JOB_GENETIC_T:
- case JOB_SHADOW_CHASER_T:
- return msg_txt(687 - JOB_ROYAL_GUARD_T+class_);
+ case JOB_ROYAL_GUARD_T: // 662
+ case JOB_SORCERER_T: // 663
+ case JOB_MINSTREL_T: // 664
+ case JOB_WANDERER_T: // 665
+ case JOB_SURA_T: // 666
+ case JOB_GENETIC_T: // 667
+ case JOB_SHADOW_CHASER_T: // 668
+ return msg_txt(662 - JOB_ROYAL_GUARD_T+class_);
case JOB_RUNE_KNIGHT2:
- case JOB_RUNE_KNIGHT_T2:
return msg_txt(625);
+ case JOB_RUNE_KNIGHT_T2:
+ return msg_txt(656);
+
case JOB_ROYAL_GUARD2:
- case JOB_ROYAL_GUARD_T2:
return msg_txt(631);
+ case JOB_ROYAL_GUARD_T2:
+ return msg_txt(662);
+
case JOB_RANGER2:
- case JOB_RANGER_T2:
return msg_txt(627);
+ case JOB_RANGER_T2:
+ return msg_txt(658);
+
case JOB_MECHANIC2:
- case JOB_MECHANIC_T2:
return msg_txt(629);
- case JOB_BABY_RUNE:
- case JOB_BABY_WARLOCK:
- case JOB_BABY_RANGER:
- case JOB_BABY_BISHOP:
- case JOB_BABY_MECHANIC:
- case JOB_BABY_CROSS:
- case JOB_BABY_GUARD:
- case JOB_BABY_SORCERER:
- case JOB_BABY_MINSTREL:
- case JOB_BABY_WANDERER:
- case JOB_BABY_SURA:
- case JOB_BABY_GENETIC:
- case JOB_BABY_CHASER:
+ case JOB_MECHANIC_T2:
+ return msg_txt(660);
+
+ case JOB_BABY_RUNE: // 638
+ case JOB_BABY_WARLOCK: // 639
+ case JOB_BABY_RANGER: // 640
+ case JOB_BABY_BISHOP: // 641
+ case JOB_BABY_MECHANIC: // 642
+ case JOB_BABY_CROSS: // 643
+ case JOB_BABY_GUARD: // 644
+ case JOB_BABY_SORCERER: // 645
+ case JOB_BABY_MINSTREL: // 646
+ case JOB_BABY_WANDERER: // 647
+ case JOB_BABY_SURA: // 648
+ case JOB_BABY_GENETIC: // 649
+ case JOB_BABY_CHASER: // 650
return msg_txt(638 - JOB_BABY_RUNE+class_);
case JOB_BABY_RUNE2:
@@ -5581,56 +5807,57 @@ const char* job_name(int class_)
case JOB_BABY_MECHANIC2:
return msg_txt(642);
- case JOB_SUPER_NOVICE_E:
- case JOB_SUPER_BABY_E:
+ case JOB_SUPER_NOVICE_E: // 651
+ case JOB_SUPER_BABY_E: // 652
return msg_txt(651 - JOB_SUPER_NOVICE_E+class_);
- case JOB_KAGEROU:
- case JOB_OBORO:
+ case JOB_KAGEROU: // 653
+ case JOB_OBORO: // 654
return msg_txt(653 - JOB_KAGEROU+class_);
- default:
+ case JOB_REBELLION:
return msg_txt(655);
+
+ default:
+ return msg_txt(620); // "Unknown Job"
}
}
-int pc_follow_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+int pc_follow_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
struct block_list *tbl;
- sd = iMap->id2sd(id);
+ sd = map->id2sd(id);
nullpo_ret(sd);
- if (sd->followtimer != tid){
+ if (sd->followtimer != tid) {
ShowError("pc_follow_timer %d != %d\n",sd->followtimer,tid);
sd->followtimer = INVALID_TIMER;
return 0;
}
sd->followtimer = INVALID_TIMER;
- tbl = iMap->id2bl(sd->followtarget);
+ tbl = map->id2bl(sd->followtarget);
- if (tbl == NULL || pc_isdead(sd) || status_isdead(tbl))
- {
+ if (tbl == NULL || pc_isdead(sd) || status->isdead(tbl)) {
pc->stop_following(sd);
return 0;
}
// either player or target is currently detached from map blocks (could be teleporting),
// but still connected to this map, so we'll just increment the timer and check back later
- if (sd->bl.prev != NULL && tbl->prev != NULL &&
- sd->ud.skilltimer == INVALID_TIMER && sd->ud.attacktimer == INVALID_TIMER && sd->ud.walktimer == INVALID_TIMER)
- {
- if((sd->bl.m == tbl->m) && unit_can_reach_bl(&sd->bl,tbl, AREA_SIZE, 0, NULL, NULL)) {
+ if (sd->bl.prev != NULL && tbl->prev != NULL
+ && sd->ud.skilltimer == INVALID_TIMER && sd->ud.attacktimer == INVALID_TIMER && sd->ud.walktimer == INVALID_TIMER
+ ) {
+ if((sd->bl.m == tbl->m) && unit->can_reach_bl(&sd->bl,tbl, AREA_SIZE, 0, NULL, NULL)) {
if (!check_distance_bl(&sd->bl, tbl, 5))
- unit_walktobl(&sd->bl, tbl, 5, 0);
+ unit->walktobl(&sd->bl, tbl, 5, 0);
} else
pc->setpos(sd, map_id2index(tbl->m), tbl->x, tbl->y, CLR_TELEPORT);
}
- sd->followtimer = iTimer->add_timer(
+ sd->followtimer = timer->add(
tick + 1000, // increase time a bit to loosen up map's load
- pc_follow_timer, sd->bl.id, 0);
+ pc->follow_timer, sd->bl.id, 0);
return 0;
}
@@ -5639,27 +5866,26 @@ int pc_stop_following (struct map_session_data *sd)
nullpo_ret(sd);
if (sd->followtimer != INVALID_TIMER) {
- iTimer->delete_timer(sd->followtimer,pc_follow_timer);
+ timer->delete(sd->followtimer,pc->follow_timer);
sd->followtimer = INVALID_TIMER;
}
sd->followtarget = -1;
sd->ud.target_to = 0;
- unit_stop_walking(&sd->bl, 1);
+ unit->stop_walking(&sd->bl, 1);
return 0;
}
-int pc_follow(struct map_session_data *sd,int target_id)
-{
- struct block_list *bl = iMap->id2bl(target_id);
+int pc_follow(struct map_session_data *sd,int target_id) {
+ struct block_list *bl = map->id2bl(target_id);
if (bl == NULL /*|| bl->type != BL_PC*/)
return 1;
if (sd->followtimer != INVALID_TIMER)
pc->stop_following(sd);
sd->followtarget = target_id;
- pc_follow_timer(INVALID_TIMER, iTimer->gettick(), sd->bl.id, 0);
+ pc->follow_timer(INVALID_TIMER, timer->gettick(), sd->bl.id, 0);
return 0;
}
@@ -5683,29 +5909,29 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
} while ((next=pc->nextbaseexp(sd)) > 0 && sd->status.base_exp >= next);
if (battle_config.pet_lv_rate && sd->pd) //<Skotlex> update pet's level
- status_calc_pet(sd->pd,0);
+ status_calc_pet(sd->pd,SCO_NONE);
clif->updatestatus(sd,SP_STATUSPOINT);
clif->updatestatus(sd,SP_BASELEVEL);
clif->updatestatus(sd,SP_BASEEXP);
clif->updatestatus(sd,SP_NEXTBASEEXP);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
status_percent_heal(&sd->bl,100,100);
if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
- sc_start(&sd->bl,status_skill2sc(PR_KYRIE),100,1,skill->get_time(PR_KYRIE,1));
- sc_start(&sd->bl,status_skill2sc(PR_IMPOSITIO),100,1,skill->get_time(PR_IMPOSITIO,1));
- sc_start(&sd->bl,status_skill2sc(PR_MAGNIFICAT),100,1,skill->get_time(PR_MAGNIFICAT,1));
- sc_start(&sd->bl,status_skill2sc(PR_GLORIA),100,1,skill->get_time(PR_GLORIA,1));
- sc_start(&sd->bl,status_skill2sc(PR_SUFFRAGIUM),100,1,skill->get_time(PR_SUFFRAGIUM,1));
+ sc_start(NULL,&sd->bl,status->skill2sc(PR_KYRIE),100,1,skill->get_time(PR_KYRIE,1));
+ sc_start(NULL,&sd->bl,status->skill2sc(PR_IMPOSITIO),100,1,skill->get_time(PR_IMPOSITIO,1));
+ sc_start(NULL,&sd->bl,status->skill2sc(PR_MAGNIFICAT),100,1,skill->get_time(PR_MAGNIFICAT,1));
+ sc_start(NULL,&sd->bl,status->skill2sc(PR_GLORIA),100,1,skill->get_time(PR_GLORIA,1));
+ sc_start(NULL,&sd->bl,status->skill2sc(PR_SUFFRAGIUM),100,1,skill->get_time(PR_SUFFRAGIUM,1));
if (sd->state.snovice_dead_flag)
sd->state.snovice_dead_flag = 0; //Reenable steelbody resurrection on dead.
} else if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) {
- sc_start(&sd->bl,status_skill2sc(AL_INCAGI),100,10,600000);
- sc_start(&sd->bl,status_skill2sc(AL_BLESSING),100,10,600000);
+ sc_start(NULL,&sd->bl,status->skill2sc(AL_INCAGI),100,10,600000);
+ sc_start(NULL,&sd->bl,status->skill2sc(AL_BLESSING),100,10,600000);
}
clif->misceffect(&sd->bl,0);
- npc_script_event(sd, NPCE_BASELVUP); //LORDALFA - LVLUPEVENT
+ npc->script_event(sd, NPCE_BASELVUP); //LORDALFA - LVLUPEVENT
if(sd->status.party_id)
party->send_levelup(sd);
@@ -5715,7 +5941,6 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
}
void pc_baselevelchanged(struct map_session_data *sd) {
-#ifdef RENEWAL
int i;
for( i = 0; i < EQI_MAX; i++ ) {
if( sd->equip_index[i] >= 0 ) {
@@ -5723,9 +5948,8 @@ void pc_baselevelchanged(struct map_session_data *sd) {
pc->unequipitem(sd, sd->equip_index[i], 3);
}
}
-#endif
-
}
+
int pc_checkjoblevelup(struct map_session_data *sd)
{
unsigned int next = pc->nextjobexp(sd);
@@ -5749,29 +5973,28 @@ int pc_checkjoblevelup(struct map_session_data *sd)
clif->updatestatus(sd,SP_JOBEXP);
clif->updatestatus(sd,SP_NEXTJOBEXP);
clif->updatestatus(sd,SP_SKILLPOINT);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
clif->misceffect(&sd->bl,1);
if (pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd))
clif->status_change(&sd->bl,SI_DEVIL1, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL.
- npc_script_event(sd, NPCE_JOBLVUP);
+ npc->script_event(sd, NPCE_JOBLVUP);
return 1;
}
-/*==========================================
- * Alters experienced based on self bonuses that do not get even shared to the party.
- *------------------------------------------*/
-static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src)
-{
+/**
+ * Alters EXP based on self bonuses that do not get shared with the party
+ **/
+void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src) {
int bonus = 0;
- struct status_data *status = status_get_status_data(src);
+ struct status_data *st = status->get_status_data(src);
- if (sd->expaddrace[status->race])
- bonus += sd->expaddrace[status->race];
- bonus += sd->expaddrace[status->mode&MD_BOSS?RC_BOSS:RC_NONBOSS];
+ if (sd->expaddrace[st->race])
+ bonus += sd->expaddrace[st->race];
+ bonus += sd->expaddrace[st->mode&MD_BOSS?RC_BOSS:RC_NONBOSS];
- if (battle_config.pk_mode &&
- (int)(status_get_lv(src) - sd->status.base_level) >= 20)
+ if (battle_config.pk_mode
+ && (int)(status->get_lv(src) - sd->status.base_level) >= 20)
bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris]
if (sd->sc.data[SC_CASH_PLUSEXP])
@@ -5784,27 +6007,36 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi
*job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * bonus/100., 1, UINT_MAX);
+ if( sd->status.mod_exp != 100 ) {
+ *base_exp = (unsigned int) cap_value((double)*base_exp * sd->status.mod_exp/100., 1, UINT_MAX);
+ *job_exp = (unsigned int) cap_value((double)*job_exp * sd->status.mod_exp/100., 1, UINT_MAX);
+
+ }
+
return;
}
-/*==========================================
- * Give x exp at sd player and calculate remaining exp for next lvl
- *------------------------------------------*/
-int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp,unsigned int job_exp,bool quest)
-{
+
+/**
+ * Gives a determined EXP amount to sd and calculates remaining EXP for next level
+ * @param src if is NULL no bonuses are taken into account
+ * @param is_quest Used to let client know that the EXP was from a quest (clif->displayexp) PACKETVER >= 20091027
+ * @retval true success
+ **/
+bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp,unsigned int job_exp,bool is_quest) {
float nextbp=0, nextjp=0;
unsigned int nextb=0, nextj=0;
nullpo_ret(sd);
if(sd->bl.prev == NULL || pc_isdead(sd))
- return 0;
+ return false;
- if(!battle_config.pvp_exp && map[sd->bl.m].flag.pvp) // [MouseJstr]
- return 0; // no exp on pvp maps
+ if(!battle_config.pvp_exp && map->list[sd->bl.m].flag.pvp) // [MouseJstr]
+ return false; // no exp on pvp maps
if(sd->status.guild_id>0)
base_exp-=guild->payexp(sd,base_exp);
- if(src) pc_calcexp(sd, &base_exp, &job_exp, src);
+ if(src) pc->calcexp(sd, &base_exp, &job_exp, src);
nextb = pc->nextbaseexp(sd);
nextj = pc->nextjobexp(sd);
@@ -5831,7 +6063,8 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int
}
}
- //Cap exp to the level up requirement of the previous level when you are at max level, otherwise cap at UINT_MAX (this is required for some S. Novice bonuses). [Skotlex]
+ // Cap exp to the level up requirement of the previous level when you are at max level,
+ // otherwise cap at UINT_MAX (this is required for some S. Novice bonuses). [Skotlex]
if (base_exp) {
nextb = nextb?UINT_MAX:pc->thisbaseexp(sd);
if(sd->status.base_exp > nextb - base_exp)
@@ -5852,18 +6085,21 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int
clif->updatestatus(sd,SP_JOBEXP);
}
+#if PACKETVER >= 20091027
if(base_exp)
- clif->displayexp(sd, base_exp, SP_BASEEXP, quest);
+ clif->displayexp(sd, base_exp, SP_BASEEXP, is_quest);
if(job_exp)
- clif->displayexp(sd, job_exp, SP_JOBEXP, quest);
+ clif->displayexp(sd, job_exp, SP_JOBEXP, is_quest);
+#endif
+
if(sd->state.showexp) {
char output[256];
sprintf(output,
"Experience Gained Base:%u (%.2f%%) Job:%u (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100);
- clif->disp_onlyself(sd,output,strlen(output));
+ clif_disp_onlyself(sd,output,strlen(output));
}
- return 1;
+ return true;
}
/*==========================================
@@ -5871,12 +6107,12 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int
*------------------------------------------*/
unsigned int pc_maxbaselv(struct map_session_data *sd)
{
- return max_level[pc->class2idx(sd->status.class_)][0];
+ return pc->max_level[pc->class2idx(sd->status.class_)][0];
}
unsigned int pc_maxjoblv(struct map_session_data *sd)
{
- return max_level[pc->class2idx(sd->status.class_)][1];
+ return pc->max_level[pc->class2idx(sd->status.class_)][1];
}
/*==========================================
@@ -5891,7 +6127,7 @@ unsigned int pc_nextbaseexp(struct map_session_data *sd)
if(sd->status.base_level>=pc->maxbaselv(sd) || sd->status.base_level<=0)
return 0;
- return exp_table[pc->class2idx(sd->status.class_)][0][sd->status.base_level-1];
+ return pc->exp_table[pc->class2idx(sd->status.class_)][0][sd->status.base_level-1];
}
//Base exp needed for this level.
@@ -5900,7 +6136,7 @@ unsigned int pc_thisbaseexp(struct map_session_data *sd)
if(sd->status.base_level>pc->maxbaselv(sd) || sd->status.base_level<=1)
return 0;
- return exp_table[pc->class2idx(sd->status.class_)][0][sd->status.base_level-2];
+ return pc->exp_table[pc->class2idx(sd->status.class_)][0][sd->status.base_level-2];
}
@@ -5918,7 +6154,7 @@ unsigned int pc_nextjobexp(struct map_session_data *sd)
if(sd->status.job_level>=pc->maxjoblv(sd) || sd->status.job_level<=0)
return 0;
- return exp_table[pc->class2idx(sd->status.class_)][1][sd->status.job_level-1];
+ return pc->exp_table[pc->class2idx(sd->status.class_)][1][sd->status.job_level-1];
}
//Job exp needed for this level.
@@ -5926,41 +6162,41 @@ unsigned int pc_thisjobexp(struct map_session_data *sd)
{
if(sd->status.job_level>pc->maxjoblv(sd) || sd->status.job_level<=1)
return 0;
- return exp_table[pc->class2idx(sd->status.class_)][1][sd->status.job_level-2];
+ return pc->exp_table[pc->class2idx(sd->status.class_)][1][sd->status.job_level-2];
}
/// Returns the value of the specified stat.
-static int pc_getstat(struct map_session_data* sd, int type)
+int pc_getstat(struct map_session_data* sd, int type)
{
nullpo_retr(-1, sd);
switch( type ) {
- case SP_STR: return sd->status.str;
- case SP_AGI: return sd->status.agi;
- case SP_VIT: return sd->status.vit;
- case SP_INT: return sd->status.int_;
- case SP_DEX: return sd->status.dex;
- case SP_LUK: return sd->status.luk;
- default:
- return -1;
+ case SP_STR: return sd->status.str;
+ case SP_AGI: return sd->status.agi;
+ case SP_VIT: return sd->status.vit;
+ case SP_INT: return sd->status.int_;
+ case SP_DEX: return sd->status.dex;
+ case SP_LUK: return sd->status.luk;
+ default:
+ return -1;
}
}
/// Sets the specified stat to the specified value.
/// Returns the new value.
-static int pc_setstat(struct map_session_data* sd, int type, int val)
+int pc_setstat(struct map_session_data* sd, int type, int val)
{
nullpo_retr(-1, sd);
switch( type ) {
- case SP_STR: sd->status.str = val; break;
- case SP_AGI: sd->status.agi = val; break;
- case SP_VIT: sd->status.vit = val; break;
- case SP_INT: sd->status.int_ = val; break;
- case SP_DEX: sd->status.dex = val; break;
- case SP_LUK: sd->status.luk = val; break;
- default:
- return -1;
+ case SP_STR: sd->status.str = val; break;
+ case SP_AGI: sd->status.agi = val; break;
+ case SP_VIT: sd->status.vit = val; break;
+ case SP_INT: sd->status.int_ = val; break;
+ case SP_DEX: sd->status.dex = val; break;
+ case SP_LUK: sd->status.luk = val; break;
+ default:
+ return -1;
}
return val;
@@ -5970,7 +6206,7 @@ static int pc_setstat(struct map_session_data* sd, int type, int val)
int pc_gets_status_point(int level)
{
if (battle_config.use_statpoint_table) //Use values from "db/statpoint.txt"
- return (statp[level+1] - statp[level]);
+ return (pc->statp[level+1] - pc->statp[level]);
else //Default increase
return ((level+15) / 5);
}
@@ -5985,7 +6221,7 @@ int pc_need_status_point(struct map_session_data* sd, int type, int val)
if ( val == 0 )
return 0;
- low = pc_getstat(sd,type);
+ low = pc->getstat(sd,type);
if ( low >= pc_maxparameter(sd) && val > 0 )
return 0; // Official servers show '0' when max is reached
@@ -6005,60 +6241,103 @@ int pc_need_status_point(struct map_session_data* sd, int type, int val)
return sp;
}
-/// Raises a stat by 1.
-/// Obeys max_parameter limits.
-/// Subtracts stat points.
-///
-/// @param type The stat to change (see enum _sp)
-int pc_statusup(struct map_session_data* sd, int type)
-{
- int max, need, val;
+/**
+ * Returns the value the specified stat can be increased by with the current
+ * amount of available status points for the current character's class.
+ *
+ * @param sd The target character.
+ * @param type Stat to verify.
+ * @return Maximum value the stat could grow by.
+ */
+int pc_maxparameterincrease(struct map_session_data* sd, int type) {
+ int base, final, status_points = sd->status.status_point;
+
+ base = final = pc->getstat(sd, type);
+
+ while (final <= pc_maxparameter(sd) && status_points >= 0) {
+#ifdef RENEWAL // renewal status point cost formula
+ status_points -= (final < 100) ? (2 + (final - 1) / 10) : (16 + 4 * ((final - 100) / 5));
+#else
+ status_points -= ( 1 + (final + 9) / 10 );
+#endif
+ final++;
+ }
+ final--;
+
+ return final > base ? final-base : 0;
+}
+
+/**
+ * Raises a stat by the specified amount.
+ *
+ * Obeys max_parameter limits.
+ * Subtracts status points according to the cost of the increased stat points.
+ *
+ * @param sd The target character.
+ * @param type The stat to change (see enum status_point_types)
+ * @param increase The stat increase (strictly positive) amount.
+ * @retval true if the stat was increased by any amount.
+ * @retval false if there were no changes.
+ */
+bool pc_statusup(struct map_session_data* sd, int type, int increase) {
+ int max_increase = 0, current = 0, needed_points = 0, final_value = 0;
nullpo_ret(sd);
// check conditions
- need = pc->need_status_point(sd,type,1);
- if( type < SP_STR || type > SP_LUK || need < 0 || need > sd->status.status_point )
- {
- clif->statusupack(sd,type,0,0);
- return 1;
+ if (type < SP_STR || type > SP_LUK || increase <= 0) {
+ clif->statusupack(sd, type, 0, 0);
+ return false;
}
// check limits
- max = pc_maxparameter(sd);
- if( pc_getstat(sd,type) >= max )
- {
- clif->statusupack(sd,type,0,0);
- return 1;
+ current = pc->getstat(sd, type);
+ max_increase = pc->maxparameterincrease(sd, type);
+ increase = cap_value(increase, 0, max_increase); // cap to the maximum status points available
+ if (increase <= 0 || current + increase > pc_maxparameter(sd)) {
+ clif->statusupack(sd, type, 0, 0);
+ return false;
+ }
+
+ // check status points
+ needed_points = pc->need_status_point(sd, type, increase);
+ if (needed_points < 0 || needed_points > sd->status.status_point) { // Sanity check
+ clif->statusupack(sd, type, 0, 0);
+ return false;
}
// set new values
- val = pc_setstat(sd, type, pc_getstat(sd,type) + 1);
- sd->status.status_point -= need;
+ final_value = pc->setstat(sd, type, current + increase);
+ sd->status.status_point -= needed_points;
- status_calc_pc(sd,0);
+ status_calc_pc(sd, SCO_NONE);
// update increase cost indicator
- if( need != pc->need_status_point(sd,type,1) )
- clif->updatestatus(sd, SP_USTR + type-SP_STR);
+ clif->updatestatus(sd, SP_USTR + type-SP_STR);
// update statpoint count
- clif->updatestatus(sd,SP_STATUSPOINT);
+ clif->updatestatus(sd, SP_STATUSPOINT);
// update stat value
- clif->statusupack(sd,type,1,val); // required
- if( val > 255 )
- clif->updatestatus(sd,type); // send after the 'ack' to override the truncated value
+ clif->statusupack(sd, type, 1, final_value); // required
+ if (final_value > 255)
+ clif->updatestatus(sd, type); // send after the 'ack' to override the truncated value
- return 0;
+ return true;
}
-/// Raises a stat by the specified amount.
-/// Obeys max_parameter limits.
-/// Does not subtract stat points.
-///
-/// @param type The stat to change (see enum _sp)
-/// @param val The stat increase amount.
+/**
+ * Raises a stat by the specified amount.
+ *
+ * Obeys max_parameter limits.
+ * Does not subtract status points for the cost of the modified stat points.
+ *
+ * @param sd The target character.
+ * @param type The stat to change (see enum status_point_types)
+ * @param val The stat increase (or decrease) amount.
+ * @return the stat increase amount.
+ * @retval 0 if no changes were made.
+ */
int pc_statusup2(struct map_session_data* sd, int type, int val)
{
int max, need;
@@ -6067,16 +6346,16 @@ int pc_statusup2(struct map_session_data* sd, int type, int val)
if( type < SP_STR || type > SP_LUK )
{
clif->statusupack(sd,type,0,0);
- return 1;
+ return 0;
}
need = pc->need_status_point(sd,type,1);
// set new value
max = pc_maxparameter(sd);
- val = pc_setstat(sd, type, cap_value(pc_getstat(sd,type) + val, 1, max));
+ val = pc->setstat(sd, type, cap_value(pc->getstat(sd,type) + val, 1, max));
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
// update increase cost indicator
if( need != pc->need_status_point(sd,type,1) )
@@ -6087,7 +6366,7 @@ int pc_statusup2(struct map_session_data* sd, int type, int val)
if( val > 255 )
clif->updatestatus(sd,type); // send after the 'ack' to override the truncated value
- return 0;
+ return val;
}
/*==========================================
@@ -6110,7 +6389,7 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
if( !(index = skill->get_index(skill_id)) )
return 0;
-
+
if( sd->status.skill_point > 0 &&
sd->status.skill[index].id &&
sd->status.skill[index].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
@@ -6118,34 +6397,29 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
{
sd->status.skill[index].lv++;
sd->status.skill_point--;
- if( !skill_db[index].inf )
- status_calc_pc(sd,0); // Only recalculate for passive skills.
+ if( !skill->db[index].inf )
+ status_calc_pc(sd,SCO_NONE); // Only recalculate for passive skills.
else if( sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )
pc->calc_skilltree(sd); // Required to grant all TK Ranger skills.
else
- pc_check_skilltree(sd, skill_id); // Check if a new skill can Lvlup
+ pc->check_skilltree(sd, skill_id); // Check if a new skill can Lvlup
- clif->skillup(sd,skill_id);
+ clif->skillup(sd,skill_id, sd->status.skill[index].lv, 1);
clif->updatestatus(sd,SP_SKILLPOINT);
if( skill_id == GN_REMODELING_CART ) /* cart weight info was updated by status_calc_pc */
clif->updatestatus(sd,SP_CARTINFO);
if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown
clif->skillinfoblock(sd);
- }else if( battle_config.skillup_limit ){
- int pts = 0, i, id;
- for(i = 0; i < MAX_SKILL_TREE && (id=skill_tree[pc_class2idx(sd->status.class_)][i].id) > 0 ; i++){
- int inf2 = skill->get_inf2(id);
- if ( inf2&INF2_QUEST_SKILL || (inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) || id == NV_BASIC )
- continue;
- if( sd->status.skill[id].id && sd->status.skill[id].flag == SKILL_FLAG_PERMANENT )
- pts += pc_checkskill(sd, id);
+ } else if( battle_config.skillup_limit ){
+ if( sd->sktree.second )
+ clif->msg_value(sd, 0x61E, sd->sktree.second);
+ else if( sd->sktree.third )
+ clif->msg_value(sd, 0x61F, sd->sktree.third);
+ else if( pc->calc_skillpoint(sd) < 9 ) {
+ /* TODO: official response? */
+ clif->colormes(sd->fd,COLOR_RED,"You need the basic skills");
}
- if( pts < sd->change_level_2nd )
- clif->msg_value(sd, 0x61E, sd->change_level_2nd-pts);
- else if( pts < (sd->change_level_3rd + sd->change_level_2nd) )
- clif->msg_value(sd, 0x61F, sd->change_level_3rd - (pts - sd->change_level_2nd));
}
-
return 0;
}
@@ -6170,22 +6444,22 @@ int pc_allskillup(struct map_session_data *sd)
if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) { //Get ALL skills except npc/guild ones. [Skotlex]
//and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage]
for(i=0;i<MAX_SKILL;i++){
- switch( skill_db[i].nameid ) {
+ switch( skill->db[i].nameid ) {
case SG_DEVIL:
case MO_TRIPLEATTACK:
case RG_SNATCHER:
continue;
default:
- if( !(skill_db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) )
- if ( ( sd->status.skill[i].lv = skill_db[i].max ) )//Nonexistant skills should return a max of 0 anyway.
- sd->status.skill[i].id = skill_db[i].nameid;
+ if( !(skill->db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) )
+ if ( ( sd->status.skill[i].lv = skill->db[i].max ) )//Nonexistant skills should return a max of 0 anyway.
+ sd->status.skill[i].id = skill->db[i].nameid;
}
}
} else {
int inf2;
- for(i=0;i < MAX_SKILL_TREE && (id=skill_tree[pc->class2idx(sd->status.class_)][i].id)>0;i++){
- int idx = skill_tree[pc->class2idx(sd->status.class_)][i].idx;
- inf2 = skill_db[idx].inf2;
+ for(i=0;i < MAX_SKILL_TREE && (id=pc->skill_tree[pc->class2idx(sd->status.class_)][i].id)>0;i++){
+ int idx = pc->skill_tree[pc->class2idx(sd->status.class_)][i].idx;
+ inf2 = skill->db[idx].inf2;
if (
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) ||
@@ -6197,7 +6471,7 @@ int pc_allskillup(struct map_session_data *sd)
sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_); // celest
}
}
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
//Required because if you could level up all skills previously,
//the update will not be sent as only the lv variable changes.
clif->skillinfoblock(sd);
@@ -6287,7 +6561,7 @@ int pc_resetlvl(struct map_session_data* sd,int type)
if ((type == 1 || type == 2 || type == 3) && sd->status.party_id)
party->send_levelup(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
clif->skillinfoblock(sd);
return 0;
@@ -6302,33 +6576,33 @@ int pc_resetstate(struct map_session_data* sd)
if (battle_config.use_statpoint_table)
{ // New statpoint table used here - Dexity
if (sd->status.base_level > MAX_LEVEL)
- { //statp[] goes out of bounds, can't reset!
+ { //pc->statp[] goes out of bounds, can't reset!
ShowError("pc_resetstate: Can't reset stats of %d:%d, the base level (%d) is greater than the max level supported (%d)\n",
sd->status.account_id, sd->status.char_id, sd->status.base_level, MAX_LEVEL);
return 0;
}
- sd->status.status_point = statp[sd->status.base_level] + ( sd->class_&JOBL_UPPER ? 52 : 0 ); // extra 52+48=100 stat points
+ sd->status.status_point = pc->statp[sd->status.base_level] + ( sd->class_&JOBL_UPPER ? 52 : 0 ); // extra 52+48=100 stat points
}
else
{
int add=0;
- add += pc->need_status_point(sd, SP_STR, 1-pc_getstat(sd, SP_STR));
- add += pc->need_status_point(sd, SP_AGI, 1-pc_getstat(sd, SP_AGI));
- add += pc->need_status_point(sd, SP_VIT, 1-pc_getstat(sd, SP_VIT));
- add += pc->need_status_point(sd, SP_INT, 1-pc_getstat(sd, SP_INT));
- add += pc->need_status_point(sd, SP_DEX, 1-pc_getstat(sd, SP_DEX));
- add += pc->need_status_point(sd, SP_LUK, 1-pc_getstat(sd, SP_LUK));
+ add += pc->need_status_point(sd, SP_STR, 1-pc->getstat(sd, SP_STR));
+ add += pc->need_status_point(sd, SP_AGI, 1-pc->getstat(sd, SP_AGI));
+ add += pc->need_status_point(sd, SP_VIT, 1-pc->getstat(sd, SP_VIT));
+ add += pc->need_status_point(sd, SP_INT, 1-pc->getstat(sd, SP_INT));
+ add += pc->need_status_point(sd, SP_DEX, 1-pc->getstat(sd, SP_DEX));
+ add += pc->need_status_point(sd, SP_LUK, 1-pc->getstat(sd, SP_LUK));
sd->status.status_point+=add;
}
- pc_setstat(sd, SP_STR, 1);
- pc_setstat(sd, SP_AGI, 1);
- pc_setstat(sd, SP_VIT, 1);
- pc_setstat(sd, SP_INT, 1);
- pc_setstat(sd, SP_DEX, 1);
- pc_setstat(sd, SP_LUK, 1);
+ pc->setstat(sd, SP_STR, 1);
+ pc->setstat(sd, SP_AGI, 1);
+ pc->setstat(sd, SP_VIT, 1);
+ pc->setstat(sd, SP_INT, 1);
+ pc->setstat(sd, SP_DEX, 1);
+ pc->setstat(sd, SP_LUK, 1);
clif->updatestatus(sd,SP_STR);
clif->updatestatus(sd,SP_AGI);
@@ -6349,10 +6623,10 @@ int pc_resetstate(struct map_session_data* sd)
if( sd->mission_mobid ) { //bugreport:2200
sd->mission_mobid = 0;
sd->mission_count = 0;
- pc_setglobalreg(sd,"TK_MISSION_ID", 0);
+ pc_setglobalreg(sd,script->add_str("TK_MISSION_ID"), 0);
}
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
return 1;
}
@@ -6382,7 +6656,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
if( pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd) ) //Remove perma blindness due to skill-reset. [Skotlex]
clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_DEVIL1);
i = sd->sc.option;
- if( i&OPTION_RIDING && (!pc->checkskill(sd, KN_RIDING) || (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) )
+ if( i&OPTION_RIDING && pc->checkskill(sd, KN_RIDING) )
i &= ~OPTION_RIDING;
if( i&OPTION_FALCON && pc->checkskill(sd, HT_FALCON) )
i &= ~OPTION_FALCON;
@@ -6405,7 +6679,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
pc->setoption(sd, i);
if( homun_alive(sd->hd) && pc->checkskill(sd, AM_CALLHOMUN) )
- homun->vaporize(sd, 0);
+ homun->vaporize(sd, HOM_ST_REST);
}
for( i = 1; i < MAX_SKILL; i++ ) {
@@ -6413,22 +6687,22 @@ int pc_resetskill(struct map_session_data* sd, int flag)
lv = sd->status.skill[i].lv;
if (lv < 1) continue;
- inf2 = skill_db[i].inf2;
+ inf2 = skill->db[i].inf2;
if( inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL) ) //Avoid reseting wedding/linker skills.
continue;
- skill_id = skill_db[i].nameid;
+ skill_id = skill->db[i].nameid;
// Don't reset trick dead if not a novice/baby
- if( skill_id == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) {
+ if( skill_id == NV_TRICKDEAD && (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) {
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = 0;
continue;
}
// do not reset basic skill
- if( skill_id == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
+ if( skill_id == NV_BASIC && (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE )
continue;
if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED )
@@ -6447,8 +6721,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
}
if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT )
skill_point += lv;
- else
- if( sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0 )
+ else if( sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0 )
skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
if( !(flag&2) ) {// reset
@@ -6461,10 +6734,25 @@ int pc_resetskill(struct map_session_data* sd, int flag)
sd->status.skill_point += skill_point;
+
+ if( !(flag&2) ) {
+ // Remove all SCs that can't be inactivated without a skill
+ if( sd->sc.data[SC_STORMKICK_READY] )
+ status_change_end(&sd->bl, SC_STORMKICK_READY, INVALID_TIMER);
+ if( sd->sc.data[SC_DOWNKICK_READY] )
+ status_change_end(&sd->bl, SC_DOWNKICK_READY, INVALID_TIMER);
+ if( sd->sc.data[SC_TURNKICK_READY] )
+ status_change_end(&sd->bl, SC_TURNKICK_READY, INVALID_TIMER);
+ if( sd->sc.data[SC_COUNTERKICK_READY] )
+ status_change_end(&sd->bl, SC_COUNTERKICK_READY, INVALID_TIMER);
+ if( sd->sc.data[SC_DODGE_READY] )
+ status_change_end(&sd->bl, SC_DODGE_READY, INVALID_TIMER);
+ }
+
if( flag&1 ) {
clif->updatestatus(sd,SP_SKILLPOINT);
clif->skillinfoblock(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
}
return skill_point;
@@ -6482,7 +6770,7 @@ int pc_resetfeel(struct map_session_data* sd)
{
sd->feel_map[i].m = -1;
sd->feel_map[i].index = 0;
- pc_setglobalreg(sd,sg_info[i].feel_var,0);
+ pc_setglobalreg(sd,script->add_str(pc->sg_info[i].feel_var),0);
}
return 0;
@@ -6496,7 +6784,7 @@ int pc_resethate(struct map_session_data* sd)
for (i=0; i<3; i++)
{
sd->hate_mob[i] = -1;
- pc_setglobalreg(sd,sg_info[i].hate_var,0);
+ pc_setglobalreg(sd,script->add_str(pc->sg_info[i].hate_var),0);
}
return 0;
}
@@ -6551,7 +6839,7 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype)
{
if( !pc_isdead(sd) )
return; // not applicable
- if( sd->bg_id && bg_member_respawn(sd) )
+ if( sd->bg_id && bg->member_respawn(sd) )
return; // member revived by battleground
pc->setstand(sd);
@@ -6560,9 +6848,8 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype)
clif->resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
}
-static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct map_session_data *sd = iMap->id2sd(id);
+int pc_respawn_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct map_session_data *sd = map->id2sd(id);
if( sd != NULL )
{
sd->pvp_point=0;
@@ -6589,86 +6876,89 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h
skill->sit(sd,0);
}
- if( sd->progressbar.npc_id )
+ if( sd->progressbar.npc_id ){
clif->progressbar_abort(sd);
+ sd->state.workinprogress = 0;
+ }
if( sd->status.pet_id > 0 && sd->pd && battle_config.pet_damage_support )
- pet_target_check(sd,src,1);
+ pet->target_check(sd,src,1);
if( sd->status.ele_id > 0 )
- elemental_set_target(sd,src);
+ elemental->set_target(sd,src);
- sd->canlog_tick = iTimer->gettick();
+ sd->canlog_tick = timer->gettick();
}
/*==========================================
* Invoked when a player has negative current hp
*------------------------------------------*/
int pc_dead(struct map_session_data *sd,struct block_list *src) {
- int i=0,j=0,k=0;
- unsigned int tick = iTimer->gettick();
+ int i=0,j=0;
+ int64 tick = timer->gettick();
- for(k = 0; k < 5; k++)
- if (sd->devotion[k]){
- struct map_session_data *devsd = iMap->id2sd(sd->devotion[k]);
+ for(j = 0; j < 5; j++) {
+ if (sd->devotion[j]){
+ struct map_session_data *devsd = map->id2sd(sd->devotion[j]);
if (devsd)
status_change_end(&devsd->bl, SC_DEVOTION, INVALID_TIMER);
- sd->devotion[k] = 0;
+ sd->devotion[j] = 0;
}
+ }
if(sd->status.pet_id > 0 && sd->pd) {
struct pet_data *pd = sd->pd;
- if( !map[sd->bl.m].flag.noexppenalty ) {
- pet_set_intimate(pd, pd->pet.intimate - pd->petDB->die);
+ if( !map->list[sd->bl.m].flag.noexppenalty ) {
+ pet->set_intimate(pd, pd->pet.intimate - pd->petDB->die);
if( pd->pet.intimate < 0 )
pd->pet.intimate = 0;
clif->send_petdata(sd,sd->pd,1,pd->pet.intimate);
}
if( sd->pd->target_id ) // Unlock all targets...
- pet_unlocktarget(sd->pd);
+ pet->unlocktarget(sd->pd);
}
if (sd->status.hom_id > 0){
- if(battle_config.homunculus_auto_vapor && sd->hd && !sd->hd->sc.data[SC_LIGHT_OF_REGENE])
- homun->vaporize(sd, 0);
+ if(battle_config.homunculus_auto_vapor && sd->hd)
+ homun->vaporize(sd, HOM_ST_REST);
}
if( sd->md )
- merc_delete(sd->md, 3); // Your mercenary soldier has ran away.
+ mercenary->delete(sd->md, 3); // Your mercenary soldier has ran away.
if( sd->ed )
- elemental_delete(sd->ed, 0);
+ elemental->delete(sd->ed, 0);
// Leave duel if you die [LuzZza]
if(battle_config.duel_autoleave_when_die) {
if(sd->duel_group > 0)
- duel_leave(sd->duel_group, sd);
+ duel->leave(sd->duel_group, sd);
if(sd->duel_invite > 0)
- duel_reject(sd->duel_invite, sd);
+ duel->reject(sd->duel_invite, sd);
}
if (sd->npc_id && sd->st && sd->st->state != RUN)
- npc_event_dequeue(sd);
+ npc->event_dequeue(sd);
- pc_setglobalreg(sd,"PC_DIE_COUNTER",sd->die_counter+1);
+ pc_setglobalreg(sd,script->add_str("PC_DIE_COUNTER"),sd->die_counter+1);
pc->setparam(sd, SP_KILLERRID, src?src->id:0);
if( sd->bg_id ) {/* TODO: purge when bgqueue is deemed ok */
- struct battleground_data *bg;
- if( (bg = bg_team_search(sd->bg_id)) != NULL && bg->die_event[0] )
- npc_event(sd, bg->die_event, 0);
+ struct battleground_data *bgd;
+ if( (bgd = bg->team_search(sd->bg_id)) != NULL && bgd->die_event[0] )
+ npc->event(sd, bgd->die_event, 0);
}
for( i = 0; i < sd->queues_count; i++ ) {
struct hQueue *queue;
if( (queue = script->queue(sd->queues[i])) && queue->onDeath[0] != '\0' )
- npc_event(sd, queue->onDeath, 0);
+ npc->event(sd, queue->onDeath, 0);
}
- npc_script_event(sd,NPCE_DIE);
+ npc->script_event(sd,NPCE_DIE);
// Clear anything NPC-related when you die and was interacting with one.
- if (sd->npc_id || sd->npc_shopid) {
+ if ( (sd->npc_id || sd->npc_shopid) && sd->state.dialog) {
if (sd->state.using_fake_npc) {
clif->clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
sd->state.using_fake_npc = 0;
@@ -6710,14 +7000,14 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
{
struct mob_data *md=(struct mob_data *)src;
if(md->target_id==sd->bl.id)
- mob_unlocktarget(md,tick);
+ mob->unlocktarget(md,tick);
if(battle_config.mobs_level_up && md->status.hp &&
(unsigned int)md->level < pc->maxbaselv(sd) &&
!md->guardian_data && !md->special_state.ai// Guardians/summons should not level. [Skotlex]
) { // monster level up [Valaris]
clif->misceffect(&md->bl,0);
md->level++;
- status_calc_mob(md, 0);
+ status_calc_mob(md, SCO_NONE);
status_percent_heal(src,10,0);
if( battle_config.show_mob_info&4 )
@@ -6743,12 +7033,12 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
if (src && src->type == BL_PC) {
struct map_session_data *ssd = (struct map_session_data *)src;
pc->setparam(ssd, SP_KILLEDRID, sd->bl.id);
- npc_script_event(ssd, NPCE_KILLPC);
+ npc->script_event(ssd, NPCE_KILLPC);
if (battle_config.pk_mode&2) {
ssd->status.manner -= 5;
if(ssd->status.manner < 0)
- sc_start(src,SC_NOCHAT,100,0,0);
+ sc_start(NULL,src,SC_NOCHAT,100,0,0);
#if 0
// PK/Karma system code (not enabled yet) [celest]
// originally from Kade Online, so i don't know if any of these is correct ^^;
@@ -6775,9 +7065,9 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
}
}
- if(battle_config.bone_drop==2
- || (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp))
- {
+ if( battle_config.bone_drop==2
+ || (battle_config.bone_drop==1 && map->list[sd->bl.m].flag.pvp)
+ ) {
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid=ITEMID_SKULL_;
@@ -6786,12 +7076,11 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
item_tmp.card[1]=0;
item_tmp.card[2]=GetWord(sd->status.char_id,0); // CharId
item_tmp.card[3]=GetWord(sd->status.char_id,1);
- iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
// activate Steel body if a super novice dies at 99+% exp [celest]
- if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && !sd->state.snovice_dead_flag)
- {
+ if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && !sd->state.snovice_dead_flag) {
unsigned int next = pc->nextbaseexp(sd);
if( next == 0 ) next = pc->thisbaseexp(sd);
if( get_percentage(sd->status.base_exp,next) >= 99 ) {
@@ -6801,79 +7090,86 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
clif->resurrection(&sd->bl, 1);
if(battle_config.pc_invincible_time)
pc->setinvincibletimer(sd, battle_config.pc_invincible_time);
- sc_start(&sd->bl,status_skill2sc(MO_STEELBODY),100,1,skill->get_time(MO_STEELBODY,1));
- if(map_flag_gvg(sd->bl.m))
- pc_respawn_timer(INVALID_TIMER, iTimer->gettick(), sd->bl.id, 0);
+ sc_start(NULL,&sd->bl,status->skill2sc(MO_STEELBODY),100,1,skill->get_time(MO_STEELBODY,1));
+ if(map_flag_gvg2(sd->bl.m))
+ pc->respawn_timer(INVALID_TIMER, timer->gettick(), sd->bl.id, 0);
return 0;
}
}
// changed penalty options, added death by player if pk_mode [Valaris]
- if(battle_config.death_penalty_type
- && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty
- && !map[sd->bl.m].flag.noexppenalty && !map_flag_gvg(sd->bl.m)
- && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_CASH_DEATHPENALTY])
- {
- unsigned int base_penalty =0;
+ if( battle_config.death_penalty_type
+ && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty
+ && !map->list[sd->bl.m].flag.noexppenalty && !map_flag_gvg2(sd->bl.m)
+ && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_CASH_DEATHPENALTY]
+ ) {
+ unsigned int base_penalty = 0;
if (battle_config.death_penalty_base > 0) {
+
switch (battle_config.death_penalty_type) {
case 1:
base_penalty = (unsigned int) ((double)pc->nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000);
- break;
+ break;
case 2:
base_penalty = (unsigned int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000);
- break;
+ break;
}
+
if(base_penalty) {
if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
+ if( sd->status.mod_death != 100 )
+ base_penalty = base_penalty * sd->status.mod_death / 100;
sd->status.base_exp -= min(sd->status.base_exp, base_penalty);
clif->updatestatus(sd,SP_BASEEXP);
}
}
- if(battle_config.death_penalty_job > 0)
- {
+
+ if(battle_config.death_penalty_job > 0) {
base_penalty = 0;
+
switch (battle_config.death_penalty_type) {
case 1:
base_penalty = (unsigned int) ((double)pc->nextjobexp(sd) * (double)battle_config.death_penalty_job/10000);
- break;
+ break;
case 2:
base_penalty = (unsigned int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000);
- break;
+ break;
}
+
if(base_penalty) {
if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
+ if( sd->status.mod_death != 100 )
+ base_penalty = base_penalty * sd->status.mod_death / 100;
sd->status.job_exp -= min(sd->status.job_exp, base_penalty);
clif->updatestatus(sd,SP_JOBEXP);
}
}
- if(battle_config.zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty)
- {
+
+ if(battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty) {
base_penalty = (unsigned int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.);
if(base_penalty)
pc->payzeny(sd, base_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL);
}
}
- if(map[sd->bl.m].flag.pvp_nightmaredrop)
- { // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker]
- for(j=0;j<map[sd->bl.m].drop_list_count;j++){
- int id = map[sd->bl.m].drop_list[j].drop_id;
- int type = map[sd->bl.m].drop_list[j].drop_type;
- int per = map[sd->bl.m].drop_list[j].drop_per;
+ if(map->list[sd->bl.m].flag.pvp_nightmaredrop) {
+ // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker]
+ for(j=0;j<map->list[sd->bl.m].drop_list_count;j++){
+ int id = map->list[sd->bl.m].drop_list[j].drop_id;
+ int type = map->list[sd->bl.m].drop_list[j].drop_type;
+ int per = map->list[sd->bl.m].drop_list[j].drop_per;
if(id == 0)
continue;
if(id == -1){
- int eq_num=0,eq_n[MAX_INVENTORY];
+ int eq_num=0,eq_n[MAX_INVENTORY],k;
memset(eq_n,0,sizeof(eq_n));
for(i=0;i<MAX_INVENTORY;i++){
if( (type == 1 && !sd->status.inventory[i].equip)
|| (type == 2 && sd->status.inventory[i].equip)
|| type == 3)
{
- int k;
ARR_FIND( 0, MAX_INVENTORY, k, eq_n[k] <= 0 );
if( k < MAX_INVENTORY )
eq_n[k] = i;
@@ -6906,10 +7202,20 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
}
}
}
+
+ // Remove autotrade to prevent autotrading from save point
+ if( (sd->state.standalone || sd->state.autotrade)
+ && (map->list[sd->bl.m].flag.pvp || map->list[sd->bl.m].flag.gvg)
+ ) {
+ sd->state.autotrade = 0;
+ sd->state.standalone = 0;
+ pc->autotrade_update(sd,PAUC_REMOVE);
+ map->quit(sd);
+ }
+
// pvp
// disable certain pvp functions on pk_mode [Valaris]
- if( map[sd->bl.m].flag.pvp && !battle_config.pk_mode && !map[sd->bl.m].flag.pvp_nocalcrank )
- {
+ if( map->list[sd->bl.m].flag.pvp && !battle_config.pk_mode && !map->list[sd->bl.m].flag.pvp_nocalcrank ) {
sd->pvp_point -= 5;
sd->pvp_lost++;
if( src && src->type == BL_PC )
@@ -6920,30 +7226,26 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
}
if( sd->pvp_point < 0 )
{
- iTimer->add_timer(tick+1000, pc_respawn_timer,sd->bl.id,0);
+ timer->add(tick+1, pc->respawn_timer,sd->bl.id,0);
return 1|8;
}
}
//GvG
- if( map_flag_gvg(sd->bl.m) )
- {
- iTimer->add_timer(tick+1000, pc_respawn_timer, sd->bl.id, 0);
+ if( map_flag_gvg2(sd->bl.m) ) {
+ timer->add(tick+1, pc->respawn_timer, sd->bl.id, 0);
return 1|8;
- }
- else if( sd->bg_id )
- {
- struct battleground_data *bg = bg_team_search(sd->bg_id);
- if( bg && bg->mapindex > 0 )
- { // Respawn by BG
- iTimer->add_timer(tick+1000, pc_respawn_timer, sd->bl.id, 0);
+ } else if( sd->bg_id ) {
+ struct battleground_data *bgd = bg->team_search(sd->bg_id);
+ if( bgd && bgd->mapindex > 0 ) { // Respawn by BG
+ timer->add(tick+1000, pc->respawn_timer, sd->bl.id, 0);
return 1|8;
}
}
-
//Reset "can log out" tick.
if( battle_config.prevent_logout )
- sd->canlog_tick = iTimer->gettick() - battle_config.prevent_logout;
+ sd->canlog_tick = timer->gettick() - battle_config.prevent_logout;
+
return 1;
}
@@ -6956,10 +7258,10 @@ void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) {
pc->setinvincibletimer(sd, battle_config.pc_invincible_time);
if( sd->state.gmaster_flag ) {
- guild->aura_refresh(sd,GD_LEADERSHIP,guild->checkskill(sd->state.gmaster_flag,GD_LEADERSHIP));
- guild->aura_refresh(sd,GD_GLORYWOUNDS,guild->checkskill(sd->state.gmaster_flag,GD_GLORYWOUNDS));
- guild->aura_refresh(sd,GD_SOULCOLD,guild->checkskill(sd->state.gmaster_flag,GD_SOULCOLD));
- guild->aura_refresh(sd,GD_HAWKEYES,guild->checkskill(sd->state.gmaster_flag,GD_HAWKEYES));
+ guild->aura_refresh(sd,GD_LEADERSHIP,guild->checkskill(sd->guild,GD_LEADERSHIP));
+ guild->aura_refresh(sd,GD_GLORYWOUNDS,guild->checkskill(sd->guild,GD_GLORYWOUNDS));
+ guild->aura_refresh(sd,GD_SOULCOLD,guild->checkskill(sd->guild,GD_SOULCOLD));
+ guild->aura_refresh(sd,GD_HAWKEYES,guild->checkskill(sd->guild,GD_HAWKEYES));
}
}
// script
@@ -7007,6 +7309,9 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_KILLEDRID: val = sd->killedrid; break;
case SP_SLOTCHANGE: val = sd->status.slotchange; break;
case SP_CHARRENAME: val = sd->status.rename; break;
+ case SP_MOD_EXP: val = sd->status.mod_exp; break;
+ case SP_MOD_DROP: val = sd->status.mod_drop; break;
+ case SP_MOD_DEATH: val = sd->status.mod_death; break;
case SP_CRITICAL: val = sd->battle_status.cri/10; break;
case SP_ASPD: val = (2000-sd->battle_status.amotion)/10; break;
case SP_BASE_ATK: val = sd->battle_status.batk; break;
@@ -7020,7 +7325,7 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_DEFELE: val = sd->battle_status.def_ele; break;
#ifndef RENEWAL_CAST
case SP_VARCASTRATE:
-#endif
+#endif
case SP_CASTRATE:
val = sd->castrate+=val;
break;
@@ -7139,7 +7444,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
clif->updatestatus(sd, SP_NEXTBASEEXP);
clif->updatestatus(sd, SP_STATUSPOINT);
clif->updatestatus(sd, SP_BASEEXP);
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
if(sd->status.party_id)
{
party->send_levelup(sd);
@@ -7156,7 +7461,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
// clif->updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom
clif->updatestatus(sd, SP_NEXTJOBEXP);
clif->updatestatus(sd, SP_JOBEXP);
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
break;
case SP_SKILLPOINT:
sd->status.skill_point = val;
@@ -7238,7 +7543,13 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
break;
case SP_MANNER:
sd->status.manner = val;
- break;
+ if( val < 0 )
+ sc_start(NULL, &sd->bl, SC_NOCHAT, 100, 0, 0);
+ else {
+ status_change_end(&sd->bl, SC_NOCHAT, INVALID_TIMER);
+ clif->manner_message(sd, 5);
+ }
+ return 1; // status_change_start/status_change_end already sends packets warning the client
case SP_FAME:
sd->status.fame = val;
break;
@@ -7254,6 +7565,15 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
case SP_CHARRENAME:
sd->status.rename = val;
return 1;
+ case SP_MOD_EXP:
+ sd->status.mod_exp = val;
+ return 1;
+ case SP_MOD_DROP:
+ sd->status.mod_drop = val;
+ return 1;
+ case SP_MOD_DEATH:
+ sd->status.mod_death = val;
+ return 1;
default:
ShowError("pc_setparam: Attempted to set unknown parameter '%d'.\n", type);
return 0;
@@ -7289,7 +7609,7 @@ void pc_heal(struct map_session_data *sd,unsigned int hp,unsigned int sp, int ty
*------------------------------------------*/
int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
{
- int bonus;
+ int bonus, tmp;
if(hp) {
int i;
@@ -7297,22 +7617,22 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
+ pc->checkskill(sd,SM_RECOVERY)*10
+ pc->checkskill(sd,AM_LEARNINGPOTION)*5;
// A potion produced by an Alchemist in the Fame Top 10 gets +50% effect [DracoRPG]
- if (potion_flag > 1)
- bonus += bonus*(potion_flag-1)*50/100;
+ if (script->potion_flag > 1)
+ bonus += bonus*(script->potion_flag-1)*50/100;
//All item bonuses.
bonus += sd->bonus.itemhealrate2;
- //Item Group bonuses
- bonus += bonus*itemdb_group_bonus(sd, itemid)/100;
//Individual item bonuses.
- for(i = 0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid; i++)
- {
- if (sd->itemhealrate[i].nameid == itemid) {
+ for(i = 0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid; i++) {
+ struct item_data *it = itemdb->exists(sd->itemhealrate[i].nameid);
+ if (sd->itemhealrate[i].nameid == itemid || (it && it->group && itemdb->in_group(it->group,itemid))) {
bonus += bonus*sd->itemhealrate[i].rate/100;
break;
}
}
- if(bonus!=100)
- hp = hp * bonus / 100;
+
+ tmp = hp*bonus/100;
+ if(bonus != 100 && tmp > hp)
+ hp = tmp;
// Recovery Potion
if( sd->sc.data[SC_HEALPLUS] )
@@ -7322,10 +7642,12 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
bonus = 100 + (sd->battle_status.int_<<1)
+ pc->checkskill(sd,MG_SRECOVERY)*10
+ pc->checkskill(sd,AM_LEARNINGPOTION)*5;
- if (potion_flag > 1)
- bonus += bonus*(potion_flag-1)*50/100;
- if(bonus != 100)
- sp = sp * bonus / 100;
+ if (script->potion_flag > 1)
+ bonus += bonus*(script->potion_flag-1)*50/100;
+
+ tmp = sp*bonus/100;
+ if(bonus != 100 && tmp > sp)
+ sp = tmp;
}
if( sd->sc.count ) {
if ( sd->sc.data[SC_CRITICALWOUND] ) {
@@ -7333,6 +7655,11 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
sp -= sp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100;
}
+ if( sd->sc.data[SC_VITALITYACTIVATION] ){
+ hp += hp / 2; // 1.5 times
+ sp -= sp / 2;
+ }
+
if ( sd->sc.data[SC_DEATHHURT] ) {
hp -= hp * 20 / 100;
sp -= sp * 20 / 100;
@@ -7348,7 +7675,7 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
#endif
}
- return status_heal(&sd->bl, hp, sp, 1);
+ return status->heal(&sd->bl, hp, sp, 1);
}
/*==========================================
@@ -7390,7 +7717,7 @@ int pc_percentheal(struct map_session_data *sd,int hp,int sp)
return 0;
}
-static int jobchange_killclone(struct block_list *bl, va_list ap)
+int jobchange_killclone(struct block_list *bl, va_list ap)
{
struct mob_data *md;
int flag;
@@ -7441,12 +7768,12 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
// changing from 1st to 2nd job
if ((b_class&JOBL_2) && !(sd->class_&JOBL_2) && (b_class&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) {
sd->change_level_2nd = sd->status.job_level;
- pc_setglobalreg (sd, "jobchange_level", sd->change_level_2nd);
+ pc_setglobalreg (sd, script->add_str("jobchange_level"), sd->change_level_2nd);
}
// changing from 2nd to 3rd job
else if((b_class&JOBL_THIRD) && !(sd->class_&JOBL_THIRD)) {
sd->change_level_3rd = sd->status.job_level;
- pc_setglobalreg (sd, "jobchange_level_3rd", sd->change_level_3rd);
+ pc_setglobalreg (sd, script->add_str("jobchange_level_3rd"), sd->change_level_3rd);
}
if(sd->cloneskill_id) {
@@ -7458,8 +7785,8 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
clif->deleteskill(sd,sd->cloneskill_id);
}
sd->cloneskill_id = 0;
- pc_setglobalreg(sd, "CLONE_SKILL", 0);
- pc_setglobalreg(sd, "CLONE_SKILL_LV", 0);
+ pc_setglobalreg(sd, script->add_str("CLONE_SKILL"), 0);
+ pc_setglobalreg(sd, script->add_str("CLONE_SKILL_LV"), 0);
}
if(sd->reproduceskill_id) {
@@ -7471,16 +7798,16 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
clif->deleteskill(sd,sd->reproduceskill_id);
}
sd->reproduceskill_id = 0;
- pc_setglobalreg(sd, "REPRODUCE_SKILL",0);
- pc_setglobalreg(sd, "REPRODUCE_SKILL_LV",0);
+ pc_setglobalreg(sd, script->add_str("REPRODUCE_SKILL"),0);
+ pc_setglobalreg(sd, script->add_str("REPRODUCE_SKILL_LV"),0);
}
if ( (b_class&MAPID_UPPERMASK) != (sd->class_&MAPID_UPPERMASK) ) { //Things to remove when changing class tree.
const int class_ = pc->class2idx(sd->status.class_);
short id;
- for(i = 0; i < MAX_SKILL_TREE && (id = skill_tree[class_][i].id) > 0; i++) {
+ for(i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[class_][i].id) > 0; i++) {
//Remove status specific to your current tree skills.
- enum sc_type sc = status_skill2sc(id);
+ enum sc_type sc = status->skill2sc(id);
if (sc > SC_COMMON_MAX && sd->sc.data[sc])
status_change_end(&sd->bl, sc, INVALID_TIMER);
}
@@ -7522,7 +7849,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
if (sd->disguise != -1)
pc->disguise(sd, -1);
- status_set_viewdata(&sd->bl, job);
+ status->set_viewdata(&sd->bl, job);
clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_); // move sprite update to prevent client crashes with incompatible equipment [Valaris]
if(sd->vd.cloth_color)
clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
@@ -7532,11 +7859,11 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
clif->skillinfoblock(sd);
if (sd->ed)
- elemental_delete(sd->ed, 0);
+ elemental->delete(sd->ed, 0);
if (sd->state.vending)
vending->close(sd);
- iMap->foreachinmap(jobchange_killclone, sd->bl.m, BL_MOB, sd->bl.id);
+ map->foreachinmap(pc->jobchange_killclone, sd->bl.m, BL_MOB, sd->bl.id);
//Remove peco/cart/falcon
i = sd->sc.option;
@@ -7563,27 +7890,27 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
pc->setoption(sd, i);
if(homun_alive(sd->hd) && !pc->checkskill(sd, AM_CALLHOMUN))
- homun->vaporize(sd, 0);
+ homun->vaporize(sd, HOM_ST_REST);
if(sd->status.manner < 0)
clif->changestatus(sd,SP_MANNER,sd->status.manner);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
pc->checkallowskill(sd);
pc->equiplookall(sd);
//if you were previously famous, not anymore.
if (fame_flag) {
- chrif_save(sd,0);
- chrif_buildfamelist();
+ chrif->save(sd,0);
+ chrif->buildfamelist();
} else if (sd->status.fame > 0) {
//It may be that now they are famous?
switch (sd->class_&MAPID_UPPERMASK) {
case MAPID_BLACKSMITH:
case MAPID_ALCHEMIST:
case MAPID_TAEKWON:
- chrif_save(sd,0);
- chrif_buildfamelist();
+ chrif->save(sd,0);
+ chrif->buildfamelist();
break;
}
}
@@ -7617,7 +7944,7 @@ int pc_changelook(struct map_session_data *sd,int type,int val)
switch(type){
case LOOK_BASE:
- status_set_viewdata(&sd->bl, val);
+ status->set_viewdata(&sd->bl, val);
clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_);
clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
if (sd->vd.cloth_color)
@@ -7631,7 +7958,7 @@ int pc_changelook(struct map_session_data *sd,int type,int val)
if (sd->status.hair != val) {
sd->status.hair=val;
if (sd->status.guild_id) //Update Guild Window. [Skotlex]
- intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id,
+ intif->guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id,
GMI_HAIR,&sd->status.hair,sizeof(sd->status.hair));
}
break;
@@ -7653,7 +7980,7 @@ int pc_changelook(struct map_session_data *sd,int type,int val)
if (sd->status.hair_color != val) {
sd->status.hair_color=val;
if (sd->status.guild_id) //Update Guild Window. [Skotlex]
- intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id,
+ intif->guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id,
GMI_HAIR_COLOR,&sd->status.hair_color,sizeof(sd->status.hair_color));
}
break;
@@ -7691,11 +8018,11 @@ int pc_setoption(struct map_session_data *sd,int type)
if( (type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc->checkskill(sd,RK_DRAGONTRAINING) > 0) ) {
// Mounting
clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_RIDING, 0, 0, 0);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
} else if( (!(type&OPTION_RIDING) && p_type&OPTION_RIDING) || (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON) ) {
// Dismount
clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_RIDING);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
#ifndef NEW_CARTS
@@ -7703,11 +8030,11 @@ int pc_setoption(struct map_session_data *sd,int type)
clif->cartlist(sd);
clif->updatestatus(sd, SP_CARTINFO);
if(pc->checkskill(sd, MC_PUSHCART) < 10)
- status_calc_pc(sd,0); //Apply speed penalty.
+ status_calc_pc(sd,SCO_NONE); //Apply speed penalty.
} else if( !( type&OPTION_CART ) && p_type&OPTION_CART ){ //Cart Off
clif->clearcart(sd->fd);
if(pc->checkskill(sd, MC_PUSHCART) < 10)
- status_calc_pc(sd,0); //Remove speed penalty.
+ status_calc_pc(sd,SCO_NONE); //Remove speed penalty.
}
#endif
@@ -7716,25 +8043,24 @@ int pc_setoption(struct map_session_data *sd,int type)
else if (!(type&OPTION_FALCON) && p_type&OPTION_FALCON) //Falcon OFF
clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_FALCON);
- if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) {
- if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting
- clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER, 0, 0, 0);
- status_calc_pc(sd,0);
- } else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount
- clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER);
- status_calc_pc(sd,0);
- }
+ if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting
+ clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER, 0, 0, 0);
+ status_calc_pc(sd,SCO_NONE);
+ } else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount
+ clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER);
+ status_calc_pc(sd,SCO_NONE);
}
- if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) {
+
+ if( (type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR))
+ || (!(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR) ) {
int i;
- if( type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR) )
- status_calc_pc(sd, 0);
- else if( !(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR )
- status_calc_pc(sd, 0);
- for( i = 0; i < SC_MAX; i++ ){
- if ( !sd->sc.data[i] || !status_get_sc_type(i) )
+ status_calc_pc(sd, SCO_NONE);
+
+ // End all SCs that can be reset when mado is taken off
+ for( i = 0; i < SC_MAX; i++ ) {
+ if ( !sd->sc.data[i] || !status->get_sc_type(i) )
continue;
- if ( status_get_sc_type(i)&SC_MADO_NO_RESET )
+ if ( status->get_sc_type(i)&SC_MADO_NO_RESET )
continue;
switch (i) {
case SC_BERSERK:
@@ -7755,7 +8081,7 @@ int pc_setoption(struct map_session_data *sd,int type)
return 0; //Disguises break sprite changes
if (new_look < 0) { //Restore normal look.
- status_set_viewdata(&sd->bl, sd->status.class_);
+ status->set_viewdata(&sd->bl, sd->status.class_);
new_look = sd->vd.class_;
}
@@ -7773,7 +8099,7 @@ int pc_setoption(struct map_session_data *sd,int type)
*------------------------------------------*/
int pc_setcart(struct map_session_data *sd,int type) {
#ifndef NEW_CARTS
- int cart[6] = {0x0000,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5};
+ int cart[6] = {OPTION_NOTHING,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5};
int option;
#endif
nullpo_ret(sd);
@@ -7801,7 +8127,7 @@ int pc_setcart(struct map_session_data *sd,int type) {
if( !sd->sc.data[SC_PUSH_CART] ) /* first time, so fill cart data */
clif->cartlist(sd);
clif->updatestatus(sd, SP_CARTINFO);
- sc_start(&sd->bl, SC_PUSH_CART, 100, type, 0);
+ sc_start(NULL,&sd->bl, SC_PUSH_CART, 100, type, 0);
clif->sc_load(&sd->bl, sd->bl.id, AREA, SI_ON_PUSH_CART, type, 0, 0);
if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */
sd->sc.data[SC_PUSH_CART]->val1 = type;
@@ -7809,7 +8135,7 @@ int pc_setcart(struct map_session_data *sd,int type) {
}
if(pc->checkskill(sd, MC_PUSHCART) < 10)
- status_calc_pc(sd,0); //Recalc speed penalty.
+ status_calc_pc(sd,SCO_NONE); //Recalc speed penalty.
#else
// Update option
option = sd->sc.option;
@@ -7851,375 +8177,322 @@ int pc_setriding(TBL_PC* sd, int flag)
return 0;
}
-/*==========================================
- * Give player a mado
- *------------------------------------------*/
-int pc_setmadogear(TBL_PC* sd, int flag)
-{
- if( flag ){
- if( pc->checkskill(sd,NC_MADOLICENCE) > 0 )
+/**
+ * Gives player a mado
+ * @param flag 1 Set mado
+ **/
+void pc_setmadogear( struct map_session_data *sd, int flag ) {
+ if( flag ) {
+ if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC )
pc->setoption(sd, sd->sc.option|OPTION_MADOGEAR);
- } else if( pc_ismadogear(sd) ){
- pc->setoption(sd, sd->sc.option&~OPTION_MADOGEAR);
- }
+ } else if( pc_ismadogear(sd) )
+ pc->setoption(sd, sd->sc.option&~OPTION_MADOGEAR);
- return 0;
-}
-
-/*==========================================
- * Check if player can drop an item
- *------------------------------------------*/
-int pc_candrop(struct map_session_data *sd, struct item *item)
-{
- if( item && item->expire_time )
- return 0;
- if( !pc->can_give_items(sd) ) //check if this GM level can drop items
- return 0;
- return (itemdb_isdropable(item, pc->get_group_level(sd)));
+ return;
}
-/*==========================================
- * Read ram register for player sd
- * get val (int) from reg for player sd
- *------------------------------------------*/
-int pc_readreg(struct map_session_data* sd, int reg)
-{
- int i;
+/**
+ * Determines whether a player can attack based on status changes
+ * Why not use status_check_skilluse?
+ * "src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack."
+ * Even ground-based attacks should be blocked by these statuses
+ * Called from unit_attack and unit_attack_timer_sub
+ * @retval true Can attack
+ **/
+bool pc_can_attack( struct map_session_data *sd, int target_id ) {
+ nullpo_retr(false, sd);
- nullpo_ret(sd);
+ if( sd->sc.data[SC_BASILICA] ||
+ sd->sc.data[SC__SHADOWFORM] ||
+ sd->sc.data[SC__MANHOLE] ||
+ sd->sc.data[SC_CURSEDCIRCLE_ATKER] ||
+ sd->sc.data[SC_CURSEDCIRCLE_TARGET] ||
+ sd->sc.data[SC_COLD] ||
+ sd->sc.data[SC_ALL_RIDING] || // The client doesn't let you, this is to make cheat-safe
+ sd->sc.data[SC_TRICKDEAD] ||
+ (sd->sc.data[SC_SIREN] && sd->sc.data[SC_SIREN]->val2 == target_id) ||
+ sd->sc.data[SC_BLADESTOP] ||
+ sd->sc.data[SC_DEEP_SLEEP] ||
+ sd->sc.data[SC_FALLENEMPIRE] )
+ return false;
- ARR_FIND( 0, sd->reg_num, i, sd->reg[i].index == reg );
- return ( i < sd->reg_num ) ? sd->reg[i].data : 0;
+ return true;
}
-/*==========================================
- * Set ram register for player sd
- * memo val(int) at reg for player sd
- *------------------------------------------*/
-int pc_setreg(struct map_session_data* sd, int reg, int val)
-{
- int i;
- nullpo_ret(sd);
-
- ARR_FIND( 0, sd->reg_num, i, sd->reg[i].index == reg );
- if( i < sd->reg_num )
- {// overwrite existing entry
- sd->reg[i].data = val;
- return 1;
- }
+/**
+ * Determines whether a player can talk/whisper based on status changes
+ * Called from clif_parse_GlobalMessage and clif_parse_WisMessage
+ * @retval true Can talk
+ **/
+bool pc_can_talk( struct map_session_data *sd ) {
+ nullpo_retr(false, sd);
- ARR_FIND( 0, sd->reg_num, i, sd->reg[i].data == 0 );
- if( i == sd->reg_num )
- {// nothing free, increase size
- sd->reg_num++;
- RECREATE(sd->reg, struct script_reg, sd->reg_num);
- }
- sd->reg[i].index = reg;
- sd->reg[i].data = val;
+ if( sd->sc.data[SC_BERSERK] ||
+ (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
+ (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
+ return false;
- return 1;
+ return true;
}
/*==========================================
- * Read ram register for player sd
- * get val (str) from reg for player sd
+ * Check if player can drop an item
*------------------------------------------*/
-char* pc_readregstr(struct map_session_data* sd, int reg)
+int pc_candrop(struct map_session_data *sd, struct item *item)
{
- int i;
+ if( item && (item->expire_time || (item->bound && !pc_can_give_bound_items(sd))) )
+ return 0;
+ if( !pc_can_give_items(sd) ) //check if this GM level can drop items
+ return 0;
+ return (itemdb_isdropable(item, pc_get_group_level(sd)));
+}
+/**
+ * For '@type' variables (temporary numeric char reg)
+ **/
+int pc_readreg(struct map_session_data* sd, int64 reg) {
+ return i64db_iget(sd->regs.vars, reg);
+}
+/**
+ * For '@type' variables (temporary numeric char reg)
+ **/
+void pc_setreg(struct map_session_data* sd, int64 reg, int val) {
+ unsigned int index = script_getvaridx(reg);
+
+ if( val ) {
+ i64db_iput(sd->regs.vars, reg, val);
+ if( index )
+ script->array_update(&sd->regs, reg, false);
+ } else {
+ i64db_remove(sd->regs.vars, reg);
+ if( index )
+ script->array_update(&sd->regs, reg, true);
+ }
+}
- nullpo_ret(sd);
+/**
+ * For '@type$' variables (temporary string char reg)
+ **/
+char* pc_readregstr(struct map_session_data* sd, int64 reg) {
+ struct script_reg_str *p = NULL;
- ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].index == reg );
- return ( i < sd->regstr_num ) ? sd->regstr[i].data : NULL;
+ p = i64db_get(sd->regs.vars, reg);
+
+ return p ? p->value : NULL;
}
-/*==========================================
- * Set ram register for player sd
- * memo val(str) at reg for player sd
- *------------------------------------------*/
-int pc_setregstr(struct map_session_data* sd, int reg, const char* str)
-{
- int i;
-
- nullpo_ret(sd);
+/**
+ * For '@type$' variables (temporary string char reg)
+ **/
+void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) {
+ struct script_reg_str *p = NULL;
+ unsigned int index = script_getvaridx(reg);
+ DBData prev;
- ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].index == reg );
- if( i < sd->regstr_num )
- {// found entry, update
- if( str == NULL || *str == '\0' )
- {// empty string
- if( sd->regstr[i].data != NULL )
- aFree(sd->regstr[i].data);
- sd->regstr[i].data = NULL;
- }
- else if( sd->regstr[i].data )
- {// recreate
- size_t len = strlen(str)+1;
- RECREATE(sd->regstr[i].data, char, len);
- memcpy(sd->regstr[i].data, str, len*sizeof(char));
+ if( str[0] ) {
+ p = ers_alloc(pc->str_reg_ers, struct script_reg_str);
+
+ p->value = aStrdup(str);
+ p->flag.type = 1;
+
+ if( sd->regs.vars->put(sd->regs.vars, DB->i642key(reg), DB->ptr2data(p), &prev) ) {
+ p = DB->data2ptr(&prev);
+ if( p->value )
+ aFree(p->value);
+ ers_free(pc->str_reg_ers, p);
+ } else {
+ if( index )
+ script->array_update(&sd->regs, reg, false);
}
- else
- {// create
- sd->regstr[i].data = aStrdup(str);
+ } else {
+ if( sd->regs.vars->remove(sd->regs.vars, DB->i642key(reg), &prev) ) {
+ p = DB->data2ptr(&prev);
+ if( p->value )
+ aFree(p->value);
+ ers_free(pc->str_reg_ers, p);
+ if( index )
+ script->array_update(&sd->regs, reg, true);
}
- return 1;
}
-
- if( str == NULL || *str == '\0' )
- return 1;// nothing to add, empty string
-
- ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].data == NULL );
- if( i == sd->regstr_num )
- {// nothing free, increase size
- sd->regstr_num++;
- RECREATE(sd->regstr, struct script_regstr, sd->regstr_num);
- }
- sd->regstr[i].index = reg;
- sd->regstr[i].data = aStrdup(str);
-
- return 1;
}
-
-int pc_readregistry(struct map_session_data *sd,const char *reg,int type)
-{
- struct global_reg *sd_reg;
- int i,max;
-
- nullpo_ret(sd);
- switch (type) {
- case 3: //Char reg
- sd_reg = sd->save_reg.global;
- max = sd->save_reg.global_num;
- break;
- case 2: //Account reg
- sd_reg = sd->save_reg.account;
- max = sd->save_reg.account_num;
- break;
- case 1: //Account2 reg
- sd_reg = sd->save_reg.account2;
- max = sd->save_reg.account2_num;
- break;
- default:
- return 0;
- }
- if (max == -1) {
- ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type);
+/**
+ * Serves the following variable types:
+ * - 'type' (permanent nuneric char reg)
+ * - '#type' (permanent numeric account reg)
+ * - '##type' (permanent numeric account reg2)
+ **/
+int pc_readregistry(struct map_session_data *sd, int64 reg) {
+ struct script_reg_num *p = NULL;
+
+ if (!sd->vars_ok) {
+ ShowError("pc_readregistry: Trying to read reg %s before it's been loaded!\n", script->get_str(script_getvarid(reg)));
//This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again.
- intif_request_registry(sd,type==3?4:type);
+ //intif->request_registry(sd,type==3?4:type);
+ set_eof(sd->fd);
return 0;
}
+
+ p = i64db_get(sd->regs.vars, reg);
- ARR_FIND( 0, max, i, strcmp(sd_reg[i].str,reg) == 0 );
- return ( i < max ) ? atoi(sd_reg[i].value) : 0;
+ return p ? p->value : 0;
}
-
-char* pc_readregistry_str(struct map_session_data *sd,const char *reg,int type)
-{
- struct global_reg *sd_reg;
- int i,max;
-
- nullpo_ret(sd);
- switch (type) {
- case 3: //Char reg
- sd_reg = sd->save_reg.global;
- max = sd->save_reg.global_num;
- break;
- case 2: //Account reg
- sd_reg = sd->save_reg.account;
- max = sd->save_reg.account_num;
- break;
- case 1: //Account2 reg
- sd_reg = sd->save_reg.account2;
- max = sd->save_reg.account2_num;
- break;
- default:
- return NULL;
- }
- if (max == -1) {
- ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type);
+/**
+ * Serves the following variable types:
+ * - 'type$' (permanent str char reg)
+ * - '#type$' (permanent str account reg)
+ * - '##type$' (permanent str account reg2)
+ **/
+char* pc_readregistry_str(struct map_session_data *sd, int64 reg) {
+ struct script_reg_str *p = NULL;
+
+ if (!sd->vars_ok) {
+ ShowError("pc_readregistry_str: Trying to read reg %s before it's been loaded!\n", script->get_str(script_getvarid(reg)));
//This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again.
- intif_request_registry(sd,type==3?4:type);
+ //intif->request_registry(sd,type==3?4:type);
+ set_eof(sd->fd);
return NULL;
}
- ARR_FIND( 0, max, i, strcmp(sd_reg[i].str,reg) == 0 );
- return ( i < max ) ? sd_reg[i].value : NULL;
+ p = i64db_get(sd->regs.vars, reg);
+
+ return p ? p->value : NULL;
}
-
-int pc_setregistry(struct map_session_data *sd,const char *reg,int val,int type)
-{
- struct global_reg *sd_reg;
- int i,*max, regmax;
-
- nullpo_ret(sd);
-
- switch( type )
- {
- case 3: //Char reg
- if( !strcmp(reg,"PC_DIE_COUNTER") && sd->die_counter != val )
- {
- i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
- sd->die_counter = val;
- if( i )
- status_calc_pc(sd,0); // Lost the bonus.
- }
- else if( !strcmp(reg,"COOK_MASTERY") && sd->cook_mastery != val )
- {
- val = cap_value(val, 0, 1999);
- sd->cook_mastery = val;
- }
- sd_reg = sd->save_reg.global;
- max = &sd->save_reg.global_num;
- regmax = GLOBAL_REG_NUM;
- break;
- case 2: //Account reg
- if( !strcmp(reg,"#CASHPOINTS") && sd->cashPoints != val )
- {
- val = cap_value(val, 0, MAX_ZENY);
- sd->cashPoints = val;
- }
- else if( !strcmp(reg,"#KAFRAPOINTS") && sd->kafraPoints != val )
- {
- val = cap_value(val, 0, MAX_ZENY);
- sd->kafraPoints = val;
- }
- sd_reg = sd->save_reg.account;
- max = &sd->save_reg.account_num;
- regmax = ACCOUNT_REG_NUM;
- break;
- case 1: //Account2 reg
- sd_reg = sd->save_reg.account2;
- max = &sd->save_reg.account2_num;
- regmax = ACCOUNT_REG2_NUM;
- break;
- default:
- return 0;
+/**
+ * Serves the following variable types:
+ * - 'type' (permanent nuneric char reg)
+ * - '#type' (permanent numeric account reg)
+ * - '##type' (permanent numeric account reg2)
+ **/
+int pc_setregistry(struct map_session_data *sd, int64 reg, int val) {
+ struct script_reg_num *p = NULL;
+ int i;
+ const char *regname = script->get_str( script_getvarid(reg) );
+ unsigned int index = script_getvaridx(reg);
+
+ /* SAAD! those things should be stored elsewhere e.g. char ones in char table, the cash ones in account_data table! */
+ switch( regname[0] ) {
+ default: //Char reg
+ if( !strcmp(regname,"PC_DIE_COUNTER") && sd->die_counter != val ) {
+ i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
+ sd->die_counter = val;
+ if( i )
+ status_calc_pc(sd,SCO_NONE); // Lost the bonus.
+ } else if( !strcmp(regname,"COOK_MASTERY") && sd->cook_mastery != val ) {
+ val = cap_value(val, 0, 1999);
+ sd->cook_mastery = val;
+ }
+ break;
+ case '#':
+ if( !strcmp(regname,"#CASHPOINTS") && sd->cashPoints != val ) {
+ val = cap_value(val, 0, MAX_ZENY);
+ sd->cashPoints = val;
+ } else if( !strcmp(regname,"#KAFRAPOINTS") && sd->kafraPoints != val ) {
+ val = cap_value(val, 0, MAX_ZENY);
+ sd->kafraPoints = val;
+ }
+ break;
}
- if (*max == -1) {
- ShowError("pc_setregistry : refusing to set %s (type %d) until vars are received.\n", reg, type);
- return 1;
+
+ if ( !pc->reg_load && !sd->vars_ok ) {
+ ShowError("pc_setregistry : refusing to set %s until vars are received.\n", regname);
+ return 0;
}
-
- // delete reg
- if (val == 0) {
- ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
- if( i < *max )
- {
- if (i != *max - 1)
- memcpy(&sd_reg[i], &sd_reg[*max - 1], sizeof(struct global_reg));
- memset(&sd_reg[*max - 1], 0, sizeof(struct global_reg));
- (*max)--;
- sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
+
+ if( (p = i64db_get(sd->regs.vars, reg) ) ) {
+ if( val ) {
+ if( !p->value && index ) /* its a entry that was deleted, so we reset array */
+ script->array_update(&sd->regs, reg, false);
+ p->value = val;
+ } else {
+ p->value = 0;
+ if( index )
+ script->array_update(&sd->regs, reg, true);
+ }
+ if( !pc->reg_load )
+ p->flag.update = 1;/* either way, it will require either delete or replace */
+ } else if( val ) {
+ DBData prev;
+
+ if( index )
+ script->array_update(&sd->regs, reg, false);
+
+ p = ers_alloc(pc->num_reg_ers, struct script_reg_num);
+
+ p->value = val;
+ if( !pc->reg_load )
+ p->flag.update = 1;
+
+ if( sd->regs.vars->put(sd->regs.vars, DB->i642key(reg), DB->ptr2data(p), &prev) ) {
+ p = DB->data2ptr(&prev);
+ ers_free(pc->num_reg_ers, p);
}
- return 1;
}
- // change value if found
- ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
- if( i < *max )
- {
- safesnprintf(sd_reg[i].value, sizeof(sd_reg[i].value), "%d", val);
- sd->state.reg_dirty |= 1<<(type-1);
- return 1;
- }
-
- // add value if not found
- if (i < regmax) {
- memset(&sd_reg[i], 0, sizeof(struct global_reg));
- safestrncpy(sd_reg[i].str, reg, sizeof(sd_reg[i].str));
- safesnprintf(sd_reg[i].value, sizeof(sd_reg[i].value), "%d", val);
- (*max)++;
- sd->state.reg_dirty |= 1<<(type-1);
- return 1;
- }
-
- ShowError("pc_setregistry : couldn't set %s, limit of registries reached (%d)\n", reg, regmax);
+
+ if( !pc->reg_load && p )
+ sd->vars_dirty = true;
- return 0;
+ return 1;
}
+/**
+ * Serves the following variable types:
+ * - 'type$' (permanent str char reg)
+ * - '#type$' (permanent str account reg)
+ * - '##type$' (permanent str account reg2)
+ **/
+int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val) {
+ struct script_reg_str *p = NULL;
+ const char *regname = script->get_str( script_getvarid(reg) );
+ unsigned int index = script_getvaridx(reg);
-int pc_setregistry_str(struct map_session_data *sd,const char *reg,const char *val,int type)
-{
- struct global_reg *sd_reg;
- int i,*max, regmax;
-
- nullpo_ret(sd);
- if (reg[strlen(reg)-1] != '$') {
- ShowError("pc_setregistry_str : reg %s must be string (end in '$') to use this!\n", reg);
+ if ( !pc->reg_load && !sd->vars_ok ) {
+ ShowError("pc_setregistry_str : refusing to set %s until vars are received.\n", regname);
return 0;
}
- switch (type) {
- case 3: //Char reg
- sd_reg = sd->save_reg.global;
- max = &sd->save_reg.global_num;
- regmax = GLOBAL_REG_NUM;
- break;
- case 2: //Account reg
- sd_reg = sd->save_reg.account;
- max = &sd->save_reg.account_num;
- regmax = ACCOUNT_REG_NUM;
- break;
- case 1: //Account2 reg
- sd_reg = sd->save_reg.account2;
- max = &sd->save_reg.account2_num;
- regmax = ACCOUNT_REG2_NUM;
- break;
- default:
- return 0;
- }
- if (*max == -1) {
- ShowError("pc_setregistry_str : refusing to set %s (type %d) until vars are received.\n", reg, type);
- return 0;
- }
-
- // delete reg
- if (!val || strcmp(val,"")==0)
- {
- ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
- if( i < *max )
- {
- if (i != *max - 1)
- memcpy(&sd_reg[i], &sd_reg[*max - 1], sizeof(struct global_reg));
- memset(&sd_reg[*max - 1], 0, sizeof(struct global_reg));
- (*max)--;
- sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
- if (type!=3) intif_saveregistry(sd,type);
+ if( (p = i64db_get(sd->regs.vars, reg) ) ) {
+ if( val[0] ) {
+ if( p->value )
+ aFree(p->value);
+ else if ( index ) /* a entry that was deleted, so we reset */
+ script->array_update(&sd->regs, reg, false);
+ p->value = aStrdup(val);
+ } else {
+ p->value = NULL;
+ if( index )
+ script->array_update(&sd->regs, reg, true);
}
- return 1;
- }
+ if( !pc->reg_load )
+ p->flag.update = 1;/* either way, it will require either delete or replace */
+ } else if( val[0] ) {
+ DBData prev;
- // change value if found
- ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
- if( i < *max )
- {
- safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value));
- sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
- if (type!=3) intif_saveregistry(sd,type);
- return 1;
- }
+ if( index )
+ script->array_update(&sd->regs, reg, false);
- // add value if not found
- if (i < regmax) {
- memset(&sd_reg[i], 0, sizeof(struct global_reg));
- safestrncpy(sd_reg[i].str, reg, sizeof(sd_reg[i].str));
- safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value));
- (*max)++;
- sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
- if (type!=3) intif_saveregistry(sd,type);
- return 1;
+ p = ers_alloc(pc->str_reg_ers, struct script_reg_str);
+
+ p->value = aStrdup(val);
+ if( !pc->reg_load )
+ p->flag.update = 1;
+ p->flag.type = 1;
+
+ if( sd->regs.vars->put(sd->regs.vars, DB->i642key(reg), DB->ptr2data(p), &prev) ) {
+ p = DB->data2ptr(&prev);
+ if( p->value )
+ aFree(p->value);
+ ers_free(pc->str_reg_ers, p);
+ }
}
-
- ShowError("pc_setregistry : couldn't set %s, limit of registries reached (%d)\n", reg, regmax);
-
- return 0;
+
+ if( !pc->reg_load && p )
+ sd->vars_dirty = true;
+
+ return 1;
}
/*==========================================
* Exec eventtimer for player sd (retrieved from map_session (id))
*------------------------------------------*/
-static int pc_eventtimer(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct map_session_data *sd=iMap->id2sd(id);
+int pc_eventtimer(int tid, int64 tick, int id, intptr_t data) {
+ struct map_session_data *sd=map->id2sd(id);
char *p = (char *)data;
int i;
if(sd==NULL)
@@ -8230,7 +8503,7 @@ static int pc_eventtimer(int tid, unsigned int tick, int id, intptr_t data)
{
sd->eventtimer[i] = INVALID_TIMER;
sd->eventcount--;
- npc_event(sd,p,0);
+ npc->event(sd,p,0);
}
else
ShowError("pc_eventtimer: no such event timer\n");
@@ -8251,7 +8524,7 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name)
if( i == MAX_EVENTTIMER )
return 0;
- sd->eventtimer[i] = iTimer->add_timer(iTimer->gettick()+tick, pc_eventtimer, sd->bl.id, (intptr_t)aStrdup(name));
+ sd->eventtimer[i] = timer->add(timer->gettick()+tick, pc->eventtimer, sd->bl.id, (intptr_t)aStrdup(name));
sd->eventcount++;
return 1;
@@ -8273,13 +8546,13 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name)
// find the named event timer
ARR_FIND( 0, MAX_EVENTTIMER, i,
sd->eventtimer[i] != INVALID_TIMER &&
- (p = (char *)(iTimer->get_timer(sd->eventtimer[i])->data)) != NULL &&
+ (p = (char *)(timer->get(sd->eventtimer[i])->data)) != NULL &&
strcmp(p, name) == 0
);
if( i == MAX_EVENTTIMER )
return 0; // not found
- iTimer->delete_timer(sd->eventtimer[i],pc_eventtimer);
+ timer->delete(sd->eventtimer[i],pc->eventtimer);
sd->eventtimer[i] = INVALID_TIMER;
sd->eventcount--;
aFree(p);
@@ -8298,8 +8571,8 @@ int pc_addeventtimercount(struct map_session_data *sd,const char *name,int tick)
for(i=0;i<MAX_EVENTTIMER;i++)
if( sd->eventtimer[i] != INVALID_TIMER && strcmp(
- (char *)(iTimer->get_timer(sd->eventtimer[i])->data), name)==0 ){
- iTimer->addtick_timer(sd->eventtimer[i],tick);
+ (char *)(timer->get(sd->eventtimer[i])->data), name)==0 ){
+ timer->addtick(sd->eventtimer[i],tick);
break;
}
@@ -8320,8 +8593,8 @@ int pc_cleareventtimer(struct map_session_data *sd)
for(i=0;i<MAX_EVENTTIMER;i++)
if( sd->eventtimer[i] != INVALID_TIMER ){
- char *p = (char *)(iTimer->get_timer(sd->eventtimer[i])->data);
- iTimer->delete_timer(sd->eventtimer[i],pc_eventtimer);
+ char *p = (char *)(timer->get(sd->eventtimer[i])->data);
+ timer->delete(sd->eventtimer[i],pc->eventtimer);
sd->eventtimer[i] = INVALID_TIMER;
sd->eventcount--;
if (p) aFree(p);
@@ -8331,17 +8604,19 @@ int pc_cleareventtimer(struct map_session_data *sd)
/* called when a item with combo is worn */
int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
int i, j, k, z;
- int index, idx, success = 0;
+ int index, success = 0;
+ struct pc_combos *combo;
for( i = 0; i < data->combos_count; i++ ) {
/* ensure this isn't a duplicate combo */
- if( sd->combos.bonus != NULL ) {
+ if( sd->combos != NULL ) {
int x;
- ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id );
+
+ ARR_FIND( 0, sd->combo_count, x, sd->combos[x].id == data->combos[i]->id );
/* found a match, skip this combo */
- if( x < sd->combos.count )
+ if( x < sd->combo_count )
continue;
}
@@ -8358,7 +8633,7 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
if(!sd->inventory_data[index])
continue;
-
+
if ( itemdb_type(id) != IT_CARD ) {
if ( sd->inventory_data[index]->nameid != id )
continue;
@@ -8392,24 +8667,16 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
/* we got here, means all items in the combo are matching */
- idx = sd->combos.count;
-
- if( sd->combos.bonus == NULL ) {
- CREATE(sd->combos.bonus, struct script_code *, 1);
- CREATE(sd->combos.id, unsigned short, 1);
- sd->combos.count = 1;
- } else {
- RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count);
- RECREATE(sd->combos.id, unsigned short, sd->combos.count);
- }
-
- /* we simply copy the pointer */
- sd->combos.bonus[idx] = data->combos[i]->script;
- /* save this combo's id */
- sd->combos.id[idx] = data->combos[i]->id;
-
+ RECREATE(sd->combos, struct pc_combos, ++sd->combo_count);
+
+ combo = &sd->combos[sd->combo_count - 1];
+
+ combo->bonus = data->combos[i]->script;
+ combo->id = data->combos[i]->id;
+
success++;
}
+
return success;
}
@@ -8417,45 +8684,45 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
int i, retval = 0;
- if( sd->combos.bonus == NULL )
+ if( !sd->combos )
return 0;/* nothing to do here, player has no combos */
+
for( i = 0; i < data->combos_count; i++ ) {
/* check if this combo exists in this user */
int x = 0, cursor = 0, j;
- ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id );
+
+ ARR_FIND( 0, sd->combo_count, x, sd->combos[x].id == data->combos[i]->id );
/* no match, skip this combo */
- if( !(x < sd->combos.count) )
+ if( x == sd->combo_count )
continue;
- sd->combos.bonus[x] = NULL;
- sd->combos.id[x] = 0;
+ sd->combos[x].bonus = NULL;
+ sd->combos[x].id = 0;
+
retval++;
- for( j = 0, cursor = 0; j < sd->combos.count; j++ ) {
- if( sd->combos.bonus[j] == NULL )
+
+ for( j = 0, cursor = 0; j < sd->combo_count; j++ ) {
+ if( sd->combos[j].bonus == NULL )
continue;
if( cursor != j ) {
- sd->combos.bonus[cursor] = sd->combos.bonus[j];
- sd->combos.id[cursor] = sd->combos.id[j];
+ sd->combos[cursor].bonus = sd->combos[j].bonus;
+ sd->combos[cursor].id = sd->combos[j].id;
}
cursor++;
}
- /* check if combo requirements still fit */
- if( pc_checkcombo( sd, data ) )
- continue;
-
/* it's empty, we can clear all the memory */
- if( (sd->combos.count = cursor) == 0 ) {
- aFree(sd->combos.bonus);
- aFree(sd->combos.id);
- sd->combos.bonus = NULL;
- sd->combos.id = NULL;
- return retval; /* we also can return at this point for we have no more combos to check */
+ if( (sd->combo_count = cursor) == 0 ) {
+ aFree(sd->combos);
+ sd->combos = NULL;
+ break;
}
-
}
+
+ /* check if combo requirements still fit -- don't touch retval! */
+ pc->checkcombo( sd, data );
return retval;
}
@@ -8467,16 +8734,16 @@ int pc_load_combo(struct map_session_data *sd) {
if( sd->equip_index[i] < 0 || !(id = sd->inventory_data[idx] ) )
continue;
if( id->combos_count )
- ret += pc_checkcombo(sd,id);
+ ret += pc->checkcombo(sd,id);
if(!itemdb_isspecial(sd->status.inventory[idx].card[0])) {
struct item_data *data;
int j;
for( j = 0; j < id->slot; j++ ) {
if (!sd->status.inventory[idx].card[j])
continue;
- if ( ( data = itemdb_exists(sd->status.inventory[idx].card[j]) ) != NULL ) {
+ if ( ( data = itemdb->exists(sd->status.inventory[idx].card[j]) ) != NULL ) {
if( data->combos_count )
- ret += pc_checkcombo(sd,data);
+ ret += pc->checkcombo(sd,data);
}
}
}
@@ -8494,13 +8761,13 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
nullpo_ret(sd);
if( n < 0 || n >= MAX_INVENTORY ) {
- clif->equipitemack(sd,0,0,0);
+ clif->equipitemack(sd,0,0,EIA_FAIL);
return 0;
}
- if( DIFF_TICK(sd->canequip_tick,iTimer->gettick()) > 0 )
+ if( DIFF_TICK(sd->canequip_tick,timer->gettick()) > 0 )
{
- clif->equipitemack(sd,n,0,0);
+ clif->equipitemack(sd,n,0,EIA_FAIL);
return 0;
}
@@ -8511,27 +8778,38 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
ShowInfo("equip %d(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos);
if(!pc->isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris]
// FIXME: pc->isequip: equip level failure uses 2 instead of 0
- clif->equipitemack(sd,n,0,0); // fail
+ clif->equipitemack(sd,n,0,EIA_FAIL); // fail
return 0;
}
- if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAY_NIGHT_FEVER] || sd->sc.data[SC__BLOODYLUST])
+ if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP])
{
- clif->equipitemack(sd,n,0,0); // fail
+ clif->equipitemack(sd,n,0,EIA_FAIL); // fail
return 0;
}
+ /* won't fail from this point onwards */
+ if( id->flag.bindonequip && !sd->status.inventory[n].bound ) {
+ sd->status.inventory[n].bound = (unsigned char)IBT_CHARACTER;
+ clif->notify_bounditem(sd,n);
+ }
+
if(pos == EQP_ACC) { //Accesories should only go in one of the two,
pos = req_pos&EQP_ACC;
if (pos == EQP_ACC) //User specified both slots..
pos = sd->equip_index[EQI_ACC_R] >= 0 ? EQP_ACC_L : EQP_ACC_R;
- }
-
- if(pos == EQP_ARMS && id->equip == EQP_HAND_R)
- { //Dual wield capable weapon.
+ } else if(pos == EQP_ARMS && id->equip == EQP_HAND_R) { //Dual wield capable weapon.
pos = (req_pos&EQP_ARMS);
if (pos == EQP_ARMS) //User specified both slots, pick one for them.
pos = sd->equip_index[EQI_HAND_R] >= 0 ? EQP_HAND_L : EQP_HAND_R;
+ } else if(pos == EQP_SHADOW_ACC) { //Accesories should only go in one of the two,
+ pos = req_pos&EQP_SHADOW_ACC;
+ if (pos == EQP_SHADOW_ACC) //User specified both slots..
+ pos = sd->equip_index[EQI_SHADOW_ACC_R] >= 0 ? EQP_SHADOW_ACC_L : EQP_SHADOW_ACC_R;
+ } else if( pos == EQP_SHADOW_ARMS && id->equip == EQP_SHADOW_WEAPON) { //Dual wield capable weapon.
+ pos = (req_pos&EQP_SHADOW_ARMS);
+ if (pos == EQP_SHADOW_ARMS) //User specified both slots, pick one for them.
+ pos = sd->equip_index[EQI_SHADOW_WEAPON] >= 0 ? EQP_SHADOW_SHIELD : EQP_SHADOW_WEAPON;
}
if (pos&EQP_HAND_R && battle_config.use_weapon_skill_range&BL_PC)
@@ -8544,7 +8822,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
}
for(i=0;i<EQI_MAX;i++) {
- if(pos & equip_pos[i]) {
+ if(pos & pc->equip_pos[i]) {
if(sd->equip_index[i] >= 0) //Slot taken, remove item from there.
pc->unequipitem(sd,sd->equip_index[i],2);
@@ -8557,33 +8835,30 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
clif->arrow_fail(sd,3);
}
else
- clif->equipitemack(sd,n,pos,1);
+ clif->equipitemack(sd,n,pos,EIA_SUCCESS);
sd->status.inventory[n].equip=pos;
- if(pos & EQP_HAND_R) {
+ if(pos & (EQP_HAND_R|EQP_SHADOW_WEAPON)) {
if(id)
sd->weapontype1 = id->look;
else
sd->weapontype1 = 0;
- pc_calcweapontype(sd);
+ pc->calcweapontype(sd);
clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
}
- if(pos & EQP_HAND_L) {
+ if(pos & (EQP_HAND_L|EQP_SHADOW_SHIELD)) {
if(id) {
if(id->type == IT_WEAPON) {
sd->status.shield = 0;
sd->weapontype2 = id->look;
- }
- else
- if(id->type == IT_ARMOR) {
+ } else if(id->type == IT_ARMOR) {
sd->status.shield = id->look;
sd->weapontype2 = 0;
}
- }
- else
+ } else
sd->status.shield = sd->weapontype2 = 0;
- pc_calcweapontype(sd);
+ pc->calcweapontype(sd);
clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
}
//Added check to prevent sending the same look on multiple slots ->
@@ -8650,7 +8925,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
/* check for combos (MUST be before status_calc_pc) */
if ( id ) {
if( id->combos_count )
- pc_checkcombo(sd,id);
+ pc->checkcombo(sd,id);
if(itemdb_isspecial(sd->status.inventory[n].card[0]))
; //No cards
else {
@@ -8658,22 +8933,22 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
struct item_data *data;
if (!sd->status.inventory[n].card[i])
continue;
- if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
+ if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
if( data->combos_count )
- pc_checkcombo(sd,data);
+ pc->checkcombo(sd,data);
}
}
}
}
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
if (flag) //Update skill data
clif->skillinfoblock(sd);
//OnEquip script [Skotlex]
if (id) {
if (id->equip_script)
- run_script(id->equip_script,0,sd->bl.id,fake_nd->bl.id);
+ script->run(id->equip_script,0,sd->bl.id,npc->fake_nd->bl.id);
if(itemdb_isspecial(sd->status.inventory[n].card[0]))
; //No cards
else {
@@ -8681,9 +8956,9 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
struct item_data *data;
if (!sd->status.inventory[n].card[i])
continue;
- if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
+ if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
if( data->equip_script )
- run_script(data->equip_script,0,sd->bl.id,fake_nd->bl.id);
+ script->run(data->equip_script,0,sd->bl.id,npc->fake_nd->bl.id);
}
}
}
@@ -8706,20 +8981,20 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
nullpo_ret(sd);
if( n < 0 || n >= MAX_INVENTORY ) {
- clif->unequipitemack(sd,0,0,0);
+ clif->unequipitemack(sd,0,0,UIA_FAIL);
return 0;
}
// if player is berserk then cannot unequip
- if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAY_NIGHT_FEVER] || sd->sc.data[SC__BLOODYLUST]))
+ if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP]) )
{
- clif->unequipitemack(sd,n,0,0);
+ clif->unequipitemack(sd,n,0,UIA_FAIL);
return 0;
}
if( !(flag&2) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] )
{
- clif->unequipitemack(sd,n,0,0);
+ clif->unequipitemack(sd,n,0,UIA_FAIL);
return 0;
}
@@ -8727,25 +9002,25 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
ShowInfo("unequip %d %x:%x\n",n,pc->equippoint(sd,n),sd->status.inventory[n].equip);
if(!sd->status.inventory[n].equip){ //Nothing to unequip
- clif->unequipitemack(sd,n,0,0);
+ clif->unequipitemack(sd,n,0,UIA_FAIL);
return 0;
}
for(i=0;i<EQI_MAX;i++) {
- if(sd->status.inventory[n].equip & equip_pos[i])
+ if(sd->status.inventory[n].equip & pc->equip_pos[i])
sd->equip_index[i] = -1;
}
if(sd->status.inventory[n].equip & EQP_HAND_R) {
sd->weapontype1 = 0;
sd->status.weapon = sd->weapontype2;
- pc_calcweapontype(sd);
+ pc->calcweapontype(sd);
clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
if( !battle_config.dancing_weaponswitch_fix )
status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER); // Unequipping => stop dancing.
}
if(sd->status.inventory[n].equip & EQP_HAND_L) {
sd->status.shield = sd->weapontype2 = 0;
- pc_calcweapontype(sd);
+ pc->calcweapontype(sd);
clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
}
if(sd->status.inventory[n].equip & EQP_HEAD_LOW && pc->checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1 ) {
@@ -8789,7 +9064,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
clif->changelook(&sd->bl,LOOK_ROBE,sd->status.robe);
}
- clif->unequipitemack(sd,n,sd->status.inventory[n].equip,1);
+ clif->unequipitemack(sd,n,sd->status.inventory[n].equip,UIA_SUCCESS);
if((sd->status.inventory[n].equip & EQP_ARMS) &&
sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_TK_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!)
@@ -8810,7 +9085,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
/* check for combos (MUST be before status_calc_pc) */
if ( sd->inventory_data[n] ) {
if( sd->inventory_data[n]->combos_count ) {
- if( pc_removecombo(sd,sd->inventory_data[n]) )
+ if( pc->removecombo(sd,sd->inventory_data[n]) )
status_cacl = true;
} if(itemdb_isspecial(sd->status.inventory[n].card[0]))
; //No cards
@@ -8819,9 +9094,9 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
struct item_data *data;
if (!sd->status.inventory[n].card[i])
continue;
- if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
+ if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
if( data->combos_count ) {
- if( pc_removecombo(sd,data) )
+ if( pc->removecombo(sd,data) )
status_cacl = true;
}
}
@@ -8831,7 +9106,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
if(flag&1 || status_cacl) {
pc->checkallowskill(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
if(sd->sc.data[SC_CRUCIS] && !battle->check_undead(sd->battle_status.race,sd->battle_status.def_ele))
@@ -8840,7 +9115,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
//OnUnEquip script [Skotlex]
if (sd->inventory_data[n]) {
if (sd->inventory_data[n]->unequip_script)
- run_script(sd->inventory_data[n]->unequip_script,0,sd->bl.id,fake_nd->bl.id);
+ script->run(sd->inventory_data[n]->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id);
if(itemdb_isspecial(sd->status.inventory[n].card[0]))
; //No cards
else {
@@ -8849,9 +9124,9 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
if (!sd->status.inventory[n].card[i])
continue;
- if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
+ if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
if( data->unequip_script )
- run_script(data->unequip_script,0,sd->bl.id,fake_nd->bl.id);
+ script->run(data->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id);
}
}
@@ -8868,31 +9143,85 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
*------------------------------------------*/
int pc_checkitem(struct map_session_data *sd)
{
- int i,id,calc_flag = 0;
+ int i, id, calc_flag = 0;
nullpo_ret(sd);
if( sd->state.vending ) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam)
return 0;
- if( battle_config.item_check ) { // check for invalid(ated) items
+ if( sd->state.itemcheck ) { // check for invalid(ated) items
for( i = 0; i < MAX_INVENTORY; i++ ) {
id = sd->status.inventory[i].nameid;
- if( id && !itemdb_available(id) ) {
+ if (!id)
+ continue;
+
+ if( !itemdb_available(id) ) {
ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id);
pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER);
+ continue;
}
+
+ if ( !sd->status.inventory[i].unique_id && !itemdb->isstackable(id) )
+ sd->status.inventory[i].unique_id = itemdb->unique_id(sd);
}
for( i = 0; i < MAX_CART; i++ ) {
id = sd->status.cart[i].nameid;
- if( id && !itemdb_available(id) ) {
+ if (!id)
+ continue;
+
+ if( !itemdb_available(id) ) {
ShowWarning("Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", id, sd->status.cart[i].amount, sd->status.char_id);
pc->cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER);
+ continue;
+ }
+
+ if ( !sd->status.cart[i].unique_id && !itemdb->isstackable(id) )
+ sd->status.cart[i].unique_id = itemdb->unique_id(sd);
+ }
+
+ for( i = 0; i < MAX_STORAGE; i++ ) {
+ id = sd->status.storage.items[i].nameid;
+
+ if (!id)
+ continue;
+
+ if( id && !itemdb_available(id) ) {
+ ShowWarning("Removed invalid/disabled item id %d from storage (amount=%d, char_id=%d).\n", id, sd->status.storage.items[i].amount, sd->status.char_id);
+ storage->delitem(sd, i, sd->status.storage.items[i].amount);
+ storage->close(sd);
+ continue;
}
+
+ if ( !sd->status.storage.items[i].unique_id && !itemdb->isstackable(id) )
+ sd->status.storage.items[i].unique_id = itemdb->unique_id(sd);
}
+
+ if (sd->guild) {
+ struct guild_storage *guild_storage = gstorage->id2storage2(sd->guild->guild_id);
+ if (guild_storage) {
+ for( i = 0; i < MAX_GUILD_STORAGE; i++ ) {
+ id = guild_storage->items[i].nameid;
+
+ if (!id)
+ continue;
+
+ if( !itemdb_available(id) ) {
+ ShowWarning("Removed invalid/disabled item id %d from guild storage (amount=%d, char_id=%d, guild_id=%d).\n", id, guild_storage->items[i].amount, sd->status.char_id, sd->guild->guild_id);
+ gstorage->delitem(sd, guild_storage, i, guild_storage->items[i].amount);
+ gstorage->close(sd); // force closing
+ continue;
+ }
+
+ if (!guild_storage->items[i].unique_id && !itemdb->isstackable(id))
+ guild_storage->items[i].unique_id = itemdb->unique_id(sd);
+ }
+ }
+ }
+ sd->state.itemcheck = 0;
}
for( i = 0; i < MAX_INVENTORY; i++) {
@@ -8910,10 +9239,10 @@ int pc_checkitem(struct map_session_data *sd)
}
}
-
+
if( calc_flag && sd->state.active ) {
pc->checkallowskill(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
return 0;
@@ -8939,17 +9268,16 @@ int pc_calc_pvprank_sub(struct block_list *bl,va_list ap)
return 0;
}
/*==========================================
- * Calculate new rank beetween all present players (iMap->foreachinarea)
+ * Calculate new rank beetween all present players (map->foreachinarea)
* and display result
*------------------------------------------*/
-int pc_calc_pvprank(struct map_session_data *sd)
-{
+int pc_calc_pvprank(struct map_session_data *sd) {
int old;
struct map_data *m;
- m=&map[sd->bl.m];
+ m=&map->list[sd->bl.m];
old=sd->pvp_rank;
sd->pvp_rank=1;
- iMap->foreachinmap(pc_calc_pvprank_sub,sd->bl.m,BL_PC,sd);
+ map->foreachinmap(pc_calc_pvprank_sub,sd->bl.m,BL_PC,sd);
if(old!=sd->pvp_rank || sd->pvp_lastusers!=m->users_pvp)
clif->pvpset(sd,sd->pvp_rank,sd->pvp_lastusers=m->users_pvp,0);
return sd->pvp_rank;
@@ -8957,11 +9285,10 @@ int pc_calc_pvprank(struct map_session_data *sd)
/*==========================================
* Calculate next sd ranking calculation from config
*------------------------------------------*/
-int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+int pc_calc_pvprank_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
- sd=iMap->id2sd(id);
+ sd=map->id2sd(id);
if(sd==NULL)
return 0;
sd->pvp_timer = INVALID_TIMER;
@@ -8972,7 +9299,7 @@ int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr_t data)
}
if( pc->calc_pvprank(sd) > 0 )
- sd->pvp_timer = iTimer->add_timer(iTimer->gettick()+PVP_CALCRANK_INTERVAL,pc->calc_pvprank_timer,id,data);
+ sd->pvp_timer = timer->add(timer->gettick()+PVP_CALCRANK_INTERVAL,pc->calc_pvprank_timer,id,data);
return 0;
}
@@ -9025,9 +9352,9 @@ int pc_divorce(struct map_session_data *sd)
if( !sd->status.partner_id )
return -1; // Char is not married
- if( (p_sd = iMap->charid2sd(sd->status.partner_id)) == NULL )
- { // Lets char server do the divorce
- if( chrif_divorce(sd->status.char_id, sd->status.partner_id) )
+ if( (p_sd = map->charid2sd(sd->status.partner_id)) == NULL ) {
+ // Lets char server do the divorce
+ if( chrif->divorce(sd->status.char_id, sd->status.partner_id) )
return -1; // No char server connected
return 0;
@@ -9053,11 +9380,10 @@ int pc_divorce(struct map_session_data *sd)
/*==========================================
* Get sd partner charid. (Married partner)
*------------------------------------------*/
-struct map_session_data *pc_get_partner(struct map_session_data *sd)
-{
+struct map_session_data *pc_get_partner(struct map_session_data *sd) {
if (sd && pc->ismarried(sd))
// charid2sd returns NULL if not found
- return iMap->charid2sd(sd->status.partner_id);
+ return map->charid2sd(sd->status.partner_id);
return NULL;
}
@@ -9065,11 +9391,10 @@ struct map_session_data *pc_get_partner(struct map_session_data *sd)
/*==========================================
* Get sd father charid. (Need to be baby)
*------------------------------------------*/
-struct map_session_data *pc_get_father (struct map_session_data *sd)
-{
+struct map_session_data *pc_get_father(struct map_session_data *sd) {
if (sd && sd->class_&JOBL_BABY && sd->status.father > 0)
// charid2sd returns NULL if not found
- return iMap->charid2sd(sd->status.father);
+ return map->charid2sd(sd->status.father);
return NULL;
}
@@ -9077,11 +9402,10 @@ struct map_session_data *pc_get_father (struct map_session_data *sd)
/*==========================================
* Get sd mother charid. (Need to be baby)
*------------------------------------------*/
-struct map_session_data *pc_get_mother (struct map_session_data *sd)
-{
+struct map_session_data *pc_get_mother(struct map_session_data *sd) {
if (sd && sd->class_&JOBL_BABY && sd->status.mother > 0)
// charid2sd returns NULL if not found
- return iMap->charid2sd(sd->status.mother);
+ return map->charid2sd(sd->status.mother);
return NULL;
}
@@ -9089,11 +9413,10 @@ struct map_session_data *pc_get_mother (struct map_session_data *sd)
/*==========================================
* Get sd children charid. (Need to be married)
*------------------------------------------*/
-struct map_session_data *pc_get_child (struct map_session_data *sd)
-{
+struct map_session_data *pc_get_child(struct map_session_data *sd) {
if (sd && pc->ismarried(sd) && sd->status.child > 0)
// charid2sd returns NULL if not found
- return iMap->charid2sd(sd->status.child);
+ return map->charid2sd(sd->status.child);
return NULL;
}
@@ -9135,8 +9458,7 @@ void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick)
//Character regen. Flag is used to know which types of regen can take place.
//&1: HP regen
//&2: SP regen
-void pc_regen (struct map_session_data *sd, unsigned int diff_tick)
-{
+void pc_regen (struct map_session_data *sd, unsigned int diff_tick) {
int hp = 0, sp = 0;
if (sd->hp_regen.value) {
@@ -9156,7 +9478,7 @@ void pc_regen (struct map_session_data *sd, unsigned int diff_tick)
}
if (hp > 0 || sp > 0)
- status_heal(&sd->bl, hp, sp, 0);
+ status->heal(&sd->bl, hp, sp, 0);
return;
}
@@ -9164,11 +9486,10 @@ void pc_regen (struct map_session_data *sd, unsigned int diff_tick)
/*==========================================
* Memo player sd savepoint. (map,x,y)
*------------------------------------------*/
-int pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y)
-{
+int pc_setsavepoint(struct map_session_data *sd, short map_index, int x, int y) {
nullpo_ret(sd);
- sd->status.save_point.map = mapindex;
+ sd->status.save_point.map = map_index;
sd->status.save_point.x = x;
sd->status.save_point.y = y;
@@ -9176,10 +9497,9 @@ int pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y)
}
/*==========================================
- * Save 1 player data at autosave intervalle
+ * Save 1 player data at autosave intervall
*------------------------------------------*/
-int pc_autosave(int tid, unsigned int tick, int id, intptr_t data)
-{
+int pc_autosave(int tid, int64 tick, int id, intptr_t data) {
int interval;
struct s_mapiterator* iter;
struct map_session_data* sd;
@@ -9205,24 +9525,23 @@ int pc_autosave(int tid, unsigned int tick, int id, intptr_t data)
last_save_id = sd->bl.id;
save_flag = 2;
- chrif_save(sd,0);
+ chrif->save(sd,0);
break;
}
mapit->free(iter);
- interval = iMap->autosave_interval/(iMap->usercount()+1);
- if(interval < iMap->minsave_interval)
- interval = iMap->minsave_interval;
- iTimer->add_timer(iTimer->gettick()+interval,pc_autosave,0,0);
+ interval = map->autosave_interval/(map->usercount()+1);
+ if(interval < map->minsave_interval)
+ interval = map->minsave_interval;
+ timer->add(timer->gettick()+interval,pc->autosave,0,0);
return 0;
}
-static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap)
-{
- if (sd->state.night != iMap->night_flag && map[sd->bl.m].flag.nightenabled) { //Night/day state does not match.
- clif->status_change(&sd->bl, SI_SKE, iMap->night_flag, 0, 0, 0, 0); //New night effect by dynamix [Skotlex]
- sd->state.night = iMap->night_flag;
+int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) {
+ if (sd->state.night != map->night_flag && map->list[sd->bl.m].flag.nightenabled) { //Night/day state does not match.
+ clif->status_change(&sd->bl, SI_SKE, map->night_flag, 0, 0, 0, 0); //New night effect by dynamix [Skotlex]
+ sd->state.night = map->night_flag;
return 1;
}
return 0;
@@ -9231,20 +9550,19 @@ static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap)
* timer to do the day [Yor]
* data: 0 = called by timer, 1 = gmcommand/script
*------------------------------------------------*/
-int map_day_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+int map_day_timer(int tid, int64 tick, int id, intptr_t data) {
char tmp_soutput[1024];
- if (data == 0 && battle_config.day_duration <= 0) // if we want a day
+ if (data == 0 && battle_config.day_duration <= 0) // if we want a day
return 0;
- if (!iMap->night_flag)
+ if (!map->night_flag)
return 0; //Already day.
- iMap->night_flag = 0; // 0=day, 1=night [Yor]
- iMap->map_foreachpc(pc_daynight_timer_sub);
+ map->night_flag = 0; // 0=day, 1=night [Yor]
+ map->foreachpc(pc->daynight_timer_sub);
strcpy(tmp_soutput, (data == 0) ? msg_txt(502) : msg_txt(60)); // The day has arrived!
- intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0);
+ intif->broadcast(tmp_soutput, strlen(tmp_soutput) + 1, BC_DEFAULT);
return 0;
}
@@ -9252,24 +9570,23 @@ int map_day_timer(int tid, unsigned int tick, int id, intptr_t data)
* timer to do the night [Yor]
* data: 0 = called by timer, 1 = gmcommand/script
*------------------------------------------------*/
-int map_night_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+int map_night_timer(int tid, int64 tick, int id, intptr_t data) {
char tmp_soutput[1024];
- if (data == 0 && battle_config.night_duration <= 0) // if we want a night
+ if (data == 0 && battle_config.night_duration <= 0) // if we want a night
return 0;
- if (iMap->night_flag)
+ if (map->night_flag)
return 0; //Already nigth.
- iMap->night_flag = 1; // 0=day, 1=night [Yor]
- iMap->map_foreachpc(pc_daynight_timer_sub);
+ map->night_flag = 1; // 0=day, 1=night [Yor]
+ map->foreachpc(pc->daynight_timer_sub);
strcpy(tmp_soutput, (data == 0) ? msg_txt(503) : msg_txt(59)); // The night has fallen...
- intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0);
+ intif->broadcast(tmp_soutput, strlen(tmp_soutput) + 1, BC_DEFAULT);
return 0;
}
-void pc_setstand(struct map_session_data *sd){
+void pc_setstand(struct map_session_data *sd) {
nullpo_retv(sd);
status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER);
@@ -9283,23 +9600,23 @@ void pc_setstand(struct map_session_data *sd){
* Mechanic (MADO GEAR)
**/
void pc_overheat(struct map_session_data *sd, int val) {
- int heat = val, skill,
+ int heat = val, skill_lv,
limit[] = { 10, 20, 28, 46, 66 };
if( !pc_ismadogear(sd) || sd->sc.data[SC_OVERHEAT] )
return; // already burning
- skill = cap_value(pc->checkskill(sd,NC_MAINFRAME),0,4);
+ skill_lv = cap_value(pc->checkskill(sd,NC_MAINFRAME),0,4);
if( sd->sc.data[SC_OVERHEAT_LIMITPOINT] ) {
heat += sd->sc.data[SC_OVERHEAT_LIMITPOINT]->val1;
status_change_end(&sd->bl,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER);
}
heat = max(0,heat); // Avoid negative HEAT
- if( heat >= limit[skill] )
- sc_start(&sd->bl,SC_OVERHEAT,100,0,1000);
+ if( heat >= limit[skill_lv] )
+ sc_start(NULL,&sd->bl,SC_OVERHEAT,100,0,1000);
else
- sc_start(&sd->bl,SC_OVERHEAT_LIMITPOINT,100,heat,30000);
+ sc_start(NULL,&sd->bl,SC_OVERHEAT_LIMITPOINT,100,heat,30000);
return;
}
@@ -9309,10 +9626,16 @@ void pc_overheat(struct map_session_data *sd, int val) {
*/
bool pc_isautolooting(struct map_session_data *sd, int nameid)
{
- int i;
- if( !sd->state.autolooting )
+ int i = 0;
+
+ if (sd->state.autoloottype && sd->state.autoloottype&(1<<itemdb_type(nameid)))
+ return true;
+
+ if (!sd->state.autolooting)
return false;
+
ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == nameid);
+
return (i != AUTOLOOTITEM_SIZE);
}
@@ -9325,12 +9648,11 @@ bool pc_can_use_command(struct map_session_data *sd, const char *command) {
return atcommand->can_use(sd,command);
}
-static int pc_charm_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+int pc_charm_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
int i, type;
- if( (sd=(struct map_session_data *)iMap->id2sd(id)) == NULL || sd->bl.type!=BL_PC )
+ if( (sd=(struct map_session_data *)map->id2sd(id)) == NULL || sd->bl.type!=BL_PC )
return 1;
ARR_FIND(1, 5, type, sd->charm[type] > 0);
@@ -9373,15 +9695,15 @@ int pc_add_charm(struct map_session_data *sd,int interval,int max,int type)
if( sd->charm[type] && sd->charm[type] >= max )
{
if(sd->charm_timer[type][0] != INVALID_TIMER)
- iTimer->delete_timer(sd->charm_timer[type][0],pc_charm_timer);
+ timer->delete(sd->charm_timer[type][0],pc->charm_timer);
sd->charm[type]--;
if( sd->charm[type] != 0 )
memmove(sd->charm_timer[type]+0, sd->charm_timer[type]+1, (sd->charm[type])*sizeof(int));
sd->charm_timer[type][sd->charm[type]] = INVALID_TIMER;
}
- tid = iTimer->add_timer(iTimer->gettick()+interval, pc_charm_timer, sd->bl.id, 0);
- ARR_FIND(0, sd->charm[type], i, sd->charm_timer[type][i] == INVALID_TIMER || DIFF_TICK(iTimer->get_timer(tid)->tick, iTimer->get_timer(sd->charm_timer[type][i])->tick) < 0);
+ tid = timer->add(timer->gettick()+interval, pc->charm_timer, sd->bl.id, 0);
+ ARR_FIND(0, sd->charm[type], i, sd->charm_timer[type][i] == INVALID_TIMER || DIFF_TICK(timer->get(tid)->tick, timer->get(sd->charm_timer[type][i])->tick) < 0);
if( i != sd->charm[type] )
memmove(sd->charm_timer[type]+i+1, sd->charm_timer[type]+i, (sd->charm[type]-i)*sizeof(int));
sd->charm_timer[type][i] = tid;
@@ -9412,7 +9734,7 @@ int pc_del_charm(struct map_session_data *sd,int count,int type)
for(i = 0; i < count; i++) {
if(sd->charm_timer[type][i] != INVALID_TIMER) {
- iTimer->delete_timer(sd->charm_timer[type][i],pc_charm_timer);
+ timer->delete(sd->charm_timer[type][i],pc->charm_timer);
sd->charm_timer[type][i] = INVALID_TIMER;
}
}
@@ -9424,19 +9746,13 @@ int pc_del_charm(struct map_session_data *sd,int count,int type)
clif->charm(sd, type);
return 0;
}
-#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
/*==========================================
* Renewal EXP/Itemdrop rate modifier base on level penalty
* 1=exp 2=itemdrop
*------------------------------------------*/
-int pc_level_penalty_mod(struct map_session_data *sd, struct mob_data *md, int type)
-{
- int diff, rate = 100, i;
-
- nullpo_ret(sd);
- nullpo_ret(md);
-
- diff = md->level - sd->status.base_level;
+int pc_level_penalty_mod(int diff, unsigned char race, unsigned short mode, int type) {
+#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
+ int rate = 100, i;
if( diff < 0 )
diff = MAX_LEVEL + ( ~diff + 1 );
@@ -9444,22 +9760,24 @@ int pc_level_penalty_mod(struct map_session_data *sd, struct mob_data *md, int t
for(i=0; i<RC_MAX; i++){
int tmp;
- if( md->status.race != i ){
- if( md->status.mode&MD_BOSS && i < RC_BOSS )
+ if( race != i ){
+ if( mode&MD_BOSS && i < RC_BOSS )
i = RC_BOSS;
else if( i <= RC_BOSS )
continue;
}
- if( (tmp=level_penalty[type][i][diff]) > 0 ){
+ if( (tmp=pc->level_penalty[type][i][diff]) > 0 ){
rate = tmp;
break;
}
}
return rate;
-}
+#else
+ return 100;
#endif
+}
int pc_split_str(char *str,char **val,int num)
{
int i;
@@ -9516,59 +9834,271 @@ int pc_split_atoui(char* str, unsigned int* val, char sep, int max)
val[j] = 0;
return i;
}
+/* [Ind/Hercules] */
+void pc_read_skill_tree(void) {
+ config_t skill_tree_conf;
+ config_setting_t *skt = NULL, *inherit = NULL, *skills = NULL, *sk = NULL;
+#ifdef RENEWAL
+ const char *config_filename = "db/re/skill_tree.conf"; // FIXME hardcoded name
+#else
+ const char *config_filename = "db/pre-re/skill_tree.conf"; // FIXME hardcoded name
+#endif
+ int i = 0, jnamelen = 0;
+ struct s_mapiterator *iter;
+ struct map_session_data *sd;
+ struct {
+ const char *name;
+ int id;
+ } jnames[] = {
+ { "Novice", JOB_NOVICE },
+ { "Swordsman", JOB_SWORDMAN },
+ { "Magician", JOB_MAGE },
+ { "Archer", JOB_ARCHER },
+ { "Acolyte", JOB_ACOLYTE },
+ { "Merchant", JOB_MERCHANT },
+ { "Thief", JOB_THIEF },
+ { "Knight", JOB_KNIGHT },
+ { "Priest", JOB_PRIEST },
+ { "Wizard", JOB_WIZARD },
+ { "Blacksmith", JOB_BLACKSMITH },
+ { "Hunter", JOB_HUNTER },
+ { "Assassin", JOB_ASSASSIN },
+ { "Crusader", JOB_CRUSADER },
+ { "Monk", JOB_MONK },
+ { "Sage", JOB_SAGE },
+ { "Rogue", JOB_ROGUE },
+ { "Alchemist", JOB_ALCHEMIST },
+ { "Bard", JOB_BARD },
+ { "Dancer", JOB_DANCER },
+ { "Super_Novice", JOB_SUPER_NOVICE },
+ { "Gunslinger", JOB_GUNSLINGER },
+ { "Ninja", JOB_NINJA },
+ { "Novice_High", JOB_NOVICE_HIGH },
+ { "Swordsman_High", JOB_SWORDMAN_HIGH },
+ { "Magician_High", JOB_MAGE_HIGH },
+ { "Archer_High", JOB_ARCHER_HIGH },
+ { "Acolyte_High", JOB_ACOLYTE_HIGH },
+ { "Merchant_High", JOB_MERCHANT_HIGH },
+ { "Thief_High", JOB_THIEF_HIGH },
+ { "Lord_Knight", JOB_LORD_KNIGHT },
+ { "High_Priest", JOB_HIGH_PRIEST },
+ { "High_Wizard", JOB_HIGH_WIZARD },
+ { "Whitesmith", JOB_WHITESMITH },
+ { "Sniper", JOB_SNIPER },
+ { "Assassin_Cross", JOB_ASSASSIN_CROSS },
+ { "Paladin", JOB_PALADIN },
+ { "Champion", JOB_CHAMPION },
+ { "Professor", JOB_PROFESSOR },
+ { "Stalker", JOB_STALKER },
+ { "Creator", JOB_CREATOR },
+ { "Clown", JOB_CLOWN },
+ { "Gypsy", JOB_GYPSY },
+ { "Baby_Novice", JOB_BABY },
+ { "Baby_Swordsman", JOB_BABY_SWORDMAN },
+ { "Baby_Magician", JOB_BABY_MAGE },
+ { "Baby_Archer", JOB_BABY_ARCHER },
+ { "Baby_Acolyte", JOB_BABY_ACOLYTE },
+ { "Baby_Merchant", JOB_BABY_MERCHANT },
+ { "Baby_Thief", JOB_BABY_THIEF },
+ { "Baby_Knight", JOB_BABY_KNIGHT },
+ { "Baby_Priest", JOB_BABY_PRIEST },
+ { "Baby_Wizard", JOB_BABY_WIZARD },
+ { "Baby_Blacksmith", JOB_BABY_BLACKSMITH },
+ { "Baby_Hunter", JOB_BABY_HUNTER },
+ { "Baby_Assassin", JOB_BABY_ASSASSIN },
+ { "Baby_Crusader", JOB_BABY_CRUSADER },
+ { "Baby_Monk", JOB_BABY_MONK },
+ { "Baby_Sage", JOB_BABY_SAGE },
+ { "Baby_Rogue", JOB_BABY_ROGUE },
+ { "Baby_Alchemist", JOB_BABY_ALCHEMIST },
+ { "Baby_Bard", JOB_BABY_BARD },
+ { "Baby_Dancer", JOB_BABY_DANCER },
+ { "Super_Baby", JOB_SUPER_BABY },
+ { "Taekwon", JOB_TAEKWON },
+ { "Star_Gladiator", JOB_STAR_GLADIATOR },
+ { "Soul_Linker", JOB_SOUL_LINKER },
+ { "Gangsi", JOB_GANGSI },
+ { "Death_Knight", JOB_DEATH_KNIGHT },
+ { "Dark_Collector", JOB_DARK_COLLECTOR },
+ { "Rune_Knight", JOB_RUNE_KNIGHT },
+ { "Warlock", JOB_WARLOCK },
+ { "Ranger", JOB_RANGER },
+ { "Arch_Bishop", JOB_ARCH_BISHOP },
+ { "Mechanic", JOB_MECHANIC },
+ { "Guillotine_Cross", JOB_GUILLOTINE_CROSS },
+ { "Rune_Knight_Trans", JOB_RUNE_KNIGHT_T },
+ { "Warlock_Trans", JOB_WARLOCK_T },
+ { "Ranger_Trans", JOB_RANGER_T },
+ { "Arch_Bishop_Trans", JOB_ARCH_BISHOP_T },
+ { "Mechanic_Trans", JOB_MECHANIC_T },
+ { "Guillotine_Cross_Trans", JOB_GUILLOTINE_CROSS_T },
+ { "Royal_Guard", JOB_ROYAL_GUARD },
+ { "Sorcerer", JOB_SORCERER },
+ { "Minstrel", JOB_MINSTREL },
+ { "Wanderer", JOB_WANDERER },
+ { "Sura", JOB_SURA },
+ { "Genetic", JOB_GENETIC },
+ { "Shadow_Chaser", JOB_SHADOW_CHASER },
+ { "Royal_Guard_Trans", JOB_ROYAL_GUARD_T },
+ { "Sorcerer_Trans", JOB_SORCERER_T },
+ { "Minstrel_Trans", JOB_MINSTREL_T },
+ { "Wanderer_Trans", JOB_WANDERER_T },
+ { "Sura_Trans", JOB_SURA_T },
+ { "Genetic_Trans", JOB_GENETIC_T },
+ { "Shadow_Chaser_Trans", JOB_SHADOW_CHASER_T },
+ { "Baby_Rune_Knight", JOB_BABY_RUNE },
+ { "Baby_Warlock", JOB_BABY_WARLOCK },
+ { "Baby_Ranger", JOB_BABY_RANGER },
+ { "Baby_Arch_Bishop", JOB_BABY_BISHOP },
+ { "Baby_Mechanic", JOB_BABY_MECHANIC },
+ { "Baby_Guillotine_Cross", JOB_BABY_CROSS },
+ { "Baby_Royal_Guard", JOB_BABY_GUARD },
+ { "Baby_Sorcerer", JOB_BABY_SORCERER },
+ { "Baby_Minstrel", JOB_BABY_MINSTREL },
+ { "Baby_Wanderer", JOB_BABY_WANDERER },
+ { "Baby_Sura", JOB_BABY_SURA },
+ { "Baby_Genetic", JOB_BABY_GENETIC },
+ { "Baby_Shadow_Chaser", JOB_BABY_CHASER },
+ { "Expanded_Super_Novice", JOB_SUPER_NOVICE_E },
+ { "Expanded_Super_Baby", JOB_SUPER_BABY_E },
+ { "Kagerou", JOB_KAGEROU },
+ { "Oboro", JOB_OBORO },
+ { "Rebellion", JOB_REBELLION },
+ };
+
+ if (libconfig->read_file(&skill_tree_conf, config_filename)) {
+ ShowError("can't read %s\n", config_filename);
+ return;
+ }
+
+ jnamelen = ARRAYLENGTH(jnames);
+
+ while( (skt = libconfig->setting_get_elem(skill_tree_conf.root,i++)) ) {
+ int k, idx;
+ const char *name = config_setting_name(skt);
+
+ ARR_FIND(0, jnamelen, k, strcmpi(jnames[k].name,name) == 0 );
+
+ if( k == jnamelen ) {
+ ShowWarning("pc_read_skill_tree: '%s' unknown job name!\n",name);
+ continue;
+ }
+
+
+ if( ( skills = libconfig->setting_get_member(skt,"skills") ) ) {
+ int c = 0;
+
+ idx = pc->class2idx(jnames[k].id);
+
+ while( ( sk = libconfig->setting_get_elem(skills,c++) ) ) {
+ const char *sk_name = config_setting_name(sk);
+ int skill_id;
+
+ if( ( skill_id = skill->name2id(sk_name) ) ) {
+ int skidx, offset = 0, h = 0, rlen = 0, rskid = 0;
+
+ ARR_FIND( 0, MAX_SKILL_TREE, skidx, pc->skill_tree[idx][skidx].id == 0 || pc->skill_tree[idx][skidx].id == skill_id );
+ if (skidx == MAX_SKILL_TREE) {
+ ShowWarning("pc_read_skill_tree: Unable to load skill %d (%s) into '%s's tree. Maximum number of skills per class has been reached.\n", skill_id, sk_name, name);
+ continue;
+ } else if (pc->skill_tree[idx][skidx].id) {
+ ShowNotice("pc_read_skill_tree: Overwriting %d for '%s' (%d)\n", skill_id, name, jnames[k].id);
+ }
+
+ pc->skill_tree[idx][skidx].id = skill_id;
+ pc->skill_tree[idx][skidx].idx = skill->get_index(skill_id);
+
+ if( config_setting_is_group(sk) ) {
+ int max = 0, jlevel = 0;
+ libconfig->setting_lookup_int(sk, "MaxLevel", &max);
+ libconfig->setting_lookup_int(sk, "MinJobLevel", &jlevel);
+ pc->skill_tree[idx][skidx].max = (unsigned char)max;
+ pc->skill_tree[idx][skidx].joblv = (unsigned char)jlevel;
+ rlen = libconfig->setting_length(sk);
+ offset += jlevel ? 2 : 1;
+ } else {
+ pc->skill_tree[idx][skidx].max = (unsigned char)libconfig->setting_get_int(sk);
+ pc->skill_tree[idx][skidx].joblv = 0;
+ }
+
+ for( h = offset; h < rlen && h < MAX_PC_SKILL_REQUIRE; h++ ) {
+ config_setting_t *rsk = libconfig->setting_get_elem(sk,h);
+ if( rsk && ( rskid = skill->name2id(config_setting_name(rsk)) ) ) {
+ pc->skill_tree[idx][skidx].need[h].id = rskid;
+ pc->skill_tree[idx][skidx].need[h].idx = skill->get_index(rskid);
+ pc->skill_tree[idx][skidx].need[h].lv = (unsigned char)libconfig->setting_get_int(rsk);
+ } else if( rsk ) {
+ ShowWarning("pc_read_skill_tree: unknown requirement '%s' for '%s' in '%s'\n",config_setting_name(rsk),sk_name,name);
+ } else {
+ ShowWarning("pc_read_skill_tree: error for '%s' in '%s'\n",sk_name,name);
+ }
+ }
+
+ } else {
+ ShowWarning("pc_read_skill_tree: unknown skill '%s' in '%s'\n",sk_name,name);
+ }
+ }
+ }
+ }
+
+ i = 0;
+ while( (skt = libconfig->setting_get_elem(skill_tree_conf.root,i++)) ) {
+ int k, idx, v = 0;
+ const char *name = config_setting_name(skt);
+ const char *iname;
-/*==========================================
- * sub DB reading.
- * Function used to read skill_tree.txt
- *------------------------------------------*/
-static bool pc_readdb_skilltree(char* fields[], int columns, int current)
-{
- unsigned char joblv = 0, skill_lv;
- uint16 skill_id;
- int idx, class_;
- unsigned int i, offset = 3, skill_idx;
+
+ ARR_FIND(0, jnamelen, k, strcmpi(jnames[k].name,name) == 0 );
+
+ if( k == jnamelen ) {
+ ShowWarning("pc_read_skill_tree: '%s' unknown job name!\n",name);
+ continue;
+ }
+ idx = pc->class2idx(jnames[k].id);
- class_ = atoi(fields[0]);
- skill_id = (uint16)atoi(fields[1]);
- skill_lv = (unsigned char)atoi(fields[2]);
+ if( ( inherit = libconfig->setting_get_member(skt,"inherit") ) ) {
+ while( ( iname = libconfig->setting_get_string_elem(inherit, v++) ) ) {
+ int b = 0, a, d, f, fidx;
- if(columns==4+MAX_PC_SKILL_REQUIRE*2)
- {// job level requirement extra column
- joblv = (unsigned char)atoi(fields[3]);
- offset++;
- }
+ ARR_FIND(0, jnamelen, b, strcmpi(jnames[b].name,iname) == 0 );
+
+ if( b == jnamelen ) {
+ ShowWarning("pc_read_skill_tree: '%s' trying to inherit unknown '%s'!\n",name,iname);
+ continue;
+ }
+
+ fidx = pc->class2idx(jnames[b].id);
+
+ ARR_FIND( 0, MAX_SKILL_TREE, d, pc->skill_tree[fidx][d].id == 0 );
- if(!pcdb_checkid(class_))
- {
- ShowWarning("pc_readdb_skilltree: Invalid job class %d specified.\n", class_);
- return false;
- }
- idx = pc->class2idx(class_);
+ for( f = 0; f < d; f++ ) {
+
+ ARR_FIND( 0, MAX_SKILL_TREE, a, pc->skill_tree[idx][a].id == 0 || pc->skill_tree[idx][a].id == pc->skill_tree[fidx][f].id );
- //This is to avoid adding two lines for the same skill. [Skotlex]
- ARR_FIND( 0, MAX_SKILL_TREE, skill_idx, skill_tree[idx][skill_idx].id == 0 || skill_tree[idx][skill_idx].id == skill_id );
- if( skill_idx == MAX_SKILL_TREE ) {
- ShowWarning("pc_readdb_skilltree: Unable to load skill %hu into job %d's tree. Maximum number of skills per class has been reached.\n", skill_id, class_);
- return false;
- } else if(skill_tree[idx][skill_idx].id) {
- ShowNotice("pc_readdb_skilltree: Overwriting skill %hu for job class %d.\n", skill_id, class_);
+ if( a == MAX_SKILL_TREE ) {
+ ShowWarning("pc_read_skill_tree: '%s' can't inherit '%s', skill tree is full!\n", name,iname);
+ break;
+ } else if ( pc->skill_tree[idx][a].id || ( pc->skill_tree[idx][a].id == NV_TRICKDEAD && ((pc->jobid2mapid(jnames[k].id)&(MAPID_BASEMASK|JOBL_2))!=MAPID_NOVICE) ) ) /* we skip trickdead for non-novices */
+ continue;/* skip */
+
+ memcpy(&pc->skill_tree[idx][a],&pc->skill_tree[fidx][f],sizeof(pc->skill_tree[fidx][f]));
+ }
+
+ }
+ }
+
}
+
+ libconfig->destroy(&skill_tree_conf);
- skill_tree[idx][skill_idx].id = skill_id;
- skill_tree[idx][skill_idx].idx = skill->get_index(skill_id);
- skill_tree[idx][skill_idx].max = skill_lv;
- skill_tree[idx][skill_idx].joblv = joblv;
-
- for(i = 0; i < MAX_PC_SKILL_REQUIRE; i++) {
- skill_tree[idx][skill_idx].need[i].id = atoi(fields[i*2+offset]);
- skill_tree[idx][skill_idx].need[i].idx = skill->get_index(atoi(fields[i*2+offset]));
- skill_tree[idx][skill_idx].need[i].lv = atoi(fields[i*2+offset+1]);
- }
- return true;
+ /* lets update all players skill tree */
+ iter = mapit_getallusers();
+ for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) )
+ clif->skillinfoblock(sd);
+ mapit->free(iter);
}
+bool pc_readdb_levelpenalty(char* fields[], int columns, int current) {
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
-static bool pc_readdb_levelpenalty(char* fields[], int columns, int current)
-{
int type, race, diff;
type = atoi(fields[0]);
@@ -9590,11 +10120,10 @@ static bool pc_readdb_levelpenalty(char* fields[], int columns, int current)
if( diff < 0 )
diff = min(MAX_LEVEL + ( ~(diff) + 1 ), MAX_LEVEL*2);
- level_penalty[type][race][diff] = atoi(fields[3]);
-
+ pc->level_penalty[type][race][diff] = atoi(fields[3]);
+#endif
return true;
}
-#endif
/*==========================================
* pc DB reading.
@@ -9602,26 +10131,24 @@ static bool pc_readdb_levelpenalty(char* fields[], int columns, int current)
* skill_tree.txt - skill tree for every class
* attr_fix.txt - elemental adjustment table
*------------------------------------------*/
-int pc_readdb(void)
-{
+int pc_readdb(void) {
int i,j,k;
unsigned int count = 0;
FILE *fp;
char line[24000],*p;
- //reset
- memset(exp_table,0,sizeof(exp_table));
- memset(max_level,0,sizeof(max_level));
+ //reset
+ memset(pc->exp_table,0,sizeof(pc->exp_table));
+ memset(pc->max_level,0,sizeof(pc->max_level));
- sprintf(line, "%s/"DBPATH"exp.txt", iMap->db_path);
+ sprintf(line, "%s/"DBPATH"exp.txt", map->db_path);
fp=fopen(line, "r");
if(fp==NULL){
ShowError("can't read %s\n", line);
return 1;
}
- while(fgets(line, sizeof(line), fp))
- {
+ while(fgets(line, sizeof(line), fp)) {
int jobs[CLASS_COUNT], job_count, job, job_id;
int type;
unsigned int ui,maxlv;
@@ -9652,23 +10179,23 @@ int pc_readdb(void)
count++;
job = jobs[0] = pc->class2idx(job_id);
//We send one less and then one more because the last entry in the exp array should hold 0.
- max_level[job][type] = pc_split_atoui(split[3], exp_table[job][type],',',maxlv-1)+1;
+ pc->max_level[job][type] = pc_split_atoui(split[3], pc->exp_table[job][type],',',maxlv-1)+1;
//Reverse check in case the array has a bunch of trailing zeros... [Skotlex]
//The reasoning behind the -2 is this... if the max level is 5, then the array
//should look like this:
//0: x, 1: x, 2: x: 3: x 4: 0 <- last valid value is at 3.
- while ((ui = max_level[job][type]) >= 2 && exp_table[job][type][ui-2] <= 0)
- max_level[job][type]--;
- if (max_level[job][type] < maxlv) {
- ShowWarning("pc_readdb: Specified max %u for job %d, but that job's exp table only goes up to level %u.\n", maxlv, job_id, max_level[job][type]);
+ while ((ui = pc->max_level[job][type]) >= 2 && pc->exp_table[job][type][ui-2] <= 0)
+ pc->max_level[job][type]--;
+ if (pc->max_level[job][type] < maxlv) {
+ ShowWarning("pc_readdb: Specified max %u for job %d, but that job's exp table only goes up to level %u.\n", maxlv, job_id, pc->max_level[job][type]);
ShowInfo("Filling the missing values with the last exp entry.\n");
//Fill the requested values with the last entry.
- ui = (max_level[job][type] <= 2? 0: max_level[job][type]-2);
+ ui = (pc->max_level[job][type] <= 2? 0: pc->max_level[job][type]-2);
for (; ui+2 < maxlv; ui++)
- exp_table[job][type][ui] = exp_table[job][type][ui-1];
- max_level[job][type] = maxlv;
+ pc->exp_table[job][type][ui] = pc->exp_table[job][type][ui-1];
+ pc->max_level[job][type] = maxlv;
}
-// ShowDebug("%s - Class %d: %d\n", type?"Job":"Base", job_id, max_level[job][type]);
+// ShowDebug("%s - Class %d: %d\n", type?"Job":"Base", job_id, pc->max_level[job][type]);
for (i = 1; i < job_count; i++) {
job_id = jobs[i];
if (!pcdb_checkid(job_id)) {
@@ -9676,9 +10203,9 @@ int pc_readdb(void)
continue;
}
job = pc->class2idx(job_id);
- memcpy(exp_table[job][type], exp_table[jobs[0]][type], sizeof(exp_table[0][0]));
- max_level[job][type] = maxlv;
-// ShowDebug("%s - Class %d: %u\n", type?"Job":"Base", job_id, max_level[job][type]);
+ memcpy(pc->exp_table[job][type], pc->exp_table[jobs[0]][type], sizeof(pc->exp_table[0][0]));
+ pc->max_level[job][type] = maxlv;
+// ShowDebug("%s - Class %d: %u\n", type?"Job":"Base", job_id, pc->max_level[job][type]);
}
}
fclose(fp);
@@ -9687,29 +10214,28 @@ int pc_readdb(void)
if (i == JOB_WEDDING || i == JOB_XMAS || i == JOB_SUMMER)
continue; //Classes that do not need exp tables.
j = pc->class2idx(i);
- if (!max_level[j][0])
+ if (!pc->max_level[j][0])
ShowWarning("Class %s (%d) does not has a base exp table.\n", pc->job_name(i), i);
- if (!max_level[j][1])
+ if (!pc->max_level[j][1])
ShowWarning("Class %s (%d) does not has a job exp table.\n", pc->job_name(i), i);
}
- ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s/"DBPATH"%s"CL_RESET"'.\n",count,iMap->db_path,"exp.txt");
+ ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s/"DBPATH"%s"CL_RESET"'.\n",count,map->db_path,"exp.txt");
count = 0;
// Reset and read skilltree
- memset(skill_tree,0,sizeof(skill_tree));
- sv->readdb(iMap->db_path, DBPATH"skill_tree.txt", ',', 3+MAX_PC_SKILL_REQUIRE*2, 4+MAX_PC_SKILL_REQUIRE*2, -1, &pc_readdb_skilltree);
-
+ memset(pc->skill_tree,0,sizeof(pc->skill_tree));
+ pc->read_skill_tree();
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
- sv->readdb(iMap->db_path, "re/level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty);
+ sv->readdb(map->db_path, "re/level_penalty.txt", ',', 4, 4, -1, pc->readdb_levelpenalty);
for( k=1; k < 3; k++ ){ // fill in the blanks
for( j = 0; j < RC_MAX; j++ ){
int tmp = 0;
for( i = 0; i < MAX_LEVEL*2; i++ ){
if( i == MAX_LEVEL+1 )
- tmp = level_penalty[k][j][0];// reset
- if( level_penalty[k][j][i] > 0 )
- tmp = level_penalty[k][j][i];
+ tmp = pc->level_penalty[k][j][0];// reset
+ if( pc->level_penalty[k][j][i] > 0 )
+ tmp = pc->level_penalty[k][j][i];
else
- level_penalty[k][j][i] = tmp;
+ pc->level_penalty[k][j][i] = tmp;
}
}
}
@@ -9719,9 +10245,9 @@ int pc_readdb(void)
for(i=0;i<4;i++)
for(j=0;j<ELE_MAX;j++)
for(k=0;k<ELE_MAX;k++)
- attr_fix_table[i][j][k]=100;
+ battle->attr_fix_table[i][j][k]=100;
- sprintf(line, "%s/"DBPATH"attr_fix.txt", iMap->db_path);
+ sprintf(line, "%s/"DBPATH"attr_fix.txt", map->db_path);
fp=fopen(line,"r");
if(fp==NULL){
@@ -9754,9 +10280,11 @@ int pc_readdb(void)
for(j=0,p=line;j<n && j<ELE_MAX && p;j++){
while(*p==32 && *p>0)
p++;
- attr_fix_table[lv-1][i][j]=atoi(p);
- if(battle_config.attr_recover == 0 && attr_fix_table[lv-1][i][j] < 0)
- attr_fix_table[lv-1][i][j] = 0;
+ battle->attr_fix_table[lv-1][i][j]=atoi(p);
+#ifndef RENEWAL
+ if(battle_config.attr_recover == 0 && battle->attr_fix_table[lv-1][i][j] < 0)
+ battle->attr_fix_table[lv-1][i][j] = 0;
+#endif
p=strchr(p,',');
if(p) *p++=0;
}
@@ -9765,13 +10293,13 @@ int pc_readdb(void)
}
}
fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s/"DBPATH"%s"CL_RESET"'.\n",count,iMap->db_path,"attr_fix.txt");
+ ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s/"DBPATH"%s"CL_RESET"'.\n",count,map->db_path,"attr_fix.txt");
count = 0;
- // reset then read statspoint
- memset(statp,0,sizeof(statp));
+ // reset then read statspoint
+ memset(pc->statp,0,sizeof(pc->statp));
i=1;
- sprintf(line, "%s/"DBPATH"statpoint.txt", iMap->db_path);
+ sprintf(line, "%s/"DBPATH"statpoint.txt", map->db_path);
fp=fopen(line,"r");
if(fp == NULL){
ShowWarning("Can't read '"CL_WHITE"%s"CL_RESET"'... Generating DB.\n",line);
@@ -9782,24 +10310,24 @@ int pc_readdb(void)
int stat;
if(line[0]=='/' && line[1]=='/')
continue;
- if ((stat=strtoul(line,NULL,10))<0)
+ if ((stat=(int)strtol(line,NULL,10))<0)
stat=0;
if (i > MAX_LEVEL)
break;
count++;
- statp[i]=stat;
+ pc->statp[i]=stat;
i++;
}
fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s/"DBPATH"%s"CL_RESET"'.\n",count,iMap->db_path,"statpoint.txt");
+ ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s/"DBPATH"%s"CL_RESET"'.\n",count,map->db_path,"statpoint.txt");
}
// generate the remaining parts of the db if necessary
k = battle_config.use_statpoint_table; //save setting
battle_config.use_statpoint_table = 0; //temporarily disable to force pc->gets_status_point use default values
- statp[0] = 45; // seed value
+ pc->statp[0] = 45; // seed value
for (; i <= MAX_LEVEL; i++)
- statp[i] = statp[i-1] + pc->gets_status_point(i-1);
+ pc->statp[i] = pc->statp[i-1] + pc->gets_status_point(i-1);
battle_config.use_statpoint_table = k; //restore setting
return 0;
@@ -9810,26 +10338,26 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) {
struct item_cd* cd = NULL;
if( load ) {
- if( !(cd = idb_get(itemcd_db, sd->status.char_id)) ) {
+ if( !(cd = idb_get(pc->itemcd_db, sd->status.char_id)) ) {
// no skill cooldown is associated with this character
return;
}
for(i = 0; i < MAX_ITEMDELAYS; i++) {
- if( cd->nameid[i] && DIFF_TICK(iTimer->gettick(),cd->tick[i]) < 0 ) {
+ if( cd->nameid[i] && DIFF_TICK(timer->gettick(),cd->tick[i]) < 0 ) {
sd->item_delay[cursor].tick = cd->tick[i];
sd->item_delay[cursor].nameid = cd->nameid[i];
cursor++;
}
}
- idb_remove(itemcd_db,sd->status.char_id);
+ idb_remove(pc->itemcd_db,sd->status.char_id);
} else {
- if( !(cd = idb_get(itemcd_db,sd->status.char_id)) ) {
+ if( !(cd = idb_get(pc->itemcd_db,sd->status.char_id)) ) {
// create a new skill cooldown object for map storage
CREATE( cd, struct item_cd, 1 );
- idb_put( itemcd_db, sd->status.char_id, cd );
+ idb_put( pc->itemcd_db, sd->status.char_id, cd );
}
for(i = 0; i < MAX_ITEMDELAYS; i++) {
- if( sd->item_delay[i].nameid && DIFF_TICK(iTimer->gettick(),sd->item_delay[i].tick) < 0 ) {
+ if( sd->item_delay[i].nameid && DIFF_TICK(timer->gettick(),sd->item_delay[i].tick) < 0 ) {
cd->tick[cursor] = sd->item_delay[i].tick;
cd->nameid[cursor] = sd->item_delay[i].nameid;
cursor++;
@@ -9839,79 +10367,456 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) {
return;
}
-/*==========================================
- * pc Init/Terminate
- *------------------------------------------*/
-void do_final_pc(void) {
+void pc_bank_deposit(struct map_session_data *sd, int money) {
+ unsigned int limit_check = money+sd->status.bank_vault;
+
+ if( money <= 0 || limit_check > MAX_BANK_ZENY ) {
+ clif->bank_deposit(sd,BDA_OVERFLOW);
+ return;
+ } else if ( money > sd->status.zeny ) {
+ clif->bank_deposit(sd,BDA_NO_MONEY);
+ return;
+ }
- db_destroy(itemcd_db);
+ if( pc->payzeny(sd,money, LOG_TYPE_BANK, NULL) )
+ clif->bank_deposit(sd,BDA_NO_MONEY);
+ else {
+ sd->status.bank_vault += money;
+ if( map->save_settings&256 )
+ chrif->save(sd,0);
+ clif->bank_deposit(sd,BDA_SUCCESS);
+ }
+}
+void pc_bank_withdraw(struct map_session_data *sd, int money) {
+ unsigned int limit_check = money+sd->status.zeny;
+
+ if( money <= 0 ) {
+ clif->bank_withdraw(sd,BWA_UNKNOWN_ERROR);
+ return;
+ } else if ( money > sd->status.bank_vault ) {
+ clif->bank_withdraw(sd,BWA_NO_MONEY);
+ return;
+ } else if ( limit_check > MAX_ZENY ) {
+ /* no official response for this scenario exists. */
+ clif->colormes(sd->fd,COLOR_RED,msg_txt(1482));
+ return;
+ }
+
+ if( pc->getzeny(sd,money, LOG_TYPE_BANK, NULL) )
+ clif->bank_withdraw(sd,BWA_NO_MONEY);
+ else {
+ sd->status.bank_vault -= money;
+ if( map->save_settings&256 )
+ chrif->save(sd,0);
+ clif->bank_withdraw(sd,BWA_SUCCESS);
+ }
+}
+/* status change data arrived from char-server */
+void pc_scdata_received(struct map_session_data *sd) {
+ pc->inventory_rentals(sd);
+ clif->show_modifiers(sd);
+
+ if (sd->expiration_time != 0) { // don't display if it's unlimited or unknow value
+ time_t exp_time = sd->expiration_time;
+ char tmpstr[1024];
+ strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(501), localtime(&exp_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S."
+ clif->wis_message(sd->fd, map->wisp_server_name, tmpstr, strlen(tmpstr)+1);
+
+ pc->expire_check(sd);
+ }
+
+ if( sd->state.standalone ) {
+ clif->pLoadEndAck(0,sd);
+ pc->autotrade_populate(sd);
+ pc->autotrade_start(sd);
+ }
+}
+int pc_expiration_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct map_session_data *sd = map->id2sd(id);
+
+ if( !sd ) return 0;
+
+ sd->expiration_tid = INVALID_TIMER;
+
+ if( sd->fd )
+ clif->authfail_fd(sd->fd,10);
+
+ map->quit(sd);
+
+ return 0;
+}
+/* this timer exists only when a character with a expire timer > 24h is online */
+/* it loops thru online players once an hour to check whether a new < 24h is available */
+int pc_global_expiration_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct s_mapiterator* iter;
+ struct map_session_data* sd;
- do_final_pc_groups();
+ iter = mapit_getallusers();
- ers_destroy(pc_sc_display_ers);
- return;
+ for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) {
+ if( sd->expiration_time )
+ pc->expire_check(sd);
+ }
+
+ mapit->free(iter);
+
+ return 0;
}
+void pc_expire_check(struct map_session_data *sd) {
+ /* ongoing timer */
+ if( sd->expiration_tid != INVALID_TIMER )
+ return;
+
+ /* not within the next 24h, enable the global check */
+ if( sd->expiration_time > ( time(NULL) + ( ( 60 * 60 ) * 24 ) ) ) {
+
+ /* global check not running, enable */
+ if( pc->expiration_tid == INVALID_TIMER ) {
+ /* starts in 1h, repeats every hour */
+ pc->expiration_tid = timer->add_interval(timer->gettick() + ((1000*60)*60), pc->global_expiration_timer, 0, 0, ((1000*60)*60));
+ }
+
+ return;
+ }
-int do_init_pc(void) {
+ sd->expiration_tid = timer->add(timer->gettick() + (int64)(sd->expiration_time - time(NULL))*1000, pc->expiration_timer, sd->bl.id, 0);
+}
+/**
+ * Loads autotraders
+ ***/
+void pc_autotrade_load(void) {
+ struct map_session_data *sd;
+ char *data;
+
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `account_id`,`char_id`,`sex`,`title` FROM `%s`",map->autotrade_merchants_db))
+ Sql_ShowDebug(map->mysql_handle);
+
+ while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) {
+ int account_id, char_id;
+ char title[MESSAGE_SIZE];
+ unsigned char sex;
+
+ SQL->GetData(map->mysql_handle, 0, &data, NULL); account_id = atoi(data);
+ SQL->GetData(map->mysql_handle, 1, &data, NULL); char_id = atoi(data);
+ SQL->GetData(map->mysql_handle, 2, &data, NULL); sex = atoi(data);
+ SQL->GetData(map->mysql_handle, 3, &data, NULL); safestrncpy(title, data, sizeof(title));
- itemcd_db = idb_alloc(DB_OPT_RELEASE_DATA);
+ CREATE(sd, TBL_PC, 1);
+
+ pc->setnewpc(sd, account_id, char_id, 0, 0, sex, 0);
+
+ safestrncpy(sd->message, title, MESSAGE_SIZE);
+
+ sd->state.standalone = 1;
+ sd->group = pcg->get_dummy_group();
+
+ chrif->authreq(sd,true);
+ }
+
+ SQL->FreeResult(map->mysql_handle);
+}
+/**
+ * Loads vending data and sets it up, is triggered when char server data that pc_autotrade_load requested arrives
+ **/
+void pc_autotrade_start(struct map_session_data *sd) {
+ unsigned int count = 0;
+ int i;
+ char *data;
- pc->readdb();
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `itemkey`,`amount`,`price` FROM `%s` WHERE `char_id` = '%d'",map->autotrade_data_db,sd->status.char_id))
+ Sql_ShowDebug(map->mysql_handle);
- iTimer->add_timer_func_list(pc_invincible_timer, "pc_invincible_timer");
- iTimer->add_timer_func_list(pc_eventtimer, "pc_eventtimer");
- iTimer->add_timer_func_list(pc_inventory_rental_end, "pc_inventory_rental_end");
- iTimer->add_timer_func_list(pc->calc_pvprank_timer, "pc->calc_pvprank_timer");
- iTimer->add_timer_func_list(pc_autosave, "pc_autosave");
- iTimer->add_timer_func_list(pc_spiritball_timer, "pc_spiritball_timer");
- iTimer->add_timer_func_list(pc_follow_timer, "pc_follow_timer");
- iTimer->add_timer_func_list(pc->endautobonus, "pc->endautobonus");
- iTimer->add_timer_func_list(pc_charm_timer, "pc_charm_timer");
+ while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) {
+ int itemkey, amount, price;
+
+ SQL->GetData(map->mysql_handle, 0, &data, NULL); itemkey = atoi(data);
+ SQL->GetData(map->mysql_handle, 1, &data, NULL); amount = atoi(data);
+ SQL->GetData(map->mysql_handle, 2, &data, NULL); price = atoi(data);
- iTimer->add_timer(iTimer->gettick() + iMap->autosave_interval, pc_autosave, 0, 0);
+ ARR_FIND(0, MAX_CART, i, sd->status.cart[i].id == itemkey);
+
+ if( i != MAX_CART && itemdb_cantrade(&sd->status.cart[i], 0, 0) ) {
+ if( amount > sd->status.cart[i].amount )
+ amount = sd->status.cart[i].amount;
+
+ if( amount ) {
+ sd->vending[count].index = i;
+ sd->vending[count].amount = amount;
+ sd->vending[count].value = cap_value(price, 0, (unsigned int)battle_config.vending_max_value);
- // 0=day, 1=night [Yor]
- iMap->night_flag = battle_config.night_at_start ? 1 : 0;
+ count++;
+ }
+ }
+ }
+
+ if( !count ) {
+ pc->autotrade_update(sd,PAUC_REMOVE);
+ map->quit(sd);
+ } else {
+ sd->state.autotrade = 1;
+ sd->vender_id = ++vending->next_id;
+ sd->vend_num = count;
+ sd->state.vending = true;
+ idb_put(vending->db, sd->status.char_id, sd);
+ if( map->list[sd->bl.m].users )
+ clif->showvendingboard(&sd->bl,sd->message,0);
+ }
+}
+/**
+ * Perform a autotrade action
+ **/
+void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update_action action) {
+ int i;
+
+ /* either way, this goes down */
+ if( action != PAUC_START ) {
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'",map->autotrade_data_db,sd->status.char_id))
+ Sql_ShowDebug(map->mysql_handle);
+ }
+
+ switch( action ) {
+ case PAUC_REMOVE:
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' LIMIT 1",map->autotrade_merchants_db,sd->status.char_id))
+ Sql_ShowDebug(map->mysql_handle);
+ break;
+ case PAUC_START: {
+ char title[MESSAGE_SIZE*2+1];
+
+ SQL->EscapeStringLen(map->mysql_handle, title, sd->message, strnlen(sd->message, MESSAGE_SIZE));
+
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s` (`account_id`,`char_id`,`sex`,`title`) VALUES ('%d','%d','%d','%s')",
+ map->autotrade_merchants_db,
+ sd->status.account_id,
+ sd->status.char_id,
+ sd->status.sex,
+ title
+ ))
+ Sql_ShowDebug(map->mysql_handle);
+ }
+ /* yes we want it to fall */
+ case PAUC_REFRESH:
+ for( i = 0; i < sd->vend_num; i++ ) {
+ if( sd->vending[i].amount == 0 )
+ continue;
+
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s` (`char_id`,`itemkey`,`amount`,`price`) VALUES ('%d','%d','%d','%d')",
+ map->autotrade_data_db,
+ sd->status.char_id,
+ sd->status.cart[sd->vending[i].index].id,
+ sd->vending[i].amount,
+ sd->vending[i].value
+ ))
+ Sql_ShowDebug(map->mysql_handle);
+ }
+ break;
+ }
+}
+/**
+ * Handles characters upon @autotrade usage
+ **/
+void pc_autotrade_prepare(struct map_session_data *sd) {
+ struct autotrade_vending *data;
+ int i, cursor = 0;
+ int account_id, char_id;
+ char title[MESSAGE_SIZE];
+ unsigned char sex;
+
+ CREATE(data, struct autotrade_vending, 1);
+
+ memcpy(data->vending, sd->vending, sizeof(sd->vending));
+
+ for(i = 0; i < sd->vend_num; i++) {
+ if( sd->vending[i].amount ) {
+ memcpy(&data->list[cursor],&sd->status.cart[sd->vending[i].index],sizeof(struct item));
+ cursor++;
+ }
+ }
+
+ data->vend_num = (unsigned char)cursor;
+
+ idb_put(pc->at_db, sd->status.char_id, data);
+
+ account_id = sd->status.account_id;
+ char_id = sd->status.char_id;
+ sex = sd->status.sex;
+ safestrncpy(title, sd->message, sizeof(title));
+
+ sd->npc_id = 0;
+ sd->npc_shopid = 0;
+ if (sd->st) {
+ sd->st->state = END;
+ sd->st = NULL;
+ }
+ map->quit(sd);
+ chrif->auth_delete(account_id, char_id, ST_LOGOUT);
+
+ CREATE(sd, TBL_PC, 1);
+
+ pc->setnewpc(sd, account_id, char_id, 0, 0, sex, 0);
+
+ safestrncpy(sd->message, title, MESSAGE_SIZE);
+
+ sd->state.standalone = 1;
+ sd->group = pcg->get_dummy_group();
+
+ chrif->authreq(sd,true);
+}
+/**
+ * Prepares autotrade data from pc->at_db from a player that has already returned from char server
+ **/
+void pc_autotrade_populate(struct map_session_data *sd) {
+ struct autotrade_vending *data;
+ int i, j, k, cursor = 0;
+
+ if( !(data = idb_get(pc->at_db,sd->status.char_id)) )
+ return;
+
+ for(i = 0; i < data->vend_num; i++) {
+ if( !data->vending[i].amount )
+ continue;
+
+ for(j = 0; j < MAX_CART; j++) {
+ if( !memcmp((char*)(&data->list[i]) + sizeof(data->list[0].id), (char*)(&sd->status.cart[j]) + sizeof(data->list[0].id), sizeof(struct item) - sizeof(data->list[0].id)) ) {
+ if( cursor ) {
+ ARR_FIND(0, cursor, k, sd->vending[k].index == j);
+ if( k != cursor )
+ continue;
+ }
+ break;
+ }
+ }
+
+ if( j != MAX_CART ) {
+ sd->vending[cursor].index = j;
+ sd->vending[cursor].amount = data->vending[i].amount;
+ sd->vending[cursor].value = data->vending[i].value;
+
+ cursor++;
+ }
+ }
+
+ sd->vend_num = cursor;
+
+ pc->autotrade_update(sd,PAUC_START);
+
+ idb_remove(pc->at_db, sd->status.char_id);
+}
+void do_final_pc(void) {
+
+ db_destroy(pc->itemcd_db);
+ db_destroy(pc->at_db);
+
+ pcg->final();
+
+ ers_destroy(pc->sc_display_ers);
+ ers_destroy(pc->num_reg_ers);
+ ers_destroy(pc->str_reg_ers);
+ return;
+}
+
+void do_init_pc(bool minimal) {
+ if (minimal)
+ return;
+
+ pc->itemcd_db = idb_alloc(DB_OPT_RELEASE_DATA);
+ pc->at_db = idb_alloc(DB_OPT_RELEASE_DATA);
+
+ pc->readdb();
+
+ timer->add_func_list(pc->invincible_timer, "pc_invincible_timer");
+ timer->add_func_list(pc->eventtimer, "pc_eventtimer");
+ timer->add_func_list(pc->inventory_rental_end, "pc_inventory_rental_end");
+ timer->add_func_list(pc->calc_pvprank_timer, "pc_calc_pvprank_timer");
+ timer->add_func_list(pc->autosave, "pc_autosave");
+ timer->add_func_list(pc->spiritball_timer, "pc_spiritball_timer");
+ timer->add_func_list(pc->follow_timer, "pc_follow_timer");
+ timer->add_func_list(pc->endautobonus, "pc_endautobonus");
+ timer->add_func_list(pc->charm_timer, "pc_charm_timer");
+ timer->add_func_list(pc->global_expiration_timer,"pc_global_expiration_timer");
+ timer->add_func_list(pc->expiration_timer,"pc_expiration_timer");
+
+ timer->add(timer->gettick() + map->autosave_interval, pc->autosave, 0, 0);
+
+ // 0=day, 1=night [Yor]
+ map->night_flag = battle_config.night_at_start ? 1 : 0;
+
if (battle_config.day_duration > 0 && battle_config.night_duration > 0) {
int day_duration = battle_config.day_duration;
int night_duration = battle_config.night_duration;
// add night/day timer [Yor]
- iTimer->add_timer_func_list(pc->map_day_timer, "pc->map_day_timer");
- iTimer->add_timer_func_list(pc->map_night_timer, "pc->map_night_timer");
-
- pc->day_timer_tid = iTimer->add_timer_interval(iTimer->gettick() + (iMap->night_flag ? 0 : day_duration) + night_duration, pc->map_day_timer, 0, 0, day_duration + night_duration);
- pc->night_timer_tid = iTimer->add_timer_interval(iTimer->gettick() + day_duration + (iMap->night_flag ? night_duration : 0), pc->map_night_timer, 0, 0, day_duration + night_duration);
+ timer->add_func_list(pc->map_day_timer, "pc_map_day_timer");
+ timer->add_func_list(pc->map_night_timer, "pc_map_night_timer");
+
+ pc->day_timer_tid = timer->add_interval(timer->gettick() + (map->night_flag ? 0 : day_duration) + night_duration, pc->map_day_timer, 0, 0, day_duration + night_duration);
+ pc->night_timer_tid = timer->add_interval(timer->gettick() + day_duration + (map->night_flag ? night_duration : 0), pc->map_night_timer, 0, 0, day_duration + night_duration);
}
-
- do_init_pc_groups();
- pc_sc_display_ers = ers_new(sizeof(struct sc_display_entry), "pc.c:pc_sc_display_ers", ERS_OPT_NONE);
+ pcg->init();
+
+ pc->sc_display_ers = ers_new(sizeof(struct sc_display_entry), "pc.c:sc_display_ers", ERS_OPT_FLEX_CHUNK);
+ pc->num_reg_ers = ers_new(sizeof(struct script_reg_num), "pc.c::num_reg_ers", ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
+ pc->str_reg_ers = ers_new(sizeof(struct script_reg_str), "pc.c::str_reg_ers", ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
- return 0;
+ ers_chunk_size(pc->sc_display_ers, 150);
+ ers_chunk_size(pc->num_reg_ers, 300);
+ ers_chunk_size(pc->str_reg_ers, 50);
}
-
/*=====================================
-* Default Functions : pc.h
+* Default Functions : pc.h
* Generated by HerculesInterfaceMaker
* created by Susu
*-------------------------------------*/
void pc_defaults(void) {
+ const struct sg_data sg_info[MAX_PC_FEELHATE] = {
+ { SG_SUN_ANGER, SG_SUN_BLESS, SG_SUN_COMFORT, "PC_FEEL_SUN", "PC_HATE_MOB_SUN", is_day_of_sun },
+ { SG_MOON_ANGER, SG_MOON_BLESS, SG_MOON_COMFORT, "PC_FEEL_MOON", "PC_HATE_MOB_MOON", is_day_of_moon },
+ { SG_STAR_ANGER, SG_STAR_BLESS, SG_STAR_COMFORT, "PC_FEEL_STAR", "PC_HATE_MOB_STAR", is_day_of_star }
+ };
+ unsigned int equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_GARMENT,EQP_AMMO, EQP_SHADOW_ARMOR, EQP_SHADOW_WEAPON, EQP_SHADOW_SHIELD, EQP_SHADOW_SHOES, EQP_SHADOW_ACC_R, EQP_SHADOW_ACC_L };
+
pc = &pc_s;
/* vars */
- // timer for night.day
- pc->day_timer_tid = day_timer_tid;
- pc->night_timer_tid = night_timer_tid;
-
+ pc->at_db = NULL;
+ pc->itemcd_db = NULL;
+ /* */
+ pc->day_timer_tid = INVALID_TIMER;
+ pc->night_timer_tid = INVALID_TIMER;
+ /* respecting order */
+ memset(pc->exp_table, 0, sizeof(pc->exp_table)
+ + sizeof(pc->max_level)
+ + sizeof(pc->statp)
+ + sizeof(pc->level_penalty)
+ + sizeof(pc->skill_tree)
+ + sizeof(pc->smith_fame_list)
+ + sizeof(pc->chemist_fame_list)
+ + sizeof(pc->taekwon_fame_list)
+ );
+ /* */
+ memcpy(pc->equip_pos, &equip_pos, sizeof(pc->equip_pos));
+ /* */
+ memcpy(pc->sg_info, sg_info, sizeof(pc->sg_info));
+ /* */
+ pc->sc_display_ers = NULL;
+ /* */
+ pc->expiration_tid = INVALID_TIMER;
+ /* */
+ pc->num_reg_ers = NULL;
+ pc->str_reg_ers = NULL;
+ /* */
+ pc->reg_load = false;
/* funcs */
-
+ pc->init = do_init_pc;
+ pc->final = do_final_pc;
+
+ pc->get_dummy_sd = pc_get_dummy_sd;
pc->class2idx = pc_class2idx;
- pc->get_group_level = pc_get_group_level;
- pc->can_give_items = pc_can_give_items;
pc->can_use_command = pc_can_use_command;
-
+ pc->set_group = pc_set_group;
+ pc->should_log_commands = pc_should_log_commands;
+
pc->setrestartvalue = pc_setrestartvalue;
pc->makesavestatus = pc_makesavestatus;
pc->respawn = pc_respawn;
@@ -9998,6 +10903,7 @@ void pc_defaults(void) {
pc->thisjobexp = pc_thisjobexp;
pc->gets_status_point = pc_gets_status_point;
pc->need_status_point = pc_need_status_point;
+ pc->maxparameterincrease = pc_maxparameterincrease;
pc->statusup = pc_statusup;
pc->statusup2 = pc_statusup2;
pc->skillup = pc_skillup;
@@ -10063,6 +10969,8 @@ void pc_defaults(void) {
pc->setstand = pc_setstand;
pc->candrop = pc_candrop;
+ pc->can_talk = pc_can_talk;
+ pc->can_attack = pc_can_attack;
pc->jobid2mapid = pc_jobid2mapid; // Skotlex
pc->mapid2jobid = pc_mapid2jobid; // Skotlex
@@ -10079,8 +10987,6 @@ void pc_defaults(void) {
pc->set_hate_mob = pc_set_hate_mob;
pc->readdb = pc_readdb;
- pc->do_init_pc = do_init_pc;
- pc->do_final_pc = do_final_pc;
pc->map_day_timer = map_day_timer; // by [yor]
pc->map_night_timer = map_night_timer; // by [yor]
// Rental System
@@ -10103,7 +11009,56 @@ void pc_defaults(void) {
pc->del_charm = pc_del_charm;
pc->baselevelchanged = pc_baselevelchanged;
-#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
pc->level_penalty_mod = pc_level_penalty_mod;
-#endif
+
+ pc->calc_skillpoint = pc_calc_skillpoint;
+
+ pc->invincible_timer = pc_invincible_timer;
+ pc->spiritball_timer = pc_spiritball_timer;
+ pc->check_banding = pc_check_banding;
+ pc->inventory_rental_end = pc_inventory_rental_end;
+ pc->check_skilltree = pc_check_skilltree;
+ pc->bonus_autospell = pc_bonus_autospell;
+ pc->bonus_autospell_onskill = pc_bonus_autospell_onskill;
+ pc->bonus_addeff = pc_bonus_addeff;
+ pc->bonus_addeff_onskill = pc_bonus_addeff_onskill;
+ pc->bonus_item_drop = pc_bonus_item_drop;
+ pc->calcexp = pc_calcexp;
+ pc->respawn_timer = pc_respawn_timer;
+ pc->jobchange_killclone = jobchange_killclone;
+ pc->getstat = pc_getstat;
+ pc->setstat = pc_setstat;
+ pc->eventtimer = pc_eventtimer;
+ pc->daynight_timer_sub = pc_daynight_timer_sub;
+ pc->charm_timer = pc_charm_timer;
+ pc->readdb_levelpenalty = pc_readdb_levelpenalty;
+ pc->autosave = pc_autosave;
+ pc->follow_timer = pc_follow_timer;
+ pc->read_skill_tree = pc_read_skill_tree;
+ pc->isUseitem = pc_isUseitem;
+ pc->show_steal = pc_show_steal;
+ pc->checkcombo = pc_checkcombo;
+ pc->calcweapontype = pc_calcweapontype;
+ pc->removecombo = pc_removecombo;
+
+ pc->bank_withdraw = pc_bank_withdraw;
+ pc->bank_deposit = pc_bank_deposit;
+
+ pc->rental_expire = pc_rental_expire;
+ pc->scdata_received = pc_scdata_received;
+
+ pc->bound_clear = pc_bound_clear;
+
+ pc->expiration_timer = pc_expiration_timer;
+ pc->global_expiration_timer = pc_global_expiration_timer;
+ pc->expire_check = pc_expire_check;
+
+ /**
+ * Autotrade persistency [Ind/Hercules <3]
+ **/
+ pc->autotrade_load = pc_autotrade_load;
+ pc->autotrade_update = pc_autotrade_update;
+ pc->autotrade_start = pc_autotrade_start;
+ pc->autotrade_prepare = pc_autotrade_prepare;
+ pc->autotrade_populate = pc_autotrade_populate;
}
diff --git a/src/map/pc.h b/src/map/pc.h
index 43d5d40c7..bec4522df 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -1,28 +1,36 @@
// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _PC_H_
-#define _PC_H_
-#include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus
-#include "../common/ers.h"
-#include "../common/timer.h" // INVALID_TIMER
-#include "atcommand.h" // AtCommandType
-#include "battle.h" // battle_config
-#include "battleground.h"
+
+#ifndef MAP_PC_H
+#define MAP_PC_H
+
+#include "../config/core.h" // AUTOLOOTITEM_SIZE, RENEWAL, SECURE_NPCTIMEOUT
+
+#include "battle.h" // battle
+#include "battleground.h" // enum bg_queue_types
#include "buyingstore.h" // struct s_buyingstore
-#include "itemdb.h" // MAX_ITEMGROUP
-#include "map.h" // RC_MAX
-#include "script.h" // struct script_reg, struct script_regstr
+#include "itemdb.h" // MAX_ITEMDELAYS
+#include "log.h" // struct e_log_pick_type
+#include "map.h" // RC_MAX, ELE_MAX
+#include "pc_groups.h" // GroupSettings
+#include "script.h" // struct reg_db
#include "searchstore.h" // struct s_search_store_info
-#include "status.h" // OPTION_*, struct weapon_atk
-#include "unit.h" // unit_stop_attack(), unit_stop_walking()
+#include "status.h" // enum sc_type, OPTION_*
+#include "unit.h" // struct unit_data, struct view_data
#include "vending.h" // struct s_vending
-#include "mob.h"
-#include "log.h"
-#include "pc_groups.h"
+#include "../common/cbasetypes.h"
+#include "../common/ers.h" // struct eri
+#include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus, NEW_CARTS
+
+/**
+ * Defines
+ **/
#define MAX_PC_BONUS 10
#define MAX_PC_SKILL_REQUIRE 5
#define MAX_PC_FEELHATE 3
+#define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval
+
//Equip indexes constants. (eg: sd->equip_index[EQI_AMMO] returns the index
//where the arrows are equipped)
enum equip_index {
@@ -41,6 +49,12 @@ enum equip_index {
EQI_COSTUME_LOW,
EQI_COSTUME_GARMENT,
EQI_AMMO,
+ EQI_SHADOW_ARMOR,
+ EQI_SHADOW_WEAPON,
+ EQI_SHADOW_SHIELD,
+ EQI_SHADOW_SHOES,
+ EQI_SHADOW_ACC_R,
+ EQI_SHADOW_ACC_L,
EQI_MAX
};
struct weapon_data {
@@ -102,6 +116,12 @@ enum npc_timeout_type {
NPCT_MENU = 1,
NPCT_WAIT = 2,
};
+
+struct pc_combos {
+ struct script_code *bonus;/* the script of the combo */
+ unsigned short id;/* this combo id */
+};
+
struct map_session_data {
struct block_list bl;
struct unit_data ud;
@@ -126,7 +146,6 @@ struct map_session_data {
unsigned int abra_flag : 2; // Abracadabra bugfix by Aru
unsigned int autocast : 1; // Autospell flag [Inkfish]
unsigned int autotrade : 1; //By Fantik
- unsigned int reg_dirty : 4; //By Skotlex (marks whether registry variables have been saved or not yet)
unsigned int showdelay :1;
unsigned int showexp :1;
unsigned int showzeny :1;
@@ -153,15 +172,22 @@ struct map_session_data {
short pmap; // Previous map on Map Change
unsigned short autoloot;
unsigned short autolootid[AUTOLOOTITEM_SIZE]; // [Zephyrus]
+ unsigned short autoloottype;
unsigned int autolooting : 1; //performance-saver, autolooting state for @alootid
unsigned short autobonus; //flag to indicate if an autobonus is activated. [Inkfish]
- struct guild *gmaster_flag;
+ unsigned int gmaster_flag : 1;
unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not.
unsigned int warping : 1;//states whether you're in the middle of a warp processing
unsigned int permanent_speed : 1; // When 1, speed cannot be changed through status_calc_pc().
unsigned int dialog : 1;
unsigned int prerefining : 1;
unsigned int workinprogress : 3; // 1 = disable skill/item, 2 = disable npc interaction, 3 = disable both
+ unsigned int hold_recalc : 1;
+ unsigned int snovice_call_flag : 3; //Summon Angel (stage 1~3)
+ unsigned int hpmeter_visible : 1;
+ unsigned int itemcheck : 1;
+ unsigned int standalone : 1;/* [Ind/Hercules <3] */
+ unsigned int loggingout : 1;
} state;
struct {
unsigned char no_weapon_damage, no_magic_damage, no_misc_damage;
@@ -177,12 +203,13 @@ struct map_session_data {
} special_state;
int login_id1, login_id2;
unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex]
- int group_id, group_pos, group_level;
- unsigned int permissions;/* group permissions */
- bool group_log_command;
+
+ /// Groups & permissions
+ int group_id;
+ GroupSettings *group;
+ unsigned int extra_temp_permissions; /* permissions from @addperm */
struct mmo_charstatus status;
- struct registry save_reg;
struct item_data* inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups)
short equip_index[EQI_MAX];
unsigned int weight,max_weight;
@@ -199,10 +226,10 @@ struct map_session_data {
char npc_str[CHATBOX_SIZE]; // for passing npc input box text to script engine
int npc_timer_id; //For player attached npc timers. [Skotlex]
unsigned int chatID;
- time_t idletime;
- struct{
+ int64 idletime;
+ struct {
int npc_id;
- unsigned int timeout;
+ int64 timeout;
} progressbar; //Progress Bar [Inkfish]
struct{
char name[NAME_LENGTH];
@@ -214,22 +241,21 @@ struct map_session_data {
uint16 skill_id_old,skill_lv_old;
uint16 skill_id_dance,skill_lv_dance;
short cook_mastery; // range: [0,1999] [Inkfish]
- unsigned char blockskill[MAX_SKILL];
+ bool blockskill[MAX_SKILL];
int cloneskill_id, reproduceskill_id;
int menuskill_id, menuskill_val, menuskill_val2;
int invincible_timer;
- unsigned int canlog_tick;
- unsigned int canuseitem_tick; // [Skotlex]
- unsigned int canusecashfood_tick;
- unsigned int canequip_tick; // [Inkfish]
- unsigned int cantalk_tick;
- unsigned int canskill_tick; // used to prevent abuse from no-delay ACT files
- unsigned int cansendmail_tick; // [Mail System Flood Protection]
- unsigned int ks_floodprotect_tick; // [Kill Steal Protection]
- unsigned int bloodylust_tick; // bloodylust player timer [out/in re full-heal protection]
+ int64 canlog_tick;
+ int64 canuseitem_tick; // [Skotlex]
+ int64 canusecashfood_tick;
+ int64 canequip_tick; // [Inkfish]
+ int64 cantalk_tick;
+ int64 canskill_tick; /// used to prevent abuse from no-delay ACT files
+ int64 cansendmail_tick; /// Mail System Flood Protection
+ int64 ks_floodprotect_tick; /// [Kill Steal Protection]
struct {
short nameid;
- unsigned int tick;
+ int64 tick;
} item_delay[MAX_ITEMDELAYS]; // [Paradox924X]
short weapontype1,weapontype2;
short disguise; // [Valaris]
@@ -256,7 +282,6 @@ struct map_session_data {
int expaddrace[RC_MAX];
int ignore_mdef[RC_MAX];
int ignore_def[RC_MAX];
- int itemgrouphealrate[MAX_ITEMGROUP];
short sp_gain_race[RC_MAX];
short sp_gain_race_attack[RC_MAX];
short hp_gain_race_attack[RC_MAX];
@@ -286,6 +311,10 @@ struct map_session_data {
short flag, rate;
unsigned char ele;
} subele2[MAX_PC_BONUS];
+ struct {
+ short value;
+ int rate, tick;
+ } def_set_race[RC_MAX], mdef_set_race[RC_MAX];
// zeroed structures end here
// manually zeroed structures start here.
struct s_autobonus autobonus[MAX_PC_BONUS], autobonus2[MAX_PC_BONUS], autobonus3[MAX_PC_BONUS]; //Auto script on attack, when attacked, on skill usage
@@ -319,14 +348,13 @@ struct map_session_data {
short add_heal_rate, add_heal2_rate;
short sp_gain_value, hp_gain_value, magic_sp_gain_value, magic_hp_gain_value;
short sp_vanish_rate;
- short sp_vanish_per;
+ short sp_vanish_per, sp_vanish_trigger;
unsigned short unbreakable; // chance to prevent ANY equipment breaking [celest]
unsigned short unbreakable_equip; //100% break resistance on certain equipment
unsigned short unstripable_equip;
int fixcastrate,varcastrate;
int add_fixcast,add_varcast;
int ematk; // matk bonus from equipment
- int eatk; // atk bonus from equipment
} bonus;
// zeroed vars end here.
int castrate,delayrate,hprate,sprate,dsprate;
@@ -345,10 +373,6 @@ struct map_session_data {
short mission_mobid; //Stores the target mob_id for TK_MISSION
int die_counter; //Total number of times you've died
int devotion[5]; //Stores the account IDs of chars devoted to.
- int reg_num; //Number of registries (type numeric)
- int regstr_num; //Number of registries (type string)
- struct script_reg *reg;
- struct script_regstr *regstr;
int trade_partner;
struct {
struct {
@@ -421,12 +445,11 @@ struct map_session_data {
bool changed; // if true, should sync with charserver on next mailbox request
} mail;
- //Quest log system [Kevin] [Inkfish]
- int num_quests;
- int avail_quests;
- int quest_index[MAX_QUEST_DB];
- struct quest quest_log[MAX_QUEST_DB];
- bool save_quest;
+ // Quest log system
+ int num_quests; ///< Number of entries in quest_log
+ int avail_quests; ///< Number of Q_ACTIVE and Q_INACTIVE entries in quest log (index of the first Q_COMPLETE entry)
+ struct quest *quest_log; ///< Quest log entries (note: Q_COMPLETE quests follow the first <avail_quests>th enties
+ bool save_quest; ///< Whether the quest_log entries were modified and are waitin to be saved
// temporary debug [flaviojs]
const char* debug_file;
@@ -434,7 +457,6 @@ struct map_session_data {
const char* debug_func;
unsigned int bg_id;
- unsigned short user_font;
/**
* For the Secure NPC Timeout option (check config/Secure.h) [RR]
@@ -452,17 +474,14 @@ struct map_session_data {
* @info
* - It is updated on every NPC iteration as mentioned above
**/
- unsigned int npc_idle_tick;
+ int64 npc_idle_tick;
/* */
enum npc_timeout_type npc_idle_type;
#endif
- struct {
- struct script_code **bonus;/* the script */
- unsigned short *id;/* array of combo ids */
- unsigned char count;
- } combos;
-
+ struct pc_combos *combos;
+ unsigned char combo_count;
+
/**
* Guarantees your friend request is legit (for bugreport:4629)
**/
@@ -477,13 +496,13 @@ struct map_session_data {
bool stealth;
unsigned char fontcolor;
unsigned int fontcolor_tid;
- unsigned int hchsysch_tick;
+ int64 hchsysch_tick;
/* [Ind/Hercules] */
struct sc_display_entry **sc_display;
unsigned char sc_display_count;
- unsigned short *instance;
+ short *instance;
unsigned short instances;
/* Possible Thanks to Yommy~! */
@@ -498,7 +517,31 @@ struct map_session_data {
unsigned int queues_count;
/* Made Possible Thanks to Yommy~! */
- unsigned int cryptKey;
+ unsigned int cryptKey; ///< Packet obfuscation key to be used for the next received packet
+ unsigned short (*parse_cmd_func)(int fd, struct map_session_data *sd); ///< parse_cmd_func used by this player
+
+ unsigned char delayed_damage;//ref. counter bugreport:7307 [Ind/Hercules]
+
+ /* HPM Custom Struct */
+ struct HPluginData **hdata;
+ unsigned int hdatac;
+
+ /* expiration_time timer id */
+ int expiration_tid;
+ time_t expiration_time;
+
+ /* */
+ struct {
+ unsigned int second,third;
+ } sktree;
+
+ /**
+ * Account/Char variables & array control of those variables
+ **/
+ struct reg_db regs;
+ unsigned char vars_received;/* char loading is only complete when you get it all. */
+ bool vars_ok;
+ bool vars_dirty;
// temporary debugging of bug #3504
const char* delunit_prevfile;
@@ -506,86 +549,14 @@ struct map_session_data {
};
-struct eri *pc_sc_display_ers;
-
-//Update this max as necessary. 55 is the value needed for Super Baby currently
-//Raised to 84 since Expanded Super Novice needs it.
-#define MAX_SKILL_TREE 84
-//Total number of classes (for data storage)
-#define CLASS_COUNT (JOB_MAX - JOB_NOVICE_HIGH + JOB_MAX_BASIC)
-
-enum weapon_type {
- W_FIST, //Bare hands
- W_DAGGER, //1
- W_1HSWORD, //2
- W_2HSWORD, //3
- W_1HSPEAR, //4
- W_2HSPEAR, //5
- W_1HAXE, //6
- W_2HAXE, //7
- W_MACE, //8
- W_2HMACE, //9 (unused)
- W_STAFF, //10
- W_BOW, //11
- W_KNUCKLE, //12
- W_MUSICAL, //13
- W_WHIP, //14
- W_BOOK, //15
- W_KATAR, //16
- W_REVOLVER, //17
- W_RIFLE, //18
- W_GATLING, //19
- W_SHOTGUN, //20
- W_GRENADE, //21
- W_HUUMA, //22
- W_2HSTAFF, //23
- MAX_WEAPON_TYPE,
- // dual-wield constants
- W_DOUBLE_DD, // 2 daggers
- W_DOUBLE_SS, // 2 swords
- W_DOUBLE_AA, // 2 axes
- W_DOUBLE_DS, // dagger + sword
- W_DOUBLE_DA, // dagger + axe
- W_DOUBLE_SA, // sword + axe
-};
-
-enum ammo_type {
- A_ARROW = 1,
- A_DAGGER, //2
- A_BULLET, //3
- A_SHELL, //4
- A_GRENADE, //5
- A_SHURIKEN, //6
- A_KUNAI, //7
- A_CANNONBALL, //8
- A_THROWWEAPON //9
-};
-
-//Equip position constants
-enum equip_pos {
- EQP_HEAD_LOW = 0x0001,
- EQP_HEAD_MID = 0x0200, //512
- EQP_HEAD_TOP = 0x0100, //256
- EQP_HAND_R = 0x0002, //2
- EQP_HAND_L = 0x0020, //32
- EQP_ARMOR = 0x0010, //16
- EQP_SHOES = 0x0040, //64
- EQP_GARMENT = 0x0004, //4
- EQP_ACC_L = 0x0008, //8
- EQP_ACC_R = 0x0080, //128
- EQP_COSTUME_HEAD_TOP = 0x0400, //1024
- EQP_COSTUME_HEAD_MID = 0x0800, //2048
- EQP_COSTUME_HEAD_LOW = 0x1000, //4096
- EQP_COSTUME_GARMENT = 0x2000, //8192
- EQP_AMMO = 0x8000, //32768
-};
-
#define EQP_WEAPON EQP_HAND_R
#define EQP_SHIELD EQP_HAND_L
#define EQP_ARMS (EQP_HAND_R|EQP_HAND_L)
#define EQP_HELM (EQP_HEAD_LOW|EQP_HEAD_MID|EQP_HEAD_TOP)
#define EQP_ACC (EQP_ACC_L|EQP_ACC_R)
#define EQP_COSTUME (EQP_COSTUME_HEAD_TOP|EQP_COSTUME_HEAD_MID|EQP_COSTUME_HEAD_LOW|EQP_COSTUME_GARMENT)
+#define EQP_SHADOW_ACC (EQP_SHADOW_ACC_R|EQP_SHADOW_ACC_L)
+#define EQP_SHADOW_ARMS (EQP_SHADOW_WEAPON|EQP_SHADOW_SHIELD)
/// Equip positions that use a visible sprite
#if PACKETVER < 20110111
@@ -598,7 +569,7 @@ enum equip_pos {
#define pc_setsit(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 2 )
#define pc_isdead(sd) ( (sd)->state.dead_sit == 1 )
#define pc_issit(sd) ( (sd)->vd.dead_sit == 2 )
-#define pc_isidle(sd) ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share )
+#define pc_isidle(sd) ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(sockt->last_tick, (sd)->idletime) >= battle->bc->idle_no_share )
#define pc_istrading(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading )
#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chatID || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend )
@@ -620,9 +591,9 @@ enum equip_pos {
#define pc_isfalcon(sd) ( (sd)->sc.option&OPTION_FALCON )
#define pc_isriding(sd) ( (sd)->sc.option&OPTION_RIDING )
#define pc_isinvisible(sd) ( (sd)->sc.option&OPTION_INVISIBLE )
-#define pc_is50overweight(sd) ( (sd)->weight*100 >= (sd)->max_weight*battle_config.natural_heal_weight_rate )
+#define pc_is50overweight(sd) ( (sd)->weight*100 >= (sd)->max_weight*battle->bc->natural_heal_weight_rate )
#define pc_is90overweight(sd) ( (sd)->weight*10 >= (sd)->max_weight*9 )
-#define pc_maxparameter(sd) ( ((((sd)->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO) || (sd)->class_&JOBL_THIRD ? ((sd)->class_&JOBL_BABY ? battle_config.max_baby_third_parameter : battle_config.max_third_parameter) : ((sd)->class_&JOBL_BABY ? battle_config.max_baby_parameter : battle_config.max_parameter)) )
+#define pc_maxparameter(sd) ( (((sd)->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO || ((sd)->class_&MAPID_UPPERMASK) == MAPID_REBELLION || ((sd)->class_&MAPID_THIRDMASK) == MAPID_SUPER_NOVICE_E) ? battle->bc->max_extended_parameter : (sd)->class_&JOBL_THIRD ? ((sd)->class_&JOBL_BABY ? battle->bc->max_baby_third_parameter : battle->bc->max_third_parameter) : ((sd)->class_&JOBL_BABY ? battle->bc->max_baby_parameter : battle->bc->max_parameter) )
/**
* Ranger
**/
@@ -633,8 +604,8 @@ enum equip_pos {
// Rune Knight Dragon
#define pc_isridingdragon(sd) ( (sd)->sc.option&OPTION_DRAGON )
-#define pc_stop_walking(sd, type) unit_stop_walking(&(sd)->bl, type)
-#define pc_stop_attack(sd) unit_stop_attack(&(sd)->bl)
+#define pc_stop_walking(sd, type) (unit->stop_walking(&(sd)->bl, (type)))
+#define pc_stop_attack(sd) (unit->stop_attack(&(sd)->bl))
//Weapon check considering dual wielding.
#define pc_check_weapontype(sd, type) ((type)&((sd)->status.weapon < MAX_WEAPON_TYPE? \
@@ -648,19 +619,20 @@ enum equip_pos {
|| ( (class_) >= JOB_RUNE_KNIGHT && (class_) <= JOB_MECHANIC_T2 ) \
|| ( (class_) >= JOB_BABY_RUNE && (class_) <= JOB_BABY_MECHANIC2 ) \
|| ( (class_) >= JOB_SUPER_NOVICE_E && (class_) <= JOB_SUPER_BABY_E ) \
-|| ( (class_) >= JOB_KAGEROU && (class_) < JOB_MAX ) \
+|| ( (class_) >= JOB_KAGEROU && (class_) <= JOB_OBORO ) \
+|| ( (class_) >= JOB_REBELLION && (class_) < JOB_MAX ) \
)
-#define pcdb_checkid(class_) pcdb_checkid_sub((unsigned int)class_)
+#define pcdb_checkid(class_) pcdb_checkid_sub((unsigned int)(class_))
// clientside display macros (values to the left/right of the "+")
#ifdef RENEWAL
#define pc_leftside_atk(sd) ((sd)->battle_status.batk)
- #define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk + (sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2 + (sd)->bonus.eatk )
+ #define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk + (sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2 + (sd)->battle_status.equip_atk )
#define pc_leftside_def(sd) ((sd)->battle_status.def2)
#define pc_rightside_def(sd) ((sd)->battle_status.def)
#define pc_leftside_mdef(sd) ((sd)->battle_status.mdef2)
#define pc_rightside_mdef(sd) ((sd)->battle_status.mdef)
-#define pc_leftside_matk(sd) (status_base_matk(status_get_status_data(&(sd)->bl), (sd)->status.base_level))
+#define pc_leftside_matk(sd) (status->base_matk(status->get_status_data(&(sd)->bl), (sd)->status.base_level))
#define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->battle_status.lhw.matk+(sd)->bonus.ematk)
#else
#define pc_leftside_atk(sd) ((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk)
@@ -685,24 +657,27 @@ enum equip_pos {
#define pc_get_group_id(sd) ( (sd)->group_id )
-#define pc_has_permission(sd, permission) ( ((sd)->permissions&permission) != 0 )
-#define pc_should_log_commands(sd) ( (sd)->group_log_command != false )
-
#define pc_checkoverhp(sd) ((sd)->battle_status.hp == (sd)->battle_status.max_hp)
#define pc_checkoversp(sd) ((sd)->battle_status.sp == (sd)->battle_status.max_sp)
-#define pc_readglobalreg(sd,reg) pc->readregistry(sd,reg,3)
-#define pc_setglobalreg(sd,reg,val) pc->setregistry(sd,reg,val,3)
-#define pc_readglobalreg_str(sd,reg) pc->readregistry_str(sd,reg,3)
-#define pc_setglobalreg_str(sd,reg,val) pc->setregistry_str(sd,reg,val,3)
-#define pc_readaccountreg(sd,reg) pc->readregistry(sd,reg,2)
-#define pc_setaccountreg(sd,reg,val) pc->setregistry(sd,reg,val,2)
-#define pc_readaccountregstr(sd,reg) pc->readregistry_str(sd,reg,2)
-#define pc_setaccountregstr(sd,reg,val) pc->setregistry_str(sd,reg,val,2)
-#define pc_readaccountreg2(sd,reg) pc->readregistry(sd,reg,1)
-#define pc_setaccountreg2(sd,reg,val) pc->setregistry(sd,reg,val,1)
-#define pc_readaccountreg2str(sd,reg) pc->readregistry_str(sd,reg,1)
-#define pc_setaccountreg2str(sd,reg,val) pc->setregistry_str(sd,reg,val,1)
+#define pc_readglobalreg(sd,reg) (pc->readregistry((sd),(reg)))
+#define pc_setglobalreg(sd,reg,val) (pc->setregistry((sd),(reg),(val)))
+#define pc_readglobalreg_str(sd,reg) (pc->readregistry_str((sd),(reg)))
+#define pc_setglobalreg_str(sd,reg,val) (pc->setregistry_str((sd),(reg),(val)))
+#define pc_readaccountreg(sd,reg) (pc->readregistry((sd),(reg)))
+#define pc_setaccountreg(sd,reg,val) (pc->setregistry((sd),(reg),(val)))
+#define pc_readaccountregstr(sd,reg) (pc->readregistry_str((sd),(reg)))
+#define pc_setaccountregstr(sd,reg,val) (pc->setregistry_str((sd),(reg),(val)))
+#define pc_readaccountreg2(sd,reg) (pc->readregistry((sd),(reg)))
+#define pc_setaccountreg2(sd,reg,val) (pc->setregistry((sd),(reg),(val)))
+#define pc_readaccountreg2str(sd,reg) (pc->readregistry_str((sd),(reg)))
+#define pc_setaccountreg2str(sd,reg,val) (pc->setregistry_str((sd),(reg),(val)))
+
+/* pc_groups easy access */
+#define pc_get_group_level(sd) ( (sd)->group->level )
+#define pc_has_permission(sd,permission) ( ((sd)->extra_temp_permissions&(permission)) != 0 || ((sd)->group->e_permissions&(permission)) != 0 )
+#define pc_can_give_items(sd) ( pc_has_permission((sd),PC_PERM_TRADE) )
+#define pc_can_give_bound_items(sd) ( pc_has_permission((sd),PC_PERM_TRADE_BOUND) )
struct skill_tree_entry {
short id;
@@ -716,54 +691,103 @@ struct skill_tree_entry {
} need[MAX_PC_SKILL_REQUIRE];
}; // Celest
-extern struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE];
-
struct sg_data {
short anger_id;
short bless_id;
short comfort_id;
char feel_var[NAME_LENGTH];
char hate_var[NAME_LENGTH];
- int (*day_func)(void);
+ bool (*day_func)(void);
};
-extern const struct sg_data sg_info[MAX_PC_FEELHATE];
+enum { ADDITEM_EXIST , ADDITEM_NEW , ADDITEM_OVERAMOUNT };
-extern struct fame_list smith_fame_list[MAX_FAME_LIST];
-extern struct fame_list chemist_fame_list[MAX_FAME_LIST];
-extern struct fame_list taekwon_fame_list[MAX_FAME_LIST];
+/**
+ * Item Cool Down Delay Saving
+ * Struct item_cd is not a member of struct map_session_data
+ * to keep cooldowns in memory between player log-ins.
+ * All cooldowns are reset when server is restarted.
+ **/
+struct item_cd {
+ int64 tick[MAX_ITEMDELAYS];//tick
+ short nameid[MAX_ITEMDELAYS];//skill id
+};
-enum {ADDITEM_EXIST,ADDITEM_NEW,ADDITEM_OVERAMOUNT};
+enum e_pc_autotrade_update_action {
+ PAUC_START,
+ PAUC_REFRESH,
+ PAUC_REMOVE,
+};
+
+/**
+ * Used to temporarily remember vending data
+ **/
+struct autotrade_vending {
+ struct item list[MAX_VENDING];
+ struct s_vending vending[MAX_VENDING];
+ unsigned char vend_num;
+};
-#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
-#endif
/*=====================================
-* Interface : pc.h
+* Interface : pc.h
* Generated by HerculesInterfaceMaker
* created by Susu
*-------------------------------------*/
struct pc_interface {
- /* vars */
- // timer for night.day
+ /* */
+ DBMap *at_db;/* char id -> struct autotrade_vending */
+ /* */
+ DBMap* itemcd_db;
+ /* */
int day_timer_tid;
int night_timer_tid;
+ /* */
+ unsigned int exp_table[CLASS_COUNT][2][MAX_LEVEL];
+ unsigned int max_level[CLASS_COUNT][2];
+ unsigned int statp[MAX_LEVEL+1];
+ unsigned int level_penalty[3][RC_MAX][MAX_LEVEL*2+1];
+ unsigned int equip_pos[EQI_MAX];
+ /* */
+ struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE];
+ struct fame_list smith_fame_list[MAX_FAME_LIST];
+ struct fame_list chemist_fame_list[MAX_FAME_LIST];
+ struct fame_list taekwon_fame_list[MAX_FAME_LIST];
+ struct sg_data sg_info[MAX_PC_FEELHATE];
+ /* */
+ struct eri *sc_display_ers;
+ /* global expiration timer id */
+ int expiration_tid;
+ /**
+ * ERS for the bulk of pc vars
+ **/
+ struct eri *num_reg_ers;
+ struct eri *str_reg_ers;
+ /* */
+ bool reg_load;
/* funcs */
+ void (*init) (bool minimal);
+ void (*final) (void);
+ struct map_session_data* (*get_dummy_sd) (void);
int (*class2idx) (int class_);
- int (*get_group_level) (struct map_session_data *sd);
- int (*getrefinebonus) (int lv,int type);
+ //int (*getrefinebonus) (int lv,int type); FIXME: This function does not exist, nor it is ever called
bool (*can_give_items) (struct map_session_data *sd);
-
+ bool (*can_give_bound_items) (struct map_session_data *sd);
+ bool (*can_talk) (struct map_session_data *sd);
+ bool (*can_attack) ( struct map_session_data *sd, int target_id );
+
bool (*can_use_command) (struct map_session_data *sd, const char *command);
-
+ int (*set_group) (struct map_session_data *sd, int group_id);
+ bool (*should_log_commands) (struct map_session_data *sd);
+
int (*setrestartvalue) (struct map_session_data *sd,int type);
- int (*makesavestatus) (struct map_session_data *);
+ int (*makesavestatus) (struct map_session_data *sd);
void (*respawn) (struct map_session_data* sd, clr_type clrtype);
- int (*setnewpc) (struct map_session_data*,int,int,int,unsigned int,int,int);
+ int (*setnewpc) (struct map_session_data *sd, int account_id, int char_id, int login_id1, unsigned int client_tick, int sex, int fd);
bool (*authok) (struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers);
- void (*authfail) (struct map_session_data *);
+ void (*authfail) (struct map_session_data *sd);
int (*reg_received) (struct map_session_data *sd);
int (*isequip) (struct map_session_data *sd,int n);
@@ -779,18 +803,19 @@ struct pc_interface {
int (*calc_skilltree_normalize_job) (struct map_session_data *sd);
int (*clean_skilltree) (struct map_session_data *sd);
- int (*setpos) (struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype);
- int (*setsavepoint) (struct map_session_data*,short,int,int);
+ int (*setpos) (struct map_session_data* sd, unsigned short map_index, int x, int y, clr_type clrtype);
+ int (*setsavepoint) (struct map_session_data *sd, short map_index, int x, int y);
int (*randomwarp) (struct map_session_data *sd,clr_type type);
int (*memo) (struct map_session_data* sd, int pos);
- int (*checkadditem) (struct map_session_data*,int,int);
- int (*inventoryblank) (struct map_session_data*);
+ int (*checkadditem) (struct map_session_data *sd,int nameid,int amount);
+ int (*inventoryblank) (struct map_session_data *sd);
int (*search_inventory) (struct map_session_data *sd,int item_id);
- int (*payzeny) (struct map_session_data*,int, enum e_log_pick_type type, struct map_session_data*);
- int (*additem) (struct map_session_data*,struct item*,int,e_log_pick_type);
- int (*getzeny) (struct map_session_data*,int, enum e_log_pick_type, struct map_session_data*);
- int (*delitem) (struct map_session_data*,int,int,int,short,e_log_pick_type);
+ int (*payzeny) (struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd);
+ int (*additem) (struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type);
+ int (*getzeny) (struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd);
+ int (*delitem) (struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type);
+
// Special Shop System
int (*paycash) (struct map_session_data *sd, int price, int points);
int (*getcash) (struct map_session_data *sd, int cash, int points);
@@ -801,8 +826,8 @@ struct pc_interface {
int (*getitemfromcart) (struct map_session_data *sd,int idx,int amount);
int (*cartitem_amount) (struct map_session_data *sd,int idx,int amount);
- int (*takeitem) (struct map_session_data*,struct flooritem_data*);
- int (*dropitem) (struct map_session_data*,int,int);
+ int (*takeitem) (struct map_session_data *sd,struct flooritem_data *fitem);
+ int (*dropitem) (struct map_session_data *sd,int n,int amount);
bool (*isequipped) (struct map_session_data *sd, int nameid);
bool (*can_Adopt) (struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd);
@@ -810,53 +835,54 @@ struct pc_interface {
int (*updateweightstatus) (struct map_session_data *sd);
- int (*addautobonus) (struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned short pos,bool onskill);
+ int (*addautobonus) (struct s_autobonus *bonus,char max,const char *bonus_script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned short pos,bool onskill);
int (*exeautobonus) (struct map_session_data* sd,struct s_autobonus *bonus);
- int (*endautobonus) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*endautobonus) (int tid, int64 tick, int id, intptr_t data);
int (*delautobonus) (struct map_session_data* sd,struct s_autobonus *bonus,char max,bool restore);
- int (*bonus) (struct map_session_data*,int,int);
- int (*bonus2) (struct map_session_data *sd,int,int,int);
- int (*bonus3) (struct map_session_data *sd,int,int,int,int);
- int (*bonus4) (struct map_session_data *sd,int,int,int,int,int);
- int (*bonus5) (struct map_session_data *sd,int,int,int,int,int,int);
- int (*skill) (struct map_session_data* sd, int id, int level, int flag);
+ int (*bonus) (struct map_session_data *sd,int type,int val);
+ int (*bonus2) (struct map_session_data *sd,int type,int type2,int val);
+ int (*bonus3) (struct map_session_data *sd,int type,int type2,int type3,int val);
+ int (*bonus4) (struct map_session_data *sd,int type,int type2,int type3,int type4,int val);
+ int (*bonus5) (struct map_session_data *sd,int type,int type2,int type3,int type4,int type5,int val);
+ int (*skill) (struct map_session_data *sd, int id, int level, int flag);
int (*insert_card) (struct map_session_data *sd,int idx_card,int idx_equip);
int (*steal_item) (struct map_session_data *sd,struct block_list *bl, uint16 skill_lv);
int (*steal_coin) (struct map_session_data *sd,struct block_list *bl);
- int (*modifybuyvalue) (struct map_session_data*,int);
- int (*modifysellvalue) (struct map_session_data*,int);
+ int (*modifybuyvalue) (struct map_session_data *sd,int orig_value);
+ int (*modifysellvalue) (struct map_session_data *sd,int orig_value);
- int (*follow) (struct map_session_data*, int); // [MouseJstr]
- int (*stop_following) (struct map_session_data*);
+ int (*follow) (struct map_session_data *sd, int target_id); // [MouseJstr]
+ int (*stop_following) (struct map_session_data *sd);
unsigned int (*maxbaselv) (struct map_session_data *sd);
unsigned int (*maxjoblv) (struct map_session_data *sd);
int (*checkbaselevelup) (struct map_session_data *sd);
int (*checkjoblevelup) (struct map_session_data *sd);
- int (*gainexp) (struct map_session_data*,struct block_list*,unsigned int,unsigned int, bool);
- unsigned int (*nextbaseexp) (struct map_session_data *);
- unsigned int (*thisbaseexp) (struct map_session_data *);
- unsigned int (*nextjobexp) (struct map_session_data *);
- unsigned int (*thisjobexp) (struct map_session_data *);
- int (*gets_status_point) (int);
- int (*need_status_point) (struct map_session_data *,int,int);
- int (*statusup) (struct map_session_data*,int);
- int (*statusup2) (struct map_session_data*,int,int);
- int (*skillup) (struct map_session_data*,uint16 skill_id);
- int (*allskillup) (struct map_session_data*);
- int (*resetlvl) (struct map_session_data*,int type);
- int (*resetstate) (struct map_session_data*);
- int (*resetskill) (struct map_session_data*, int);
- int (*resetfeel) (struct map_session_data*);
- int (*resethate) (struct map_session_data*);
- int (*equipitem) (struct map_session_data*,int,int);
- int (*unequipitem) (struct map_session_data*,int,int);
- int (*checkitem) (struct map_session_data*);
- int (*useitem) (struct map_session_data*,int);
+ bool (*gainexp) (struct map_session_data *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, bool is_quest);
+ unsigned int (*nextbaseexp) (struct map_session_data *sd);
+ unsigned int (*thisbaseexp) (struct map_session_data *sd);
+ unsigned int (*nextjobexp) (struct map_session_data *sd);
+ unsigned int (*thisjobexp) (struct map_session_data *sd);
+ int (*gets_status_point) (int level);
+ int (*need_status_point) (struct map_session_data *sd,int type,int val);
+ int (*maxparameterincrease) (struct map_session_data* sd, int type);
+ bool (*statusup) (struct map_session_data *sd, int type, int increase);
+ int (*statusup2) (struct map_session_data *sd,int type,int val);
+ int (*skillup) (struct map_session_data *sd,uint16 skill_id);
+ int (*allskillup) (struct map_session_data *sd);
+ int (*resetlvl) (struct map_session_data *sd,int type);
+ int (*resetstate) (struct map_session_data *sd);
+ int (*resetskill) (struct map_session_data *sd, int flag);
+ int (*resetfeel) (struct map_session_data *sd);
+ int (*resethate) (struct map_session_data *sd);
+ int (*equipitem) (struct map_session_data *sd,int n,int req_pos);
+ int (*unequipitem) (struct map_session_data *sd,int n,int flag);
+ int (*checkitem) (struct map_session_data *sd);
+ int (*useitem) (struct map_session_data *sd,int n);
int (*skillatk_bonus) (struct map_session_data *sd, uint16 skill_id);
int (*skillheal_bonus) (struct map_session_data *sd, uint16 skill_id);
@@ -867,26 +893,26 @@ struct pc_interface {
void (*revive) (struct map_session_data *sd,unsigned int hp, unsigned int sp);
void (*heal) (struct map_session_data *sd,unsigned int hp,unsigned int sp, int type);
int (*itemheal) (struct map_session_data *sd,int itemid, int hp,int sp);
- int (*percentheal) (struct map_session_data *sd,int,int);
- int (*jobchange) (struct map_session_data *,int, int);
- int (*setoption) (struct map_session_data *,int);
+ int (*percentheal) (struct map_session_data *sd,int hp,int sp);
+ int (*jobchange) (struct map_session_data *sd,int job, int upper);
+ int (*setoption) (struct map_session_data *sd,int type);
int (*setcart) (struct map_session_data* sd, int type);
int (*setfalcon) (struct map_session_data* sd, int flag);
int (*setriding) (struct map_session_data* sd, int flag);
- int (*setmadogear) (struct map_session_data* sd, int flag);
- int (*changelook) (struct map_session_data *,int,int);
+ void (*setmadogear) (struct map_session_data* sd, int flag);
+ int (*changelook) (struct map_session_data *sd,int type,int val);
int (*equiplookall) (struct map_session_data *sd);
- int (*readparam) (struct map_session_data*,int);
- int (*setparam) (struct map_session_data*,int,int);
- int (*readreg) (struct map_session_data*,int);
- int (*setreg) (struct map_session_data*,int,int);
- char * (*readregstr) (struct map_session_data *sd,int reg);
- int (*setregstr) (struct map_session_data *sd,int reg,const char *str);
- int (*readregistry) (struct map_session_data*,const char*,int);
- int (*setregistry) (struct map_session_data*,const char*,int,int);
- char * (*readregistry_str) (struct map_session_data*,const char*,int);
- int (*setregistry_str) (struct map_session_data*,const char*,const char*,int);
+ int (*readparam) (struct map_session_data *sd,int type);
+ int (*setparam) (struct map_session_data *sd,int type,int val);
+ int (*readreg) (struct map_session_data *sd, int64 reg);
+ void (*setreg) (struct map_session_data *sd, int64 reg,int val);
+ char * (*readregstr) (struct map_session_data *sd, int64 reg);
+ void (*setregstr) (struct map_session_data *sd, int64 reg, const char *str);
+ int (*readregistry) (struct map_session_data *sd, int64 reg);
+ int (*setregistry) (struct map_session_data *sd, int64 reg, int val);
+ char * (*readregistry_str) (struct map_session_data *sd, int64 reg);
+ int (*setregistry_str) (struct map_session_data *sd, int64 reg, const char *val);
int (*addeventtimer) (struct map_session_data *sd,int tick,const char *name);
int (*deleventtimer) (struct map_session_data *sd,const char *name);
@@ -894,7 +920,7 @@ struct pc_interface {
int (*addeventtimercount) (struct map_session_data *sd,const char *name,int tick);
int (*calc_pvprank) (struct map_session_data *sd);
- int (*calc_pvprank_timer) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*calc_pvprank_timer) (int tid, int64 tick, int id, intptr_t data);
int (*ismarried) (struct map_session_data *sd);
int (*marriage) (struct map_session_data *sd,struct map_session_data *dstsd);
@@ -918,17 +944,15 @@ struct pc_interface {
void (*setinvincibletimer) (struct map_session_data* sd, int val);
void (*delinvincibletimer) (struct map_session_data* sd);
- int (*addspiritball) (struct map_session_data *sd,int,int);
- int (*delspiritball) (struct map_session_data *sd,int,int);
+ int (*addspiritball) (struct map_session_data *sd,int interval,int max);
+ int (*delspiritball) (struct map_session_data *sd,int count,int type);
void (*addfame) (struct map_session_data *sd,int count);
unsigned char (*famerank) (int char_id, int job);
int (*set_hate_mob) (struct map_session_data *sd, int pos, struct block_list *bl);
int (*readdb) (void);
- int (*do_init_pc) (void);
- void (*do_final_pc) (void);
- int (*map_day_timer) (int tid, unsigned int tick, int id, intptr_t data); // by [yor]
- int (*map_night_timer) (int tid, unsigned int tick, int id, intptr_t data); // by [yor]
+ int (*map_day_timer) (int tid, int64 tick, int id, intptr_t data); // by [yor]
+ int (*map_night_timer) (int tid, int64 tick, int id, intptr_t data); // by [yor]
// Rental System
void (*inventory_rentals) (struct map_session_data *sd);
int (*inventory_rental_clear) (struct map_session_data *sd);
@@ -949,13 +973,61 @@ struct pc_interface {
int (*del_charm) (struct map_session_data *sd,int count,int type);
void (*baselevelchanged) (struct map_session_data *sd);
-#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
- int (*level_penalty_mod) (struct map_session_data *sd, struct mob_data * md, int type);
-#endif
-} pc_s;
+ int (*level_penalty_mod) (int diff, unsigned char race, unsigned short mode, int type);
+ int (*calc_skillpoint) (struct map_session_data* sd);
+
+ int (*invincible_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*spiritball_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*check_banding) ( struct block_list *bl, va_list ap );
+ int (*inventory_rental_end) (int tid, int64 tick, int id, intptr_t data);
+ void (*check_skilltree) (struct map_session_data *sd, int skill_id);
+ int (*bonus_autospell) (struct s_autospell *spell, int max, short id, short lv, short rate, short flag, short card_id);
+ int (*bonus_autospell_onskill) (struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, short card_id);
+ int (*bonus_addeff) (struct s_addeffect* effect, int max, enum sc_type id, short rate, short arrow_rate, unsigned char flag);
+ int (*bonus_addeff_onskill) (struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill_id, unsigned char target);
+ int (*bonus_item_drop) (struct s_add_drop *drop, const short max, short id, short group, int race, int rate);
+ void (*calcexp) (struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src);
+ int (*respawn_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*jobchange_killclone) (struct block_list *bl, va_list ap);
+ int (*getstat) (struct map_session_data* sd, int type);
+ int (*setstat) (struct map_session_data* sd, int type, int val);
+ int (*eventtimer) (int tid, int64 tick, int id, intptr_t data);
+ int (*daynight_timer_sub) (struct map_session_data *sd,va_list ap);
+ int (*charm_timer) (int tid, int64 tick, int id, intptr_t data);
+ bool (*readdb_levelpenalty) (char* fields[], int columns, int current);
+ int (*autosave) (int tid, int64 tick, int id, intptr_t data);
+ int (*follow_timer) (int tid, int64 tick, int id, intptr_t data);
+ void (*read_skill_tree) (void);
+ int (*isUseitem) (struct map_session_data *sd,int n);
+ int (*show_steal) (struct block_list *bl,va_list ap);
+ int (*checkcombo) (struct map_session_data *sd, struct item_data *data );
+ int (*calcweapontype) (struct map_session_data *sd);
+ int (*removecombo) (struct map_session_data *sd, struct item_data *data );
+
+ void (*bank_deposit) (struct map_session_data *sd, int money);
+ void (*bank_withdraw) (struct map_session_data *sd, int money);
+
+ void (*rental_expire) (struct map_session_data *sd, int i);
+ void (*scdata_received) (struct map_session_data *sd);
+
+ void (*bound_clear) (struct map_session_data *sd, enum e_item_bound_type type);
+
+ int (*expiration_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*global_expiration_timer) (int tid, int64 tick, int id, intptr_t data);
+ void (*expire_check) (struct map_session_data *sd);
+
+ /**
+ * Autotrade persistency [Ind/Hercules <3]
+ **/
+ void (*autotrade_load) (void);
+ void (*autotrade_update) (struct map_session_data *sd, enum e_pc_autotrade_update_action action);
+ void (*autotrade_start) (struct map_session_data *sd);
+ void (*autotrade_prepare) (struct map_session_data *sd);
+ void (*autotrade_populate) (struct map_session_data *sd);
+};
struct pc_interface *pc;
void pc_defaults(void);
-#endif /* _PC_H_ */
+#endif /* MAP_PC_H */
diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c
index f1f69f7cb..e577c642f 100644
--- a/src/map/pc_groups.c
+++ b/src/map/pc_groups.c
@@ -2,48 +2,34 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
+#define HERCULES_CORE
+
+#include "pc_groups.h"
+
+#include "atcommand.h" // atcommand->exists(), atcommand->load_groups()
+#include "clif.h" // clif->GM_kick()
+#include "map.h" // mapiterator
+#include "pc.h" // pc->set_group()
+#include "../common/cbasetypes.h"
#include "../common/conf.h"
#include "../common/db.h"
#include "../common/malloc.h"
#include "../common/nullpo.h"
#include "../common/showmsg.h"
#include "../common/strlib.h" // strcmp
-#include "../common/socket.h"
-#include "atcommand.h" // AtCommandType
-#include "pc_groups.h"
-#include "pc.h" // e_pc_permission
-
-typedef struct GroupSettings GroupSettings;
-
-// Cached config settings/pointers for quick lookup
-struct GroupSettings {
- unsigned int id; // groups.[].id
- int level; // groups.[].level
- char name[60]; // copy of groups.[].name
- unsigned int e_permissions; // packed groups.[].permissions
- bool log_commands; // groups.[].log_commands
- int group_pos;/* pos on load [Ind] */
- /// Following are used/avaialble only during config reading
- config_setting_t *commands; // groups.[].commands
- config_setting_t *permissions; // groups.[].permissions
- config_setting_t *inherit; // groups.[].inherit
- bool inheritance_done; // have all inheritance rules been evaluated?
- config_setting_t *root; // groups.[]
-};
-
-int pc_group_max; /* known number of groups */
-
-static DBMap* pc_group_db; // id -> GroupSettings
-static DBMap* pc_groupname_db; // name -> GroupSettings
+static GroupSettings dummy_group; ///< dummy group used in dummy map sessions @see pc_get_dummy_sd()
+
+struct pc_groups_interface pcg_s;
/**
- * @retval NULL if not found
- * @private
+ * Returns dummy group.
+ * Used in dummy map sessions.
+ * @see pc_get_dummy_sd()
*/
-static inline GroupSettings* id2group(int group_id)
+GroupSettings* pc_group_get_dummy_group(void)
{
- return (GroupSettings*)idb_get(pc_group_db, group_id);
+ return &dummy_group;
}
/**
@@ -52,7 +38,7 @@ static inline GroupSettings* id2group(int group_id)
*/
static inline GroupSettings* name2group(const char* group_name)
{
- return (GroupSettings*)strdb_get(pc_groupname_db, group_name);
+ return strdb_get(pcg->name_db, group_name);
}
/**
@@ -65,43 +51,43 @@ static void read_config(void) {
const char *config_filename = "conf/groups.conf"; // FIXME hardcoded name
int group_count = 0;
- if (conf_read_file(&pc_group_config, config_filename))
+ if (libconfig->read_file(&pc_group_config, config_filename))
return;
- groups = config_lookup(&pc_group_config, "groups");
+ groups = libconfig->lookup(&pc_group_config, "groups");
if (groups != NULL) {
GroupSettings *group_settings = NULL;
DBIterator *iter = NULL;
int i, loop = 0;
- group_count = config_setting_length(groups);
+ group_count = libconfig->setting_length(groups);
for (i = 0; i < group_count; ++i) {
int id = 0, level = 0;
const char *groupname = NULL;
int log_commands = 0;
- config_setting_t *group = config_setting_get_elem(groups, i);
+ config_setting_t *group = libconfig->setting_get_elem(groups, i);
- if (!config_setting_lookup_int(group, "id", &id)) {
+ if (!libconfig->setting_lookup_int(group, "id", &id)) {
ShowConfigWarning(group, "pc_groups:read_config: \"groups\" list member #%d has undefined id, removing...", i);
- config_setting_remove_elem(groups, i);
+ libconfig->setting_remove_elem(groups, i);
--i;
--group_count;
continue;
}
- if (id2group(id) != NULL) {
+ if (pcg->exists(id)) {
ShowConfigWarning(group, "pc_groups:read_config: duplicate group id %d, removing...", i);
- config_setting_remove_elem(groups, i);
+ libconfig->setting_remove_elem(groups, i);
--i;
--group_count;
continue;
}
- config_setting_lookup_int(group, "level", &level);
- config_setting_lookup_bool(group, "log_commands", &log_commands);
+ libconfig->setting_lookup_int(group, "level", &level);
+ libconfig->setting_lookup_bool(group, "log_commands", &log_commands);
- if (!config_setting_lookup_string(group, "name", &groupname)) {
+ if (!libconfig->setting_lookup_string(group, "name", &groupname)) {
char temp[20];
config_setting_t *name = NULL;
snprintf(temp, sizeof(temp), "Group %d", id);
@@ -109,14 +95,16 @@ static void read_config(void) {
!config_setting_set_string(name, temp)) {
ShowError("pc_groups:read_config: failed to set missing group name, id=%d, skipping... (%s:%d)\n",
id, config_setting_source_file(group), config_setting_source_line(group));
+ --i;
+ --group_count;
continue;
}
- config_setting_lookup_string(group, "name", &groupname); // Retrieve the pointer
+ libconfig->setting_lookup_string(group, "name", &groupname); // Retrieve the pointer
}
if (name2group(groupname) != NULL) {
ShowConfigWarning(group, "pc_groups:read_config: duplicate group name %s, removing...", groupname);
- config_setting_remove_elem(groups, i);
+ libconfig->setting_remove_elem(groups, i);
--i;
--group_count;
continue;
@@ -125,38 +113,39 @@ static void read_config(void) {
CREATE(group_settings, GroupSettings, 1);
group_settings->id = id;
group_settings->level = level;
- safestrncpy(group_settings->name, groupname, 60);
+ group_settings->name = aStrdup(groupname);
group_settings->log_commands = (bool)log_commands;
- group_settings->inherit = config_setting_get_member(group, "inherit");
- group_settings->commands = config_setting_get_member(group, "commands");
- group_settings->permissions = config_setting_get_member(group, "permissions");
+ group_settings->inherit = libconfig->setting_get_member(group, "inherit");
+ group_settings->commands = libconfig->setting_get_member(group, "commands");
+ group_settings->permissions = libconfig->setting_get_member(group, "permissions");
group_settings->inheritance_done = false;
group_settings->root = group;
- group_settings->group_pos = i;
+ group_settings->index = i;
- strdb_put(pc_groupname_db, groupname, group_settings);
- idb_put(pc_group_db, id, group_settings);
+ strdb_put(pcg->name_db, groupname, group_settings);
+ idb_put(pcg->db, id, group_settings);
}
- group_count = config_setting_length(groups); // Save number of groups
+ group_count = libconfig->setting_length(groups); // Save number of groups
+ assert(group_count == db_size(pcg->db));
// Check if all commands and permissions exist
- iter = db_iterator(pc_group_db);
+ iter = db_iterator(pcg->db);
for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
config_setting_t *commands = group_settings->commands, *permissions = group_settings->permissions;
- int count = 0, i;
+ int count = 0;
// Make sure there is "commands" group
if (commands == NULL)
- commands = group_settings->commands = config_setting_add(group_settings->root, "commands", CONFIG_TYPE_GROUP);
- count = config_setting_length(commands);
+ commands = group_settings->commands = libconfig->setting_add(group_settings->root, "commands", CONFIG_TYPE_GROUP);
+ count = libconfig->setting_length(commands);
for (i = 0; i < count; ++i) {
- config_setting_t *command = config_setting_get_elem(commands, i);
+ config_setting_t *command = libconfig->setting_get_elem(commands, i);
const char *name = config_setting_name(command);
if (!atcommand->exists(name)) {
ShowConfigWarning(command, "pc_groups:read_config: non-existent command name '%s', removing...", name);
- config_setting_remove(commands, name);
+ libconfig->setting_remove(commands, name);
--i;
--count;
}
@@ -164,18 +153,18 @@ static void read_config(void) {
// Make sure there is "permissions" group
if (permissions == NULL)
- permissions = group_settings->permissions = config_setting_add(group_settings->root, "permissions", CONFIG_TYPE_GROUP);
- count = config_setting_length(permissions);
+ permissions = group_settings->permissions = libconfig->setting_add(group_settings->root, "permissions", CONFIG_TYPE_GROUP);
+ count = libconfig->setting_length(permissions);
for(i = 0; i < count; ++i) {
- config_setting_t *permission = config_setting_get_elem(permissions, i);
+ config_setting_t *permission = libconfig->setting_get_elem(permissions, i);
const char *name = config_setting_name(permission);
int j;
- ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0);
- if (j == ARRAYLENGTH(pc_g_permission_name)) {
+ ARR_FIND(0, pcg->permission_count, j, strcmp(pcg->permissions[j].name, name) == 0);
+ if (j == pcg->permission_count) {
ShowConfigWarning(permission, "pc_groups:read_config: non-existent permission name '%s', removing...", name);
- config_setting_remove(permissions, name);
+ libconfig->setting_remove(permissions, name);
--i;
--count;
}
@@ -186,7 +175,7 @@ static void read_config(void) {
// Apply inheritance
i = 0; // counter for processed groups
while (i < group_count) {
- iter = db_iterator(pc_group_db);
+ iter = db_iterator(pcg->db);
for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
config_setting_t *inherit = NULL,
*commands = group_settings->commands,
@@ -194,10 +183,10 @@ static void read_config(void) {
int j, inherit_count = 0, done = 0;
if (group_settings->inheritance_done) // group already processed
- continue;
+ continue;
if ((inherit = group_settings->inherit) == NULL ||
- (inherit_count = config_setting_length(inherit)) <= 0) { // this group does not inherit from others
+ (inherit_count = libconfig->setting_length(inherit)) <= 0) { // this group does not inherit from others
++i;
group_settings->inheritance_done = true;
continue;
@@ -205,16 +194,16 @@ static void read_config(void) {
for (j = 0; j < inherit_count; ++j) {
GroupSettings *inherited_group = NULL;
- const char *groupname = config_setting_get_string_elem(inherit, j);
+ const char *groupname = libconfig->setting_get_string_elem(inherit, j);
if (groupname == NULL) {
ShowConfigWarning(inherit, "pc_groups:read_config: \"inherit\" array member #%d is not a name, removing...", j);
- config_setting_remove_elem(inherit,j);
+ libconfig->setting_remove_elem(inherit,j);
continue;
}
if ((inherited_group = name2group(groupname)) == NULL) {
ShowConfigWarning(inherit, "pc_groups:read_config: non-existent group name \"%s\", removing...", groupname);
- config_setting_remove_elem(inherit,j);
+ libconfig->setting_remove_elem(inherit,j);
continue;
}
if (!inherited_group->inheritance_done)
@@ -222,15 +211,15 @@ static void read_config(void) {
// Copy settings (commands/permissions) that are not defined yet
if (inherited_group->commands != NULL) {
- int i = 0, commands_count = config_setting_length(inherited_group->commands);
- for (i = 0; i < commands_count; ++i)
- config_setting_copy(commands, config_setting_get_elem(inherited_group->commands, i));
+ int k = 0, commands_count = libconfig->setting_length(inherited_group->commands);
+ for (k = 0; k < commands_count; ++k)
+ libconfig->setting_copy(commands, libconfig->setting_get_elem(inherited_group->commands, k));
}
if (inherited_group->permissions != NULL) {
- int i = 0, permissions_count = config_setting_length(inherited_group->permissions);
- for (i = 0; i < permissions_count; ++i)
- config_setting_copy(permissions, config_setting_get_elem(inherited_group->permissions, i));
+ int k = 0, permissions_count = libconfig->setting_length(inherited_group->permissions);
+ for (k = 0; k < permissions_count; ++k)
+ libconfig->setting_copy(permissions, libconfig->setting_get_elem(inherited_group->permissions, k));
}
++done; // copied commands and permissions from one of inherited groups
@@ -249,131 +238,71 @@ static void read_config(void) {
break;
}
} // while(i < group_count)
-
+
// Pack permissions into GroupSettings.e_permissions for faster checking
- iter = db_iterator(pc_group_db);
+ iter = db_iterator(pcg->db);
for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
config_setting_t *permissions = group_settings->permissions;
- int i, count = config_setting_length(permissions);
+ int count = libconfig->setting_length(permissions);
for (i = 0; i < count; ++i) {
- config_setting_t *perm = config_setting_get_elem(permissions, i);
+ config_setting_t *perm = libconfig->setting_get_elem(permissions, i);
const char *name = config_setting_name(perm);
- int val = config_setting_get_bool(perm);
+ int val = libconfig->setting_get_bool(perm);
int j;
if (val == 0) // does not have this permission
continue;
- ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0);
- group_settings->e_permissions |= pc_g_permission_name[j].permission;
+ ARR_FIND(0, pcg->permission_count, j, strcmp(pcg->permissions[j].name, name) == 0);
+ group_settings->e_permissions |= pcg->permissions[j].permission;
}
}
dbi_destroy(iter);
- }
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' groups in '"CL_WHITE"%s"CL_RESET"'.\n", group_count, config_filename);
-
-
- if( ( pc_group_max = group_count ) ) {
- DBIterator *iter = db_iterator(pc_group_db);
- GroupSettings *group_settings = NULL;
- unsigned int* group_ids = aMalloc( pc_group_max * sizeof(unsigned int) );
- int i = 0;
- for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
- group_ids[i++] = group_settings->id;
+ // Atcommand permissions are processed by atcommand module.
+ // Fetch all groups and relevant config setting and send them
+ // to atcommand->load_group() for processing.
+ if (group_count > 0) {
+ GroupSettings **pc_groups = NULL;
+ config_setting_t **commands = NULL;
+ CREATE(pc_groups, GroupSettings*, group_count);
+ CREATE(commands, config_setting_t*, group_count);
+ i = 0;
+ iter = db_iterator(pcg->db);
+ for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
+ pc_groups[i] = group_settings;
+ commands[i] = group_settings->commands;
+ i++;
+ }
+ atcommand->load_groups(pc_groups, commands, group_count);
+ dbi_destroy(iter);
+ aFree(pc_groups);
+ aFree(commands);
}
-
- if( atcommand->group_ids )
- aFree(atcommand->group_ids);
- atcommand->group_ids = group_ids;
-
- atcommand->load_groups();
-
- dbi_destroy(iter);
}
-
- config_destroy(&pc_group_config);
-}
-
-/**
- * In group configuration file, setting for each command is either
- * <commandname> : <bool> (only atcommand), or
- * <commandname> : [ <bool>, <bool> ] ([ atcommand, charcommand ])
- * Maps AtCommandType enums to indexes of <commandname> value array,
- * COMMAND_ATCOMMAND (1) being index 0, COMMAND_CHARCOMMAND (2) being index 1.
- * @private
- */
-static inline int AtCommandType2idx(AtCommandType type) { return (type-1); }
-/**
- * Checks if player group can use @/#command, used only during parse (only available during parse)
- * @param group_id ID of the group
- * @param command Command name without @/# and params
- * @param type enum AtCommanndType { COMMAND_ATCOMMAND = 1, COMMAND_CHARCOMMAND = 2 }
- */
-bool pc_group_can_use_command(int group_id, const char *command, AtCommandType type) {
- int result = 0;
- config_setting_t *commands = NULL;
- GroupSettings *group = NULL;
-
- if (pc_group_has_permission(group_id, PC_PERM_USE_ALL_COMMANDS))
- return true;
-
- if ((group = id2group(group_id)) == NULL)
- return false;
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' groups in '"CL_WHITE"%s"CL_RESET"'.\n", group_count, config_filename);
- commands = group->commands;
- if (commands != NULL) {
- config_setting_t *cmd = NULL;
-
- // <commandname> : <bool> (only atcommand)
- if (type == COMMAND_ATCOMMAND && config_setting_lookup_bool(commands, command, &result))
- return (bool)result;
-
- // <commandname> : [ <bool>, <bool> ] ([ atcommand, charcommand ])
- if ((cmd = config_setting_get_member(commands, command)) != NULL &&
- config_setting_is_aggregate(cmd) && config_setting_length(cmd) == 2)
- return (bool)config_setting_get_bool_elem(cmd, AtCommandType2idx(type));
- }
- return false;
-}
-void pc_group_pc_load(struct map_session_data * sd) {
- GroupSettings *group = NULL;
- if ((group = id2group(sd->group_id)) == NULL) {
- ShowWarning("pc_group_pc_load: %s (AID:%d) logged in with unknown group id (%d)! kicking...\n",
- sd->status.name,
- sd->status.account_id,
- sd->group_id);
- set_eof(sd->fd);
- return;
- }
- sd->permissions = group->e_permissions;
- sd->group_pos = group->group_pos;
- sd->group_level = group->level;
- sd->group_log_command = group->log_commands;
+ // All data is loaded now, discard config
+ libconfig->destroy(&pc_group_config);
}
+
/**
* Checks if player group has a permission
- * @param group_id ID of the group
+ * @param group group
* @param permission permission to check
*/
-bool pc_group_has_permission(int group_id, int permission)
+bool pc_group_has_permission(GroupSettings *group, unsigned int permission)
{
- GroupSettings *group = NULL;
- if ((group = id2group(group_id)) == NULL)
- return false;
return ((group->e_permissions&permission) != 0);
}
/**
- * Checks commands used by player group should be logged
- * @param group_id ID of the group
+ * Checks if commands used by player group should be logged
+ * @param group group
*/
-bool pc_group_should_log_commands(int group_id)
+bool pc_group_should_log_commands(GroupSettings *group)
{
- GroupSettings *group = NULL;
- if ((group = id2group(group_id)) == NULL)
- return false;
return group->log_commands;
}
@@ -384,71 +313,165 @@ bool pc_group_should_log_commands(int group_id)
*/
bool pc_group_exists(int group_id)
{
- return idb_exists(pc_group_db, group_id);
+ return idb_exists(pcg->db, group_id);
}
/**
- * Group ID -> group name lookup. Used only in @who atcommands.
- * @param group_id group id
+ * @retval NULL if not found
+ */
+GroupSettings* pc_group_id2group(int group_id)
+{
+ return idb_get(pcg->db, group_id);
+}
+
+/**
+ * Group name lookup. Used only in @who atcommands.
+ * @param group group
* @return group name
* @public
*/
-const char* pc_group_id2name(int group_id)
+const char* pc_group_get_name(GroupSettings *group)
{
- GroupSettings *group = id2group(group_id);
- if (group == NULL)
- return "Non-existent group!";
return group->name;
}
/**
- * Group ID -> group level lookup. A way to provide backward compatibility with GM level system.
- * @param group id
+ * Group level lookup. A way to provide backward compatibility with GM level system.
+ * @param group group
* @return group level
* @public
*/
-int pc_group_id2level(int group_id)
+int pc_group_get_level(GroupSettings *group)
{
- GroupSettings *group = id2group(group_id);
- if (group == NULL)
- return 0;
return group->level;
}
+
/**
- * Group ID -> group level lookup.
- * @param group id
+ * Group -> index lookup.
+ * @param group group
* @return group index
* @public
*/
-int pc_group_id2idx(int group_id)
+int pc_group_get_idx(GroupSettings *group)
{
- GroupSettings *group = id2group(group_id);
- if (group == NULL)
- return 0;
- return group->group_pos;
+ return group->index;
}
/**
+ * Insert a new permission
+ * @return inserted key or 0 upon failure.
+ **/
+unsigned int pc_groups_add_permission(const char *name) {
+ uint64 key = 0x1;
+ unsigned char i;
+
+ for(i = 0; i < pcg->permission_count; i++) {
+ if( strcmpi(name,pcg->permissions[i].name) == 0 ) {
+ ShowError("pc_groups_add_permission(%s): failed! duplicate permission name!\n",name);
+ return 0;
+ }
+ }
+
+ if( i != 0 )
+ key = (uint64)pcg->permissions[i - 1].permission << 1;
+
+ if( key >= UINT_MAX ) {
+ ShowError("pc_groups_add_permission(%s): failed! not enough room, too many permissions!\n",name);
+ return 0;
+ }
+
+ i = pcg->permission_count;
+ RECREATE(pcg->permissions, struct pc_groups_permission_table, ++pcg->permission_count);
+
+ pcg->permissions[i].name = aStrdup(name);
+ pcg->permissions[i].permission = (unsigned int)key;
+
+ return (unsigned int)key;
+}
+/**
* Initialize PC Groups: allocate DBMaps and read config.
* @public
*/
-void do_init_pc_groups(void)
-{
- pc_group_db = idb_alloc(DB_OPT_RELEASE_DATA);
- pc_groupname_db = stridb_alloc(DB_OPT_DUP_KEY, 0);
+void do_init_pc_groups(void) {
+ const struct {
+ const char *name;
+ unsigned int permission;
+ } pc_g_defaults[] = {
+ { "can_trade", PC_PERM_TRADE },
+ { "can_party", PC_PERM_PARTY },
+ { "all_skill", PC_PERM_ALL_SKILL },
+ { "all_equipment", PC_PERM_USE_ALL_EQUIPMENT },
+ { "skill_unconditional", PC_PERM_SKILL_UNCONDITIONAL },
+ { "join_chat", PC_PERM_JOIN_ALL_CHAT },
+ { "kick_chat", PC_PERM_NO_CHAT_KICK },
+ { "hide_session", PC_PERM_HIDE_SESSION },
+ { "who_display_aid", PC_PERM_WHO_DISPLAY_AID },
+ { "hack_info", PC_PERM_RECEIVE_HACK_INFO },
+ { "any_warp", PC_PERM_WARP_ANYWHERE },
+ { "view_hpmeter", PC_PERM_VIEW_HPMETER },
+ { "view_equipment", PC_PERM_VIEW_EQUIPMENT },
+ { "use_check", PC_PERM_USE_CHECK },
+ { "use_changemaptype", PC_PERM_USE_CHANGEMAPTYPE },
+ { "all_commands", PC_PERM_USE_ALL_COMMANDS },
+ { "receive_requests", PC_PERM_RECEIVE_REQUESTS },
+ { "show_bossmobs", PC_PERM_SHOW_BOSS },
+ { "disable_pvm", PC_PERM_DISABLE_PVM },
+ { "disable_pvp", PC_PERM_DISABLE_PVP },
+ { "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD },
+ { "hchsys_admin", PC_PERM_HCHSYS_ADMIN },
+ { "can_trade_bound", PC_PERM_TRADE_BOUND },
+ };
+ unsigned char i, len = ARRAYLENGTH(pc_g_defaults);
+
+ for(i = 0; i < len; i++) {
+ unsigned int p;
+ if( ( p = pc_groups_add_permission(pc_g_defaults[i].name) ) != pc_g_defaults[i].permission )
+ ShowError("do_init_pc_groups: %s error : %d != %d\n",pc_g_defaults[i].name,p,pc_g_defaults[i].permission);
+ }
+
+ /**
+ * Handle plugin-provided permissions
+ **/
+ for(i = 0; i < pcg->HPMpermissions_count; i++) {
+ *pcg->HPMpermissions[i].mask = pc_groups_add_permission(pcg->HPMpermissions[i].name);
+ }
+
+ pcg->db = idb_alloc(DB_OPT_RELEASE_DATA);
+ pcg->name_db = stridb_alloc(DB_OPT_DUP_KEY, 0);
+
read_config();
}
/**
+ * @see DBApply
+ */
+static int group_db_clear_sub(DBKey key, DBData *data, va_list args)
+{
+ GroupSettings *group = DB->data2ptr(data);
+ if (group->name)
+ aFree(group->name);
+ return 0;
+}
+
+/**
* Finalize PC Groups: free DBMaps and config.
* @public
*/
void do_final_pc_groups(void)
{
- if (pc_group_db != NULL)
- db_destroy(pc_group_db);
- if (pc_groupname_db != NULL )
- db_destroy(pc_groupname_db);
+ if (pcg->db != NULL)
+ pcg->db->destroy(pcg->db, group_db_clear_sub);
+ if (pcg->name_db != NULL)
+ db_destroy(pcg->name_db);
+
+ if(pcg->permissions != NULL) {
+ unsigned char i;
+ for(i = 0; i < pcg->permission_count; i++)
+ aFree(pcg->permissions[i].name);
+ aFree(pcg->permissions);
+ pcg->permissions = NULL;
+ }
+ pcg->permission_count = 0;
}
/**
@@ -457,18 +480,50 @@ void do_final_pc_groups(void)
* @public
*/
void pc_groups_reload(void) {
- struct map_session_data* sd = NULL;
- struct s_mapiterator* iter;
+ struct map_session_data *sd = NULL;
+ struct s_mapiterator *iter;
- do_final_pc_groups();
- do_init_pc_groups();
+ pcg->final();
+ pcg->init();
/* refresh online users permissions */
iter = mapit_getallusers();
- for (sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter)) {
- pc_group_pc_load(sd);
+ for (sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter)) {
+ if (pc->set_group(sd, sd->group_id) != 0) {
+ ShowWarning("pc_groups_reload: %s (AID:%d) has unknown group id (%d)! kicking...\n",
+ sd->status.name, sd->status.account_id, pc_get_group_id(sd));
+ clif->GM_kick(NULL, sd);
+ }
}
mapit->free(iter);
+}
+/**
+ * Connect Interface
+ **/
+void pc_groups_defaults(void) {
+ pcg = &pcg_s;
+ /* */
+ pcg->db = NULL;
+ pcg->name_db = NULL;
+ /* */
+ pcg->permissions = NULL;
+ pcg->permission_count = 0;
+ /* */
+ pcg->HPMpermissions = NULL;
+ pcg->HPMpermissions_count = 0;
+ /* */
+ pcg->init = do_init_pc_groups;
+ pcg->final = do_final_pc_groups;
+ pcg->reload = pc_groups_reload;
+ /* */
+ pcg->get_dummy_group = pc_group_get_dummy_group;
+ pcg->exists = pc_group_exists;
+ pcg->id2group = pc_group_id2group;
+ pcg->has_permission = pc_group_has_permission;
+ pcg->should_log_commands = pc_group_should_log_commands;
+ pcg->get_name = pc_group_get_name;
+ pcg->get_level = pc_group_get_level;
+ pcg->get_idx = pc_group_get_idx;
}
diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h
index 0ce7b0d51..f52e2ba22 100644
--- a/src/map/pc_groups.h
+++ b/src/map/pc_groups.h
@@ -2,29 +2,17 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _PC_GROUPS_H_
-#define _PC_GROUPS_H_
+#ifndef MAP_PC_GROUPS_H
+#define MAP_PC_GROUPS_H
-#include "atcommand.h" // AtCommandType
-
-extern int pc_group_max;
-
-bool pc_group_exists(int group_id);
-bool pc_group_can_use_command(int group_id, const char *command, AtCommandType type);
-bool pc_group_has_permission(int group_id, int permission);
-bool pc_group_should_log_commands(int group_id);
-const char* pc_group_id2name(int group_id);
-int pc_group_id2level(int group_id);
-int pc_group_id2idx(int group_id);
-void pc_group_pc_load(struct map_session_data *);
-
-void do_init_pc_groups(void);
-void do_final_pc_groups(void);
-void pc_groups_reload(void);
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/db.h"
+/// PC permissions
enum e_pc_permission {
- PC_PERM_NONE = 0,
- PC_PERM_TRADE = 0x000001,
+ PC_PERM_NONE = 0, // #0
+ PC_PERM_TRADE = 0x000001, // #1
PC_PERM_PARTY = 0x000002,
PC_PERM_ALL_SKILL = 0x000004,
PC_PERM_USE_ALL_EQUIPMENT = 0x000008,
@@ -33,7 +21,7 @@ enum e_pc_permission {
PC_PERM_NO_CHAT_KICK = 0x000040,
PC_PERM_HIDE_SESSION = 0x000080,
PC_PERM_WHO_DISPLAY_AID = 0x000100,
- PC_PERM_RECEIVE_HACK_INFO = 0x000200,
+ PC_PERM_RECEIVE_HACK_INFO = 0x000200, // #10
PC_PERM_WARP_ANYWHERE = 0x000400,
PC_PERM_VIEW_HPMETER = 0x000800,
PC_PERM_VIEW_EQUIPMENT = 0x001000,
@@ -41,39 +29,71 @@ enum e_pc_permission {
PC_PERM_USE_CHANGEMAPTYPE = 0x004000,
PC_PERM_USE_ALL_COMMANDS = 0x008000,
PC_PERM_RECEIVE_REQUESTS = 0x010000,
- PC_PERM_SHOW_BOSS = 0x020000,
- PC_PERM_DISABLE_PVM = 0x040000,
- PC_PERM_DISABLE_PVP = 0x080000,
+ PC_PERM_SHOW_BOSS = 0x020000,
+ PC_PERM_DISABLE_PVM = 0x040000,
+ PC_PERM_DISABLE_PVP = 0x080000, // #20
PC_PERM_DISABLE_CMD_DEAD = 0x100000,
- PC_PERM_HCHSYS_ADMIN = 0x200000,
+ PC_PERM_HCHSYS_ADMIN = 0x200000,
+ PC_PERM_TRADE_BOUND = 0x400000,
};
-static const struct {
- const char *name;
+// Cached config settings for quick lookup
+struct GroupSettings {
+ unsigned int id; // groups.[].id
+ int level; // groups.[].level
+ char *name; // copy of groups.[].name
+ unsigned int e_permissions; // packed groups.[].permissions
+ bool log_commands; // groups.[].log_commands
+ int index; // internal index of the group (contiguous range starting at 0) [Ind]
+ /// Following are used/available only during config reading
+ config_setting_t *commands; // groups.[].commands
+ config_setting_t *permissions; // groups.[].permissions
+ config_setting_t *inherit; // groups.[].inherit
+ bool inheritance_done; // have all inheritance rules been evaluated?
+ config_setting_t *root; // groups.[]
+};
+
+typedef struct GroupSettings GroupSettings;
+
+struct pc_groups_permission_table {
+ char *name;
unsigned int permission;
-} pc_g_permission_name[] = {
- { "can_trade", PC_PERM_TRADE },
- { "can_party", PC_PERM_PARTY },
- { "all_skill", PC_PERM_ALL_SKILL },
- { "all_equipment", PC_PERM_USE_ALL_EQUIPMENT },
- { "skill_unconditional", PC_PERM_SKILL_UNCONDITIONAL },
- { "join_chat", PC_PERM_JOIN_ALL_CHAT },
- { "kick_chat", PC_PERM_NO_CHAT_KICK },
- { "hide_session", PC_PERM_HIDE_SESSION },
- { "who_display_aid", PC_PERM_WHO_DISPLAY_AID },
- { "hack_info", PC_PERM_RECEIVE_HACK_INFO },
- { "any_warp", PC_PERM_WARP_ANYWHERE },
- { "view_hpmeter", PC_PERM_VIEW_HPMETER },
- { "view_equipment", PC_PERM_VIEW_EQUIPMENT },
- { "use_check", PC_PERM_USE_CHECK },
- { "use_changemaptype", PC_PERM_USE_CHANGEMAPTYPE },
- { "all_commands", PC_PERM_USE_ALL_COMMANDS },
- { "receive_requests", PC_PERM_RECEIVE_REQUESTS },
- { "show_bossmobs", PC_PERM_SHOW_BOSS },
- { "disable_pvm", PC_PERM_DISABLE_PVM },
- { "disable_pvp", PC_PERM_DISABLE_PVP },
- { "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD },
- { "hchsys_admin", PC_PERM_HCHSYS_ADMIN },
};
-#endif // _PC_GROUPS_H_
+/* used by plugins to list permissions */
+struct pc_groups_new_permission {
+ unsigned int pID;/* plugin identity (for the future unload during runtime support) */
+ char *name;/* aStrdup' of the permission name */
+ unsigned int *mask;/* pointer to the plugin val that will store the value of the mask */
+};
+
+struct pc_groups_interface {
+ /* */
+ DBMap* db; // id -> GroupSettings
+ DBMap* name_db; // name -> GroupSettings
+ /* */
+ struct pc_groups_permission_table *permissions;
+ unsigned char permission_count;
+ /* */
+ struct pc_groups_new_permission *HPMpermissions;
+ unsigned char HPMpermissions_count;
+ /* */
+ void (*init) (void);
+ void (*final) (void);
+ void (*reload) (void);
+ /* */
+ GroupSettings* (*get_dummy_group) (void);
+ bool (*exists) (int group_id);
+ GroupSettings* (*id2group) (int group_id);
+ bool (*has_permission) (GroupSettings *group, unsigned int permission);
+ bool (*should_log_commands) (GroupSettings *group);
+ const char* (*get_name) (GroupSettings *group);
+ int (*get_level) (GroupSettings *group);
+ int (*get_idx) (GroupSettings *group);
+};
+
+struct pc_groups_interface *pcg;
+
+void pc_groups_defaults(void);
+
+#endif /* MAP_PC_GROUPS_H */
diff --git a/src/map/pet.c b/src/map/pet.c
index 00402f9d4..9275a6de5 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -2,46 +2,44 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/db.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/malloc.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
-#include "../common/ers.h"
+#define HERCULES_CORE
-#include "pc.h"
-#include "status.h"
-#include "map.h"
-#include "path.h"
-#include "intif.h"
-#include "clif.h"
-#include "chrif.h"
#include "pet.h"
-#include "itemdb.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "atcommand.h" // msg_txt()
#include "battle.h"
+#include "chrif.h"
+#include "clif.h"
+#include "intif.h"
+#include "itemdb.h"
+#include "log.h"
+#include "map.h"
#include "mob.h"
#include "npc.h"
+#include "path.h"
+#include "pc.h"
#include "script.h"
#include "skill.h"
+#include "status.h"
#include "unit.h"
-#include "atcommand.h" // msg_txt()
-#include "log.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include "../common/db.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
+struct pet_interface pet_s;
#define MIN_PETTHINKTIME 100
-struct s_pet_db pet_db[MAX_PET_DB];
-
-static struct eri *item_drop_ers; //For loot drops delay structures.
-static struct eri *item_drop_list_ers;
-
int pet_hungry_val(struct pet_data *pd)
{
nullpo_ret(pd);
@@ -69,21 +67,21 @@ void pet_set_intimate(struct pet_data *pd, int value)
pd->pet.intimate = value;
if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) )
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
int pet_create_egg(struct map_session_data *sd, int item_id)
{
- int pet_id = search_petDB_index(item_id, PET_EGG);
+ int pet_id = pet->search_petDB_index(item_id, PET_EGG);
if (pet_id < 0) return 0; //No pet egg here.
if (!pc->inventoryblank(sd)) return 0; // Inventory full
- sd->catch_target_class = pet_db[pet_id].class_;
- intif_create_pet(sd->status.account_id, sd->status.char_id,
- (short)pet_db[pet_id].class_,
- (short)mob_db(pet_db[pet_id].class_)->lv,
- (short)pet_db[pet_id].EggID, 0,
- (short)pet_db[pet_id].intimate,
- 100, 0, 1, pet_db[pet_id].jname);
+ sd->catch_target_class = pet->db[pet_id].class_;
+ intif->create_pet(sd->status.account_id, sd->status.char_id,
+ (short)pet->db[pet_id].class_,
+ (short)mob->db(pet->db[pet_id].class_)->lv,
+ (short)pet->db[pet_id].EggID, 0,
+ (short)pet->db[pet_id].intimate,
+ 100, 0, 1, pet->db[pet_id].jname);
return 1;
}
@@ -100,37 +98,35 @@ int pet_unlocktarget(struct pet_data *pd)
/*==========================================
* Pet Attack Skill [Skotlex]
*------------------------------------------*/
-int pet_attackskill(struct pet_data *pd, int target_id)
-{
- if (!battle_config.pet_status_support || !pd->a_skill ||
+int pet_attackskill(struct pet_data *pd, int target_id) {
+ if (!battle_config.pet_status_support || !pd->a_skill ||
(battle_config.pet_equip_required && !pd->pet.equip))
return 0;
- if (DIFF_TICK(pd->ud.canact_tick, iTimer->gettick()) > 0)
+ if (DIFF_TICK(pd->ud.canact_tick, timer->gettick()) > 0)
return 0;
- if (rnd()%100 < (pd->a_skill->rate +pd->pet.intimate*pd->a_skill->bonusrate/1000))
- { //Skotlex: Use pet's skill
+ if (rnd()%100 < (pd->a_skill->rate +pd->pet.intimate*pd->a_skill->bonusrate/1000)) {
+ //Skotlex: Use pet's skill
int inf;
struct block_list *bl;
- bl=iMap->id2bl(target_id);
- if(bl == NULL || pd->bl.m != bl->m || bl->prev == NULL || status_isdead(bl) ||
- !check_distance_bl(&pd->bl, bl, pd->db->range3))
+ bl=map->id2bl(target_id);
+ if( bl == NULL || pd->bl.m != bl->m || bl->prev == NULL
+ || status->isdead(bl) || !check_distance_bl(&pd->bl, bl, pd->db->range3))
return 0;
inf = skill->get_inf(pd->a_skill->id);
if (inf & INF_GROUND_SKILL)
- unit_skilluse_pos(&pd->bl, bl->x, bl->y, pd->a_skill->id, pd->a_skill->lv);
- else //Offensive self skill? Could be stuff like GX.
- unit_skilluse_id(&pd->bl,(inf&INF_SELF_SKILL?pd->bl.id:bl->id), pd->a_skill->id, pd->a_skill->lv);
+ unit->skilluse_pos(&pd->bl, bl->x, bl->y, pd->a_skill->id, pd->a_skill->lv);
+ else //Offensive self skill? Could be stuff like GX.
+ unit->skilluse_id(&pd->bl,(inf&INF_SELF_SKILL?pd->bl.id:bl->id), pd->a_skill->id, pd->a_skill->lv);
return 1; //Skill invoked.
}
return 0;
}
-int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type)
-{
+int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type) {
struct pet_data *pd;
int rate;
@@ -138,17 +134,17 @@ int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type)
Assert((pd->msd == 0) || (pd->msd->pd == pd));
- if(bl == NULL || bl->type != BL_MOB || bl->prev == NULL ||
- pd->pet.intimate < battle_config.pet_support_min_friendly ||
- pd->pet.hungry < 1 ||
- pd->pet.class_ == status_get_class(bl))
+ if( bl == NULL || bl->type != BL_MOB || bl->prev == NULL
+ || pd->pet.intimate < battle_config.pet_support_min_friendly
+ || pd->pet.hungry < 1
+ || pd->pet.class_ == status->get_class(bl))
return 0;
- if(pd->bl.m != bl->m ||
- !check_distance_bl(&pd->bl, bl, pd->db->range2))
+ if( pd->bl.m != bl->m
+ || !check_distance_bl(&pd->bl, bl, pd->db->range2))
return 0;
- if (!status_check_skilluse(&pd->bl, bl, 0, 0))
+ if (!status->check_skilluse(&pd->bl, bl, 0, 0))
return 0;
if(!type) {
@@ -162,7 +158,7 @@ int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type)
if(pd->petDB->defence_attack_rate > 0 && rate <= 0)
rate = 1;
}
- if(rnd()%10000 < rate)
+ if(rnd()%10000 < rate)
{
if(pd->target_id == 0 || rnd()%10000 < pd->petDB->change_target_rate)
pd->target_id = bl->id;
@@ -187,18 +183,17 @@ int pet_sc_check(struct map_session_data *sd, int type)
|| pd->recovery->type != type )
return 1;
- pd->recovery->timer = iTimer->add_timer(iTimer->gettick()+pd->recovery->delay*1000,pet_recovery_timer,sd->bl.id,0);
+ pd->recovery->timer = timer->add(timer->gettick()+pd->recovery->delay*1000,pet->recovery_timer,sd->bl.id,0);
return 0;
}
-static int pet_hungry(int tid, unsigned int tick, int id, intptr_t data)
-{
+int pet_hungry(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
struct pet_data *pd;
int interval;
- sd=iMap->id2sd(id);
+ sd=map->id2sd(id);
if(!sd)
return 1;
@@ -220,13 +215,13 @@ static int pet_hungry(int tid, unsigned int tick, int id, intptr_t data)
{
pet_stop_attack(pd);
pd->pet.hungry = 0;
- pet_set_intimate(pd, pd->pet.intimate - battle_config.pet_hungry_friendly_decrease);
+ pet->set_intimate(pd, pd->pet.intimate - battle_config.pet_hungry_friendly_decrease);
if( pd->pet.intimate <= 0 )
{
pd->pet.intimate = 0;
pd->status.speed = pd->db->status.speed;
}
- status_calc_pet(pd, 0);
+ status_calc_pet(pd, SCO_NONE);
clif->send_petdata(sd,pd,1,pd->pet.intimate);
}
clif->send_petdata(sd,pd,2,pd->pet.hungry);
@@ -237,7 +232,7 @@ static int pet_hungry(int tid, unsigned int tick, int id, intptr_t data)
interval = pd->petDB->hungry_delay;
if(interval <= 0)
interval = 1;
- pd->pet_hungry_timer = iTimer->add_timer(tick+interval,pet_hungry,sd->bl.id,0);
+ pd->pet_hungry_timer = timer->add(tick+interval,pet->hungry,sd->bl.id,0);
return 0;
}
@@ -248,14 +243,14 @@ int search_petDB_index(int key,int type)
for( i = 0; i < MAX_PET_DB; i++ )
{
- if(pet_db[i].class_ <= 0)
+ if(pet->db[i].class_ <= 0)
continue;
switch(type) {
- case PET_CLASS: if(pet_db[i].class_ == key) return i; break;
- case PET_CATCH: if(pet_db[i].itemID == key) return i; break;
- case PET_EGG: if(pet_db[i].EggID == key) return i; break;
- case PET_EQUIP: if(pet_db[i].AcceID == key) return i; break;
- case PET_FOOD: if(pet_db[i].FoodID == key) return i; break;
+ case PET_CLASS: if(pet->db[i].class_ == key) return i; break;
+ case PET_CATCH: if(pet->db[i].itemID == key) return i; break;
+ case PET_EGG: if(pet->db[i].EggID == key) return i; break;
+ case PET_EQUIP: if(pet->db[i].AcceID == key) return i; break;
+ case PET_FOOD: if(pet->db[i].FoodID == key) return i; break;
default:
return -1;
}
@@ -267,14 +262,14 @@ int pet_hungry_timer_delete(struct pet_data *pd)
{
nullpo_ret(pd);
if(pd->pet_hungry_timer != INVALID_TIMER) {
- iTimer->delete_timer(pd->pet_hungry_timer,pet_hungry);
+ timer->delete(pd->pet_hungry_timer,pet->hungry);
pd->pet_hungry_timer = INVALID_TIMER;
}
return 1;
}
-static int pet_performance(struct map_session_data *sd, struct pet_data *pd)
+int pet_performance(struct map_session_data *sd, struct pet_data *pd)
{
int val;
@@ -287,16 +282,16 @@ static int pet_performance(struct map_session_data *sd, struct pet_data *pd)
pet_stop_walking(pd,2000<<8);
clif->send_petdata(NULL, pd, 4, rnd()%val + 1);
- pet_lootitem_drop(pd,NULL);
+ pet->lootitem_drop(pd,NULL);
return 1;
}
-static int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
+int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
{
struct item tmp_item;
int flag;
- pet_lootitem_drop(pd,sd);
+ pet->lootitem_drop(pd,sd);
memset(&tmp_item,0,sizeof(tmp_item));
tmp_item.nameid = pd->petDB->EggID;
tmp_item.identify = 1;
@@ -306,135 +301,139 @@ static int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
tmp_item.card[3] = pd->pet.rename_flag;
if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) {
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
- pd->pet.incuvate = 1;
- unit_free(&pd->bl,CLR_OUTSIGHT);
+ pd->pet.incubate = 1;
+ unit->free(&pd->bl,CLR_OUTSIGHT);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
sd->status.pet_id = 0;
return 1;
}
-int pet_data_init(struct map_session_data *sd, struct s_pet *pet)
+int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo)
{
struct pet_data *pd;
int i=0,interval=0;
nullpo_retr(1, sd);
- Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
- if(sd->status.account_id != pet->account_id || sd->status.char_id != pet->char_id) {
+ if(sd->status.account_id != petinfo->account_id || sd->status.char_id != petinfo->char_id) {
sd->status.pet_id = 0;
return 1;
}
- if (sd->status.pet_id != pet->pet_id) {
+ if (sd->status.pet_id != petinfo->pet_id) {
if (sd->status.pet_id) {
- //Wrong pet?? Set incuvate to no and send it back for saving.
- pet->incuvate = 1;
- intif_save_petdata(sd->status.account_id,pet);
+ //Wrong pet?? Set incubate to no and send it back for saving.
+ petinfo->incubate = 1;
+ intif->save_petdata(sd->status.account_id,petinfo);
sd->status.pet_id = 0;
return 1;
}
//The pet_id value was lost? odd... restore it.
- sd->status.pet_id = pet->pet_id;
+ sd->status.pet_id = petinfo->pet_id;
}
- i = search_petDB_index(pet->class_,PET_CLASS);
+ i = pet->search_petDB_index(petinfo->class_,PET_CLASS);
if(i < 0) {
sd->status.pet_id = 0;
return 1;
}
sd->pd = pd = (struct pet_data *)aCalloc(1,sizeof(struct pet_data));
pd->bl.type = BL_PET;
- pd->bl.id = npc_get_new_npc_id();
+ pd->bl.id = npc->get_new_npc_id();
pd->msd = sd;
- pd->petDB = &pet_db[i];
- pd->db = mob_db(pet->class_);
- memcpy(&pd->pet, pet, sizeof(struct s_pet));
- status_set_viewdata(&pd->bl, pet->class_);
- unit_dataset(&pd->bl);
+ pd->petDB = &pet->db[i];
+ pd->db = mob->db(petinfo->class_);
+ memcpy(&pd->pet, petinfo, sizeof(struct s_pet));
+ status->set_viewdata(&pd->bl, petinfo->class_);
+ unit->dataset(&pd->bl);
pd->ud.dir = sd->ud.dir;
pd->bl.m = sd->bl.m;
pd->bl.x = sd->bl.x;
pd->bl.y = sd->bl.y;
- unit_calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
+ unit->calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
pd->bl.x = pd->ud.to_x;
pd->bl.y = pd->ud.to_y;
- iMap->addiddb(&pd->bl);
- status_calc_pet(pd,1);
+ map->addiddb(&pd->bl);
+ status_calc_pet(pd,SCO_FIRST);
- pd->last_thinktime = iTimer->gettick();
+ pd->last_thinktime = timer->gettick();
pd->state.skillbonus = 0;
+
if( battle_config.pet_status_support )
- run_script(pet_db[i].pet_script,0,sd->bl.id,0);
- if( pd->petDB && pd->petDB->equip_script )
- status_calc_pc(sd,0);
+ script->run(pet->db[i].pet_script,0,sd->bl.id,0);
+
+ if( pd->petDB ) {
+ if( pd->petDB->equip_script )
+ status_calc_pc(sd,SCO_NONE);
- if( battle_config.pet_hungry_delay_rate != 100 )
- interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100;
- else
- interval = pd->petDB->hungry_delay;
+ if( battle_config.pet_hungry_delay_rate != 100 )
+ interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100;
+ else
+ interval = pd->petDB->hungry_delay;
+ }
+
if( interval <= 0 )
interval = 1;
- pd->pet_hungry_timer = iTimer->add_timer(iTimer->gettick() + interval, pet_hungry, sd->bl.id, 0);
+ pd->pet_hungry_timer = timer->add(timer->gettick() + interval, pet->hungry, sd->bl.id, 0);
return 0;
}
-int pet_birth_process(struct map_session_data *sd, struct s_pet *pet)
+int pet_birth_process(struct map_session_data *sd, struct s_pet *petinfo)
{
nullpo_retr(1, sd);
- Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
- if(sd->status.pet_id && pet->incuvate == 1) {
+ if(sd->status.pet_id && petinfo->incubate == 1) {
sd->status.pet_id = 0;
return 1;
}
- pet->incuvate = 0;
- pet->account_id = sd->status.account_id;
- pet->char_id = sd->status.char_id;
- sd->status.pet_id = pet->pet_id;
- if(pet_data_init(sd, pet)) {
+ petinfo->incubate = 0;
+ petinfo->account_id = sd->status.account_id;
+ petinfo->char_id = sd->status.char_id;
+ sd->status.pet_id = petinfo->pet_id;
+ if(pet->data_init(sd, petinfo)) {
sd->status.pet_id = 0;
return 1;
}
- intif_save_petdata(sd->status.account_id,pet);
- if (iMap->save_settings&8)
- chrif_save(sd,0); //is it REALLY Needed to save the char for hatching a pet? [Skotlex]
+ intif->save_petdata(sd->status.account_id,petinfo);
+ if (map->save_settings&8)
+ chrif->save(sd,0); //is it REALLY Needed to save the char for hatching a pet? [Skotlex]
if(sd->bl.prev != NULL) {
- iMap->addblock(&sd->pd->bl);
+ map->addblock(&sd->pd->bl);
clif->spawn(&sd->pd->bl);
clif->send_petdata(sd,sd->pd, 0,0);
clif->send_petdata(sd,sd->pd, 5,battle_config.pet_hair_style);
clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom);
clif->send_petstatus(sd);
}
- Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
+ Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd);
return 0;
}
-int pet_recv_petdata(int account_id,struct s_pet *p,int flag)
-{
+int pet_recv_petdata(int account_id,struct s_pet *p,int flag) {
struct map_session_data *sd;
- sd = iMap->id2sd(account_id);
+ sd = map->id2sd(account_id);
if(sd == NULL)
return 1;
if(flag == 1) {
sd->status.pet_id = 0;
return 1;
}
- if(p->incuvate == 1) {
+ if(p->incubate == 1) {
int i;
//Delete egg from inventory. [Skotlex]
for (i = 0; i < MAX_INVENTORY; i++) {
@@ -447,12 +446,12 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag)
sd->status.pet_id = 0;
return 1;
}
- if (!pet_birth_process(sd,p)) //Pet hatched. Delete egg.
+ if (!pet->birth_process(sd,p)) //Pet hatched. Delete egg.
pc->delitem(sd,i,1,0,0,LOG_TYPE_OTHER);
} else {
- pet_data_init(sd,p);
+ pet->data_init(sd,p);
if(sd->pd && sd->bl.prev != NULL) {
- iMap->addblock(&sd->pd->bl);
+ map->addblock(&sd->pd->bl);
clif->spawn(&sd->pd->bl);
clif->send_petdata(sd,sd->pd,0,0);
clif->send_petdata(sd,sd->pd,5,battle_config.pet_hair_style);
@@ -472,7 +471,7 @@ int pet_select_egg(struct map_session_data *sd,short egg_index)
return 0; //Forged packet!
if(sd->status.inventory[egg_index].card[0] == CARD0_PET)
- intif_request_petdata(sd->status.account_id, sd->status.char_id, MakeDWord(sd->status.inventory[egg_index].card[1], sd->status.inventory[egg_index].card[2]) );
+ intif->request_petdata(sd->status.account_id, sd->status.char_id, MakeDWord(sd->status.inventory[egg_index].card[1], sd->status.inventory[egg_index].card[2]) );
else
ShowError("wrong egg item inventory %d\n",egg_index);
@@ -489,16 +488,15 @@ int pet_catch_process1(struct map_session_data *sd,int target_class)
return 0;
}
-int pet_catch_process2(struct map_session_data* sd, int target_id)
-{
+int pet_catch_process2(struct map_session_data* sd, int target_id) {
struct mob_data* md;
int i = 0, pet_catch_rate = 0;
nullpo_retr(1, sd);
- md = (struct mob_data*)iMap->id2bl(target_id);
- if(!md || md->bl.type != BL_MOB || md->bl.prev == NULL)
- { // Invalid inputs/state, abort capture.
+ md = (struct mob_data*)map->id2bl(target_id);
+ if(!md || md->bl.type != BL_MOB || md->bl.prev == NULL) {
+ // Invalid inputs/state, abort capture.
clif->pet_roulette(sd,0);
sd->catch_target_class = -1;
sd->itemid = sd->itemindex = -1;
@@ -507,7 +505,7 @@ int pet_catch_process2(struct map_session_data* sd, int target_id)
//FIXME: delete taming item here, if this was an item-invoked capture and the item was flagged as delay-consume [ultramage]
- i = search_petDB_index(md->class_,PET_CLASS);
+ i = pet->search_petDB_index(md->class_,PET_CLASS);
//catch_target_class == 0 is used for universal lures (except bosses for now). [Skotlex]
if (sd->catch_target_class == 0 && !(md->status.mode&MD_BOSS))
sd->catch_target_class = md->class_;
@@ -518,7 +516,7 @@ int pet_catch_process2(struct map_session_data* sd, int target_id)
return 1;
}
- pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - md->level)*30 + sd->battle_status.luk*20)*(200 - get_percentage(md->status.hp, md->status.max_hp))/100;
+ pet_catch_rate = (pet->db[i].capture + (sd->status.base_level - md->level)*30 + sd->battle_status.luk*20)*(200 - get_percentage(md->status.hp, md->status.max_hp))/100;
if(pet_catch_rate < 1) pet_catch_rate = 1;
if(battle_config.pet_catch_rate != 100)
@@ -526,11 +524,11 @@ int pet_catch_process2(struct map_session_data* sd, int target_id)
if(rnd()%10000 < pet_catch_rate)
{
- unit_remove_map(&md->bl,CLR_OUTSIGHT);
+ unit->remove_map(&md->bl,CLR_OUTSIGHT,ALC_MARK);
status_kill(&md->bl);
clif->pet_roulette(sd,1);
- intif_create_pet(sd->status.account_id,sd->status.char_id,pet_db[i].class_,mob_db(pet_db[i].class_)->lv,
- pet_db[i].EggID,0,pet_db[i].intimate,100,0,1,pet_db[i].jname);
+ intif->create_pet(sd->status.account_id,sd->status.char_id,pet->db[i].class_,mob->db(pet->db[i].class_)->lv,
+ pet->db[i].EggID,0,pet->db[i].intimate,100,0,1,pet->db[i].jname);
}
else
{
@@ -541,29 +539,42 @@ int pet_catch_process2(struct map_session_data* sd, int target_id)
return 0;
}
-int pet_get_egg(int account_id,int pet_id,int flag)
-{ //This function is invoked when a new pet has been created, and at no other time!
+/**
+ * Is invoked _only_ when a new pet has been created is a product of packet 0x3880
+ * see mapif_pet_created@int_pet.c for more information
+ * Handles new pet data from inter-server and prepares item information
+ * to add pet egg
+ *
+ * pet_id - Should contain pet id otherwise means failure
+ * returns true on success
+ **/
+bool pet_get_egg(int account_id, short pet_class, int pet_id ) {
struct map_session_data *sd;
struct item tmp_item;
- int i=0,ret=0;
+ int i = 0, ret = 0;
- if(flag)
- return 0;
-
- sd = iMap->id2sd(account_id);
- if(sd == NULL)
- return 0;
+ if( pet_id == 0 || pet_class == 0 )
+ return false;
- i = search_petDB_index(sd->catch_target_class,PET_CLASS);
+ sd = map->id2sd(account_id);
+ if( sd == NULL )
+ return false;
+
+ // i = pet->search_petDB_index(sd->catch_target_class,PET_CLASS);
+ // issue: 8150
+ // Before this change in cases where more than one pet egg were requested in a short
+ // period of time it wasn't possible to know which kind of egg was being requested after
+ // the first request. [Panikon]
+ i = pet->search_petDB_index(pet_class,PET_CLASS);
sd->catch_target_class = -1;
if(i < 0) {
- intif_delete_petdata(pet_id);
- return 0;
+ intif->delete_petdata(pet_id);
+ return false;
}
memset(&tmp_item,0,sizeof(tmp_item));
- tmp_item.nameid = pet_db[i].EggID;
+ tmp_item.nameid = pet->db[i].EggID;
tmp_item.identify = 1;
tmp_item.card[0] = CARD0_PET;
tmp_item.card[1] = GetWord(pet_id,0);
@@ -571,16 +582,12 @@ int pet_get_egg(int account_id,int pet_id,int flag)
tmp_item.card[3] = 0; //New pets are not named.
if((ret = pc->additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER))) {
clif->additem(sd,0,0,ret);
- iMap->addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
- return 1;
+ return true;
}
-static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd);
-static int pet_food(struct map_session_data *sd, struct pet_data *pd);
-static int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap);
-
int pet_menu(struct map_session_data *sd,int menunum)
{
struct item_data *egg_id;
@@ -589,12 +596,12 @@ int pet_menu(struct map_session_data *sd,int menunum)
return 1;
//You lost the pet already.
- if(!sd->status.pet_id || sd->pd->pet.intimate <= 0 || sd->pd->pet.incuvate)
+ if(!sd->status.pet_id || sd->pd->pet.intimate <= 0 || sd->pd->pet.incubate)
return 1;
- egg_id = itemdb_exists(sd->pd->petDB->EggID);
+ egg_id = itemdb->exists(sd->pd->petDB->EggID);
if (egg_id) {
- if ((egg_id->flag.trade_restriction&0x01) && !pc->inventoryblank(sd)) {
+ if ((egg_id->flag.trade_restriction&ITR_NODROP) && !pc->inventoryblank(sd)) {
clif->message(sd->fd, msg_txt(451)); // You can't return your pet because your inventory is full.
return 1;
}
@@ -605,16 +612,16 @@ int pet_menu(struct map_session_data *sd,int menunum)
clif->send_petstatus(sd);
break;
case 1:
- pet_food(sd, sd->pd);
+ pet->food(sd, sd->pd);
break;
case 2:
- pet_performance(sd, sd->pd);
+ pet->performance(sd, sd->pd);
break;
case 3:
- pet_return_egg(sd, sd->pd);
+ pet->return_egg(sd, sd->pd);
break;
case 4:
- pet_unequipitem(sd, sd->pd);
+ pet->unequipitem(sd, sd->pd);
break;
}
return 0;
@@ -658,8 +665,7 @@ int pet_change_name_ack(struct map_session_data *sd, char* name, int flag)
return 1;
}
-int pet_equipitem(struct map_session_data *sd,int index)
-{
+int pet_equipitem(struct map_session_data *sd,int index) {
struct pet_data *pd;
int nameid;
@@ -670,33 +676,31 @@ int pet_equipitem(struct map_session_data *sd,int index)
nameid = sd->status.inventory[index].nameid;
if(pd->petDB->AcceID == 0 || nameid != pd->petDB->AcceID || pd->pet.equip != 0) {
- clif->equipitemack(sd,0,0,0);
+ clif->equipitemack(sd,0,0,EIA_FAIL);
return 1;
}
pc->delitem(sd,index,1,0,0,LOG_TYPE_OTHER);
pd->pet.equip = nameid;
- status_set_viewdata(&pd->bl, pd->pet.class_); //Updates view_data.
+ status->set_viewdata(&pd->bl, pd->pet.class_); //Updates view_data.
clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom);
- if (battle_config.pet_equip_required)
- { //Skotlex: start support timers if need
- unsigned int tick = iTimer->gettick();
- if (pd->s_skill && pd->s_skill->timer == INVALID_TIMER)
- {
+ if (battle_config.pet_equip_required) {
+ //Skotlex: start support timers if need
+ int64 tick = timer->gettick();
+ if (pd->s_skill && pd->s_skill->timer == INVALID_TIMER) {
if (pd->s_skill->id)
- pd->s_skill->timer=iTimer->add_timer(tick+pd->s_skill->delay*1000, pet_skill_support_timer, sd->bl.id, 0);
+ pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000, pet->skill_support_timer, sd->bl.id, 0);
else
- pd->s_skill->timer=iTimer->add_timer(tick+pd->s_skill->delay*1000, pet_heal_timer, sd->bl.id, 0);
+ pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000, pet->heal_timer, sd->bl.id, 0);
}
if (pd->bonus && pd->bonus->timer == INVALID_TIMER)
- pd->bonus->timer=iTimer->add_timer(tick+pd->bonus->delay*1000, pet_skill_bonus_timer, sd->bl.id, 0);
+ pd->bonus->timer=timer->add(tick+pd->bonus->delay*1000, pet->skill_bonus_timer, sd->bl.id, 0);
}
return 0;
}
-static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd)
-{
+int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) {
struct item tmp_item;
int nameid,flag;
@@ -705,33 +709,33 @@ static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd)
nameid = pd->pet.equip;
pd->pet.equip = 0;
- status_set_viewdata(&pd->bl, pd->pet.class_);
+ status->set_viewdata(&pd->bl, pd->pet.class_);
clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom);
memset(&tmp_item,0,sizeof(tmp_item));
tmp_item.nameid = nameid;
tmp_item.identify = 1;
if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) {
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
if( battle_config.pet_equip_required )
{ // Skotlex: halt support timers if needed
if( pd->state.skillbonus )
{
pd->state.skillbonus = 0;
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
if( pd->s_skill && pd->s_skill->timer != INVALID_TIMER )
{
if( pd->s_skill->id )
- iTimer->delete_timer(pd->s_skill->timer, pet_skill_support_timer);
+ timer->delete(pd->s_skill->timer, pet->skill_support_timer);
else
- iTimer->delete_timer(pd->s_skill->timer, pet_heal_timer);
+ timer->delete(pd->s_skill->timer, pet->heal_timer);
pd->s_skill->timer = INVALID_TIMER;
}
if( pd->bonus && pd->bonus->timer != INVALID_TIMER )
{
- iTimer->delete_timer(pd->bonus->timer, pet_skill_bonus_timer);
+ timer->delete(pd->bonus->timer, pet->skill_bonus_timer);
pd->bonus->timer = INVALID_TIMER;
}
}
@@ -739,43 +743,40 @@ static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd)
return 0;
}
-static int pet_food(struct map_session_data *sd, struct pet_data *pd)
-{
- int i,k;
+int pet_food(struct map_session_data *sd, struct pet_data *pd) {
+ int i, food_id;
- k=pd->petDB->FoodID;
- i=pc->search_inventory(sd,k);
- if(i < 0) {
- clif->pet_food(sd,k,0);
+ food_id = pd->petDB->FoodID;
+ i = pc->search_inventory(sd, food_id);
+ if(i == INDEX_NOT_FOUND) {
+ clif->pet_food(sd, food_id, 0);
return 1;
}
pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME);
- if( pd->pet.hungry > 90 )
- pet_set_intimate(pd, pd->pet.intimate - pd->petDB->r_full);
- else
- {
- if( battle_config.pet_friendly_rate != 100 )
- k = (pd->petDB->r_hungry * battle_config.pet_friendly_rate)/100;
+ if (pd->pet.hungry > 90) {
+ pet->set_intimate(pd, pd->pet.intimate - pd->petDB->r_full);
+ } else {
+ int add_intimate = 0;
+ if (battle_config.pet_friendly_rate != 100)
+ add_intimate = (pd->petDB->r_hungry * battle_config.pet_friendly_rate)/100;
else
- k = pd->petDB->r_hungry;
- if( pd->pet.hungry > 75 )
- {
- k = k >> 1;
- if( k <= 0 )
- k = 1;
+ add_intimate = pd->petDB->r_hungry;
+ if (pd->pet.hungry > 75) {
+ add_intimate = add_intimate >> 1;
+ if (add_intimate <= 0)
+ add_intimate = 1;
}
- pet_set_intimate(pd, pd->pet.intimate + k);
+ pet->set_intimate(pd, pd->pet.intimate + add_intimate);
}
- if( pd->pet.intimate <= 0 )
- {
+ if (pd->pet.intimate <= 0) {
pd->pet.intimate = 0;
pet_stop_attack(pd);
pd->status.speed = pd->db->status.speed;
- }
- else if( pd->pet.intimate > 1000 )
+ } else if (pd->pet.intimate > 1000) {
pd->pet.intimate = 1000;
- status_calc_pet(pd, 0);
+ }
+ status_calc_pet(pd, SCO_NONE);
pd->pet.hungry += pd->petDB->fullness;
if( pd->pet.hungry > 100 )
pd->pet.hungry = 100;
@@ -787,13 +788,12 @@ static int pet_food(struct map_session_data *sd, struct pet_data *pd)
return 0;
}
-static int pet_randomwalk(struct pet_data *pd,unsigned int tick)
-{
+int pet_randomwalk(struct pet_data *pd, int64 tick) {
nullpo_ret(pd);
Assert((pd->msd == 0) || (pd->msd->pd == pd));
- if(DIFF_TICK(pd->next_walktime,tick) < 0 && unit_can_move(&pd->bl)) {
+ if(DIFF_TICK(pd->next_walktime,tick) < 0 && unit->can_move(&pd->bl)) {
const int retrycount=20;
int i,x,y,c,d=12-pd->move_fail_count;
if(d<5) d=5;
@@ -801,7 +801,7 @@ static int pet_randomwalk(struct pet_data *pd,unsigned int tick)
int r=rnd();
x=pd->bl.x+r%(d*2+1)-d;
y=pd->bl.y+r/(d*2+1)%(d*2+1)-d;
- if(iMap->getcell(pd->bl.m,x,y,CELL_CHKPASS) && unit_walktoxy(&pd->bl,x,y,0)){
+ if(map->getcell(pd->bl.m,x,y,CELL_CHKPASS) && unit->walktoxy(&pd->bl,x,y,0)) {
pd->move_fail_count=0;
break;
}
@@ -817,7 +817,7 @@ static int pet_randomwalk(struct pet_data *pd,unsigned int tick)
}
for(i=c=0;i<pd->ud.walkpath.path_len;i++){
if(pd->ud.walkpath.path[i]&1)
- c+=pd->status.speed*14/10;
+ c+=pd->status.speed*MOVE_DIAGONAL_COST/MOVE_COST;
else
c+=pd->status.speed;
}
@@ -828,8 +828,7 @@ static int pet_randomwalk(struct pet_data *pd,unsigned int tick)
return 0;
}
-static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, unsigned int tick)
-{
+int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick) {
struct block_list *target = NULL;
if(pd->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL)
@@ -847,14 +846,14 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
if(pd->pet.intimate <= 0) {
//Pet should just... well, random walk.
- pet_randomwalk(pd,tick);
+ pet->randomwalk(pd,tick);
return 0;
}
if (!check_distance_bl(&sd->bl, &pd->bl, pd->db->range3)) {
//Master too far, chase.
if(pd->target_id)
- pet_unlocktarget(pd);
+ pet->unlocktarget(pd);
if(pd->ud.walktimer != INVALID_TIMER && pd->ud.target == sd->bl.id)
return 0; //Already walking to him
if (DIFF_TICK(tick, pd->ud.canmove_tick) < 0)
@@ -862,8 +861,8 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
pd->status.speed = (sd->battle_status.speed>>1);
if(pd->status.speed <= 0)
pd->status.speed = 1;
- if (!unit_walktobl(&pd->bl, &sd->bl, 3, 0))
- pet_randomwalk(pd,tick);
+ if (!unit->walktobl(&pd->bl, &sd->bl, 3, 0))
+ pet->randomwalk(pd,tick);
return 0;
}
@@ -876,18 +875,18 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
}
if (pd->target_id) {
- target= iMap->id2bl(pd->target_id);
- if (!target || pd->bl.m != target->m || status_isdead(target) ||
- !check_distance_bl(&pd->bl, target, pd->db->range3))
- {
+ target= map->id2bl(pd->target_id);
+ if (!target || pd->bl.m != target->m || status->isdead(target)
+ || !check_distance_bl(&pd->bl, target, pd->db->range3)
+ ) {
target = NULL;
- pet_unlocktarget(pd);
+ pet->unlocktarget(pd);
}
}
if(!target && pd->loot && pd->msd && pc_has_permission(pd->msd, PC_PERM_TRADE) && pd->loot->count < pd->loot->max && DIFF_TICK(tick,pd->ud.canact_tick)>0) {
//Use half the pet's range of sight.
- iMap->foreachinrange(pet_ai_sub_hard_lootsearch,&pd->bl,
+ map->foreachinrange(pet->ai_sub_hard_lootsearch,&pd->bl,
pd->db->range2/2, BL_ITEM,pd,&target);
}
@@ -899,9 +898,9 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
if(pd->ud.walktimer != INVALID_TIMER && check_distance_blxy(&sd->bl, pd->ud.to_x,pd->ud.to_y, 3))
return 0; //Already walking to him
- unit_calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
- if(!unit_walktoxy(&pd->bl,pd->ud.to_x,pd->ud.to_y,0))
- pet_randomwalk(pd,tick);
+ unit->calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir);
+ if(!unit->walktoxy(&pd->bl,pd->ud.to_x,pd->ud.to_y,0))
+ pet->randomwalk(pd,tick);
return 0;
}
@@ -910,53 +909,51 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns
(pd->ud.attacktimer != INVALID_TIMER || pd->ud.walktimer != INVALID_TIMER))
return 0; //Target already locked.
- if (target->type != BL_ITEM)
+ if (target->type != BL_ITEM)
{ //enemy targetted
if(!battle->check_range(&pd->bl,target,pd->status.rhw.range))
{ //Chase
- if(!unit_walktobl(&pd->bl, target, pd->status.rhw.range, 2))
- pet_unlocktarget(pd); //Unreachable target.
+ if(!unit->walktobl(&pd->bl, target, pd->status.rhw.range, 2))
+ pet->unlocktarget(pd); //Unreachable target.
return 0;
}
//Continuous attack.
- unit_attack(&pd->bl, pd->target_id, 1);
+ unit->attack(&pd->bl, pd->target_id, 1);
} else { //Item Targeted, attempt loot
if (!check_distance_bl(&pd->bl, target, 1))
{ //Out of range
- if(!unit_walktobl(&pd->bl, target, 1, 1)) //Unreachable target.
- pet_unlocktarget(pd);
+ if(!unit->walktobl(&pd->bl, target, 1, 1)) //Unreachable target.
+ pet->unlocktarget(pd);
return 0;
} else{
struct flooritem_data *fitem = (struct flooritem_data *)target;
if(pd->loot->count < pd->loot->max){
memcpy(&pd->loot->item[pd->loot->count++],&fitem->item_data,sizeof(pd->loot->item[0]));
pd->loot->weight += itemdb_weight(fitem->item_data.nameid)*fitem->item_data.amount;
- iMap->clearflooritem(target);
- }
+ map->clearflooritem(target);
+ }
//Target is unlocked regardless of whether it was picked or not.
- pet_unlocktarget(pd);
+ pet->unlocktarget(pd);
}
}
return 0;
}
-static int pet_ai_sub_foreachclient(struct map_session_data *sd,va_list ap)
-{
- unsigned int tick = va_arg(ap,unsigned int);
+int pet_ai_sub_foreachclient(struct map_session_data *sd,va_list ap) {
+ int64 tick = va_arg(ap,int64);
if(sd->status.pet_id && sd->pd)
- pet_ai_sub_hard(sd->pd,sd,tick);
+ pet->ai_sub_hard(sd->pd,sd,tick);
return 0;
}
-static int pet_ai_hard(int tid, unsigned int tick, int id, intptr_t data)
-{
- iMap->map_foreachpc(pet_ai_sub_foreachclient,tick);
+int pet_ai_hard(int tid, int64 tick, int id, intptr_t data) {
+ map->foreachpc(pet->ai_sub_foreachclient,tick);
return 0;
}
-static int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
+int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
{
struct pet_data* pd;
struct flooritem_data *fitem = (struct flooritem_data *)bl;
@@ -971,7 +968,7 @@ static int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
if(sd_charid && sd_charid != pd->msd->status.char_id)
return 0;
- if(unit_can_reach_bl(&pd->bl,bl, pd->db->range2, 1, NULL, NULL) &&
+ if(unit->can_reach_bl(&pd->bl,bl, pd->db->range2, 1, NULL, NULL) &&
((*target) == NULL || //New target closer than previous one.
!check_distance_bl(&pd->bl, *target, distance_bl(&pd->bl, bl))))
{
@@ -983,21 +980,20 @@ static int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
return 0;
}
-static int pet_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data)
-{
+int pet_delay_item_drop(int tid, int64 tick, int id, intptr_t data) {
struct item_drop_list *list;
struct item_drop *ditem, *ditem_prev;
list=(struct item_drop_list *)data;
ditem = list->item;
while (ditem) {
- iMap->addflooritem(&ditem->item_data,ditem->item_data.amount,
+ map->addflooritem(&ditem->item_data,ditem->item_data.amount,
list->m,list->x,list->y,
list->first_charid,list->second_charid,list->third_charid,0);
ditem_prev = ditem;
ditem = ditem->next;
- ers_free(item_drop_ers, ditem_prev);
+ ers_free(pet->item_drop_ers, ditem_prev);
}
- ers_free(item_drop_list_ers, list);
+ ers_free(pet->item_drop_list_ers, list);
return 0;
}
@@ -1009,7 +1005,7 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd)
struct item *it;
if(!pd || !pd->loot || !pd->loot->count)
return 0;
- dlist = ers_alloc(item_drop_list_ers, struct item_drop_list);
+ dlist = ers_alloc(pet->item_drop_list_ers, struct item_drop_list);
dlist->m = pd->bl.m;
dlist->x = pd->bl.x;
dlist->y = pd->bl.y;
@@ -1023,14 +1019,14 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd)
if(sd){
if((flag = pc->additem(sd,it,it->amount,LOG_TYPE_PICKDROP_PLAYER))){
clif->additem(sd,0,0,flag);
- ditem = ers_alloc(item_drop_ers, struct item_drop);
+ ditem = ers_alloc(pet->item_drop_ers, struct item_drop);
memcpy(&ditem->item_data, it, sizeof(struct item));
ditem->next = dlist->item;
dlist->item = ditem;
}
}
else {
- ditem = ers_alloc(item_drop_ers, struct item_drop);
+ ditem = ers_alloc(pet->item_drop_ers, struct item_drop);
memcpy(&ditem->item_data, it, sizeof(struct item));
ditem->next = dlist->item;
dlist->item = ditem;
@@ -1040,30 +1036,29 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd)
memset(pd->loot->item,0,pd->loot->max * sizeof(struct item));
pd->loot->count = 0;
pd->loot->weight = 0;
- pd->ud.canact_tick = iTimer->gettick()+10000; //prevent picked up during 10*1000ms
+ pd->ud.canact_tick = timer->gettick()+10000; //prevent picked up during 10*1000ms
if (dlist->item)
- iTimer->add_timer(iTimer->gettick()+540,pet_delay_item_drop,0,(intptr_t)dlist);
+ timer->add(timer->gettick()+540,pet->delay_item_drop,0,(intptr_t)dlist);
else
- ers_free(item_drop_list_ers, dlist);
+ ers_free(pet->item_drop_list_ers, dlist);
return 1;
}
/*==========================================
* pet bonus giving skills [Valaris] / Rewritten by [Skotlex]
- *------------------------------------------*/
-int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct map_session_data *sd=iMap->id2sd(id);
+ *------------------------------------------*/
+int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct map_session_data *sd=map->id2sd(id);
struct pet_data *pd;
int bonus;
- int timer = 0;
-
+ int duration = 0;
+
if(sd == NULL || sd->pd==NULL || sd->pd->bonus == NULL)
return 1;
pd=sd->pd;
-
+
if(pd->bonus->timer != tid) {
ShowError("pet_skill_bonus_timer %d != %d\n",pd->bonus->timer,tid);
pd->bonus->timer = INVALID_TIMER;
@@ -1073,30 +1068,29 @@ int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data)
// determine the time for the next timer
if (pd->state.skillbonus && pd->bonus->delay > 0) {
bonus = 0;
- timer = pd->bonus->delay*1000; // the duration until pet bonuses will be reactivated again
+ duration = pd->bonus->delay*1000; // the duration until pet bonuses will be reactivated again
} else if (pd->pet.intimate) {
bonus = 1;
- timer = pd->bonus->duration*1000; // the duration for pet bonuses to be in effect
+ duration = pd->bonus->duration*1000; // the duration for pet bonuses to be in effect
} else { //Lost pet...
pd->bonus->timer = INVALID_TIMER;
return 0;
}
-
+
if (pd->state.skillbonus != bonus) {
pd->state.skillbonus = bonus;
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_NONE);
}
// wait for the next timer
- pd->bonus->timer=iTimer->add_timer(tick+timer,pet_skill_bonus_timer,sd->bl.id,0);
+ pd->bonus->timer=timer->add(tick+duration,pet->skill_bonus_timer,sd->bl.id,0);
return 0;
}
/*==========================================
* pet recovery skills [Valaris] / Rewritten by [Skotlex]
- *------------------------------------------*/
-int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct map_session_data *sd=iMap->id2sd(id);
+ *------------------------------------------*/
+int pet_recovery_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct map_session_data *sd=map->id2sd(id);
struct pet_data *pd;
if(sd==NULL || sd->pd == NULL || sd->pd->recovery == NULL)
@@ -1110,7 +1104,7 @@ int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data)
}
if(sd->sc.data[pd->recovery->type])
- { //Display a heal animation?
+ { //Display a heal animation?
//Detoxify is chosen for now.
clif->skill_nodamage(&pd->bl,&sd->bl,TF_DETOXIFY,1,1);
status_change_end(&sd->bl, pd->recovery->type, INVALID_TIMER);
@@ -1122,10 +1116,9 @@ int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data)
return 0;
}
-int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct map_session_data *sd=iMap->id2sd(id);
- struct status_data *status;
+int pet_heal_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct map_session_data *sd=map->id2sd(id);
+ struct status_data *st;
struct pet_data *pd;
unsigned int rate = 100;
@@ -1139,32 +1132,31 @@ int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data)
return 0;
}
- status = status_get_status_data(&sd->bl);
+ st = status->get_status_data(&sd->bl);
if(pc_isdead(sd) ||
- (rate = get_percentage(status->sp, status->max_sp)) > pd->s_skill->sp ||
- (rate = get_percentage(status->hp, status->max_hp)) > pd->s_skill->hp ||
+ (rate = get_percentage(st->sp, st->max_sp)) > pd->s_skill->sp ||
+ (rate = get_percentage(st->hp, st->max_hp)) > pd->s_skill->hp ||
(rate = (pd->ud.skilltimer != INVALID_TIMER)) //Another skill is in effect
) { //Wait (how long? 1 sec for every 10% of remaining)
- pd->s_skill->timer=iTimer->add_timer(iTimer->gettick()+(rate>10?rate:10)*100,pet_heal_timer,sd->bl.id,0);
+ pd->s_skill->timer=timer->add(timer->gettick()+(rate>10?rate:10)*100,pet->heal_timer,sd->bl.id,0);
return 0;
}
pet_stop_attack(pd);
pet_stop_walking(pd,1);
clif->skill_nodamage(&pd->bl,&sd->bl,AL_HEAL,pd->s_skill->lv,1);
- status_heal(&sd->bl, pd->s_skill->lv,0, 0);
- pd->s_skill->timer=iTimer->add_timer(tick+pd->s_skill->delay*1000,pet_heal_timer,sd->bl.id,0);
+ status->heal(&sd->bl, pd->s_skill->lv,0, 0);
+ pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000,pet->heal_timer,sd->bl.id,0);
return 0;
}
/*==========================================
* pet support skills [Skotlex]
- *------------------------------------------*/
-int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct map_session_data *sd=iMap->id2sd(id);
+ *------------------------------------------*/
+int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct map_session_data *sd=map->id2sd(id);
struct pet_data *pd;
- struct status_data *status;
+ struct status_data *st;
short rate = 100;
if(sd==NULL || sd->pd == NULL || sd->pd->s_skill == NULL)
return 1;
@@ -1176,80 +1168,77 @@ int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data)
return 0;
}
- status = status_get_status_data(&sd->bl);
+ st = status->get_status_data(&sd->bl);
if (DIFF_TICK(pd->ud.canact_tick, tick) > 0)
{ //Wait until the pet can act again.
- pd->s_skill->timer=iTimer->add_timer(pd->ud.canact_tick,pet_skill_support_timer,sd->bl.id,0);
+ pd->s_skill->timer=timer->add(pd->ud.canact_tick,pet->skill_support_timer,sd->bl.id,0);
return 0;
}
if(pc_isdead(sd) ||
- (rate = get_percentage(status->sp, status->max_sp)) > pd->s_skill->sp ||
- (rate = get_percentage(status->hp, status->max_hp)) > pd->s_skill->hp ||
+ (rate = get_percentage(st->sp, st->max_sp)) > pd->s_skill->sp ||
+ (rate = get_percentage(st->hp, st->max_hp)) > pd->s_skill->hp ||
(rate = (pd->ud.skilltimer != INVALID_TIMER)) //Another skill is in effect
) { //Wait (how long? 1 sec for every 10% of remaining)
- pd->s_skill->timer=iTimer->add_timer(tick+(rate>10?rate:10)*100,pet_skill_support_timer,sd->bl.id,0);
+ pd->s_skill->timer=timer->add(tick+(rate>10?rate:10)*100,pet->skill_support_timer,sd->bl.id,0);
return 0;
}
pet_stop_attack(pd);
pet_stop_walking(pd,1);
- pd->s_skill->timer=iTimer->add_timer(tick+pd->s_skill->delay*1000,pet_skill_support_timer,sd->bl.id,0);
+ pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000,pet->skill_support_timer,sd->bl.id,0);
if (skill->get_inf(pd->s_skill->id) & INF_GROUND_SKILL)
- unit_skilluse_pos(&pd->bl, sd->bl.x, sd->bl.y, pd->s_skill->id, pd->s_skill->lv);
+ unit->skilluse_pos(&pd->bl, sd->bl.x, sd->bl.y, pd->s_skill->id, pd->s_skill->lv);
else
- unit_skilluse_id(&pd->bl, sd->bl.id, pd->s_skill->id, pd->s_skill->lv);
+ unit->skilluse_id(&pd->bl, sd->bl.id, pd->s_skill->id, pd->s_skill->lv);
return 0;
}
/*==========================================
* Pet read db data
- * pet_db.txt
- * pet_db2.txt
- *------------------------------------------*/
+ * pet->db.txt
+ * pet->db2.txt
+ *------------------------------------------*/
int read_petdb()
{
char* filename[] = {"pet_db.txt","pet_db2.txt"};
FILE *fp;
- int nameid,i,j,k;
+ int nameid,i,j,k;
// Remove any previous scripts in case reloaddb was invoked.
for( j = 0; j < MAX_PET_DB; j++ )
{
- if( pet_db[j].pet_script )
+ if( pet->db[j].pet_script )
{
- script_free_code(pet_db[j].pet_script);
- pet_db[j].pet_script = NULL;
+ script->free_code(pet->db[j].pet_script);
+ pet->db[j].pet_script = NULL;
}
- if( pet_db[j].equip_script )
+ if( pet->db[j].equip_script )
{
- script_free_code(pet_db[j].equip_script);
- pet_db[j].pet_script = NULL;
+ script->free_code(pet->db[j].equip_script);
+ pet->db[j].pet_script = NULL;
}
}
// clear database
- memset(pet_db,0,sizeof(pet_db));
+ memset(pet->db,0,sizeof(pet->db));
j = 0; // entry counter
- for( i = 0; i < ARRAYLENGTH(filename); i++ )
- {
+ for( i = 0; i < ARRAYLENGTH(filename); i++ ) {
char line[1024];
int lines, entries;
- sprintf(line, "%s/%s", iMap->db_path, filename[i]);
+ sprintf(line, "%s/%s", map->db_path, filename[i]);
fp=fopen(line,"r");
- if( fp == NULL )
- {
+ if( fp == NULL ) {
if( i == 0 )
ShowError("can't read %s\n",line);
continue;
}
lines = entries = 0;
- while( fgets(line, sizeof(line), fp) && j < MAX_PET_DB )
- {
+ while( fgets(line, sizeof(line), fp) && j < MAX_PET_DB ) {
char *str[22], *p;
lines++;
@@ -1305,41 +1294,41 @@ int read_petdb()
if( (nameid = atoi(str[0])) <= 0 )
continue;
- if( !mobdb_checkid(nameid) )
+ if( !mob->db_checkid(nameid) )
{
ShowWarning("pet_db reading: Invalid mob-class %d, pet not read.\n", nameid);
continue;
}
- pet_db[j].class_ = nameid;
- safestrncpy(pet_db[j].name,str[1],NAME_LENGTH);
- safestrncpy(pet_db[j].jname,str[2],NAME_LENGTH);
- pet_db[j].itemID=atoi(str[3]);
- pet_db[j].EggID=atoi(str[4]);
- pet_db[j].AcceID=atoi(str[5]);
- pet_db[j].FoodID=atoi(str[6]);
- pet_db[j].fullness=atoi(str[7]);
- pet_db[j].hungry_delay=atoi(str[8])*1000;
- pet_db[j].r_hungry=atoi(str[9]);
- if( pet_db[j].r_hungry <= 0 )
- pet_db[j].r_hungry=1;
- pet_db[j].r_full=atoi(str[10]);
- pet_db[j].intimate=atoi(str[11]);
- pet_db[j].die=atoi(str[12]);
- pet_db[j].capture=atoi(str[13]);
- pet_db[j].speed=atoi(str[14]);
- pet_db[j].s_perfor=(char)atoi(str[15]);
- pet_db[j].talk_convert_class=atoi(str[16]);
- pet_db[j].attack_rate=atoi(str[17]);
- pet_db[j].defence_attack_rate=atoi(str[18]);
- pet_db[j].change_target_rate=atoi(str[19]);
- pet_db[j].pet_script = NULL;
- pet_db[j].equip_script = NULL;
+ pet->db[j].class_ = nameid;
+ safestrncpy(pet->db[j].name,str[1],NAME_LENGTH);
+ safestrncpy(pet->db[j].jname,str[2],NAME_LENGTH);
+ pet->db[j].itemID=atoi(str[3]);
+ pet->db[j].EggID=atoi(str[4]);
+ pet->db[j].AcceID=atoi(str[5]);
+ pet->db[j].FoodID=atoi(str[6]);
+ pet->db[j].fullness=atoi(str[7]);
+ pet->db[j].hungry_delay=atoi(str[8])*1000;
+ pet->db[j].r_hungry=atoi(str[9]);
+ if( pet->db[j].r_hungry <= 0 )
+ pet->db[j].r_hungry=1;
+ pet->db[j].r_full=atoi(str[10]);
+ pet->db[j].intimate=atoi(str[11]);
+ pet->db[j].die=atoi(str[12]);
+ pet->db[j].capture=atoi(str[13]);
+ pet->db[j].speed=atoi(str[14]);
+ pet->db[j].s_perfor=(char)atoi(str[15]);
+ pet->db[j].talk_convert_class=atoi(str[16]);
+ pet->db[j].attack_rate=atoi(str[17]);
+ pet->db[j].defence_attack_rate=atoi(str[18]);
+ pet->db[j].change_target_rate=atoi(str[19]);
+ pet->db[j].pet_script = NULL;
+ pet->db[j].equip_script = NULL;
if( *str[20] )
- pet_db[j].pet_script = parse_script(str[20], filename[i], lines, 0);
+ pet->db[j].pet_script = script->parse(str[20], filename[i], lines, 0, NULL);
if( *str[21] )
- pet_db[j].equip_script = parse_script(str[21], filename[i], lines, 0);
+ pet->db[j].equip_script = script->parse(str[21], filename[i], lines, 0, NULL);
j++;
entries++;
@@ -1356,21 +1345,23 @@ int read_petdb()
/*==========================================
* Initialization process relationship skills
*------------------------------------------*/
-int do_init_pet(void)
-{
- read_petdb();
+int do_init_pet(bool minimal) {
+ if (minimal)
+ return 0;
- item_drop_ers = ers_new(sizeof(struct item_drop),"pet.c::item_drop_ers",ERS_OPT_NONE);
- item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"pet.c::item_drop_list_ers",ERS_OPT_NONE);
+ pet->read_db();
+
+ pet->item_drop_ers = ers_new(sizeof(struct item_drop),"pet.c::item_drop_ers",ERS_OPT_NONE);
+ pet->item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"pet.c::item_drop_list_ers",ERS_OPT_NONE);
- iTimer->add_timer_func_list(pet_hungry,"pet_hungry");
- iTimer->add_timer_func_list(pet_ai_hard,"pet_ai_hard");
- iTimer->add_timer_func_list(pet_skill_bonus_timer,"pet_skill_bonus_timer"); // [Valaris]
- iTimer->add_timer_func_list(pet_delay_item_drop,"pet_delay_item_drop");
- iTimer->add_timer_func_list(pet_skill_support_timer, "pet_skill_support_timer"); // [Skotlex]
- iTimer->add_timer_func_list(pet_recovery_timer,"pet_recovery_timer"); // [Valaris]
- iTimer->add_timer_func_list(pet_heal_timer,"pet_heal_timer"); // [Valaris]
- iTimer->add_timer_interval(iTimer->gettick()+MIN_PETTHINKTIME,pet_ai_hard,0,0,MIN_PETTHINKTIME);
+ timer->add_func_list(pet->hungry,"pet_hungry");
+ timer->add_func_list(pet->ai_hard,"pet_ai_hard");
+ timer->add_func_list(pet->skill_bonus_timer,"pet_skill_bonus_timer"); // [Valaris]
+ timer->add_func_list(pet->delay_item_drop,"pet_delay_item_drop");
+ timer->add_func_list(pet->skill_support_timer, "pet_skill_support_timer"); // [Skotlex]
+ timer->add_func_list(pet->recovery_timer,"pet_recovery_timer"); // [Valaris]
+ timer->add_func_list(pet->heal_timer,"pet_heal_timer"); // [Valaris]
+ timer->add_interval(timer->gettick()+MIN_PETTHINKTIME,pet->ai_hard,0,0,MIN_PETTHINKTIME);
return 0;
}
@@ -1380,18 +1371,68 @@ int do_final_pet(void)
int i;
for( i = 0; i < MAX_PET_DB; i++ )
{
- if( pet_db[i].pet_script )
+ if( pet->db[i].pet_script )
{
- script_free_code(pet_db[i].pet_script);
- pet_db[i].pet_script = NULL;
+ script->free_code(pet->db[i].pet_script);
+ pet->db[i].pet_script = NULL;
}
- if( pet_db[i].equip_script )
+ if( pet->db[i].equip_script )
{
- script_free_code(pet_db[i].equip_script);
- pet_db[i].equip_script = NULL;
+ script->free_code(pet->db[i].equip_script);
+ pet->db[i].equip_script = NULL;
}
}
- ers_destroy(item_drop_ers);
- ers_destroy(item_drop_list_ers);
+ ers_destroy(pet->item_drop_ers);
+ ers_destroy(pet->item_drop_list_ers);
return 0;
}
+void pet_defaults(void) {
+ pet = &pet_s;
+
+ memset(pet->db,0,sizeof(pet->db));
+ pet->item_drop_ers = NULL;
+ pet->item_drop_list_ers = NULL;
+
+ /* */
+ pet->init = do_init_pet;
+ pet->final = do_final_pet;
+
+ /* */
+ pet->hungry_val = pet_hungry_val;
+ pet->set_intimate = pet_set_intimate;
+ pet->create_egg = pet_create_egg;
+ pet->unlocktarget = pet_unlocktarget;
+ pet->attackskill = pet_attackskill;
+ pet->target_check = pet_target_check;
+ pet->sc_check = pet_sc_check;
+ pet->hungry = pet_hungry;
+ pet->search_petDB_index = search_petDB_index;
+ pet->hungry_timer_delete = pet_hungry_timer_delete;
+ pet->performance = pet_performance;
+ pet->return_egg = pet_return_egg;
+ pet->data_init = pet_data_init;
+ pet->birth_process = pet_birth_process;
+ pet->recv_petdata = pet_recv_petdata;
+ pet->select_egg = pet_select_egg;
+ pet->catch_process1 = pet_catch_process1;
+ pet->catch_process2 = pet_catch_process2;
+ pet->get_egg = pet_get_egg;
+ pet->unequipitem = pet_unequipitem;
+ pet->food = pet_food;
+ pet->ai_sub_hard_lootsearch = pet_ai_sub_hard_lootsearch;
+ pet->menu = pet_menu;
+ pet->change_name = pet_change_name;
+ pet->change_name_ack = pet_change_name_ack;
+ pet->equipitem = pet_equipitem;
+ pet->randomwalk = pet_randomwalk;
+ pet->ai_sub_hard = pet_ai_sub_hard;
+ pet->ai_sub_foreachclient = pet_ai_sub_foreachclient;
+ pet->ai_hard = pet_ai_hard;
+ pet->delay_item_drop = pet_delay_item_drop;
+ pet->lootitem_drop = pet_lootitem_drop;
+ pet->skill_bonus_timer = pet_skill_bonus_timer;
+ pet->recovery_timer = pet_recovery_timer;
+ pet->heal_timer = pet_heal_timer;
+ pet->skill_support_timer = pet_skill_support_timer;
+ pet->read_db = read_petdb;
+}
diff --git a/src/map/pet.h b/src/map/pet.h
index b46f55229..5c890ef85 100644
--- a/src/map/pet.h
+++ b/src/map/pet.h
@@ -1,11 +1,18 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _PET_H_
-#define _PET_H_
+#ifndef MAP_PET_H
+#define MAP_PET_H
-#define MAX_PET_DB 300
-#define MAX_PETLOOT_SIZE 30
+#include "map.h" // struct block_list
+#include "status.h" // enum sc_type
+#include "unit.h" // struct unit_data
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h" // NAME_LENGTH, struct s_pet
+
+#define MAX_PET_DB 300
+#define MAX_PETLOOT_SIZE 30
struct s_pet_db {
short class_;
@@ -30,7 +37,6 @@ struct s_pet_db {
struct script_code *equip_script;
struct script_code *pet_script;
};
-extern struct s_pet_db pet_db[MAX_PET_DB];
enum { PET_CLASS,PET_CATCH,PET_EGG,PET_EQUIP,PET_FOOD };
@@ -86,7 +92,7 @@ struct pet_data {
unsigned skillbonus : 1;
} state;
int move_fail_count;
- unsigned int next_walktime,last_thinktime;
+ int64 next_walktime, last_thinktime;
short rate_fix; //Support rate as modified by intimacy (1000 = 100%) [Skotlex]
struct pet_recovery* recovery;
@@ -98,39 +104,58 @@ struct pet_data {
struct map_session_data *msd;
};
+#define pet_stop_walking(pd, type) (unit->stop_walking(&(pd)->bl, (type)))
+#define pet_stop_attack(pd) (unit->stop_attack(&(pd)->bl))
+
+struct pet_interface {
+ struct s_pet_db db[MAX_PET_DB];
+ struct eri *item_drop_ers; //For loot drops delay structures.
+ struct eri *item_drop_list_ers;
+ /* */
+ int (*init) (bool minimal);
+ int (*final) (void);
+ /* */
+ int (*hungry_val) (struct pet_data *pd);
+ void (*set_intimate) (struct pet_data *pd, int value);
+ int (*create_egg) (struct map_session_data *sd, int item_id);
+ int (*unlocktarget) (struct pet_data *pd);
+ int (*attackskill) (struct pet_data *pd, int target_id);
+ int (*target_check) (struct map_session_data *sd, struct block_list *bl, int type);
+ int (*sc_check) (struct map_session_data *sd, int type);
+ int (*hungry) (int tid, int64 tick, int id, intptr_t data);
+ int (*search_petDB_index) (int key, int type);
+ int (*hungry_timer_delete) (struct pet_data *pd);
+ int (*performance) (struct map_session_data *sd, struct pet_data *pd);
+ int (*return_egg) (struct map_session_data *sd, struct pet_data *pd);
+ int (*data_init) (struct map_session_data *sd, struct s_pet *petinfo);
+ int (*birth_process) (struct map_session_data *sd, struct s_pet *petinfo);
+ int (*recv_petdata) (int account_id, struct s_pet *p, int flag);
+ int (*select_egg) (struct map_session_data *sd, short egg_index);
+ int (*catch_process1) (struct map_session_data *sd, int target_class);
+ int (*catch_process2) (struct map_session_data *sd, int target_id);
+ bool (*get_egg) (int account_id, short pet_class, int pet_id );
+ int (*unequipitem) (struct map_session_data *sd, struct pet_data *pd);
+ int (*food) (struct map_session_data *sd, struct pet_data *pd);
+ int (*ai_sub_hard_lootsearch) (struct block_list *bl, va_list ap);
+ int (*menu) (struct map_session_data *sd, int menunum);
+ int (*change_name) (struct map_session_data *sd, char *name);
+ int (*change_name_ack) (struct map_session_data *sd, char *name, int flag);
+ int (*equipitem) (struct map_session_data *sd, int index);
+ int (*randomwalk) (struct pet_data *pd, int64 tick);
+ int (*ai_sub_hard) (struct pet_data *pd, struct map_session_data *sd, int64 tick);
+ int (*ai_sub_foreachclient) (struct map_session_data *sd, va_list ap);
+ int (*ai_hard) (int tid, int64 tick, int id, intptr_t data);
+ int (*delay_item_drop) (int tid, int64 tick, int id, intptr_t data);
+ int (*lootitem_drop) (struct pet_data *pd, struct map_session_data *sd);
+ int (*skill_bonus_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*recovery_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*heal_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*skill_support_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*read_db) ();
+};
+
+struct pet_interface *pet;
+void pet_defaults(void);
-int pet_create_egg(struct map_session_data *sd, int item_id);
-int pet_hungry_val(struct pet_data *pd);
-void pet_set_intimate(struct pet_data *pd, int value);
-int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type);
-int pet_unlocktarget(struct pet_data *pd);
-int pet_sc_check(struct map_session_data *sd, int type); //Skotlex
-int search_petDB_index(int key,int type);
-int pet_hungry_timer_delete(struct pet_data *pd);
-int pet_data_init(struct map_session_data *sd, struct s_pet *pet);
-int pet_birth_process(struct map_session_data *sd, struct s_pet *pet);
-int pet_recv_petdata(int account_id,struct s_pet *p,int flag);
-int pet_select_egg(struct map_session_data *sd,short egg_index);
-int pet_catch_process1(struct map_session_data *sd,int target_class);
-int pet_catch_process2(struct map_session_data *sd,int target_id);
-int pet_get_egg(int account_id,int pet_id,int flag);
-int pet_menu(struct map_session_data *sd,int menunum);
-int pet_change_name(struct map_session_data *sd,char *name);
-int pet_change_name_ack(struct map_session_data *sd, char* name, int flag);
-int pet_equipitem(struct map_session_data *sd,int index);
-int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd);
-int pet_attackskill(struct pet_data *pd, int target_id);
-int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data); // [Skotlex]
-int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data); // [Valaris]
-int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data); // [Valaris]
-int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data); // [Valaris]
-
-#define pet_stop_walking(pd, type) unit_stop_walking(&(pd)->bl, type)
-#define pet_stop_attack(pd) unit_stop_attack(&(pd)->bl)
-
-int read_petdb(void);
-int do_init_pet(void);
-int do_final_pet(void);
-
-#endif /* _PET_H_ */
+#endif /* MAP_PET_H */
diff --git a/src/map/quest.c b/src/map/quest.c
index b56088886..b76d6bc82 100644
--- a/src/map/quest.c
+++ b/src/map/quest.c
@@ -1,246 +1,305 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/malloc.h"
-#include "../common/nullpo.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
+#define HERCULES_CORE
-#include "map.h"
-#include "pc.h"
-#include "npc.h"
-#include "itemdb.h"
-#include "script.h"
-#include "intif.h"
-#include "battle.h"
-#include "mob.h"
-#include "party.h"
-#include "unit.h"
-#include "log.h"
-#include "clif.h"
#include "quest.h"
-#include "intif.h"
-#include "chrif.h"
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdarg.h>
#include <time.h>
+#include "battle.h"
+#include "chrif.h"
+#include "clif.h"
+#include "intif.h"
+#include "itemdb.h"
+#include "log.h"
+#include "map.h"
+#include "mob.h"
+#include "npc.h"
+#include "party.h"
+#include "pc.h"
+#include "script.h"
+#include "unit.h"
+#include "../common/cbasetypes.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-struct s_quest_db quest_db[MAX_QUEST_DB];
-
+struct quest_interface quest_s;
+
+/**
+ * Searches a quest by ID.
+ *
+ * @param quest_id ID to lookup
+ * @return Quest entry (equals to &quest->dummy if the ID is invalid)
+ */
+struct quest_db *quest_db(int quest_id) {
+ if (quest_id < 0 || quest_id > MAX_QUEST_DB || quest->db_data[quest_id] == NULL)
+ return &quest->dummy;
+ return quest->db_data[quest_id];
+}
-int quest_search_db(int quest_id)
-{
+/**
+ * Sends quest info to the player on login.
+ *
+ * @param sd Player's data
+ * @return 0 in case of success, nonzero otherwise (i.e. the player has no quests)
+ */
+int quest_pc_login(TBL_PC *sd) {
int i;
- ARR_FIND(0, MAX_QUEST_DB,i,quest_id == quest_db[i].id);
- if( i == MAX_QUEST_DB )
- return -1;
-
- return i;
-}
-
-//Send quest info on login
-int quest_pc_login(TBL_PC * sd)
-{
if(sd->avail_quests == 0)
return 1;
clif->quest_send_list(sd);
clif->quest_send_mission(sd);
+ for( i = 0; i < sd->avail_quests; i++ ) {
+ // TODO[Haru]: is this necessary? Does quest_send_mission not take care of this?
+ clif->quest_update_objective(sd, &sd->quest_log[i]);
+ }
return 0;
}
-int quest_add(TBL_PC * sd, int quest_id)
-{
-
- int i, j;
-
- if( sd->num_quests >= MAX_QUEST_DB )
- {
- ShowError("quest_add: Character %d has got all the quests.(max quests: %d)\n", sd->status.char_id, MAX_QUEST_DB);
- return 1;
+/**
+ * Adds a quest to the player's list.
+ *
+ * New quest will be added as Q_ACTIVE.
+ *
+ * @param sd Player's data
+ * @param quest_id ID of the quest to add.
+ * @return 0 in case of success, nonzero otherwise
+ */
+int quest_add(TBL_PC *sd, int quest_id) {
+ int n;
+ struct quest_db *qi = quest->db(quest_id);
+
+ if( qi == &quest->dummy ) {
+ ShowError("quest_add: quest %d not found in DB.\n", quest_id);
+ return -1;
}
- if( quest_check(sd, quest_id, HAVEQUEST) >= 0 )
- {
+ if( quest->check(sd, quest_id, HAVEQUEST) >= 0 ) {
ShowError("quest_add: Character %d already has quest %d.\n", sd->status.char_id, quest_id);
return -1;
}
- if( (j = quest_search_db(quest_id)) < 0 )
- {
- ShowError("quest_add: quest %d not found in DB.\n", quest_id);
- return -1;
+ n = sd->avail_quests; // Insertion point
+
+ sd->num_quests++;
+ sd->avail_quests++;
+ RECREATE(sd->quest_log, struct quest, sd->num_quests);
+
+ if( sd->avail_quests != sd->num_quests ) {
+ // The character has some completed quests, make room before them so that they will stay at the end of the array
+ memmove(&sd->quest_log[n+1], &sd->quest_log[n], sizeof(struct quest)*(sd->num_quests-sd->avail_quests));
}
- i = sd->avail_quests;
- memmove(&sd->quest_log[i+1], &sd->quest_log[i], sizeof(struct quest)*(sd->num_quests-sd->avail_quests));
- memmove(sd->quest_index+i+1, sd->quest_index+i, sizeof(int)*(sd->num_quests-sd->avail_quests));
+ memset(&sd->quest_log[n], 0, sizeof(struct quest));
- memset(&sd->quest_log[i], 0, sizeof(struct quest));
- sd->quest_log[i].quest_id = quest_db[j].id;
- if( quest_db[j].time )
- sd->quest_log[i].time = (unsigned int)(time(NULL) + quest_db[j].time);
- sd->quest_log[i].state = Q_ACTIVE;
+ sd->quest_log[n].quest_id = qi->id;
+ if( qi->time )
+ sd->quest_log[n].time = (unsigned int)(time(NULL) + qi->time);
+ sd->quest_log[n].state = Q_ACTIVE;
- sd->quest_index[i] = j;
- sd->num_quests++;
- sd->avail_quests++;
sd->save_quest = true;
- clif->quest_add(sd, &sd->quest_log[i], sd->quest_index[i]);
+ clif->quest_add(sd, &sd->quest_log[n]);
+ clif->quest_update_objective(sd, &sd->quest_log[n]);
- if( iMap->save_settings&64 )
- chrif_save(sd,0);
+ if( map->save_settings&64 )
+ chrif->save(sd,0);
return 0;
}
-int quest_change(TBL_PC * sd, int qid1, int qid2)
-{
-
- int i, j;
+/**
+ * Replaces a quest in a player's list with another one.
+ *
+ * @param sd Player's data
+ * @param qid1 Current quest to replace
+ * @param qid2 New quest to add
+ * @return 0 in case of success, nonzero otherwise
+ */
+int quest_change(TBL_PC *sd, int qid1, int qid2) {
+ int i;
+ struct quest_db *qi = quest->db(qid2);
- if( quest_check(sd, qid2, HAVEQUEST) >= 0 )
- {
- ShowError("quest_change: Character %d already has quest %d.\n", sd->status.char_id, qid2);
+ if( qi == &quest->dummy ) {
+ ShowError("quest_change: quest %d not found in DB.\n", qid2);
return -1;
}
- if( quest_check(sd, qid1, HAVEQUEST) < 0 )
- {
- ShowError("quest_change: Character %d doesn't have quest %d.\n", sd->status.char_id, qid1);
+ if( quest->check(sd, qid2, HAVEQUEST) >= 0 ) {
+ ShowError("quest_change: Character %d already has quest %d.\n", sd->status.char_id, qid2);
return -1;
}
- if( (j = quest_search_db(qid2)) < 0 )
- {
- ShowError("quest_change: quest %d not found in DB.\n",qid2);
+ if( quest->check(sd, qid1, HAVEQUEST) < 0 ) {
+ ShowError("quest_change: Character %d doesn't have quest %d.\n", sd->status.char_id, qid1);
return -1;
}
ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == qid1);
- if(i == sd->avail_quests)
- {
- ShowError("quest_change: Character %d has completed quests %d.\n", sd->status.char_id, qid1);
+ if( i == sd->avail_quests ) {
+ ShowError("quest_change: Character %d has completed quest %d.\n", sd->status.char_id, qid1);
return -1;
}
memset(&sd->quest_log[i], 0, sizeof(struct quest));
- sd->quest_log[i].quest_id = quest_db[j].id;
- if( quest_db[j].time )
- sd->quest_log[i].time = (unsigned int)(time(NULL) + quest_db[j].time);
+ sd->quest_log[i].quest_id = qi->id;
+ if( qi->time )
+ sd->quest_log[i].time = (unsigned int)(time(NULL) + qi->time);
sd->quest_log[i].state = Q_ACTIVE;
- sd->quest_index[i] = j;
sd->save_quest = true;
clif->quest_delete(sd, qid1);
- clif->quest_add(sd, &sd->quest_log[i], sd->quest_index[i]);
+ clif->quest_add(sd, &sd->quest_log[i]);
+ clif->quest_update_objective(sd, &sd->quest_log[i]);
- if( iMap->save_settings&64 )
- chrif_save(sd,0);
+ if( map->save_settings&64 )
+ chrif->save(sd,0);
return 0;
}
-int quest_delete(TBL_PC * sd, int quest_id)
-{
+/**
+ * Removes a quest from a player's list
+ *
+ * @param sd Player's data
+ * @param quest_id ID of the quest to remove
+ * @return 0 in case of success, nonzero otherwise
+ */
+int quest_delete(TBL_PC *sd, int quest_id) {
int i;
//Search for quest
ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id);
- if(i == sd->num_quests)
- {
+
+ if(i == sd->num_quests) {
ShowError("quest_delete: Character %d doesn't have quest %d.\n", sd->status.char_id, quest_id);
return -1;
}
if( sd->quest_log[i].state != Q_COMPLETE )
sd->avail_quests--;
- if( sd->num_quests-- < MAX_QUEST_DB && sd->quest_log[i+1].quest_id )
- {
+
+ if( i < --sd->num_quests ) {
+ // Compact the array
memmove(&sd->quest_log[i], &sd->quest_log[i+1], sizeof(struct quest)*(sd->num_quests-i));
- memmove(sd->quest_index+i, sd->quest_index+i+1, sizeof(int)*(sd->num_quests-i));
}
- memset(&sd->quest_log[sd->num_quests], 0, sizeof(struct quest));
- sd->quest_index[sd->num_quests] = 0;
+ if( sd->num_quests == 0 ) {
+ aFree(sd->quest_log);
+ sd->quest_log = NULL;
+ } else {
+ RECREATE(sd->quest_log, struct quest, sd->num_quests);
+ }
sd->save_quest = true;
clif->quest_delete(sd, quest_id);
- if( iMap->save_settings&64 )
- chrif_save(sd,0);
+ if( map->save_settings&64 )
+ chrif->save(sd,0);
return 0;
}
-int quest_update_objective_sub(struct block_list *bl, va_list ap)
-{
- struct map_session_data * sd;
- int mob, party;
+/**
+ * Map iterator subroutine to update quest objectives for a party after killing a monster.
+ *
+ * @see map_foreachinrange
+ * @param ap Argument list, expecting:
+ * int Party ID
+ * int Mob ID
+ */
+int quest_update_objective_sub(struct block_list *bl, va_list ap) {
+ struct map_session_data *sd;
+ int mob_id, party_id;
nullpo_ret(bl);
nullpo_ret(sd = (struct map_session_data *)bl);
- party = va_arg(ap,int);
- mob = va_arg(ap,int);
+ party_id = va_arg(ap,int);
+ mob_id = va_arg(ap,int);
if( !sd->avail_quests )
return 0;
- if( sd->status.party_id != party )
+ if( sd->status.party_id != party_id )
return 0;
- quest_update_objective(sd, mob);
+ quest->update_objective(sd, mob_id);
return 1;
}
-void quest_update_objective(TBL_PC * sd, int mob) {
+/**
+ * Updates the quest objectives for a character after killing a monster.
+ *
+ * @param sd Character's data
+ * @param mob_id Monster ID
+ */
+void quest_update_objective(TBL_PC *sd, int mob_id) {
int i,j;
for( i = 0; i < sd->avail_quests; i++ ) {
- if( sd->quest_log[i].state != Q_ACTIVE )
+ struct quest_db *qi = NULL;
+
+ if( sd->quest_log[i].state != Q_ACTIVE ) // Skip inactive quests
continue;
- for( j = 0; j < MAX_QUEST_OBJECTIVES; j++ )
- if( quest_db[sd->quest_index[i]].mob[j] == mob && sd->quest_log[i].count[j] < quest_db[sd->quest_index[i]].count[j] ) {
+ qi = quest->db(sd->quest_log[i].quest_id);
+
+ for( j = 0; j < qi->num_objectives; j++ ) {
+ if( qi->mob[j] == mob_id && sd->quest_log[i].count[j] < qi->count[j] ) {
sd->quest_log[i].count[j]++;
sd->save_quest = true;
- clif->quest_update_objective(sd,&sd->quest_log[i],sd->quest_index[i]);
+ clif->quest_update_objective(sd, &sd->quest_log[i]);
}
+ }
}
}
-int quest_update_status(TBL_PC * sd, int quest_id, quest_state status) {
+/**
+ * Updates a quest's state.
+ *
+ * Only status of active and inactive quests can be updated. Completed quests can't (for now). [Inkfish]
+ *
+ * @param sd Character's data
+ * @param quest_id Quest ID to update
+ * @param qs New quest state
+ * @return 0 in case of success, nonzero otherwise
+ */
+int quest_update_status(TBL_PC *sd, int quest_id, enum quest_state qs) {
int i;
- //Only status of active and inactive quests can be updated. Completed quests can't (for now). [Inkfish]
ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == quest_id);
- if(i == sd->avail_quests) {
+ if( i == sd->avail_quests ) {
ShowError("quest_update_status: Character %d doesn't have quest %d.\n", sd->status.char_id, quest_id);
return -1;
}
- sd->quest_log[i].state = status;
+ sd->quest_log[i].state = qs;
sd->save_quest = true;
- if( status < Q_COMPLETE ) {
- clif->quest_update_status(sd, quest_id, (bool)status);
+ if( qs < Q_COMPLETE ) {
+ clif->quest_update_status(sd, quest_id, qs == Q_ACTIVE ? true : false);
return 0;
}
- if( i != (--sd->avail_quests) ) {
+ // The quest is complete, so it needs to be moved to the completed quests block at the end of the array.
+
+ if( i < (--sd->avail_quests) ) {
struct quest tmp_quest;
memcpy(&tmp_quest, &sd->quest_log[i],sizeof(struct quest));
memcpy(&sd->quest_log[i], &sd->quest_log[sd->avail_quests],sizeof(struct quest));
@@ -249,13 +308,28 @@ int quest_update_status(TBL_PC * sd, int quest_id, quest_state status) {
clif->quest_delete(sd, quest_id);
- if( iMap->save_settings&64 )
- chrif_save(sd,0);
+ if( map->save_settings&64 )
+ chrif->save(sd,0);
return 0;
}
-int quest_check(TBL_PC * sd, int quest_id, quest_check_type type) {
+/**
+ * Queries quest information for a character.
+ *
+ * @param sd Character's data
+ * @param quest_id Quest ID
+ * @param type Check type
+ * @return -1 if the quest was not found, otherwise it depends on the type:
+ * HAVEQUEST: The quest's state
+ * PLAYTIME: 2 if the quest's timeout has expired
+ * 1 if the quest was completed
+ * 0 otherwise
+ * HUNTING: 2 if the quest has not been marked as completed yet, and its objectives have been fulfilled
+ * 1 if the quest's timeout has expired
+ * 0 otherwise
+ */
+int quest_check(TBL_PC *sd, int quest_id, enum quest_check_type type) {
int i;
ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id);
@@ -267,18 +341,17 @@ int quest_check(TBL_PC * sd, int quest_id, quest_check_type type) {
return sd->quest_log[i].state;
case PLAYTIME:
return (sd->quest_log[i].time < (unsigned int)time(NULL) ? 2 : sd->quest_log[i].state == Q_COMPLETE ? 1 : 0);
- case HUNTING: {
- if( sd->quest_log[i].state == 0 || sd->quest_log[i].state == 1 ) {
- int j;
- ARR_FIND(0, MAX_QUEST_OBJECTIVES, j, sd->quest_log[i].count[j] < quest_db[sd->quest_index[i]].count[j]);
- if( j == MAX_QUEST_OBJECTIVES )
- return 2;
- if( sd->quest_log[i].time < (unsigned int)time(NULL) )
- return 1;
- return 0;
- } else
- return 0;
+ case HUNTING:
+ if( sd->quest_log[i].state == Q_INACTIVE || sd->quest_log[i].state == Q_ACTIVE ) {
+ int j;
+ struct quest_db *qi = quest->db(sd->quest_log[i].quest_id);
+ ARR_FIND(0, MAX_QUEST_OBJECTIVES, j, sd->quest_log[i].count[j] < qi->count[j]);
+ if( j == MAX_QUEST_OBJECTIVES )
+ return 2;
+ if( sd->quest_log[i].time < (unsigned int)time(NULL) )
+ return 1;
}
+ return 0;
default:
ShowError("quest_check_quest: Unknown parameter %d",type);
break;
@@ -287,72 +360,181 @@ int quest_check(TBL_PC * sd, int quest_id, quest_check_type type) {
return -1;
}
+/**
+ * Loads quests from the quest db.
+ *
+ * @return Number of loaded quests, or -1 if the file couldn't be read.
+ */
int quest_read_db(void) {
+ // TODO[Haru] This duplicates some sv_readdb functionalities, and it would be
+ // nice if it could be replaced by it. The reason why it wasn't is probably
+ // because we need to accept commas (which is also used as delimiter) in the
+ // last field (quest name), and sv_readdb isn't capable of doing so.
FILE *fp;
char line[1024];
- int i,j,k = 0;
- char *str[20],*p,*np;
+ int i, count = 0;
+ char *str[20], *p, *np;
+ struct quest_db entry;
- sprintf(line, "%s/quest_db.txt", iMap->db_path);
- if( (fp=fopen(line,"r"))==NULL ){
+ sprintf(line, "%s/quest_db.txt", map->db_path);
+ if ((fp=fopen(line,"r"))==NULL) {
ShowError("can't read %s\n", line);
return -1;
}
-
- while(fgets(line, sizeof(line), fp)) {
-
- if (k == MAX_QUEST_DB) {
- ShowError("quest_read_db: Too many entries specified in %s/quest_db.txt!\n", iMap->db_path);
- break;
- }
-
- if(line[0]=='/' && line[1]=='/')
+
+ while (fgets(line, sizeof(line), fp)) {
+ if (line[0]=='/' && line[1]=='/')
continue;
memset(str,0,sizeof(str));
- for( j = 0, p = line; j < 8; j++ ) {
- if( ( np = strchr(p,',') ) != NULL ) {
- str[j] = p;
+ for (i = 0, p = line; i < 8; i++) {
+ if (( np = strchr(p,',') ) != NULL) {
+ str[i] = p;
*np = 0;
p = np + 1;
- }
- else if (str[0] == NULL)
- continue;
- else {
+ } else if (str[0] == NULL) {
+ break;
+ } else {
ShowError("quest_read_db: insufficient columns in line %s\n", line);
continue;
}
}
- if(str[0]==NULL)
+ if (str[0] == NULL)
+ continue;
+
+ memset(&entry, 0, sizeof(entry));
+
+ entry.id = atoi(str[0]);
+
+ if (entry.id < 0 || entry.id >= MAX_QUEST_DB) {
+ ShowError("quest_read_db: Invalid quest ID '%d' in line '%s' (min: 0, max: %d.)\n", entry.id, line, MAX_QUEST_DB);
continue;
+ }
- memset(&quest_db[k], 0, sizeof(quest_db[0]));
+ entry.time = atoi(str[1]);
- quest_db[k].id = atoi(str[0]);
- quest_db[k].time = atoi(str[1]);
-
- for( i = 0; i < MAX_QUEST_OBJECTIVES; i++ ) {
- quest_db[k].mob[i] = atoi(str[2*i+2]);
- quest_db[k].count[i] = atoi(str[2*i+3]);
+ for (i = 0; i < MAX_QUEST_OBJECTIVES; i++) {
+ entry.mob[i] = atoi(str[2*i+2]);
+ entry.count[i] = atoi(str[2*i+3]);
- if( !quest_db[k].mob[i] || !quest_db[k].count[i] )
+ if (!entry.mob[i] || !entry.count[i])
break;
}
-
- quest_db[k].num_objectives = i;
- k++;
+ entry.num_objectives = i;
+
+ if (quest->db_data[entry.id] == NULL)
+ quest->db_data[entry.id] = aMalloc(sizeof(struct quest_db));
+
+ memcpy(quest->db_data[entry.id], &entry, sizeof(struct quest_db));
+ count++;
}
fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", k, "quest_db.txt");
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, "quest_db.txt");
return 0;
}
-void do_init_quest(void) {
- quest_read_db();
+/**
+ * Map iterator to ensures a player has no invalid quest log entries.
+ *
+ * Any entries that are no longer in the db are removed.
+ *
+ * @see map->foreachpc
+ * @param ap Ignored
+ */
+int quest_reload_check_sub(struct map_session_data *sd, va_list ap) {
+ int i, j;
+
+ nullpo_ret(sd);
+
+ j = 0;
+ for (i = 0; i < sd->num_quests; i++) {
+ struct quest_db *qi = quest->db(sd->quest_log[i].quest_id);
+ if (qi == &quest->dummy) { // Remove no longer existing entries
+ if (sd->quest_log[i].state != Q_COMPLETE) // And inform the client if necessary
+ clif->quest_delete(sd, sd->quest_log[i].quest_id);
+ continue;
+ }
+ if (i != j) {
+ // Move entries if there's a gap to fill
+ memcpy(&sd->quest_log[j], &sd->quest_log[i], sizeof(struct quest));
+ }
+ j++;
+ }
+ sd->num_quests = j;
+ ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].state == Q_COMPLETE);
+ sd->avail_quests = i;
+
+ return 1;
+}
+
+/**
+ * Clears the quest database for shutdown or reload.
+ */
+void quest_clear_db(void) {
+ int i;
+
+ for (i = 0; i < MAX_QUEST_DB; i++) {
+ if (quest->db_data[i]) {
+ aFree(quest->db_data[i]);
+ quest->db_data[i] = NULL;
+ }
+ }
}
+/**
+ * Initializes the quest interface.
+ *
+ * @param minimal Run in minimal mode (skips most of the loading)
+ */
+void do_init_quest(bool minimal) {
+ if (minimal)
+ return;
+
+ quest->read_db();
+}
+
+/**
+ * Finalizes the quest interface before shutdown.
+ */
+void do_final_quest(void) {
+ quest->clear();
+}
+
+/**
+ * Reloads the quest database.
+ */
void do_reload_quest(void) {
- memset(&quest_db, 0, sizeof(quest_db));
- quest_read_db();
+ quest->clear();
+
+ quest->read_db();
+
+ // Update quest data for players, to ensure no entries about removed quests are left over.
+ map->foreachpc(&quest_reload_check_sub);
+}
+
+/**
+ * Initializes default values for the quest interface.
+ */
+void quest_defaults(void) {
+ quest = &quest_s;
+
+ memset(&quest->db, 0, sizeof(quest->db));
+ memset(&quest->dummy, 0, sizeof(quest->dummy));
+ /* */
+ quest->init = do_init_quest;
+ quest->final = do_final_quest;
+ quest->reload = do_reload_quest;
+ /* */
+ quest->db = quest_db;
+ quest->pc_login = quest_pc_login;
+ quest->add = quest_add;
+ quest->change = quest_change;
+ quest->delete = quest_delete;
+ quest->update_objective_sub = quest_update_objective_sub;
+ quest->update_objective = quest_update_objective;
+ quest->update_status = quest_update_status;
+ quest->check = quest_check;
+ quest->clear = quest_clear_db;
+ quest->read_db = quest_read_db;
}
diff --git a/src/map/quest.h b/src/map/quest.h
index 7f638a54c..9d617e369 100644
--- a/src/map/quest.h
+++ b/src/map/quest.h
@@ -1,10 +1,17 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _QUEST_H_
-#define _QUEST_H_
+#ifndef MAP_QUEST_H
+#define MAP_QUEST_H
-struct s_quest_db {
+#include "map.h" // TBL_PC
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h" // MAX_QUEST_OBJECTIVES
+
+#define MAX_QUEST_DB (60355+1) // Highest quest ID + 1
+
+struct quest_db {
int id;
unsigned int time;
int mob[MAX_QUEST_OBJECTIVES];
@@ -12,23 +19,37 @@ struct s_quest_db {
int num_objectives;
//char name[NAME_LENGTH];
};
-extern struct s_quest_db quest_db[MAX_QUEST_DB];
-
-typedef enum quest_check_type { HAVEQUEST, PLAYTIME, HUNTING } quest_check_type;
-int quest_pc_login(TBL_PC * sd);
+// Questlog check types
+enum quest_check_type {
+ HAVEQUEST, ///< Query the state of the given quest
+ PLAYTIME, ///< Check if the given quest has been completed or has yet to expire
+ HUNTING, ///< Check if the given hunting quest's requirements have been met
+};
-int quest_add(TBL_PC * sd, int quest_id);
-int quest_delete(TBL_PC * sd, int quest_id);
-int quest_change(TBL_PC * sd, int qid1, int qid2);
-int quest_update_objective_sub(struct block_list *bl, va_list ap);
-void quest_update_objective(TBL_PC * sd, int mob);
-int quest_update_status(TBL_PC * sd, int quest_id, quest_state status);
-int quest_check(TBL_PC * sd, int quest_id, quest_check_type type);
+struct quest_interface {
+ struct quest_db *db_data[MAX_QUEST_DB]; ///< Quest database
+ struct quest_db dummy; ///< Dummy entry for invalid quest lookups
+ /* */
+ void (*init) (bool minimal);
+ void (*final) (void);
+ void (*reload) (void);
+ /* */
+ struct quest_db *(*db) (int quest_id);
+ int (*pc_login) (TBL_PC *sd);
+ int (*add) (TBL_PC *sd, int quest_id);
+ int (*change) (TBL_PC *sd, int qid1, int qid2);
+ int (*delete) (TBL_PC *sd, int quest_id);
+ int (*update_objective_sub) (struct block_list *bl, va_list ap);
+ void (*update_objective) (TBL_PC *sd, int mob_id);
+ int (*update_status) (TBL_PC *sd, int quest_id, enum quest_state qs);
+ int (*check) (TBL_PC *sd, int quest_id, enum quest_check_type type);
+ void (*clear) (void);
+ int (*read_db) (void);
+};
-int quest_search_db(int quest_id);
+struct quest_interface *quest;
-void do_init_quest();
-void do_reload_quest(void);
+void quest_defaults(void);
-#endif
+#endif /* MAP_QUEST_H */
diff --git a/src/map/script.c b/src/map/script.c
index 682faa42b..ecd12a3c1 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -2,250 +2,78 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-//#define DEBUG_DISP
-//#define DEBUG_DISASM
-//#define DEBUG_RUN
-//#define DEBUG_HASH
-//#define DEBUG_DUMP_STACK
+#define HERCULES_CORE
-#include "../common/cbasetypes.h"
-#include "../common/malloc.h"
-#include "../common/md5calc.h"
-#include "../common/nullpo.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/socket.h" // usage: getcharip
-#include "../common/strlib.h"
-#include "../common/timer.h"
-#include "../common/utils.h"
+#include "../config/core.h" // RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, SECURE_NPCTIMEOUT_INTERVAL
+#include "script.h"
-#include "map.h"
-#include "path.h"
-#include "clif.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "atcommand.h"
+#include "battle.h"
+#include "battleground.h"
+#include "chat.h"
#include "chrif.h"
+#include "clif.h"
+#include "elemental.h"
+#include "guild.h"
+#include "homunculus.h"
+#include "instance.h"
+#include "intif.h"
#include "itemdb.h"
-#include "pc.h"
-#include "status.h"
-#include "storage.h"
+#include "log.h"
+#include "mail.h"
+#include "map.h"
+#include "mapreg.h"
+#include "mercenary.h"
#include "mob.h"
#include "npc.h"
+#include "party.h"
+#include "path.h"
+#include "pc.h"
#include "pet.h"
-#include "mapreg.h"
-#include "homunculus.h"
-#include "instance.h"
-#include "mercenary.h"
-#include "intif.h"
+#include "pet.h"
+#include "quest.h"
#include "skill.h"
#include "status.h"
-#include "chat.h"
-#include "battle.h"
-#include "battleground.h"
-#include "party.h"
-#include "guild.h"
-#include "atcommand.h"
-#include "log.h"
+#include "status.h"
+#include "storage.h"
#include "unit.h"
-#include "pet.h"
-#include "mail.h"
-#include "script.h"
-#include "quest.h"
-#include "elemental.h"
-#include "../config/core.h"
+#include "../common/cbasetypes.h"
+#include "../common/malloc.h"
+#include "../common/md5calc.h"
+#include "../common/mmo.h" // NEW_CARTS
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h" // usage: getcharip
+#include "../common/strlib.h"
+#include "../common/sysinfo.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
#ifndef WIN32
#include <sys/time.h>
#endif
-#include <time.h>
-#include <setjmp.h>
-#include <errno.h>
-
-#define FETCH(n, t) \
- if( script_hasdata(st,n) ) \
- (t)=script_getnum(st,n);
-
-/// Maximum amount of elements in script arrays
-#define SCRIPT_MAX_ARRAYSIZE 128
-#define SCRIPT_BLOCK_SIZE 512
-enum { LABEL_NEXTLINE=1,LABEL_START };
-
-/// temporary buffer for passing around compiled bytecode
-/// @see add_scriptb, set_label, parse_script
-static unsigned char* script_buf = NULL;
-static int script_pos = 0, script_size = 0;
-
-static inline int GETVALUE(const unsigned char* buf, int i)
-{
+static inline int GETVALUE(const unsigned char* buf, int i) {
return (int)MakeDWord(MakeWord(buf[i], buf[i+1]), MakeWord(buf[i+2], 0));
}
-static inline void SETVALUE(unsigned char* buf, int i, int n)
-{
+static inline void SETVALUE(unsigned char* buf, int i, int n) {
buf[i] = GetByte(n, 0);
buf[i+1] = GetByte(n, 1);
buf[i+2] = GetByte(n, 2);
}
-// Using a prime number for SCRIPT_HASH_SIZE should give better distributions
-#define SCRIPT_HASH_SIZE 1021
-int str_hash[SCRIPT_HASH_SIZE];
-// Specifies which string hashing method to use
-//#define SCRIPT_HASH_DJB2
-//#define SCRIPT_HASH_SDBM
-#define SCRIPT_HASH_ELF
-
-static DBMap* scriptlabel_db=NULL; // const char* label_name -> int script_pos
-static DBMap* userfunc_db=NULL; // const char* func_name -> struct script_code*
-static int parse_options=0;
-DBMap* script_get_label_db(void){ return scriptlabel_db; }
-DBMap* script_get_userfunc_db(void){ return userfunc_db; }
-
-// important buildin function references for usage in scripts
-static int buildin_set_ref = 0;
-static int buildin_callsub_ref = 0;
-static int buildin_callfunc_ref = 0;
-static int buildin_getelementofarray_ref = 0;
-
-// Caches compiled autoscript item code.
-// Note: This is not cleared when reloading itemdb.
-static DBMap* autobonus_db=NULL; // char* script -> char* bytecode
-
-struct Script_Config script_config = {
- 1, // warn_func_mismatch_argtypes
- 1, 65535, 2048, //warn_func_mismatch_paramnum/check_cmdcount/check_gotocount
- 0, INT_MAX, // input_min_value/input_max_value
- "OnPCDieEvent", //die_event_name
- "OnPCKillEvent", //kill_pc_event_name
- "OnNPCKillEvent", //kill_mob_event_name
- "OnPCLoginEvent", //login_event_name
- "OnPCLogoutEvent", //logout_event_name
- "OnPCLoadMapEvent", //loadmap_event_name
- "OnPCBaseLvUpEvent", //baselvup_event_name
- "OnPCJobLvUpEvent", //joblvup_event_name
- "OnTouch_", //ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves)
- "OnTouch", //ontouch2_name (run whenever a char walks into the OnTouch area)
-};
-
-static jmp_buf error_jump;
-static char* error_msg;
-static const char* error_pos;
-static int error_report; // if the error should produce output
-
-// for advanced scripting support ( nested if, switch, while, for, do-while, function, etc )
-// [Eoe / jA 1080, 1081, 1094, 1164]
-enum curly_type {
- TYPE_NULL = 0,
- TYPE_IF,
- TYPE_SWITCH,
- TYPE_WHILE,
- TYPE_FOR,
- TYPE_DO,
- TYPE_USERFUNC,
- TYPE_ARGLIST // function argument list
-};
-
-enum e_arglist
-{
- ARGLIST_UNDEFINED = 0,
- ARGLIST_NO_PAREN = 1,
- ARGLIST_PAREN = 2,
-};
-
-static struct {
- struct {
- enum curly_type type;
- int index;
- int count;
- int flag;
- struct linkdb_node *case_label;
- } curly[256]; // Information right parenthesis
- int curly_count; // The number of right brackets
- int index; // Number of the syntax used in the script
-} syntax;
+struct script_interface script_s;
-const char* parse_curly_close(const char* p);
-const char* parse_syntax_close(const char* p);
-const char* parse_syntax_close_sub(const char* p,int* flag);
-const char* parse_syntax(const char* p);
-static int parse_syntax_for_flag = 0;
-
-extern int current_equip_item_index; //for New CARDS Scripts. It contains Inventory Index of the EQUIP_SCRIPT caller item. [Lupus]
-int potion_flag=0; //For use on Alchemist improved potions/Potion Pitcher. [Skotlex]
-int potion_hp=0, potion_per_hp=0, potion_sp=0, potion_per_sp=0;
-int potion_target=0;
-
-
-c_op get_com(unsigned char *script,int *pos);
-int get_num(unsigned char *script,int *pos);
-
-/*==========================================
- * (Only those needed) local declaration prototype
- *------------------------------------------*/
-const char* parse_subexpr(const char* p,int limit);
-int run_func(struct script_state *st);
-
-enum {
- MF_NOMEMO, //0
- MF_NOTELEPORT,
- MF_NOSAVE,
- MF_NOBRANCH,
- MF_NOPENALTY,
- MF_NOZENYPENALTY,
- MF_PVP,
- MF_PVP_NOPARTY,
- MF_PVP_NOGUILD,
- MF_GVG,
- MF_GVG_NOPARTY, //10
- MF_NOTRADE,
- MF_NOSKILL,
- MF_NOWARP,
- MF_PARTYLOCK,
- MF_NOICEWALL,
- MF_SNOW,
- MF_FOG,
- MF_SAKURA,
- MF_LEAVES,
- /* 21 - 22 free */
- MF_CLOUDS = 23,
- MF_CLOUDS2,
- MF_FIREWORKS,
- MF_GVG_CASTLE,
- MF_GVG_DUNGEON,
- MF_NIGHTENABLED,
- MF_NOBASEEXP,
- MF_NOJOBEXP, //30
- MF_NOMOBLOOT,
- MF_NOMVPLOOT,
- MF_NORETURN,
- MF_NOWARPTO,
- MF_NIGHTMAREDROP,
- MF_ZONE,
- MF_NOCOMMAND,
- MF_NODROP,
- MF_JEXP,
- MF_BEXP, //40
- MF_NOVENDING,
- MF_LOADEVENT,
- MF_NOCHAT,
- MF_NOEXPPENALTY,
- MF_GUILDLOCK,
- MF_TOWN,
- MF_AUTOTRADE,
- MF_ALLOWKS,
- MF_MONSTER_NOTELEPORT,
- MF_PVP_NOCALCRANK, //50
- MF_BATTLEGROUND,
- MF_RESET
-};
-
-const char* script_op2name(int op)
-{
+const char* script_op2name(int op) {
#define RETURN_OP_NAME(type) case type: return #type
- switch( op )
- {
+ switch( op ) {
RETURN_OP_NAME(C_NOP);
RETURN_OP_NAME(C_POS);
RETURN_OP_NAME(C_INT);
@@ -260,6 +88,8 @@ const char* script_op2name(int op)
RETURN_OP_NAME(C_USERFUNC);
RETURN_OP_NAME(C_USERFUNC_POS);
+ RETURN_OP_NAME(C_REF);
+
// operators
RETURN_OP_NAME(C_OP3);
RETURN_OP_NAME(C_LOR);
@@ -283,6 +113,14 @@ const char* script_op2name(int op)
RETURN_OP_NAME(C_NOT);
RETURN_OP_NAME(C_R_SHIFT);
RETURN_OP_NAME(C_L_SHIFT);
+ RETURN_OP_NAME(C_ADD_POST);
+ RETURN_OP_NAME(C_SUB_POST);
+ RETURN_OP_NAME(C_ADD_PRE);
+ RETURN_OP_NAME(C_SUB_PRE);
+#ifdef PCRE_SUPPORT
+ RETURN_OP_NAME(C_RE_EQ);
+ RETURN_OP_NAME(C_RE_NE);
+#endif // PCRE_SUPPORT
default:
ShowDebug("script_op2name: unexpected op=%d\n", op);
@@ -291,7 +129,7 @@ const char* script_op2name(int op)
#undef RETURN_OP_NAME
}
-#ifdef DEBUG_DUMP_STACK
+#ifdef SCRIPT_DEBUG_DUMP_STACK
static void script_dump_stack(struct script_state* st)
{
int i;
@@ -322,7 +160,7 @@ static void script_dump_stack(struct script_state* st)
case C_RETINFO:
{
struct script_retinfo* ri = data->u.ri;
- ShowMessage(" %p {var_function=%p, script=%p, pos=%d, nargs=%d, defsp=%d}\n", ri, ri->var_function, ri->script, ri->pos, ri->nargs, ri->defsp);
+ ShowMessage(" %p {scope.vars=%p, scope.arrays=%p, script=%p, pos=%d, nargs=%d, defsp=%d}\n", ri, ri->scope.vars, ri->scope.arrays, ri->script, ri->pos, ri->nargs, ri->defsp);
}
break;
default:
@@ -334,35 +172,34 @@ static void script_dump_stack(struct script_state* st)
#endif
/// Reports on the console the src of a script error.
-static void script_reportsrc(struct script_state *st)
-{
+void script_reportsrc(struct script_state *st) {
struct block_list* bl;
if( st->oid == 0 )
return; //Can't report source.
- bl = iMap->id2bl(st->oid);
+ bl = map->id2bl(st->oid);
if( bl == NULL )
return;
switch( bl->type ) {
case BL_NPC:
if( bl->m >= 0 )
- ShowDebug("Source (NPC): %s at %s (%d,%d)\n", ((struct npc_data *)bl)->name, map[bl->m].name, bl->x, bl->y);
+ ShowDebug("Source (NPC): %s at %s (%d,%d)\n", ((struct npc_data *)bl)->name, map->list[bl->m].name, bl->x, bl->y);
else
ShowDebug("Source (NPC): %s (invisible/not on a map)\n", ((struct npc_data *)bl)->name);
break;
default:
if( bl->m >= 0 )
- ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status_get_name(bl), map[bl->m].name, bl->x, bl->y);
+ ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status->get_name(bl), map->list[bl->m].name, bl->x, bl->y);
else
- ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status_get_name(bl));
+ ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status->get_name(bl));
break;
}
}
/// Reports on the console information about the script data.
-static void script_reportdata(struct script_data* data)
+void script_reportdata(struct script_data* data)
{
if( data == NULL )
return;
@@ -371,7 +208,7 @@ static void script_reportdata(struct script_data* data)
ShowDebug("Data: nothing (nil)\n");
break;
case C_INT:// number
- ShowDebug("Data: number value=%d\n", data->u.num);
+ ShowDebug("Data: number value=%"PRId64"\n", data->u.num);
break;
case C_STR:
case C_CONSTSTR:// string
@@ -384,31 +221,28 @@ static void script_reportdata(struct script_data* data)
case C_NAME:// reference
if( reference_tovariable(data) ) {// variable
const char* name = reference_getname(data);
- if( not_array_variable(*name) )
- ShowDebug("Data: variable name='%s'\n", name);
- else
- ShowDebug("Data: variable name='%s' index=%d\n", name, reference_getindex(data));
+ ShowDebug("Data: variable name='%s' index=%d\n", name, reference_getindex(data));
} else if( reference_toconstant(data) ) {// constant
ShowDebug("Data: constant name='%s' value=%d\n", reference_getname(data), reference_getconstant(data));
} else if( reference_toparam(data) ) {// param
ShowDebug("Data: param name='%s' type=%d\n", reference_getname(data), reference_getparamtype(data));
} else {// ???
- ShowDebug("Data: reference name='%s' type=%s\n", reference_getname(data), script_op2name(data->type));
- ShowDebug("Please report this!!! - script->str_data.type=%s\n", script_op2name(script->str_data[reference_getid(data)].type));
+ ShowDebug("Data: reference name='%s' type=%s\n", reference_getname(data), script->op2name(data->type));
+ ShowDebug("Please report this!!! - script->str_data.type=%s\n", script->op2name(script->str_data[reference_getid(data)].type));
}
break;
case C_POS:// label
- ShowDebug("Data: label pos=%d\n", data->u.num);
+ ShowDebug("Data: label pos=%"PRId64"\n", data->u.num);
break;
default:
- ShowDebug("Data: %s\n", script_op2name(data->type));
+ ShowDebug("Data: %s\n", script->op2name(data->type));
break;
}
}
/// Reports on the console information about the current built-in function.
-static void script_reportfunc(struct script_state* st)
+void script_reportfunc(struct script_state* st)
{
int i, params, id;
struct script_data* data;
@@ -430,16 +264,16 @@ static void script_reportfunc(struct script_state* st)
if( params > 0 )
{
- ShowDebug("Function: %s (%d parameter%s):\n", get_str(id), params, ( params == 1 ) ? "" : "s");
+ ShowDebug("Function: %s (%d parameter%s):\n", script->get_str(id), params, ( params == 1 ) ? "" : "s");
for( i = 2; i <= script_lastdata(st); i++ )
{
- script_reportdata(script_getdata(st,i));
+ script->reportdata(script_getdata(st,i));
}
}
else
{
- ShowDebug("Function: %s (no parameters)\n", get_str(id));
+ ShowDebug("Function: %s (no parameters)\n", script->get_str(id));
}
}
@@ -447,35 +281,73 @@ static void script_reportfunc(struct script_state* st)
/*==========================================
* Output error message
*------------------------------------------*/
-static void disp_error_message2(const char *mes,const char *pos,int report)
-{
- error_msg = aStrdup(mes);
- error_pos = pos;
- error_report = report;
- longjmp( error_jump, 1 );
+static void disp_error_message2(const char *mes,const char *pos,int report) analyzer_noreturn;
+static void disp_error_message2(const char *mes,const char *pos,int report) {
+ script->error_msg = aStrdup(mes);
+ script->error_pos = pos;
+ script->error_report = report;
+ longjmp( script->error_jump, 1 );
+}
+#define disp_error_message(mes,pos) (disp_error_message2((mes),(pos),1))
+
+void disp_warning_message(const char *mes, const char *pos) {
+ script->warning(script->parser_current_src,script->parser_current_file,script->parser_current_line,mes,pos);
}
-#define disp_error_message(mes,pos) disp_error_message2(mes,pos,1)
/// Checks event parameter validity
-static void check_event(struct script_state *st, const char *evt)
+void check_event(struct script_state *st, const char *evt)
{
if( evt && evt[0] && !stristr(evt, "::On") )
{
ShowWarning("NPC event parameter deprecated! Please use 'NPCNAME::OnEVENT' instead of '%s'.\n", evt);
- script_reportsrc(st);
+ script->reportsrc(st);
}
}
/*==========================================
* Hashes the input string
*------------------------------------------*/
-static unsigned int calc_hash(const char* p)
-{
+unsigned int calc_hash(const char* p) {
unsigned int h;
#if defined(SCRIPT_HASH_DJB2)
h = 5381;
while( *p ) // hash*33 + c
+ h = ( h << 5 ) + h + ((unsigned char)(*p++));
+#elif defined(SCRIPT_HASH_SDBM)
+ h = 0;
+ while( *p ) // hash*65599 + c
+ h = ( h << 6 ) + ( h << 16 ) - h + ((unsigned char)(*p++));
+#elif defined(SCRIPT_HASH_ELF) // UNIX ELF hash
+ h = 0;
+ while( *p ) {
+ unsigned int g;
+ h = ( h << 4 ) + ((unsigned char)(*p++));
+ g = h & 0xF0000000;
+ if( g ) {
+ h ^= g >> 24;
+ h &= ~g;
+ }
+ }
+#else // athena hash
+ h = 0;
+ while( *p )
+ h = ( h << 1 ) + ( h >> 3 ) + ( h >> 5 ) + ( h >> 8 ) + (unsigned char)(*p++);
+#endif
+
+ return h % SCRIPT_HASH_SIZE;
+}
+
+/*==========================================
+ * Hashes the input string in a case insensitive way
+ *------------------------------------------*/
+unsigned int calc_hash_ci(const char* p) {
+ unsigned int h = 0;
+#ifdef ENABLE_CASE_CHECK
+
+#if defined(SCRIPT_HASH_DJB2)
+ h = 5381;
+ while( *p ) // hash*33 + c
h = ( h << 5 ) + h + ((unsigned char)TOLOWER(*p++));
#elif defined(SCRIPT_HASH_SDBM)
h = 0;
@@ -483,12 +355,11 @@ static unsigned int calc_hash(const char* p)
h = ( h << 6 ) + ( h << 16 ) - h + ((unsigned char)TOLOWER(*p++));
#elif defined(SCRIPT_HASH_ELF) // UNIX ELF hash
h = 0;
- while( *p ){
+ while( *p ) {
unsigned int g;
h = ( h << 4 ) + ((unsigned char)TOLOWER(*p++));
g = h & 0xF0000000;
- if( g )
- {
+ if( g ) {
h ^= g >> 24;
h &= ~g;
}
@@ -499,6 +370,7 @@ static unsigned int calc_hash(const char* p)
h = ( h << 1 ) + ( h >> 3 ) + ( h >> 5 ) + ( h >> 8 ) + (unsigned char)TOLOWER(*p++);
#endif
+#endif // ENABLE_CASE_CHECK
return h % SCRIPT_HASH_SIZE;
}
@@ -508,39 +380,129 @@ static unsigned int calc_hash(const char* p)
*------------------------------------------*/
/// Looks up string using the provided id.
-const char* get_str(int id)
+const char* script_get_str(int id)
{
Assert( id >= LABEL_START && id < script->str_size );
return script->str_buf+script->str_data[id].str;
}
/// Returns the uid of the string, or -1.
-static int search_str(const char* p)
+int script_search_str(const char* p)
{
int i;
- for( i = str_hash[calc_hash(p)]; i != 0; i = script->str_data[i].next )
- if( strcasecmp(get_str(i),p) == 0 )
+ for( i = script->str_hash[script->calc_hash(p)]; i != 0; i = script->str_data[i].next ) {
+ if( strcmp(script->get_str(i),p) == 0 ) {
return i;
+ }
+ }
return -1;
}
+void script_casecheck_clear_sub(struct casecheck_data *ccd) {
+#ifdef ENABLE_CASE_CHECK
+ if (ccd->str_data) {
+ aFree(ccd->str_data);
+ ccd->str_data = NULL;
+ }
+ ccd->str_data_size = 0;
+ ccd->str_num = 1;
+ if (ccd->str_buf) {
+ aFree(ccd->str_buf);
+ ccd->str_buf = NULL;
+ }
+ ccd->str_pos = 0;
+ ccd->str_size = 0;
+ memset(ccd->str_hash, 0, sizeof(ccd->str_hash));
+#endif // ENABLE_CASE_CHECK
+}
+
+void script_global_casecheck_clear(void) {
+ script_casecheck_clear_sub(&script->global_casecheck);
+}
+
+void script_local_casecheck_clear(void) {
+ script_casecheck_clear_sub(&script->local_casecheck);
+}
+
+const char *script_casecheck_add_str_sub(struct casecheck_data *ccd, const char *p) {
+#ifdef ENABLE_CASE_CHECK
+ int len, i;
+ int h = script->calc_hash_ci(p);
+ if( ccd->str_hash[h] == 0 ) { //empty bucket, add new node here
+ ccd->str_hash[h] = ccd->str_num;
+ } else {
+ const char *s = NULL;
+ for( i = ccd->str_hash[h]; ; i = ccd->str_data[i].next ) {
+ Assert( i >= 0 && i < ccd->str_size );
+ s = ccd->str_buf+ccd->str_data[i].str;
+ if( strcasecmp(s,p) == 0 ) {
+ return s; // string already in list
+ }
+ if( ccd->str_data[i].next == 0 )
+ break; // reached the end
+ }
+
+ // append node to end of list
+ ccd->str_data[i].next = ccd->str_num;
+ }
+
+ // grow list if neccessary
+ if( ccd->str_num >= ccd->str_data_size ) {
+ ccd->str_data_size += 1280;
+ RECREATE(ccd->str_data,struct str_data_struct,ccd->str_data_size);
+ memset(ccd->str_data + (ccd->str_data_size - 1280), '\0', 1280);
+ }
+
+ len=(int)strlen(p);
+
+ // grow string buffer if neccessary
+ while( ccd->str_pos+len+1 >= ccd->str_size ) {
+ ccd->str_size += 10240;
+ RECREATE(ccd->str_buf,char,ccd->str_size);
+ memset(ccd->str_buf + (ccd->str_size - 10240), '\0', 10240);
+ }
+
+ safestrncpy(ccd->str_buf+ccd->str_pos, p, len+1);
+ ccd->str_data[ccd->str_num].type = C_NOP;
+ ccd->str_data[ccd->str_num].str = ccd->str_pos;
+ ccd->str_data[ccd->str_num].val = 0;
+ ccd->str_data[ccd->str_num].next = 0;
+ ccd->str_data[ccd->str_num].func = NULL;
+ ccd->str_data[ccd->str_num].backpatch = -1;
+ ccd->str_data[ccd->str_num].label = -1;
+ ccd->str_pos += len+1;
+
+ ccd->str_num++;
+#endif // ENABLE_CASE_CHECK
+ return NULL;
+}
+
+const char *script_global_casecheck_add_str(const char *p) {
+ return script_casecheck_add_str_sub(&script->global_casecheck, p);
+}
+
+const char *script_local_casecheck_add_str(const char *p) {
+ return script_casecheck_add_str_sub(&script->local_casecheck, p);
+}
+
/// Stores a copy of the string and returns its id.
/// If an identical string is already present, returns its id instead.
-int add_str(const char* p)
+int script_add_str(const char* p)
{
- int i, h;
- int len;
+ int i, len, h = script->calc_hash(p);
+#ifdef ENABLE_CASE_CHECK
+ const char *existingentry = NULL;
+#endif // ENABLE_CASE_CHECK
- h = calc_hash(p);
-
- if( str_hash[h] == 0 ) {// empty bucket, add new node here
- str_hash[h] = script->str_num;
+ if( script->str_hash[h] == 0 ) {// empty bucket, add new node here
+ script->str_hash[h] = script->str_num;
} else {// scan for end of list, or occurence of identical string
- for( i = str_hash[h]; ; i = script->str_data[i].next ) {
- if( strcasecmp(get_str(i),p) == 0 )
+ for( i = script->str_hash[h]; ; i = script->str_data[i].next ) {
+ if( strcmp(script->get_str(i),p) == 0 ) {
return i; // string already in list
+ }
if( script->str_data[i].next == 0 )
break; // reached the end
}
@@ -549,6 +511,25 @@ int add_str(const char* p)
script->str_data[i].next = script->str_num;
}
+#ifdef ENABLE_CASE_CHECK
+ if( (strncmp(p, ".@", 2) == 0) ) // Local scope vars are checked separately to decrease false positives
+ existingentry = script->local_casecheck.add_str(p);
+ else {
+ existingentry = script->global_casecheck.add_str(p);
+ if( existingentry ) {
+ if( strcasecmp(p, "disguise") == 0 || strcasecmp(p, "Poison_Spore") == 0
+ || strcasecmp(p, "PecoPeco_Egg") == 0 || strcasecmp(p, "Soccer_Ball") == 0
+ || strcasecmp(p, "Horn") == 0 || strcasecmp(p, "Treasure_Box_") == 0
+ || strcasecmp(p, "Lord_of_Death") == 0
+ ) // Known duplicates, don't bother warning the user
+ existingentry = NULL;
+ }
+ }
+ if( existingentry ) {
+ DeprecationWarning2("script_add_str", p, existingentry, script->parser_current_file); // TODO
+ }
+#endif // ENABLE_CASE_CHECK
+
// grow list if neccessary
if( script->str_num >= script->str_data_size ) {
script->str_data_size += 1280;
@@ -568,6 +549,7 @@ int add_str(const char* p)
safestrncpy(script->str_buf+script->str_pos, p, len+1);
script->str_data[script->str_num].type = C_NOP;
script->str_data[script->str_num].str = script->str_pos;
+ script->str_data[script->str_num].val = 0;
script->str_data[script->str_num].next = 0;
script->str_data[script->str_num].func = NULL;
script->str_data[script->str_num].backpatch = -1;
@@ -579,43 +561,43 @@ int add_str(const char* p)
/// Appends 1 byte to the script buffer.
-static void add_scriptb(int a)
+void add_scriptb(int a)
{
- if( script_pos+1 >= script_size )
+ if( script->pos+1 >= script->size )
{
- script_size += SCRIPT_BLOCK_SIZE;
- RECREATE(script_buf,unsigned char,script_size);
+ script->size += SCRIPT_BLOCK_SIZE;
+ RECREATE(script->buf,unsigned char,script->size);
}
- script_buf[script_pos++] = (uint8)(a);
+ script->buf[script->pos++] = (uint8)(a);
}
/// Appends a c_op value to the script buffer.
/// The value is variable-length encoded into 8-bit blocks.
/// The encoding scheme is ( 01?????? )* 00??????, LSB first.
/// All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries).
-static void add_scriptc(int a)
+void add_scriptc(int a)
{
while( a >= 0x40 )
{
- add_scriptb((a&0x3f)|0x40);
+ script->addb((a&0x3f)|0x40);
a = (a - 0x40) >> 6;
}
- add_scriptb(a);
+ script->addb(a);
}
/// Appends an integer value to the script buffer.
/// The value is variable-length encoded into 8-bit blocks.
/// The encoding scheme is ( 11?????? )* 10??????, LSB first.
/// All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries).
-static void add_scripti(int a)
+void add_scripti(int a)
{
while( a >= 0x40 )
{
- add_scriptb((a&0x3f)|0xc0);
+ script->addb((a&0x3f)|0xc0);
a = (a - 0x40) >> 6;
}
- add_scriptb(a|0x80);
+ script->addb(a|0x80);
}
/// Appends a script->str_data object (label/function/variable/integer) to the script buffer.
@@ -623,37 +605,37 @@ static void add_scripti(int a)
///
/// @param l The id of the script->str_data entry
// Maximum up to 16M
-static void add_scriptl(int l)
+void add_scriptl(int l)
{
int backpatch = script->str_data[l].backpatch;
- switch(script->str_data[l].type){
+ switch(script->str_data[l].type) {
case C_POS:
case C_USERFUNC_POS:
- add_scriptc(C_POS);
- add_scriptb(script->str_data[l].label);
- add_scriptb(script->str_data[l].label>>8);
- add_scriptb(script->str_data[l].label>>16);
+ script->addc(C_POS);
+ script->addb(script->str_data[l].label);
+ script->addb(script->str_data[l].label>>8);
+ script->addb(script->str_data[l].label>>16);
break;
case C_NOP:
case C_USERFUNC:
// Embedded data backpatch there is a possibility of label
- add_scriptc(C_NAME);
- script->str_data[l].backpatch = script_pos;
- add_scriptb(backpatch);
- add_scriptb(backpatch>>8);
- add_scriptb(backpatch>>16);
+ script->addc(C_NAME);
+ script->str_data[l].backpatch = script->pos;
+ script->addb(backpatch);
+ script->addb(backpatch>>8);
+ script->addb(backpatch>>16);
break;
case C_INT:
- add_scripti(abs(script->str_data[l].val));
+ script->addi(abs(script->str_data[l].val));
if( script->str_data[l].val < 0 ) //Notice that this is negative, from jA (Rayce)
- add_scriptc(C_NEG);
+ script->addc(C_NEG);
break;
default: // assume C_NAME
- add_scriptc(C_NAME);
- add_scriptb(l);
- add_scriptb(l>>8);
- add_scriptb(l>>16);
+ script->addc(C_NAME);
+ script->addb(l);
+ script->addb(l>>8);
+ script->addb(l>>16);
break;
}
}
@@ -665,27 +647,27 @@ void set_label(int l,int pos, const char* script_pos)
{
int i,next;
- if(script->str_data[l].type==C_INT || script->str_data[l].type==C_PARAM || script->str_data[l].type==C_FUNC)
- { //Prevent overwriting constants values, parameters and built-in functions [Skotlex]
+ if(script->str_data[l].type==C_INT || script->str_data[l].type==C_PARAM || script->str_data[l].type==C_FUNC) {
+ //Prevent overwriting constants values, parameters and built-in functions [Skotlex]
disp_error_message("set_label: invalid label name",script_pos);
return;
}
- if(script->str_data[l].label!=-1){
+ if(script->str_data[l].label!=-1) {
disp_error_message("set_label: dup label ",script_pos);
return;
}
script->str_data[l].type=(script->str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS);
script->str_data[l].label=pos;
- for(i=script->str_data[l].backpatch;i>=0 && i!=0x00ffffff;){
- next=GETVALUE(script_buf,i);
- script_buf[i-1]=(script->str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS);
- SETVALUE(script_buf,i,pos);
+ for(i=script->str_data[l].backpatch;i>=0 && i!=0x00ffffff;) {
+ next=GETVALUE(script->buf,i);
+ script->buf[i-1]=(script->str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS);
+ SETVALUE(script->buf,i,pos);
i=next;
}
}
/// Skips spaces and/or comments.
-const char* skip_space(const char* p)
+const char* script_skip_space(const char* p)
{
if( p == NULL )
return NULL;
@@ -703,8 +685,10 @@ const char* skip_space(const char* p)
p += 2;
for(;;)
{
- if( *p == '\0' )
- return p;//disp_error_message("script:skip_space: end of file while parsing block comment. expected "CL_BOLD"*/"CL_NORM, p);
+ if( *p == '\0' ) {
+ script->disp_warning_message("script:script->skip_space: end of file while parsing block comment. expected "CL_BOLD"*/"CL_NORM, p);
+ return p;
+ }
if( *p == '*' && p[1] == '/' )
{// end of block comment
p += 2;
@@ -722,7 +706,7 @@ const char* skip_space(const char* p)
/// Skips a word.
/// A word consists of undercores and/or alphanumeric characters,
/// and valid variable prefixes/postfixes.
-static const char* skip_word(const char* p) {
+const char* skip_word(const char* p) {
// prefix
switch( *p ) {
case '@':// temporary char variable
@@ -737,7 +721,7 @@ static const char* skip_word(const char* p) {
p += ( p[1] == '@' ? 2 : 1 ); break;
}
- while( ISALNUM(*p) || *p == '_' )
+ while( ISALNUM(*p) || *p == '_' || *p == '\'' )
++p;
// postfix
@@ -748,26 +732,26 @@ static const char* skip_word(const char* p) {
}
/// Adds a word to script->str_data.
/// @see skip_word
-/// @see add_str
-static int add_word(const char* p) {
- int len;
+/// @see script->add_str
+int add_word(const char* p) {
+ size_t len;
int i;
// Check for a word
- len = skip_word(p) - p;
+ len = script->skip_word(p) - p;
if( len == 0 )
disp_error_message("script:add_word: invalid word. A word consists of undercores and/or alphanumeric characters, and valid variable prefixes/postfixes.", p);
// Duplicate the word
if( len+1 > script->word_size )
RECREATE(script->word_buf, char, (script->word_size = (len+1)));
-
+
memcpy(script->word_buf, p, len);
script->word_buf[len] = 0;
// add the word
- i = add_str(script->word_buf);
-
+ i = script->add_str(script->word_buf);
+
return i;
}
@@ -779,109 +763,109 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom)
{
const char *p2;
char *arg = NULL;
+ char null_arg = '\0';
int func;
- func = add_word(p);
- if( script->str_data[func].type == C_FUNC ){
- char argT = 0;
+ func = script->add_word(p);
+ if( script->str_data[func].type == C_FUNC ) {
// buildin function
- add_scriptl(func);
- add_scriptc(C_ARG);
+ script->addl(func);
+ script->addc(C_ARG);
arg = script->buildin[script->str_data[func].val];
- if( !arg ) arg = &argT;
- } else if( script->str_data[func].type == C_USERFUNC || script->str_data[func].type == C_USERFUNC_POS ){
+ if( !arg ) arg = &null_arg; // Use a dummy, null string
+ } else if( script->str_data[func].type == C_USERFUNC || script->str_data[func].type == C_USERFUNC_POS ) {
// script defined function
- add_scriptl(buildin_callsub_ref);
- add_scriptc(C_ARG);
- add_scriptl(func);
- arg = script->buildin[script->str_data[buildin_callsub_ref].val];
+ script->addl(script->buildin_callsub_ref);
+ script->addc(C_ARG);
+ script->addl(func);
+ arg = script->buildin[script->str_data[script->buildin_callsub_ref].val];
if( *arg == 0 )
disp_error_message("parse_callfunc: callsub has no arguments, please review its definition",p);
if( *arg != '*' )
++arg; // count func as argument
} else {
#ifdef SCRIPT_CALLFUNC_CHECK
- const char* name = get_str(func);
- if( !is_custom && strdb_get(userfunc_db, name) == NULL ) {
+ const char* name = script->get_str(func);
+ if( !is_custom && strdb_get(script->userfunc_db, name) == NULL ) {
#endif
disp_error_message("parse_line: expect command, missing function name or calling undeclared function",p);
#ifdef SCRIPT_CALLFUNC_CHECK
} else {;
- add_scriptl(buildin_callfunc_ref);
- add_scriptc(C_ARG);
- add_scriptc(C_STR);
- while( *name ) add_scriptb(*name ++);
- add_scriptb(0);
- arg = script->buildin[script->str_data[buildin_callfunc_ref].val];
+ script->addl(script->buildin_callfunc_ref);
+ script->addc(C_ARG);
+ script->addc(C_STR);
+ while( *name ) script->addb(*name ++);
+ script->addb(0);
+ arg = script->buildin[script->str_data[script->buildin_callfunc_ref].val];
if( *arg != '*' ) ++ arg;
}
#endif
}
- p = skip_word(p);
- p = skip_space(p);
- syntax.curly[syntax.curly_count].type = TYPE_ARGLIST;
- syntax.curly[syntax.curly_count].count = 0;
+ p = script->skip_word(p);
+ p = script->skip_space(p);
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_ARGLIST;
+ script->syntax.curly[script->syntax.curly_count].count = 0;
if( *p == ';' )
{// <func name> ';'
- syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN;
- } else if( *p == '(' && *(p2=skip_space(p+1)) == ')' )
+ script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_NO_PAREN;
+ } else if( *p == '(' && *(p2=script->skip_space(p+1)) == ')' )
{// <func name> '(' ')'
- syntax.curly[syntax.curly_count].flag = ARGLIST_PAREN;
+ script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_PAREN;
p = p2;
/*
} else if( 0 && require_paren && *p != '(' )
{// <func name>
- syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN;
+ script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_NO_PAREN;
*/
} else {// <func name> <arg list>
- if( require_paren ){
+ if( require_paren ) {
if( *p != '(' )
disp_error_message("need '('",p);
++p; // skip '('
- syntax.curly[syntax.curly_count].flag = ARGLIST_PAREN;
- } else if( *p == '(' ){
- syntax.curly[syntax.curly_count].flag = ARGLIST_UNDEFINED;
+ script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_PAREN;
+ } else if( *p == '(' ) {
+ script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_UNDEFINED;
} else {
- syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN;
+ script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_NO_PAREN;
}
- ++syntax.curly_count;
+ ++script->syntax.curly_count;
while( *arg ) {
- p2=parse_subexpr(p,-1);
+ p2=script->parse_subexpr(p,-1);
if( p == p2 )
break; // not an argument
if( *arg != '*' )
++arg; // next argument
- p=skip_space(p2);
+ p=script->skip_space(p2);
if( *arg == 0 || *p != ',' )
break; // no more arguments
++p; // skip comma
}
- --syntax.curly_count;
+ --script->syntax.curly_count;
}
if( arg && *arg && *arg != '?' && *arg != '*' )
- disp_error_message2("parse_callfunc: not enough arguments, expected ','", p, script_config.warn_func_mismatch_paramnum);
- if( syntax.curly[syntax.curly_count].type != TYPE_ARGLIST )
+ disp_error_message2("parse_callfunc: not enough arguments, expected ','", p, script->config.warn_func_mismatch_paramnum);
+ if( script->syntax.curly[script->syntax.curly_count].type != TYPE_ARGLIST )
disp_error_message("parse_callfunc: DEBUG last curly is not an argument list",p);
- if( syntax.curly[syntax.curly_count].flag == ARGLIST_PAREN ){
+ if( script->syntax.curly[script->syntax.curly_count].flag == ARGLIST_PAREN ) {
if( *p != ')' )
disp_error_message("parse_callfunc: expected ')' to close argument list",p);
++p;
}
- add_scriptc(C_FUNC);
+ script->addc(C_FUNC);
return p;
}
/// Processes end of logical script line.
/// @param first When true, only fix up scheduling data is initialized
/// @param p Script position for error reporting in set_label
-static void parse_nextline(bool first, const char* p)
+void parse_nextline(bool first, const char* p)
{
if( !first )
{
- add_scriptc(C_EOL); // mark end of line for stack cleanup
- set_label(LABEL_NEXTLINE, script_pos, p); // fix up '-' labels
+ script->addc(C_EOL); // mark end of line for stack cleanup
+ script->set_label(LABEL_NEXTLINE, script->pos, p); // fix up '-' labels
}
// initialize data for new '-' label fix up scheduling
@@ -890,6 +874,38 @@ static void parse_nextline(bool first, const char* p)
script->str_data[LABEL_NEXTLINE].label = -1;
}
+/**
+ * Pushes a variable into stack, processing its array index if needed.
+ * @see parse_variable
+ */
+void parse_variable_sub_push(int word, const char *p2) {
+ const char* p3 = NULL;
+
+ if( p2 ) {
+ // process the variable index
+
+ // push the getelementofarray method into the stack
+ script->addl(script->buildin_getelementofarray_ref);
+ script->addc(C_ARG);
+ script->addl(word);
+
+ // process the sub-expression for this assignment
+ p3 = script->parse_subexpr(p2 + 1, 1);
+ p3 = script->skip_space(p3);
+
+ if( *p3 != ']' ) {// closing parenthesis is required for this script
+ disp_error_message("Missing closing ']' parenthesis for the variable assignment.", p3);
+ }
+
+ // push the closing function stack operator onto the stack
+ script->addc(C_FUNC);
+ p3++;
+ } else {
+ // No array index, simply push the variable or value onto the stack
+ script->addl(word);
+ }
+}
+
/// Parse a variable assignment using the direct equals operator
/// @param p script position where the function should run from
/// @return NULL if not a variable assignment, the new position otherwise
@@ -899,21 +915,30 @@ const char* parse_variable(const char* p) {
const char *p2 = NULL;
const char *var = p;
+ if( ( p[0] == '+' && p[1] == '+' && (type = C_ADD_PRE) ) // pre ++
+ || ( p[0] == '-' && p[1] == '-' && (type = C_SUB_PRE) ) // pre --
+ ) {
+ var = p = script->skip_space(&p[2]);
+ }
+
// skip the variable where applicable
- p = skip_word(p);
- p = skip_space(p);
+ p = script->skip_word(p);
+ p = script->skip_space(p);
- if( p == NULL ) {// end of the line or invalid buffer
+ if( p == NULL ) {
+ // end of the line or invalid buffer
return NULL;
}
- if( *p == '[' ) {// array variable so process the array as appropriate
+ if( *p == '[' ) {
+ // array variable so process the array as appropriate
for( p2 = p, i = 0, j = 1; p; ++ i ) {
if( *p ++ == ']' && --(j) == 0 ) break;
if( *p == '[' ) ++ j;
}
- if( !(p = skip_space(p)) ) {// end of line or invalid characters remaining
+ if( !(p = script->skip_space(p)) ) {
+ // end of line or invalid characters remaining
disp_error_message("Missing right expression or closing bracket for variable.", p);
}
}
@@ -928,9 +953,8 @@ const char* parse_variable(const char* p) {
|| ( p[0] == '*' && p[1] == '=' && (type = C_MUL) ) // *=
|| ( p[0] == '/' && p[1] == '=' && (type = C_DIV) ) // /=
|| ( p[0] == '%' && p[1] == '=' && (type = C_MOD) ) // %=
- || ( p[0] == '~' && p[1] == '=' && (type = C_NOT) ) // ~=
- || ( p[0] == '+' && p[1] == '+' && (type = C_ADD_PP) ) // ++
- || ( p[0] == '-' && p[1] == '-' && (type = C_SUB_PP) ) // --
+ || ( p[0] == '+' && p[1] == '+' && (type = C_ADD_POST) ) // post ++
+ || ( p[0] == '-' && p[1] == '-' && (type = C_SUB_POST) ) // post --
|| ( p[0] == '<' && p[1] == '<' && p[2] == '=' && (type = C_L_SHIFT) ) // <<=
|| ( p[0] == '>' && p[1] == '>' && p[2] == '=' && (type = C_R_SHIFT) ) // >>=
) )
@@ -939,188 +963,229 @@ const char* parse_variable(const char* p) {
}
switch( type ) {
- case C_EQ: {// incremental modifier
- p = skip_space( &p[1] );
- }
- break;
+ case C_ADD_PRE: // pre ++
+ case C_SUB_PRE: // pre --
+ // (nothing more to skip)
+ break;
- case C_L_SHIFT:
- case C_R_SHIFT: {// left or right shift modifier
- p = skip_space( &p[3] );
- }
- break;
+ case C_EQ: // =
+ p = script->skip_space( &p[1] );
+ break;
- default: {// normal incremental command
- p = skip_space( &p[2] );
- }
+ case C_L_SHIFT: // <<=
+ case C_R_SHIFT: // >>=
+ p = script->skip_space( &p[3] );
+ break;
+
+ default: // everything else
+ p = script->skip_space( &p[2] );
}
- if( p == NULL ) {// end of line or invalid buffer
+ if( p == NULL ) {
+ // end of line or invalid buffer
return NULL;
}
// push the set function onto the stack
- add_scriptl(buildin_set_ref);
- add_scriptc(C_ARG);
+ script->addl(script->buildin_set_ref);
+ script->addc(C_ARG);
// always append parenthesis to avoid errors
- syntax.curly[syntax.curly_count].type = TYPE_ARGLIST;
- syntax.curly[syntax.curly_count].count = 0;
- syntax.curly[syntax.curly_count].flag = ARGLIST_PAREN;
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_ARGLIST;
+ script->syntax.curly[script->syntax.curly_count].count = 0;
+ script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_PAREN;
// increment the total curly count for the position in the script
- ++ syntax.curly_count;
+ ++script->syntax.curly_count;
// parse the variable currently being modified
- word = add_word(var);
+ word = script->add_word(var);
- if( script->str_data[word].type == C_FUNC || script->str_data[word].type == C_USERFUNC || script->str_data[word].type == C_USERFUNC_POS )
- {// cannot assign a variable which exists as a function or label
+ if( script->str_data[word].type == C_FUNC
+ || script->str_data[word].type == C_USERFUNC
+ || script->str_data[word].type == C_USERFUNC_POS
+ ) {
+ // cannot assign a variable which exists as a function or label
disp_error_message("Cannot modify a variable which has the same name as a function or label.", p);
}
- if( p2 ) {// process the variable index
- const char* p3 = NULL;
-
- // push the getelementofarray method into the stack
- add_scriptl(buildin_getelementofarray_ref);
- add_scriptc(C_ARG);
- add_scriptl(word);
-
- // process the sub-expression for this assignment
- p3 = parse_subexpr(p2 + 1, 1);
- p3 = skip_space(p3);
+ parse_variable_sub_push(word, p2); // Push variable onto the stack
- if( *p3 != ']' ) {// closing parenthesis is required for this script
- disp_error_message("Missing closing ']' parenthesis for the variable assignment.", p3);
- }
-
- // push the closing function stack operator onto the stack
- add_scriptc(C_FUNC);
- p3 ++;
- } else {// simply push the variable or value onto the stack
- add_scriptl(word);
+ if( type != C_EQ ) {
+ parse_variable_sub_push(word, p2); // Push variable onto the stack once again (first argument of setr)
}
- if( type != C_EQ )
- add_scriptc(C_REF);
+ if( type == C_ADD_POST || type == C_SUB_POST ) { // post ++ / --
+ script->addi(1);
+ script->addc(type == C_ADD_POST ? C_ADD : C_SUB);
- if( type == C_ADD_PP || type == C_SUB_PP ) {// incremental operator for the method
- add_scripti(1);
- add_scriptc(type == C_ADD_PP ? C_ADD : C_SUB);
- } else {// process the value as an expression
- p = parse_subexpr(p, -1);
+ parse_variable_sub_push(word, p2); // Push variable onto the stack (third argument of setr)
+ } else if( type == C_ADD_PRE || type == C_SUB_PRE ) { // pre ++ / --
+ script->addi(1);
+ script->addc(type == C_ADD_PRE ? C_ADD : C_SUB);
+ } else {
+ // process the value as an expression
+ p = script->parse_subexpr(p, -1);
- if( type != C_EQ )
- {// push the type of modifier onto the stack
- add_scriptc(type);
+ if( type != C_EQ ) {
+ // push the type of modifier onto the stack
+ script->addc(type);
}
}
// decrement the curly count for the position within the script
- -- syntax.curly_count;
+ --script->syntax.curly_count;
// close the script by appending the function operator
- add_scriptc(C_FUNC);
+ script->addc(C_FUNC);
// push the buffer from the method
return p;
}
+/*
+ * Checks whether the gives string is a number literal
+ *
+ * Mainly necessary to differentiate between number literals and NPC name
+ * constants, since several of those start with a digit.
+ *
+ * All this does is to check if the string begins with an optional + or - sign,
+ * followed by a hexadecimal or decimal number literal literal and is NOT
+ * followed by a underscore or letter.
+ *
+ * @param p Pointer to the string to check
+ * @return Whether the string is a number literal
+ */
+bool is_number(const char *p) {
+ const char *np;
+ if (!p)
+ return false;
+ if (*p == '-' || *p == '+')
+ p++;
+ np = p;
+ if (*p == '0' && p[1] == 'x') {
+ p+=2;
+ np = p;
+ // Hexadecimal
+ while (ISXDIGIT(*np))
+ np++;
+ } else {
+ // Decimal
+ while (ISDIGIT(*np))
+ np++;
+ }
+ if (p != np && *np != '_' && !ISALPHA(*np)) // At least one digit, and next isn't a letter or _
+ return true;
+ return false;
+}
+
/*==========================================
* Analysis section
*------------------------------------------*/
-const char* parse_simpleexpr(const char *p)
-{
+const char* parse_simpleexpr(const char *p) {
int i;
- p=skip_space(p);
+ p=script->skip_space(p);
if(*p==';' || *p==',')
disp_error_message("parse_simpleexpr: unexpected end of expression",p);
- if(*p=='('){
- if( (i=syntax.curly_count-1) >= 0 && syntax.curly[i].type == TYPE_ARGLIST )
- ++syntax.curly[i].count;
- p=parse_subexpr(p+1,-1);
- p=skip_space(p);
- if( (i=syntax.curly_count-1) >= 0 && syntax.curly[i].type == TYPE_ARGLIST &&
- syntax.curly[i].flag == ARGLIST_UNDEFINED && --syntax.curly[i].count == 0
- ){
- if( *p == ',' ){
- syntax.curly[i].flag = ARGLIST_PAREN;
+ if(*p=='(') {
+ if( (i=script->syntax.curly_count-1) >= 0 && script->syntax.curly[i].type == TYPE_ARGLIST )
+ ++script->syntax.curly[i].count;
+ p=script->parse_subexpr(p+1,-1);
+ p=script->skip_space(p);
+ if( (i=script->syntax.curly_count-1) >= 0 && script->syntax.curly[i].type == TYPE_ARGLIST
+ && script->syntax.curly[i].flag == ARGLIST_UNDEFINED && --script->syntax.curly[i].count == 0
+ ) {
+ if( *p == ',' ) {
+ script->syntax.curly[i].flag = ARGLIST_PAREN;
return p;
- } else
- syntax.curly[i].flag = ARGLIST_NO_PAREN;
+ } else {
+ script->syntax.curly[i].flag = ARGLIST_NO_PAREN;
+ }
}
if( *p != ')' )
disp_error_message("parse_simpleexpr: unmatched ')'",p);
++p;
- } else if(ISDIGIT(*p) || ((*p=='-' || *p=='+') && ISDIGIT(p[1]))){
+ } else if(is_number(p)) {
char *np;
- while(*p == '0' && ISDIGIT(p[1])) p++;
- i=strtoul(p,&np,0);
- add_scripti(i);
+ long long lli;
+ while(*p == '0' && ISDIGIT(p[1])) p++; // Skip leading zeros, we don't support octal literals
+ lli=strtoll(p,&np,0);
+ if( lli < INT_MIN ) {
+ lli = INT_MIN;
+ script->disp_warning_message("parse_simpleexpr: underflow detected, capping value to INT_MIN",p);
+ } else if( lli > INT_MAX ) {
+ lli = INT_MAX;
+ script->disp_warning_message("parse_simpleexpr: overflow detected, capping value to INT_MAX",p);
+ }
+ script->addi((int)lli); // Cast is safe, as it's already been checked for overflows
p=np;
- } else if(*p=='"'){
- add_scriptc(C_STR);
- p++;
- while( *p && *p != '"' ){
- if( (unsigned char)p[-1] <= 0x7e && *p == '\\' ) {
- char buf[8];
- size_t len = sv->skip_escaped_c(p) - p;
- size_t n = sv->unescape_c(buf, p, len);
- if( n != 1 )
- ShowDebug("parse_simpleexpr: unexpected length %d after unescape (\"%.*s\" -> %.*s)\n", (int)n, (int)len, p, (int)n, buf);
- p += len;
- add_scriptb(*buf);
- continue;
- } else if( *p == '\n' )
- disp_error_message("parse_simpleexpr: unexpected newline @ string",p);
- add_scriptb(*p++);
- }
- if(!*p)
- disp_error_message("parse_simpleexpr: unexpected end of file @ string",p);
- add_scriptb(0);
- p++; //'"'
+ } else if(*p=='"') {
+ script->addc(C_STR);
+ do {
+ p++;
+ while( *p && *p != '"' ) {
+ if( (unsigned char)p[-1] <= 0x7e && *p == '\\' ) {
+ char buf[8];
+ size_t len = sv->skip_escaped_c(p) - p;
+ size_t n = sv->unescape_c(buf, p, len);
+ if( n != 1 )
+ ShowDebug("parse_simpleexpr: unexpected length %d after unescape (\"%.*s\" -> %.*s)\n", (int)n, (int)len, p, (int)n, buf);
+ p += len;
+ script->addb(*buf);
+ continue;
+ } else if( *p == '\n' ) {
+ disp_error_message("parse_simpleexpr: unexpected newline @ string",p);
+ }
+ script->addb(*p++);
+ }
+ if(!*p)
+ disp_error_message("parse_simpleexpr: unexpected end of file @ string",p);
+ p++; //'"'
+ p = script->skip_space(p);
+ } while( *p && *p == '"' );
+ script->addb(0);
} else {
int l;
const char* pv;
// label , register , function etc
- if(skip_word(p)==p)
+ if(script->skip_word(p)==p)
disp_error_message("parse_simpleexpr: unexpected character",p);
- l=add_word(p);
- if( script->str_data[l].type == C_FUNC || script->str_data[l].type == C_USERFUNC || script->str_data[l].type == C_USERFUNC_POS)
- return parse_callfunc(p,1,0);
+ l=script->add_word(p);
+ if( script->str_data[l].type == C_FUNC || script->str_data[l].type == C_USERFUNC || script->str_data[l].type == C_USERFUNC_POS) {
+ return script->parse_callfunc(p,1,0);
#ifdef SCRIPT_CALLFUNC_CHECK
- else {
- const char* name = get_str(l);
- if( strdb_get(userfunc_db,name) != NULL ) {
- return parse_callfunc(p,1,1);
+ } else {
+ const char* name = script->get_str(l);
+ if( strdb_get(script->userfunc_db,name) != NULL ) {
+ return script->parse_callfunc(p,1,1);
}
- }
#endif
+ }
- if( (pv = parse_variable(p)) )
- {// successfully processed a variable assignment
+ if( (pv = script->parse_variable(p)) ) {
+ // successfully processed a variable assignment
return pv;
}
- p=skip_word(p);
- if( *p == '[' ){
+ p=script->skip_word(p);
+ if( *p == '[' ) {
// array(name[i] => getelementofarray(name,i) )
- add_scriptl(buildin_getelementofarray_ref);
- add_scriptc(C_ARG);
- add_scriptl(l);
+ script->addl(script->buildin_getelementofarray_ref);
+ script->addc(C_ARG);
+ script->addl(l);
- p=parse_subexpr(p+1,-1);
- p=skip_space(p);
+ p=script->parse_subexpr(p+1,-1);
+ p=script->skip_space(p);
if( *p != ']' )
disp_error_message("parse_simpleexpr: unmatched ']'",p);
++p;
- add_scriptc(C_FUNC);
- }else
- add_scriptl(l);
+ script->addc(C_FUNC);
+ } else {
+ script->addl(l);
+ }
}
@@ -1130,60 +1195,67 @@ const char* parse_simpleexpr(const char *p)
/*==========================================
* Analysis of the expression
*------------------------------------------*/
-const char* parse_subexpr(const char* p,int limit)
-{
+const char* script_parse_subexpr(const char* p,int limit) {
int op,opl,len;
const char* tmpp;
- p=skip_space(p);
+ p=script->skip_space(p);
- if( *p == '-' ){
- tmpp = skip_space(p+1);
- if( *tmpp == ';' || *tmpp == ',' ){
- add_scriptl(LABEL_NEXTLINE);
+ if( *p == '-' ) {
+ tmpp = script->skip_space(p+1);
+ if( *tmpp == ';' || *tmpp == ',' ) {
+ script->addl(LABEL_NEXTLINE);
p++;
return p;
}
}
- if((op=C_NEG,*p=='-') || (op=C_LNOT,*p=='!') || (op=C_NOT,*p=='~')){
- p=parse_subexpr(p+1,10);
- add_scriptc(op);
- } else
- p=parse_simpleexpr(p);
- p=skip_space(p);
+ if( (p[0]=='+' && p[1]=='+') /* C_ADD_PRE */ || (p[0]=='-'&&p[1]=='-') /* C_SUB_PRE */ ) { // Pre ++ -- operators
+ p=script->parse_variable(p);
+ } else if( (op=C_NEG,*p=='-') || (op=C_LNOT,*p=='!') || (op=C_NOT,*p=='~') ) { // Unary - ! ~ operators
+ p=script->parse_subexpr(p+1,11);
+ script->addc(op);
+ } else {
+ p=script->parse_simpleexpr(p);
+ }
+ p=script->skip_space(p);
while((
- (op=C_OP3,opl=0,len=1,*p=='?') ||
- (op=C_ADD,opl=8,len=1,*p=='+') ||
- (op=C_SUB,opl=8,len=1,*p=='-') ||
- (op=C_MUL,opl=9,len=1,*p=='*') ||
- (op=C_DIV,opl=9,len=1,*p=='/') ||
- (op=C_MOD,opl=9,len=1,*p=='%') ||
- (op=C_LAND,opl=2,len=2,*p=='&' && p[1]=='&') ||
- (op=C_AND,opl=6,len=1,*p=='&') ||
- (op=C_LOR,opl=1,len=2,*p=='|' && p[1]=='|') ||
- (op=C_OR,opl=5,len=1,*p=='|') ||
- (op=C_XOR,opl=4,len=1,*p=='^') ||
- (op=C_EQ,opl=3,len=2,*p=='=' && p[1]=='=') ||
- (op=C_NE,opl=3,len=2,*p=='!' && p[1]=='=') ||
- (op=C_R_SHIFT,opl=7,len=2,*p=='>' && p[1]=='>') ||
- (op=C_GE,opl=3,len=2,*p=='>' && p[1]=='=') ||
- (op=C_GT,opl=3,len=1,*p=='>') ||
- (op=C_L_SHIFT,opl=7,len=2,*p=='<' && p[1]=='<') ||
- (op=C_LE,opl=3,len=2,*p=='<' && p[1]=='=') ||
- (op=C_LT,opl=3,len=1,*p=='<')) && opl>limit){
+ (op=C_OP3, opl=0, len=1,*p=='?') // ?:
+ || (op=C_ADD, opl=9, len=1,*p=='+') // +
+ || (op=C_SUB, opl=9, len=1,*p=='-') // -
+ || (op=C_MUL, opl=10,len=1,*p=='*') // *
+ || (op=C_DIV, opl=10,len=1,*p=='/') // /
+ || (op=C_MOD, opl=10,len=1,*p=='%') // %
+ || (op=C_LAND, opl=2, len=2,*p=='&' && p[1]=='&') // &&
+ || (op=C_AND, opl=5, len=1,*p=='&') // &
+ || (op=C_LOR, opl=1, len=2,*p=='|' && p[1]=='|') // ||
+ || (op=C_OR, opl=3, len=1,*p=='|') // |
+ || (op=C_XOR, opl=4, len=1,*p=='^') // ^
+ || (op=C_EQ, opl=6, len=2,*p=='=' && p[1]=='=') // ==
+ || (op=C_NE, opl=6, len=2,*p=='!' && p[1]=='=') // !=
+#ifdef PCRE_SUPPORT
+ || (op=C_RE_EQ, opl=6, len=2,*p=='~' && p[1]=='=') // ~=
+ || (op=C_RE_NE, opl=6, len=2,*p=='~' && p[1]=='!') // ~!
+#endif // PCRE_SUPPORT
+ || (op=C_R_SHIFT,opl=8, len=2,*p=='>' && p[1]=='>') // >>
+ || (op=C_GE, opl=7, len=2,*p=='>' && p[1]=='=') // >=
+ || (op=C_GT, opl=7, len=1,*p=='>') // >
+ || (op=C_L_SHIFT,opl=8, len=2,*p=='<' && p[1]=='<') // <<
+ || (op=C_LE, opl=7, len=2,*p=='<' && p[1]=='=') // <=
+ || (op=C_LT, opl=7, len=1,*p=='<') // <
+ ) && opl>limit) {
p+=len;
if(op == C_OP3) {
- p=parse_subexpr(p,-1);
- p=skip_space(p);
+ p=script->parse_subexpr(p,-1);
+ p=script->skip_space(p);
if( *(p++) != ':')
disp_error_message("parse_subexpr: need ':'", p-1);
- p=parse_subexpr(p,-1);
+ p=script->parse_subexpr(p,-1);
} else {
- p=parse_subexpr(p,opl);
+ p=script->parse_subexpr(p,opl);
}
- add_scriptc(op);
- p=skip_space(p);
+ script->addc(op);
+ p=script->skip_space(p);
}
return p; /* return first untreated operator */
@@ -1194,12 +1266,12 @@ const char* parse_subexpr(const char* p,int limit)
*------------------------------------------*/
const char* parse_expr(const char *p)
{
- switch(*p){
+ switch(*p) {
case ')': case ';': case ':': case '[': case ']':
case '}':
disp_error_message("parse_expr: unexpected char",p);
}
- p=parse_subexpr(p,-1);
+ p=script->parse_subexpr(p,-1);
return p;
}
@@ -1210,43 +1282,43 @@ const char* parse_line(const char* p)
{
const char* p2;
- p=skip_space(p);
+ p=script->skip_space(p);
if(*p==';') {
//Close decision for if(); for(); while();
- p = parse_syntax_close(p + 1);
+ p = script->parse_syntax_close(p + 1);
return p;
}
- if(*p==')' && parse_syntax_for_flag)
+ if(*p==')' && script->parse_syntax_for_flag)
return p+1;
- p = skip_space(p);
+ p = script->skip_space(p);
if(p[0] == '{') {
- syntax.curly[syntax.curly_count].type = TYPE_NULL;
- syntax.curly[syntax.curly_count].count = -1;
- syntax.curly[syntax.curly_count].index = -1;
- syntax.curly_count++;
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_NULL;
+ script->syntax.curly[script->syntax.curly_count].count = -1;
+ script->syntax.curly[script->syntax.curly_count].index = -1;
+ script->syntax.curly_count++;
return p + 1;
} else if(p[0] == '}') {
- return parse_curly_close(p);
+ return script->parse_curly_close(p);
}
// Syntax-related processing
- p2 = parse_syntax(p);
+ p2 = script->parse_syntax(p);
if(p2 != NULL)
return p2;
// attempt to process a variable assignment
- p2 = parse_variable(p);
+ p2 = script->parse_variable(p);
if( p2 != NULL )
{// variable assignment processed so leave the method
- return parse_syntax_close(p2 + 1);
+ return script->parse_syntax_close(p2 + 1);
}
- p = parse_callfunc(p,0,0);
- p = skip_space(p);
+ p = script->parse_callfunc(p,0,0);
+ p = script->skip_space(p);
- if(parse_syntax_for_flag) {
+ if(script->parse_syntax_for_flag) {
if( *p != ')' )
disp_error_message("parse_line: need ')'",p);
} else {
@@ -1255,7 +1327,7 @@ const char* parse_line(const char* p)
}
//Binding decision for if(), for(), while()
- p = parse_syntax_close(p+1);
+ p = script->parse_syntax_close(p+1);
return p;
}
@@ -1263,52 +1335,52 @@ const char* parse_line(const char* p)
// { ... } Closing process
const char* parse_curly_close(const char* p)
{
- if(syntax.curly_count <= 0) {
+ if(script->syntax.curly_count <= 0) {
disp_error_message("parse_curly_close: unexpected string",p);
return p + 1;
- } else if(syntax.curly[syntax.curly_count-1].type == TYPE_NULL) {
- syntax.curly_count--;
+ } else if(script->syntax.curly[script->syntax.curly_count-1].type == TYPE_NULL) {
+ script->syntax.curly_count--;
//Close decision if, for , while
- p = parse_syntax_close(p + 1);
+ p = script->parse_syntax_close(p + 1);
return p;
- } else if(syntax.curly[syntax.curly_count-1].type == TYPE_SWITCH) {
+ } else if(script->syntax.curly[script->syntax.curly_count-1].type == TYPE_SWITCH) {
//Closing switch()
- int pos = syntax.curly_count-1;
+ int pos = script->syntax.curly_count-1;
char label[256];
int l;
// Remove temporary variables
- sprintf(label,"set $@__SW%x_VAL,0;",syntax.curly[pos].index);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ sprintf(label,"set $@__SW%x_VAL,0;",script->syntax.curly[pos].index);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
// Go to the end pointer unconditionally
- sprintf(label,"goto __SW%x_FIN;",syntax.curly[pos].index);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ sprintf(label,"goto __SW%x_FIN;",script->syntax.curly[pos].index);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
// You are here labeled
- sprintf(label,"__SW%x_%x",syntax.curly[pos].index,syntax.curly[pos].count);
- l=add_str(label);
- set_label(l,script_pos, p);
+ sprintf(label,"__SW%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count);
+ l=script->add_str(label);
+ script->set_label(l,script->pos, p);
- if(syntax.curly[pos].flag) {
+ if(script->syntax.curly[pos].flag) {
//Exists default
- sprintf(label,"goto __SW%x_DEF;",syntax.curly[pos].index);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ sprintf(label,"goto __SW%x_DEF;",script->syntax.curly[pos].index);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
}
// Label end
- sprintf(label,"__SW%x_FIN",syntax.curly[pos].index);
- l=add_str(label);
- set_label(l,script_pos, p);
- linkdb_final(&syntax.curly[pos].case_label); // free the list of case label
- syntax.curly_count--;
+ sprintf(label,"__SW%x_FIN",script->syntax.curly[pos].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos, p);
+ linkdb_final(&script->syntax.curly[pos].case_label); // free the list of case label
+ script->syntax.curly_count--;
//Closing decision if, for , while
- p = parse_syntax_close(p + 1);
+ p = script->parse_syntax_close(p + 1);
return p;
} else {
disp_error_message("parse_curly_close: unexpected string",p);
@@ -1321,27 +1393,27 @@ const char* parse_curly_close(const char* p)
// if, switch, while ? will handle this internally.
const char* parse_syntax(const char* p)
{
- const char *p2 = skip_word(p);
+ const char *p2 = script->skip_word(p);
switch(*p) {
case 'B':
case 'b':
- if(p2 - p == 5 && !strncasecmp(p,"break",5)) {
+ if( p2 - p == 5 && strncmp(p,"break",5) == 0 ) {
// break Processing
char label[256];
- int pos = syntax.curly_count - 1;
+ int pos = script->syntax.curly_count - 1;
while(pos >= 0) {
- if(syntax.curly[pos].type == TYPE_DO) {
- sprintf(label,"goto __DO%x_FIN;",syntax.curly[pos].index);
+ if(script->syntax.curly[pos].type == TYPE_DO) {
+ sprintf(label,"goto __DO%x_FIN;",script->syntax.curly[pos].index);
break;
- } else if(syntax.curly[pos].type == TYPE_FOR) {
- sprintf(label,"goto __FR%x_FIN;",syntax.curly[pos].index);
+ } else if(script->syntax.curly[pos].type == TYPE_FOR) {
+ sprintf(label,"goto __FR%x_FIN;",script->syntax.curly[pos].index);
break;
- } else if(syntax.curly[pos].type == TYPE_WHILE) {
- sprintf(label,"goto __WL%x_FIN;",syntax.curly[pos].index);
+ } else if(script->syntax.curly[pos].type == TYPE_WHILE) {
+ sprintf(label,"goto __WL%x_FIN;",script->syntax.curly[pos].index);
break;
- } else if(syntax.curly[pos].type == TYPE_SWITCH) {
- sprintf(label,"goto __SW%x_FIN;",syntax.curly[pos].index);
+ } else if(script->syntax.curly[pos].type == TYPE_SWITCH) {
+ sprintf(label,"goto __SW%x_FIN;",script->syntax.curly[pos].index);
break;
}
pos--;
@@ -1349,107 +1421,113 @@ const char* parse_syntax(const char* p)
if(pos < 0) {
disp_error_message("parse_syntax: unexpected 'break'",p);
} else {
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
}
- p = skip_space(p2);
+ p = script->skip_space(p2);
if(*p != ';')
disp_error_message("parse_syntax: need ';'",p);
// Closing decision if, for , while
- p = parse_syntax_close(p + 1);
+ p = script->parse_syntax_close(p + 1);
return p;
+#ifdef ENABLE_CASE_CHECK
+ } else if( p2 - p == 5 && strncasecmp(p, "break", 5) == 0 ) {
+ disp_deprecation_message("parse_syntax", "break", p); // TODO
+#endif // ENABLE_CASE_CHECK
}
break;
case 'c':
case 'C':
- if(p2 - p == 4 && !strncasecmp(p,"case",4)) {
+ if( p2 - p == 4 && strncmp(p, "case", 4) == 0 ) {
//Processing case
- int pos = syntax.curly_count-1;
- if(pos < 0 || syntax.curly[pos].type != TYPE_SWITCH) {
+ int pos = script->syntax.curly_count-1;
+ if(pos < 0 || script->syntax.curly[pos].type != TYPE_SWITCH) {
disp_error_message("parse_syntax: unexpected 'case' ",p);
return p+1;
} else {
char label[256];
int l,v;
char *np;
- if(syntax.curly[pos].count != 1) {
+ if(script->syntax.curly[pos].count != 1) {
//Jump for FALLTHRU
- sprintf(label,"goto __SW%x_%xJ;",syntax.curly[pos].index,syntax.curly[pos].count);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ sprintf(label,"goto __SW%x_%xJ;",script->syntax.curly[pos].index,script->syntax.curly[pos].count);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
// You are here labeled
- sprintf(label,"__SW%x_%x",syntax.curly[pos].index,syntax.curly[pos].count);
- l=add_str(label);
- set_label(l,script_pos, p);
+ sprintf(label,"__SW%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count);
+ l=script->add_str(label);
+ script->set_label(l,script->pos, p);
}
//Decision statement switch
- p = skip_space(p2);
+ p = script->skip_space(p2);
if(p == p2) {
disp_error_message("parse_syntax: expect space ' '",p);
}
// check whether case label is integer or not
- v = strtol(p,&np,0);
- if(np == p) { //Check for constants
- p2 = skip_word(p);
- v = p2-p; // length of word at p2
- memcpy(label,p,v);
- label[v]='\0';
- if( !script_get_constant(label, &v) )
- disp_error_message("parse_syntax: 'case' label is not an integer",p);
- p = skip_word(p);
- } else { //Numeric value
- if((*p == '-' || *p == '+') && ISDIGIT(p[1])) // pre-skip because '-' can not skip_word
+ if(is_number(p)) {
+ //Numeric value
+ v = (int)strtol(p,&np,0);
+ if((*p == '-' || *p == '+') && ISDIGIT(p[1])) // pre-skip because '-' can not skip_word
p++;
- p = skip_word(p);
+ p = script->skip_word(p);
if(np != p)
disp_error_message("parse_syntax: 'case' label is not an integer",np);
+ } else {
+ //Check for constants
+ p2 = script->skip_word(p);
+ v = (int)(size_t) (p2-p); // length of word at p2
+ memcpy(label,p,v);
+ label[v]='\0';
+ if( !script->get_constant(label, &v) )
+ disp_error_message("parse_syntax: 'case' label is not an integer",p);
+ p = script->skip_word(p);
}
- p = skip_space(p);
+ p = script->skip_space(p);
if(*p != ':')
disp_error_message("parse_syntax: expect ':'",p);
sprintf(label,"if(%d != $@__SW%x_VAL) goto __SW%x_%x;",
- v,syntax.curly[pos].index,syntax.curly[pos].index,syntax.curly[pos].count+1);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
+ v,script->syntax.curly[pos].index,script->syntax.curly[pos].index,script->syntax.curly[pos].count+1);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
// Bad I do not parse twice
- p2 = parse_line(label);
- parse_line(p2);
- syntax.curly_count--;
- if(syntax.curly[pos].count != 1) {
+ p2 = script->parse_line(label);
+ script->parse_line(p2);
+ script->syntax.curly_count--;
+ if(script->syntax.curly[pos].count != 1) {
// Label after the completion of FALLTHRU
- sprintf(label,"__SW%x_%xJ",syntax.curly[pos].index,syntax.curly[pos].count);
- l=add_str(label);
- set_label(l,script_pos,p);
+ sprintf(label,"__SW%x_%xJ",script->syntax.curly[pos].index,script->syntax.curly[pos].count);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
}
// check duplication of case label [Rayce]
- if(linkdb_search(&syntax.curly[pos].case_label, (void*)__64BPTRSIZE(v)) != NULL)
+ if(linkdb_search(&script->syntax.curly[pos].case_label, (void*)h64BPTRSIZE(v)) != NULL)
disp_error_message("parse_syntax: dup 'case'",p);
- linkdb_insert(&syntax.curly[pos].case_label, (void*)__64BPTRSIZE(v), (void*)1);
+ linkdb_insert(&script->syntax.curly[pos].case_label, (void*)h64BPTRSIZE(v), (void*)1);
- sprintf(label,"set $@__SW%x_VAL,0;",syntax.curly[pos].index);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
+ sprintf(label,"set $@__SW%x_VAL,0;",script->syntax.curly[pos].index);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
- syntax.curly[pos].count++;
+ script->parse_line(label);
+ script->syntax.curly_count--;
+ script->syntax.curly[pos].count++;
}
return p + 1;
- } else if(p2 - p == 8 && !strncasecmp(p,"continue",8)) {
+ } else if( p2 - p == 8 && strncmp(p, "continue", 8) == 0 ) {
// Processing continue
char label[256];
- int pos = syntax.curly_count - 1;
+ int pos = script->syntax.curly_count - 1;
while(pos >= 0) {
- if(syntax.curly[pos].type == TYPE_DO) {
- sprintf(label,"goto __DO%x_NXT;",syntax.curly[pos].index);
- syntax.curly[pos].flag = 1; //Flag put the link for continue
+ if(script->syntax.curly[pos].type == TYPE_DO) {
+ sprintf(label,"goto __DO%x_NXT;",script->syntax.curly[pos].index);
+ script->syntax.curly[pos].flag = 1; //Flag put the link for continue
break;
- } else if(syntax.curly[pos].type == TYPE_FOR) {
- sprintf(label,"goto __FR%x_NXT;",syntax.curly[pos].index);
+ } else if(script->syntax.curly[pos].type == TYPE_FOR) {
+ sprintf(label,"goto __FR%x_NXT;",script->syntax.curly[pos].index);
break;
- } else if(syntax.curly[pos].type == TYPE_WHILE) {
- sprintf(label,"goto __WL%x_NXT;",syntax.curly[pos].index);
+ } else if(script->syntax.curly[pos].type == TYPE_WHILE) {
+ sprintf(label,"goto __WL%x_NXT;",script->syntax.curly[pos].index);
break;
}
pos--;
@@ -1457,162 +1535,173 @@ const char* parse_syntax(const char* p)
if(pos < 0) {
disp_error_message("parse_syntax: unexpected 'continue'",p);
} else {
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
}
- p = skip_space(p2);
+ p = script->skip_space(p2);
if(*p != ';')
disp_error_message("parse_syntax: need ';'",p);
//Closing decision if, for , while
- p = parse_syntax_close(p + 1);
+ p = script->parse_syntax_close(p + 1);
return p;
+#ifdef ENABLE_CASE_CHECK
+ } else if( p2 - p == 4 && strncasecmp(p, "case", 4) == 0 ) {
+ disp_deprecation_message("parse_syntax", "case", p); // TODO
+ } else if( p2 - p == 8 && strncasecmp(p, "continue", 8) == 0 ) {
+ disp_deprecation_message("parse_syntax", "continue", p); // TODO
+#endif // ENABLE_CASE_CHECK
}
break;
case 'd':
case 'D':
- if(p2 - p == 7 && !strncasecmp(p,"default",7)) {
+ if( p2 - p == 7 && strncmp(p, "default", 7) == 0 ) {
// Switch - default processing
- int pos = syntax.curly_count-1;
- if(pos < 0 || syntax.curly[pos].type != TYPE_SWITCH) {
+ int pos = script->syntax.curly_count-1;
+ if(pos < 0 || script->syntax.curly[pos].type != TYPE_SWITCH) {
disp_error_message("parse_syntax: unexpected 'default'",p);
- } else if(syntax.curly[pos].flag) {
+ } else if(script->syntax.curly[pos].flag) {
disp_error_message("parse_syntax: dup 'default'",p);
} else {
char label[256];
int l;
// Put the label location
- p = skip_space(p2);
+ p = script->skip_space(p2);
if(*p != ':') {
disp_error_message("parse_syntax: need ':'",p);
}
- sprintf(label,"__SW%x_%x",syntax.curly[pos].index,syntax.curly[pos].count);
- l=add_str(label);
- set_label(l,script_pos,p);
+ sprintf(label,"__SW%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
// Skip to the next link w/o condition
- sprintf(label,"goto __SW%x_%x;",syntax.curly[pos].index,syntax.curly[pos].count+1);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ sprintf(label,"goto __SW%x_%x;",script->syntax.curly[pos].index,script->syntax.curly[pos].count+1);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
// The default label
- sprintf(label,"__SW%x_DEF",syntax.curly[pos].index);
- l=add_str(label);
- set_label(l,script_pos,p);
+ sprintf(label,"__SW%x_DEF",script->syntax.curly[pos].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
- syntax.curly[syntax.curly_count - 1].flag = 1;
- syntax.curly[pos].count++;
+ script->syntax.curly[script->syntax.curly_count - 1].flag = 1;
+ script->syntax.curly[pos].count++;
}
return p + 1;
- } else if(p2 - p == 2 && !strncasecmp(p,"do",2)) {
+ } else if( p2 - p == 2 && strncmp(p, "do", 2) == 0 ) {
int l;
char label[256];
- p=skip_space(p2);
+ p=script->skip_space(p2);
- syntax.curly[syntax.curly_count].type = TYPE_DO;
- syntax.curly[syntax.curly_count].count = 1;
- syntax.curly[syntax.curly_count].index = syntax.index++;
- syntax.curly[syntax.curly_count].flag = 0;
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_DO;
+ script->syntax.curly[script->syntax.curly_count].count = 1;
+ script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++;
+ script->syntax.curly[script->syntax.curly_count].flag = 0;
// Label of the (do) form here
- sprintf(label,"__DO%x_BGN",syntax.curly[syntax.curly_count].index);
- l=add_str(label);
- set_label(l,script_pos,p);
- syntax.curly_count++;
+ sprintf(label,"__DO%x_BGN",script->syntax.curly[script->syntax.curly_count].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
+ script->syntax.curly_count++;
return p;
+#ifdef ENABLE_CASE_CHECK
+ } else if( p2 - p == 7 && strncasecmp(p, "default", 7) == 0 ) {
+ disp_deprecation_message("parse_syntax", "default", p); // TODO
+ } else if( p2 - p == 2 && strncasecmp(p, "do", 2) == 0 ) {
+ disp_deprecation_message("parse_syntax", "do", p); // TODO
+#endif // ENABLE_CASE_CHECK
}
break;
case 'f':
case 'F':
- if(p2 - p == 3 && !strncasecmp(p,"for",3)) {
+ if( p2 - p == 3 && strncmp(p, "for", 3) == 0 ) {
int l;
char label[256];
- int pos = syntax.curly_count;
- syntax.curly[syntax.curly_count].type = TYPE_FOR;
- syntax.curly[syntax.curly_count].count = 1;
- syntax.curly[syntax.curly_count].index = syntax.index++;
- syntax.curly[syntax.curly_count].flag = 0;
- syntax.curly_count++;
+ int pos = script->syntax.curly_count;
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_FOR;
+ script->syntax.curly[script->syntax.curly_count].count = 1;
+ script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++;
+ script->syntax.curly[script->syntax.curly_count].flag = 0;
+ script->syntax.curly_count++;
- p=skip_space(p2);
+ p=script->skip_space(p2);
if(*p != '(')
disp_error_message("parse_syntax: need '('",p);
p++;
// Execute the initialization statement
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- p=parse_line(p);
- syntax.curly_count--;
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ p=script->parse_line(p);
+ script->syntax.curly_count--;
// Form the start of label decision
- sprintf(label,"__FR%x_J",syntax.curly[pos].index);
- l=add_str(label);
- set_label(l,script_pos,p);
+ sprintf(label,"__FR%x_J",script->syntax.curly[pos].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
- p=skip_space(p);
+ p=script->skip_space(p);
if(*p == ';') {
// For (; Because the pattern of always true ;)
;
} else {
// Skip to the end point if the condition is false
- sprintf(label,"__FR%x_FIN",syntax.curly[pos].index);
- add_scriptl(add_str("jump_zero"));
- add_scriptc(C_ARG);
- p=parse_expr(p);
- p=skip_space(p);
- add_scriptl(add_str(label));
- add_scriptc(C_FUNC);
+ sprintf(label,"__FR%x_FIN",script->syntax.curly[pos].index);
+ script->addl(script->add_str("jump_zero"));
+ script->addc(C_ARG);
+ p=script->parse_expr(p);
+ p=script->skip_space(p);
+ script->addl(script->add_str(label));
+ script->addc(C_FUNC);
}
if(*p != ';')
disp_error_message("parse_syntax: need ';'",p);
p++;
// Skip to the beginning of the loop
- sprintf(label,"goto __FR%x_BGN;",syntax.curly[pos].index);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ sprintf(label,"goto __FR%x_BGN;",script->syntax.curly[pos].index);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
// Labels to form the next loop
- sprintf(label,"__FR%x_NXT",syntax.curly[pos].index);
- l=add_str(label);
- set_label(l,script_pos,p);
+ sprintf(label,"__FR%x_NXT",script->syntax.curly[pos].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
// Process the next time you enter the loop
// A ')' last for; flag to be treated as'
- parse_syntax_for_flag = 1;
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- p=parse_line(p);
- syntax.curly_count--;
- parse_syntax_for_flag = 0;
+ script->parse_syntax_for_flag = 1;
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ p=script->parse_line(p);
+ script->syntax.curly_count--;
+ script->parse_syntax_for_flag = 0;
// Skip to the determination process conditions
- sprintf(label,"goto __FR%x_J;",syntax.curly[pos].index);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ sprintf(label,"goto __FR%x_J;",script->syntax.curly[pos].index);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
// Loop start labeling
- sprintf(label,"__FR%x_BGN",syntax.curly[pos].index);
- l=add_str(label);
- set_label(l,script_pos,p);
+ sprintf(label,"__FR%x_BGN",script->syntax.curly[pos].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
return p;
- }
- else if( p2 - p == 8 && strncasecmp(p,"function",8) == 0 )
- {// internal script function
+ } else if( p2 - p == 8 && strncmp(p, "function", 8) == 0 ) {
+ // internal script function
const char *func_name;
- func_name = skip_space(p2);
- p = skip_word(func_name);
+ func_name = script->skip_space(p2);
+ p = script->skip_word(func_name);
if( p == func_name )
disp_error_message("parse_syntax:function: function name is missing or invalid", p);
- p2 = skip_space(p);
+ p2 = script->skip_space(p);
if( *p2 == ';' )
{// function <name> ;
// function declaration - just register the name
int l;
- l = add_word(func_name);
+ l = script->add_word(func_name);
if( script->str_data[l].type == C_NOP )// register only, if the name was not used by something else
script->str_data[l].type = C_USERFUNC;
else if( script->str_data[l].type == C_USERFUNC )
@@ -1621,7 +1710,7 @@ const char* parse_syntax(const char* p)
disp_error_message("parse_syntax:function: function name is invalid", func_name);
// Close condition of if, for, while
- p = parse_syntax_close(p2 + 1);
+ p = script->parse_syntax_close(p2 + 1);
return p;
}
else if(*p2 == '{')
@@ -1629,118 +1718,136 @@ const char* parse_syntax(const char* p)
char label[256];
int l;
- syntax.curly[syntax.curly_count].type = TYPE_USERFUNC;
- syntax.curly[syntax.curly_count].count = 1;
- syntax.curly[syntax.curly_count].index = syntax.index++;
- syntax.curly[syntax.curly_count].flag = 0;
- ++syntax.curly_count;
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_USERFUNC;
+ script->syntax.curly[script->syntax.curly_count].count = 1;
+ script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++;
+ script->syntax.curly[script->syntax.curly_count].flag = 0;
+ ++script->syntax.curly_count;
// Jump over the function code
- sprintf(label, "goto __FN%x_FIN;", syntax.curly[syntax.curly_count-1].index);
- syntax.curly[syntax.curly_count].type = TYPE_NULL;
- ++syntax.curly_count;
- parse_line(label);
- --syntax.curly_count;
+ sprintf(label, "goto __FN%x_FIN;", script->syntax.curly[script->syntax.curly_count-1].index);
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_NULL;
+ ++script->syntax.curly_count;
+ script->parse_line(label);
+ --script->syntax.curly_count;
// Set the position of the function (label)
- l=add_word(func_name);
+ l=script->add_word(func_name);
if( script->str_data[l].type == C_NOP || script->str_data[l].type == C_USERFUNC )// register only, if the name was not used by something else
{
script->str_data[l].type = C_USERFUNC;
- set_label(l, script_pos, p);
- if( parse_options&SCRIPT_USE_LABEL_DB )
- strdb_iput(scriptlabel_db, get_str(l), script_pos);
+ script->set_label(l, script->pos, p);
+ if( script->parse_options&SCRIPT_USE_LABEL_DB )
+ script->label_add(l,script->pos);
}
else
disp_error_message("parse_syntax:function: function name is invalid", func_name);
- return skip_space(p);
+ return script->skip_space(p);
}
else
{
disp_error_message("expect ';' or '{' at function syntax",p);
}
+#ifdef ENABLE_CASE_CHECK
+ } else if( p2 - p == 3 && strncasecmp(p, "for", 3) == 0 ) {
+ disp_deprecation_message("parse_syntax", "for", p); // TODO
+ } else if( p2 - p == 8 && strncasecmp(p, "function", 8) == 0 ) {
+ disp_deprecation_message("parse_syntax", "function", p); // TODO
+#endif // ENABLE_CASE_CHECK
}
break;
case 'i':
case 'I':
- if(p2 - p == 2 && !strncasecmp(p,"if",2)) {
+ if( p2 - p == 2 && strncmp(p, "if", 2) == 0 ) {
// If process
char label[256];
- p=skip_space(p2);
- if(*p != '(') { //Prevent if this {} non-c syntax. from Rayce (jA)
+ p=script->skip_space(p2);
+ if(*p != '(') { //Prevent if this {} non-c script->syntax. from Rayce (jA)
disp_error_message("need '('",p);
}
- syntax.curly[syntax.curly_count].type = TYPE_IF;
- syntax.curly[syntax.curly_count].count = 1;
- syntax.curly[syntax.curly_count].index = syntax.index++;
- syntax.curly[syntax.curly_count].flag = 0;
- sprintf(label,"__IF%x_%x",syntax.curly[syntax.curly_count].index,syntax.curly[syntax.curly_count].count);
- syntax.curly_count++;
- add_scriptl(add_str("jump_zero"));
- add_scriptc(C_ARG);
- p=parse_expr(p);
- p=skip_space(p);
- add_scriptl(add_str(label));
- add_scriptc(C_FUNC);
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_IF;
+ script->syntax.curly[script->syntax.curly_count].count = 1;
+ script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++;
+ script->syntax.curly[script->syntax.curly_count].flag = 0;
+ sprintf(label,"__IF%x_%x",script->syntax.curly[script->syntax.curly_count].index,script->syntax.curly[script->syntax.curly_count].count);
+ script->syntax.curly_count++;
+ script->addl(script->add_str("jump_zero"));
+ script->addc(C_ARG);
+ p=script->parse_expr(p);
+ p=script->skip_space(p);
+ script->addl(script->add_str(label));
+ script->addc(C_FUNC);
return p;
+#ifdef ENABLE_CASE_CHECK
+ } else if( p2 - p == 2 && strncasecmp(p, "if", 2) == 0 ) {
+ disp_deprecation_message("parse_syntax", "if", p); // TODO
+#endif // ENABLE_CASE_CHECK
}
break;
case 's':
case 'S':
- if(p2 - p == 6 && !strncasecmp(p,"switch",6)) {
+ if( p2 - p == 6 && strncmp(p, "switch", 6) == 0 ) {
// Processing of switch ()
char label[256];
- p=skip_space(p2);
+ p=script->skip_space(p2);
if(*p != '(') {
disp_error_message("need '('",p);
}
- syntax.curly[syntax.curly_count].type = TYPE_SWITCH;
- syntax.curly[syntax.curly_count].count = 1;
- syntax.curly[syntax.curly_count].index = syntax.index++;
- syntax.curly[syntax.curly_count].flag = 0;
- sprintf(label,"$@__SW%x_VAL",syntax.curly[syntax.curly_count].index);
- syntax.curly_count++;
- add_scriptl(add_str("set"));
- add_scriptc(C_ARG);
- add_scriptl(add_str(label));
- p=parse_expr(p);
- p=skip_space(p);
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_SWITCH;
+ script->syntax.curly[script->syntax.curly_count].count = 1;
+ script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++;
+ script->syntax.curly[script->syntax.curly_count].flag = 0;
+ sprintf(label,"$@__SW%x_VAL",script->syntax.curly[script->syntax.curly_count].index);
+ script->syntax.curly_count++;
+ script->addl(script->add_str("set"));
+ script->addc(C_ARG);
+ script->addl(script->add_str(label));
+ p=script->parse_expr(p);
+ p=script->skip_space(p);
if(*p != '{') {
disp_error_message("parse_syntax: need '{'",p);
}
- add_scriptc(C_FUNC);
+ script->addc(C_FUNC);
return p + 1;
+#ifdef ENABLE_CASE_CHECK
+ } else if( p2 - p == 6 && strncasecmp(p, "switch", 6) == 0 ) {
+ disp_deprecation_message("parse_syntax", "switch", p); // TODO
+#endif // ENABLE_CASE_CHECK
}
break;
case 'w':
case 'W':
- if(p2 - p == 5 && !strncasecmp(p,"while",5)) {
+ if( p2 - p == 5 && strncmp(p, "while", 5) == 0 ) {
int l;
char label[256];
- p=skip_space(p2);
+ p=script->skip_space(p2);
if(*p != '(') {
disp_error_message("need '('",p);
}
- syntax.curly[syntax.curly_count].type = TYPE_WHILE;
- syntax.curly[syntax.curly_count].count = 1;
- syntax.curly[syntax.curly_count].index = syntax.index++;
- syntax.curly[syntax.curly_count].flag = 0;
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_WHILE;
+ script->syntax.curly[script->syntax.curly_count].count = 1;
+ script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++;
+ script->syntax.curly[script->syntax.curly_count].flag = 0;
// Form the start of label decision
- sprintf(label,"__WL%x_NXT",syntax.curly[syntax.curly_count].index);
- l=add_str(label);
- set_label(l,script_pos,p);
+ sprintf(label,"__WL%x_NXT",script->syntax.curly[script->syntax.curly_count].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
// Skip to the end point if the condition is false
- sprintf(label,"__WL%x_FIN",syntax.curly[syntax.curly_count].index);
- syntax.curly_count++;
- add_scriptl(add_str("jump_zero"));
- add_scriptc(C_ARG);
- p=parse_expr(p);
- p=skip_space(p);
- add_scriptl(add_str(label));
- add_scriptc(C_FUNC);
+ sprintf(label,"__WL%x_FIN",script->syntax.curly[script->syntax.curly_count].index);
+ script->syntax.curly_count++;
+ script->addl(script->add_str("jump_zero"));
+ script->addc(C_ARG);
+ p=script->parse_expr(p);
+ p=script->skip_space(p);
+ script->addl(script->add_str(label));
+ script->addc(C_FUNC);
return p;
+#ifdef ENABLE_CASE_CHECK
+ } else if( p2 - p == 5 && strncasecmp(p, "while", 5) == 0 ) {
+ disp_deprecation_message("parse_syntax", "while", p); // TODO
+#endif // ENABLE_CASE_CHECK
}
break;
}
@@ -1752,183 +1859,190 @@ const char* parse_syntax_close(const char *p) {
int flag;
do {
- p = parse_syntax_close_sub(p,&flag);
+ p = script->parse_syntax_close_sub(p,&flag);
} while(flag);
return p;
}
// Close judgment if, for, while, of do
-// flag == 1 : closed
-// flag == 0 : not closed
+// flag == 1 : closed
+// flag == 0 : not closed
const char* parse_syntax_close_sub(const char* p,int* flag)
{
char label[256];
- int pos = syntax.curly_count - 1;
+ int pos = script->syntax.curly_count - 1;
int l;
*flag = 1;
- if(syntax.curly_count <= 0) {
+ if(script->syntax.curly_count <= 0) {
*flag = 0;
return p;
- } else if(syntax.curly[pos].type == TYPE_IF) {
+ } else if(script->syntax.curly[pos].type == TYPE_IF) {
const char *bp = p;
const char *p2;
// if-block and else-block end is a new line
- parse_nextline(false, p);
+ script->parse_nextline(false, p);
// Skip to the last location if
- sprintf(label,"goto __IF%x_FIN;",syntax.curly[pos].index);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ sprintf(label,"goto __IF%x_FIN;",script->syntax.curly[pos].index);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
// Put the label of the location
- sprintf(label,"__IF%x_%x",syntax.curly[pos].index,syntax.curly[pos].count);
- l=add_str(label);
- set_label(l,script_pos,p);
-
- syntax.curly[pos].count++;
- p = skip_space(p);
- p2 = skip_word(p);
- if(!syntax.curly[pos].flag && p2 - p == 4 && !strncasecmp(p,"else",4)) {
+ sprintf(label,"__IF%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
+
+ script->syntax.curly[pos].count++;
+ p = script->skip_space(p);
+ p2 = script->skip_word(p);
+ if( !script->syntax.curly[pos].flag && p2 - p == 4 && strncmp(p, "else", 4) == 0 ) {
// else or else - if
- p = skip_space(p2);
- p2 = skip_word(p);
- if(p2 - p == 2 && !strncasecmp(p,"if",2)) {
+ p = script->skip_space(p2);
+ p2 = script->skip_word(p);
+ if( p2 - p == 2 && strncmp(p, "if", 2) == 0 ) {
// else - if
- p=skip_space(p2);
+ p=script->skip_space(p2);
if(*p != '(') {
disp_error_message("need '('",p);
}
- sprintf(label,"__IF%x_%x",syntax.curly[pos].index,syntax.curly[pos].count);
- add_scriptl(add_str("jump_zero"));
- add_scriptc(C_ARG);
- p=parse_expr(p);
- p=skip_space(p);
- add_scriptl(add_str(label));
- add_scriptc(C_FUNC);
+ sprintf(label,"__IF%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count);
+ script->addl(script->add_str("jump_zero"));
+ script->addc(C_ARG);
+ p=script->parse_expr(p);
+ p=script->skip_space(p);
+ script->addl(script->add_str(label));
+ script->addc(C_FUNC);
*flag = 0;
return p;
+#ifdef ENABLE_CASE_CHECK
+ } else if( p2 - p == 2 && strncasecmp(p, "if", 2) == 0 ) {
+ disp_deprecation_message("parse_syntax", "if", p); // TODO
+#endif // ENABLE_CASE_CHECK
} else {
// else
- if(!syntax.curly[pos].flag) {
- syntax.curly[pos].flag = 1;
+ if(!script->syntax.curly[pos].flag) {
+ script->syntax.curly[pos].flag = 1;
*flag = 0;
return p;
}
}
+#ifdef ENABLE_CASE_CHECK
+ } else if( !script->syntax.curly[pos].flag && p2 - p == 4 && strncasecmp(p, "else", 4) == 0 ) {
+ disp_deprecation_message("parse_syntax", "else", p); // TODO
+#endif // ENABLE_CASE_CHECK
}
// Close if
- syntax.curly_count--;
+ script->syntax.curly_count--;
// Put the label of the final location
- sprintf(label,"__IF%x_FIN",syntax.curly[pos].index);
- l=add_str(label);
- set_label(l,script_pos,p);
- if(syntax.curly[pos].flag == 1) {
+ sprintf(label,"__IF%x_FIN",script->syntax.curly[pos].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
+ if(script->syntax.curly[pos].flag == 1) {
// Because the position of the pointer is the same if not else for this
return bp;
}
return p;
- } else if(syntax.curly[pos].type == TYPE_DO) {
- int l;
- char label[256];
+ } else if(script->syntax.curly[pos].type == TYPE_DO) {
const char *p2;
- if(syntax.curly[pos].flag) {
+ if(script->syntax.curly[pos].flag) {
// (Come here continue) to form the label here
- sprintf(label,"__DO%x_NXT",syntax.curly[pos].index);
- l=add_str(label);
- set_label(l,script_pos,p);
+ sprintf(label,"__DO%x_NXT",script->syntax.curly[pos].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
}
// Skip to the end point if the condition is false
- p = skip_space(p);
- p2 = skip_word(p);
- if(p2 - p != 5 || strncasecmp(p,"while",5))
+ p = script->skip_space(p);
+ p2 = script->skip_word(p);
+ if( p2 - p != 5 || strncmp(p, "while", 5) != 0 ) {
+#ifdef ENABLE_CASE_CHECK
+ if( p2 - p == 5 && strncasecmp(p, "while", 5) == 0 ) disp_deprecation_message("parse_syntax", "while", p); // TODO
+#endif // ENABLE_CASE_CHECK
disp_error_message("parse_syntax: need 'while'",p);
+ }
- p = skip_space(p2);
+ p = script->skip_space(p2);
if(*p != '(') {
disp_error_message("need '('",p);
}
// do-block end is a new line
- parse_nextline(false, p);
+ script->parse_nextline(false, p);
- sprintf(label,"__DO%x_FIN",syntax.curly[pos].index);
- add_scriptl(add_str("jump_zero"));
- add_scriptc(C_ARG);
- p=parse_expr(p);
- p=skip_space(p);
- add_scriptl(add_str(label));
- add_scriptc(C_FUNC);
+ sprintf(label,"__DO%x_FIN",script->syntax.curly[pos].index);
+ script->addl(script->add_str("jump_zero"));
+ script->addc(C_ARG);
+ p=script->parse_expr(p);
+ p=script->skip_space(p);
+ script->addl(script->add_str(label));
+ script->addc(C_FUNC);
// Skip to the starting point
- sprintf(label,"goto __DO%x_BGN;",syntax.curly[pos].index);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ sprintf(label,"goto __DO%x_BGN;",script->syntax.curly[pos].index);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
// Form label of the end point conditions
- sprintf(label,"__DO%x_FIN",syntax.curly[pos].index);
- l=add_str(label);
- set_label(l,script_pos,p);
- p = skip_space(p);
+ sprintf(label,"__DO%x_FIN",script->syntax.curly[pos].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
+ p = script->skip_space(p);
if(*p != ';') {
disp_error_message("parse_syntax: need ';'",p);
return p+1;
}
p++;
- syntax.curly_count--;
+ script->syntax.curly_count--;
return p;
- } else if(syntax.curly[pos].type == TYPE_FOR) {
+ } else if(script->syntax.curly[pos].type == TYPE_FOR) {
// for-block end is a new line
- parse_nextline(false, p);
+ script->parse_nextline(false, p);
// Skip to the next loop
- sprintf(label,"goto __FR%x_NXT;",syntax.curly[pos].index);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ sprintf(label,"goto __FR%x_NXT;",script->syntax.curly[pos].index);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
// End for labeling
- sprintf(label,"__FR%x_FIN",syntax.curly[pos].index);
- l=add_str(label);
- set_label(l,script_pos,p);
- syntax.curly_count--;
+ sprintf(label,"__FR%x_FIN",script->syntax.curly[pos].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
+ script->syntax.curly_count--;
return p;
- } else if(syntax.curly[pos].type == TYPE_WHILE) {
+ } else if(script->syntax.curly[pos].type == TYPE_WHILE) {
// while-block end is a new line
- parse_nextline(false, p);
+ script->parse_nextline(false, p);
// Skip to the decision while
- sprintf(label,"goto __WL%x_NXT;",syntax.curly[pos].index);
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ sprintf(label,"goto __WL%x_NXT;",script->syntax.curly[pos].index);
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
// End while labeling
- sprintf(label,"__WL%x_FIN",syntax.curly[pos].index);
- l=add_str(label);
- set_label(l,script_pos,p);
- syntax.curly_count--;
+ sprintf(label,"__WL%x_FIN",script->syntax.curly[pos].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
+ script->syntax.curly_count--;
return p;
- } else if(syntax.curly[syntax.curly_count-1].type == TYPE_USERFUNC) {
- int pos = syntax.curly_count-1;
- char label[256];
- int l;
+ } else if(script->syntax.curly[pos].type == TYPE_USERFUNC) {
// Back
sprintf(label,"return;");
- syntax.curly[syntax.curly_count++].type = TYPE_NULL;
- parse_line(label);
- syntax.curly_count--;
+ script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
+ script->parse_line(label);
+ script->syntax.curly_count--;
// Put the label of the location
- sprintf(label,"__FN%x_FIN",syntax.curly[pos].index);
- l=add_str(label);
- set_label(l,script_pos,p);
- syntax.curly_count--;
+ sprintf(label,"__FN%x_FIN",script->syntax.curly[pos].index);
+ l=script->add_str(label);
+ script->set_label(l,script->pos,p);
+ script->syntax.curly_count--;
return p;
} else {
*flag = 0;
@@ -1939,7 +2053,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
/// Retrieves the value of a constant.
bool script_get_constant(const char* name, int* value)
{
- int n = search_str(name);
+ int n = script->search_str(name);
if( n == -1 || script->str_data[n].type != C_INT )
{// not found or not a constant
@@ -1951,287 +2065,380 @@ bool script_get_constant(const char* name, int* value)
}
/// Creates new constant or parameter with given value.
-void script_set_constant(const char* name, int value, bool isparameter)
-{
- int n = add_str(name);
+void script_set_constant(const char* name, int value, bool isparameter) {
+ int n = script->add_str(name);
- if( script->str_data[n].type == C_NOP )
- {// new
+ if( script->str_data[n].type == C_NOP ) {// new
script->str_data[n].type = isparameter ? C_PARAM : C_INT;
script->str_data[n].val = value;
- }
- else if( script->str_data[n].type == C_PARAM || script->str_data[n].type == C_INT )
- {// existing parameter or constant
+ } else if( script->str_data[n].type == C_PARAM || script->str_data[n].type == C_INT ) {// existing parameter or constant
ShowError("script_set_constant: Attempted to overwrite existing %s '%s' (old value=%d, new value=%d).\n", ( script->str_data[n].type == C_PARAM ) ? "parameter" : "constant", name, script->str_data[n].val, value);
- }
- else
- {// existing name
- ShowError("script_set_constant: Invalid name for %s '%s' (already defined as %s).\n", isparameter ? "parameter" : "constant", name, script_op2name(script->str_data[n].type));
+ } else {// existing name
+ ShowError("script_set_constant: Invalid name for %s '%s' (already defined as %s).\n", isparameter ? "parameter" : "constant", name, script->op2name(script->str_data[n].type));
}
}
+/* adds data to a existent constant in the database, inserted normally via parse */
+void script_set_constant2(const char *name, int value, bool isparameter) {
+ int n = script->add_str(name);
+ if( script->str_data[n].type == C_PARAM ) {
+ ShowError("script_set_constant2: Attempted to overwrite existing parameter '%s' with a constant (value=%d).\n", name, value);
+ return;
+ }
+
+ if( script->str_data[n].type == C_NAME && script->str_data[n].val ) {
+ ShowWarning("script_set_constant2: Attempted to overwrite existing variable '%s' with a constant (value=%d).\n", name, value);
+ return;
+ }
+
+ if( script->str_data[n].type == C_INT && value && value != script->str_data[n].val ) { // existing constant
+ ShowWarning("script_set_constant2: Attempted to overwrite existing constant '%s' (old value=%d, new value=%d).\n", name, script->str_data[n].val, value);
+ return;
+ }
+
+ if( script->str_data[n].type != C_NOP ) {
+ script->str_data[n].func = NULL;
+ script->str_data[n].backpatch = -1;
+ script->str_data[n].label = -1;
+ }
+
+ script->str_data[n].type = isparameter ? C_PARAM : C_INT;
+ script->str_data[n].val = value;
+
+}
/*==========================================
* Reading constant databases
* const.txt
*------------------------------------------*/
-static void read_constdb(void)
-{
+void read_constdb(void) {
FILE *fp;
char line[1024],name[1024],val[1024];
int type;
- sprintf(line, "%s/const.txt", iMap->db_path);
+ sprintf(line, "%s/const.txt", map->db_path);
fp=fopen(line, "r");
- if(fp==NULL){
+ if(fp==NULL) {
ShowError("can't read %s\n", line);
return ;
}
- while(fgets(line, sizeof(line), fp))
- {
- if(line[0]=='/' && line[1]=='/')
+ while (fgets(line, sizeof(line), fp)) {
+ if (line[0] == '/' && line[1] == '/')
continue;
- type=0;
- if(sscanf(line,"%[A-Za-z0-9_],%[-0-9xXA-Fa-f],%d",name,val,&type)>=2 ||
- sscanf(line,"%[A-Za-z0-9_] %[-0-9xXA-Fa-f] %d",name,val,&type)>=2){
- script_set_constant(name, (int)strtol(val, NULL, 0), (bool)type);
+ type = 0;
+ if (sscanf(line, "%1023[A-Za-z0-9_],%1023[-0-9xXA-Fa-f],%d", name, val, &type) >=2
+ || sscanf(line, "%1023[A-Za-z0-9_] %1023[-0-9xXA-Fa-f] %d", name, val, &type) >=2
+ ) {
+ script->set_constant(name, (int)strtol(val, NULL, 0), (bool)type);
}
}
fclose(fp);
}
+// Standard UNIX tab size is 8
+#define TAB_SIZE 8
+#define update_tabstop(tabstop,chars) \
+ do { \
+ (tabstop) -= (chars); \
+ while ((tabstop) <= 0) (tabstop) += TAB_SIZE; \
+ } while (false)
+
/*==========================================
* Display emplacement line of script
*------------------------------------------*/
-static const char* script_print_line(StringBuf* buf, const char* p, const char* mark, int line)
+const char* script_print_line(StringBuf* buf, const char* p, const char* mark, int line)
{
- int i;
+ int i, mark_pos = 0, tabstop = TAB_SIZE;
if( p == NULL || !p[0] ) return NULL;
if( line < 0 )
- StrBuf->Printf(buf, "*% 5d : ", -line);
+ StrBuf->Printf(buf, "*%5d: ", -line); // len = 8
else
- StrBuf->Printf(buf, " % 5d : ", line);
- for(i=0;p[i] && p[i] != '\n';i++){
- if(p + i != mark)
- StrBuf->Printf(buf, "%c", p[i]);
+ StrBuf->Printf(buf, " %5d: ", line); // len = 8
+ update_tabstop(tabstop,8); // len = 8
+ for( i=0; p[i] && p[i] != '\n'; i++ ) {
+ char c = p[i];
+ int w = 1;
+ // Like Clang does, let's print the code with tabs expanded to spaces to ensure that the marker will be under the right character
+ if( c == '\t' ) {
+ c = ' ';
+ w = tabstop;
+ }
+ update_tabstop(tabstop, w);
+ if( p + i < mark)
+ mark_pos += w;
+ if( p + i != mark)
+ StrBuf->Printf(buf, "%*c", w, c);
else
- StrBuf->Printf(buf, "\'%c\'", p[i]);
+ StrBuf->Printf(buf, CL_BT_RED"%*c"CL_RESET, w, c);
}
StrBuf->AppendStr(buf, "\n");
+ if( mark ) {
+ StrBuf->AppendStr(buf, " "CL_BT_CYAN); // len = 8
+ for( ; mark_pos > 0; mark_pos-- ) {
+ StrBuf->AppendStr(buf, "~");
+ }
+ StrBuf->AppendStr(buf, CL_RESET CL_BT_GREEN"^"CL_RESET"\n");
+ }
return p+i+(p[i] == '\n' ? 1 : 0);
}
+#undef TAB_SIZE
+#undef update_tabstop
-void script_error(const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos)
-{
+#define CONTEXTLINES 3
+void script_errorwarning_sub(StringBuf *buf, const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos) {
// Find the line where the error occurred
int j;
int line = start_line;
- const char *p;
- const char *linestart[5] = { NULL, NULL, NULL, NULL, NULL };
- StringBuf buf;
+ const char *p, *error_linepos;
+ const char *linestart[CONTEXTLINES] = { NULL };
- for(p=src;p && *p;line++){
+ for(p=src;p && *p;line++) {
const char *lineend=strchr(p,'\n');
- if(lineend==NULL || error_pos<lineend){
+ if(lineend==NULL || error_pos<lineend) {
break;
}
- for( j = 0; j < 4; j++ ) {
+ for( j = 0; j < CONTEXTLINES-1; j++ ) {
linestart[j] = linestart[j+1];
}
- linestart[4] = p;
- p=lineend+1;
+ linestart[CONTEXTLINES-1] = p;
+ p = lineend+1;
}
+ error_linepos = p;
- StrBuf->Init(&buf);
- StrBuf->AppendStr(&buf, "\a\n");
if( line >= 0 )
- StrBuf->Printf(&buf, "script error on %s line %d\n", file, line);
+ StrBuf->Printf(buf, "script error in file '%s' line %d column %"PRIdPTR"\n", file, line, error_pos-error_linepos+1);
else
- StrBuf->Printf(&buf, "script error on %s item ID %d\n", file, -line);
+ StrBuf->Printf(buf, "script error in file '%s' item ID %d\n", file, -line);
- StrBuf->Printf(&buf, " %s\n", error_msg);
- for(j = 0; j < 5; j++ ) {
- script_print_line(&buf, linestart[j], NULL, line + j - 5);
+ StrBuf->Printf(buf, " %s\n", error_msg);
+ for(j = 0; j < CONTEXTLINES; j++ ) {
+ script->print_line(buf, linestart[j], NULL, line + j - CONTEXTLINES);
}
- p = script_print_line(&buf, p, error_pos, -line);
- for(j = 0; j < 5; j++) {
- p = script_print_line(&buf, p, NULL, line + j + 1 );
+ p = script->print_line(buf, p, error_pos, -line);
+ for(j = 0; j < CONTEXTLINES; j++) {
+ p = script->print_line(buf, p, NULL, line + j + 1 );
}
+}
+#undef CONTEXTLINES
+
+void script_error(const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos) {
+ StringBuf buf;
+
+ StrBuf->Init(&buf);
+ StrBuf->AppendStr(&buf, "\a");
+
+ script->errorwarning_sub(&buf, src, file, start_line, error_msg, error_pos);
+
ShowError("%s", StrBuf->Value(&buf));
StrBuf->Destroy(&buf);
}
+void script_warning(const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos) {
+ StringBuf buf;
+
+ StrBuf->Init(&buf);
+
+ script->errorwarning_sub(&buf, src, file, start_line, error_msg, error_pos);
+
+ ShowWarning("%s", StrBuf->Value(&buf));
+ StrBuf->Destroy(&buf);
+}
+
/*==========================================
* Analysis of the script
*------------------------------------------*/
-struct script_code* parse_script(const char *src,const char *file,int line,int options)
-{
+struct script_code* parse_script(const char *src,const char *file,int line,int options, int *retval) {
const char *p,*tmpp;
int i;
struct script_code* code = NULL;
char end;
bool unresolved_names = false;
+ script->parser_current_src = src;
+ script->parser_current_file = file;
+ script->parser_current_line = line;
+
if( src == NULL )
return NULL;// empty script
- memset(&syntax,0,sizeof(syntax));
+ memset(&script->syntax,0,sizeof(script->syntax));
- script_buf=(unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE*sizeof(unsigned char));
- script_pos=0;
- script_size=SCRIPT_BLOCK_SIZE;
- parse_nextline(true, NULL);
+ script->buf=(unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE*sizeof(unsigned char));
+ script->pos=0;
+ script->size=SCRIPT_BLOCK_SIZE;
+ script->parse_nextline(true, NULL);
// who called parse_script is responsible for clearing the database after using it, but just in case... lets clear it here
if( options&SCRIPT_USE_LABEL_DB )
- db_clear(scriptlabel_db);
- parse_options = options;
+ script->label_count = 0;
+ script->parse_options = options;
- if( setjmp( error_jump ) != 0 ) {
+ if( setjmp( script->error_jump ) != 0 ) {
//Restore program state when script has problems. [from jA]
- int i;
- const int size = ARRAYLENGTH(syntax.curly);
- if( error_report )
- script_error(src,file,line,error_msg,error_pos);
- aFree( error_msg );
- aFree( script_buf );
- script_pos = 0;
- script_size = 0;
- script_buf = NULL;
+ const int size = ARRAYLENGTH(script->syntax.curly);
+ if( script->error_report )
+ script->error(src,file,line,script->error_msg,script->error_pos);
+ aFree( script->error_msg );
+ aFree( script->buf );
+ script->pos = 0;
+ script->size = 0;
+ script->buf = NULL;
for(i=LABEL_START;i<script->str_num;i++)
if(script->str_data[i].type == C_NOP) script->str_data[i].type = C_NAME;
for(i=0; i<size; i++)
- linkdb_final(&syntax.curly[i].case_label);
+ linkdb_final(&script->syntax.curly[i].case_label);
+#ifdef ENABLE_CASE_CHECK
+ script->local_casecheck.clear();
+ script->parser_current_src = NULL;
+ script->parser_current_file = NULL;
+ script->parser_current_line = 0;
+#endif // ENABLE_CASE_CHECK
+ if (retval) *retval = EXIT_FAILURE;
return NULL;
}
- parse_syntax_for_flag=0;
+ script->parse_syntax_for_flag=0;
p=src;
- p=skip_space(p);
+ p=script->skip_space(p);
if( options&SCRIPT_IGNORE_EXTERNAL_BRACKETS )
{// does not require brackets around the script
if( *p == '\0' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) )
{// empty script and can return NULL
- aFree( script_buf );
- script_pos = 0;
- script_size = 0;
- script_buf = NULL;
+ aFree( script->buf );
+ script->pos = 0;
+ script->size = 0;
+ script->buf = NULL;
+#ifdef ENABLE_CASE_CHECK
+ script->local_casecheck.clear();
+ script->parser_current_src = NULL;
+ script->parser_current_file = NULL;
+ script->parser_current_line = 0;
+#endif // ENABLE_CASE_CHECK
return NULL;
}
end = '\0';
}
else
{// requires brackets around the script
- if( *p != '{' )
+ if( *p != '{' ) {
disp_error_message("not found '{'",p);
- p = skip_space(p+1);
+ if (retval) *retval = EXIT_FAILURE;
+ }
+ p = script->skip_space(p+1);
if( *p == '}' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) )
{// empty script and can return NULL
- aFree( script_buf );
- script_pos = 0;
- script_size = 0;
- script_buf = NULL;
+ aFree( script->buf );
+ script->pos = 0;
+ script->size = 0;
+ script->buf = NULL;
+#ifdef ENABLE_CASE_CHECK
+ script->local_casecheck.clear();
+ script->parser_current_src = NULL;
+ script->parser_current_file = NULL;
+ script->parser_current_line = 0;
+#endif // ENABLE_CASE_CHECK
return NULL;
}
end = '}';
}
// clear references of labels, variables and internal functions
- for(i=LABEL_START;i<script->str_num;i++){
+ for(i=LABEL_START;i<script->str_num;i++) {
if(
script->str_data[i].type==C_POS || script->str_data[i].type==C_NAME ||
script->str_data[i].type==C_USERFUNC || script->str_data[i].type == C_USERFUNC_POS
- ){
+ ) {
script->str_data[i].type=C_NOP;
script->str_data[i].backpatch=-1;
script->str_data[i].label=-1;
}
}
- while( syntax.curly_count != 0 || *p != end )
+ while( script->syntax.curly_count != 0 || *p != end )
{
if( *p == '\0' )
disp_error_message("unexpected end of script",p);
// Special handling only label
- tmpp=skip_space(skip_word(p));
- if(*tmpp==':' && !(!strncasecmp(p,"default:",8) && p + 7 == tmpp)){
- i=add_word(p);
- set_label(i,script_pos,p);
- if( parse_options&SCRIPT_USE_LABEL_DB )
- strdb_iput(scriptlabel_db, get_str(i), script_pos);
+ tmpp=script->skip_space(script->skip_word(p));
+ if(*tmpp==':' && !(strncmp(p,"default:",8) == 0 && p + 7 == tmpp)) {
+ i=script->add_word(p);
+ script->set_label(i,script->pos,p);
+ if( script->parse_options&SCRIPT_USE_LABEL_DB )
+ script->label_add(i,script->pos);
p=tmpp+1;
- p=skip_space(p);
+ p=script->skip_space(p);
continue;
}
// All other lumped
- p=parse_line(p);
- p=skip_space(p);
+ p=script->parse_line(p);
+ p=script->skip_space(p);
- parse_nextline(false, p);
+ script->parse_nextline(false, p);
}
- add_scriptc(C_NOP);
+ script->addc(C_NOP);
// trim code to size
- script_size = script_pos;
- RECREATE(script_buf,unsigned char,script_pos);
+ script->size = script->pos;
+ RECREATE(script->buf,unsigned char,script->pos);
// default unknown references to variables
- for(i=LABEL_START;i<script->str_num;i++){
- if(script->str_data[i].type==C_NOP){
+ for(i=LABEL_START;i<script->str_num;i++) {
+ if(script->str_data[i].type==C_NOP) {
int j,next;
script->str_data[i].type=C_NAME;
script->str_data[i].label=i;
- for(j=script->str_data[i].backpatch;j>=0 && j!=0x00ffffff;){
- next=GETVALUE(script_buf,j);
- SETVALUE(script_buf,j,i);
+ for(j=script->str_data[i].backpatch;j>=0 && j!=0x00ffffff;) {
+ next=GETVALUE(script->buf,j);
+ SETVALUE(script->buf,j,i);
j=next;
}
}
else if( script->str_data[i].type == C_USERFUNC )
{// 'function name;' without follow-up code
ShowError("parse_script: function '%s' declared but not defined.\n", script->str_buf+script->str_data[i].str);
+ if (retval) *retval = EXIT_FAILURE;
unresolved_names = true;
}
}
- if( unresolved_names )
- {
+ if( unresolved_names ) {
disp_error_message("parse_script: unresolved function references", p);
+ if (retval) *retval = EXIT_FAILURE;
}
-#ifdef DEBUG_DISP
- for(i=0;i<script_pos;i++){
+#ifdef SCRIPT_DEBUG_DISP
+ for(i=0;i<script->pos;i++) {
if((i&15)==0) ShowMessage("%04x : ",i);
- ShowMessage("%02x ",script_buf[i]);
+ ShowMessage("%02x ",script->buf[i]);
if((i&15)==15) ShowMessage("\n");
}
ShowMessage("\n");
#endif
-#ifdef DEBUG_DISASM
+#ifdef SCRIPT_DEBUG_DISASM
{
int i = 0,j;
- while(i < script_pos) {
- c_op op = get_com(script_buf,&i);
+ while(i < script->pos) {
+ c_op op = script->get_com(script->buf,&i);
- ShowMessage("%06x %s", i, script_op2name(op));
+ ShowMessage("%06x %s", i, script->op2name(op));
j = i;
switch(op) {
case C_INT:
- ShowMessage(" %d", get_num(script_buf,&i));
+ ShowMessage(" %d", script->get_num(script->buf,&i));
break;
case C_POS:
- ShowMessage(" 0x%06x", *(int*)(script_buf+i)&0xffffff);
+ ShowMessage(" 0x%06x", *(int*)(script->buf+i)&0xffffff);
i += 3;
break;
case C_NAME:
- j = (*(int*)(script_buf+i)&0xffffff);
- ShowMessage(" %s", ( j == 0xffffff ) ? "?? unknown ??" : get_str(j));
+ j = (*(int*)(script->buf+i)&0xffffff);
+ ShowMessage(" %s", ( j == 0xffffff ) ? "?? unknown ??" : script->get_str(j));
i += 3;
break;
case C_STR:
- j = strlen(script_buf + i);
- ShowMessage(" %s", script_buf + i);
+ j = strlen((char*)script->buf + i);
+ ShowMessage(" %s", script->buf + i);
i += j+1;
break;
}
@@ -2241,9 +2448,16 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
#endif
CREATE(code,struct script_code,1);
- code->script_buf = script_buf;
- code->script_size = script_size;
- code->script_vars = NULL;
+ code->script_buf = script->buf;
+ code->script_size = script->size;
+ code->local.vars = NULL;
+ code->local.arrays = NULL;
+#ifdef ENABLE_CASE_CHECK
+ script->local_casecheck.clear();
+ script->parser_current_src = NULL;
+ script->parser_current_file = NULL;
+ script->parser_current_line = 0;
+#endif // ENABLE_CASE_CHECK
return code;
}
@@ -2251,28 +2465,30 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
/// If there is no player attached, the script is terminated.
TBL_PC *script_rid2sd(struct script_state *st) {
TBL_PC *sd;
- if( !( sd = iMap->id2sd(st->rid) ) ){
+ if( !( sd = map->id2sd(st->rid) ) ) {
ShowError("script_rid2sd: fatal error ! player not attached!\n");
- script_reportfunc(st);
- script_reportsrc(st);
+ script->reportfunc(st);
+ script->reportsrc(st);
st->state = END;
}
return sd;
}
-/// Dereferences a variable/constant, replacing it with a copy of the value.
-///
-/// @param st Script state
-/// @param data Variable/constant
-void get_val(struct script_state* st, struct script_data* data)
-{
+/**
+ * Dereferences a variable/constant, replacing it with a copy of the value.
+ *
+ * @param st[in] script state.
+ * @param data[in,out] variable/constant.
+ * @return pointer to data, for convenience.
+ */
+struct script_data *get_val(struct script_state* st, struct script_data* data) {
const char* name;
char prefix;
char postfix;
TBL_PC* sd = NULL;
if( !data_isreference(data) )
- return;// not a variable/constant
+ return data;// not a variable/constant
name = reference_getname(data);
prefix = name[0];
@@ -2280,18 +2496,18 @@ void get_val(struct script_state* st, struct script_data* data)
//##TODO use reference_tovariable(data) when it's confirmed that it works [FlavioJS]
if( !reference_toconstant(data) && not_server_variable(prefix) ) {
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL ) {// needs player attached
if( postfix == '$' ) {// string variable
- ShowWarning("script:script->get_val: cannot access player variable '%s', defaulting to \"\"\n", name);
+ ShowWarning("script_get_val: cannot access player variable '%s', defaulting to \"\"\n", name);
data->type = C_CONSTSTR;
data->u.str = "";
} else {// integer variable
- ShowWarning("script:script->get_val: cannot access player variable '%s', defaulting to 0\n", name);
+ ShowWarning("script_get_val: cannot access player variable '%s', defaulting to 0\n", name);
data->type = C_INT;
data->u.num = 0;
}
- return;
+ return data;
}
}
@@ -2302,36 +2518,36 @@ void get_val(struct script_state* st, struct script_data* data)
data->u.str = pc->readregstr(sd, data->u.num);
break;
case '$':
- data->u.str = mapreg_readregstr(data->u.num);
+ data->u.str = mapreg->readregstr(data->u.num);
break;
case '#':
if( name[1] == '#' )
- data->u.str = pc_readaccountreg2str(sd, name);// global
+ data->u.str = pc_readaccountreg2str(sd, data->u.num);// global
else
- data->u.str = pc_readaccountregstr(sd, name);// local
+ data->u.str = pc_readaccountregstr(sd, data->u.num);// local
break;
case '.':
{
- struct DBMap* n =
- data->ref ? *data->ref:
- name[1] == '@' ? st->stack->var_function:// instance/scope variable
- st->script->script_vars;// npc variable
+ struct DBMap* n = data->ref ?
+ data->ref->vars : name[1] == '@' ?
+ st->stack->scope.vars : // instance/scope variable
+ st->script->local.vars; // npc variable
if( n )
- data->u.str = (char*)idb_get(n,reference_getuid(data));
+ data->u.str = (char*)i64db_get(n,reference_getuid(data));
else
data->u.str = NULL;
}
break;
case '\'':
if ( st->instance_id >= 0 ) {
- data->u.str = (char*)idb_get(instances[st->instance_id].vars,reference_getuid(data));
+ data->u.str = (char*)i64db_get(instance->list[st->instance_id].regs.vars, reference_getuid(data));
} else {
- ShowWarning("script:script->get_val: cannot access instance variable '%s', defaulting to \"\"\n", name);
+ ShowWarning("script_get_val: cannot access instance variable '%s', defaulting to \"\"\n", name);
data->u.str = NULL;
}
break;
default:
- data->u.str = pc_readglobalreg_str(sd, name);
+ data->u.str = pc_readglobalreg_str(sd, data->u.num);
break;
}
@@ -2357,106 +2573,362 @@ void get_val(struct script_state* st, struct script_data* data)
data->u.num = pc->readreg(sd, data->u.num);
break;
case '$':
- data->u.num = mapreg_readreg(data->u.num);
+ data->u.num = mapreg->readreg(data->u.num);
break;
case '#':
if( name[1] == '#' )
- data->u.num = pc_readaccountreg2(sd, name);// global
+ data->u.num = pc_readaccountreg2(sd, data->u.num);// global
else
- data->u.num = pc_readaccountreg(sd, name);// local
+ data->u.num = pc_readaccountreg(sd, data->u.num);// local
break;
case '.':
{
- struct DBMap* n =
- data->ref ? *data->ref:
- name[1] == '@' ? st->stack->var_function:// instance/scope variable
- st->script->script_vars;// npc variable
+ struct DBMap* n = data->ref ?
+ data->ref->vars : name[1] == '@' ?
+ st->stack->scope.vars : // instance/scope variable
+ st->script->local.vars; // npc variable
if( n )
- data->u.num = (int)idb_iget(n,reference_getuid(data));
+ data->u.num = (int)i64db_iget(n,reference_getuid(data));
else
data->u.num = 0;
}
break;
case '\'':
if( st->instance_id >= 0 )
- data->u.num = (int)idb_iget(instances[st->instance_id].vars,reference_getuid(data));
+ data->u.num = (int)i64db_iget(instance->list[st->instance_id].regs.vars, reference_getuid(data));
else {
- ShowWarning("script:script->get_val: cannot access instance variable '%s', defaulting to 0\n", name);
+ ShowWarning("script_get_val: cannot access instance variable '%s', defaulting to 0\n", name);
data->u.num = 0;
}
break;
default:
- data->u.num = pc_readglobalreg(sd, name);
+ data->u.num = pc_readglobalreg(sd, data->u.num);
break;
}
}
+ data->ref = NULL;
- return;
+ return data;
}
-/// Retrieves the value of a reference identified by uid (variable, constant, param)
-/// The value is left in the top of the stack and needs to be removed manually.
-void* get_val2(struct script_state* st, int uid, struct DBMap** ref) {
+/**
+ * Retrieves the value of a reference identified by uid (variable, constant, param)
+ *
+ * The value is left in the top of the stack and needs to be removed manually.
+ *
+ * @param st[in] script state.
+ * @param uid[in] reference identifier.
+ * @param ref[in] the container to look up the reference into.
+ * @return the retrieved value of the reference.
+ */
+void* get_val2(struct script_state* st, int64 uid, struct reg_db *ref) {
struct script_data* data;
script->push_val(st->stack, C_NAME, uid, ref);
data = script_getdatatop(st, -1);
script->get_val(st, data);
- return (data->type == C_INT ? (void*)__64BPTRSIZE(data->u.num) : (void*)__64BPTRSIZE(data->u.str));
+ return (data->type == C_INT ? (void*)h64BPTRSIZE((int32)data->u.num) : (void*)h64BPTRSIZE(data->u.str)); // u.num is int32 because it comes from script->get_val
+}
+/**
+ * Because, currently, array members with key 0 are indifferenciable from normal variables, we should ensure its actually in
+ * Will be gone as soon as undefined var feature is implemented
+ **/
+void script_array_ensure_zero(struct script_state *st, struct map_session_data *sd, int64 uid, struct reg_db *ref) {
+ const char *name = script->get_str(script_getvarid(uid));
+ struct reg_db *src = script->array_src(st, sd ? sd : st->rid ? map->id2sd(st->rid) : NULL, name, ref);
+ struct script_array *sa = NULL;
+ bool insert = false;
+
+ if( sd && !st ) /* when sd comes, st isn't available */
+ insert = true;
+ else {
+ if( is_string_variable(name) ) {
+ char* str = (char*)script->get_val2(st, uid, ref);
+ if( str && *str )
+ insert = true;
+ script_removetop(st, -1, 0);
+ } else {
+ int32 num = (int32)h64BPTRSIZE(script->get_val2(st, uid, ref));
+ if( num )
+ insert = true;
+ script_removetop(st, -1, 0);
+ }
+ }
+
+ if( src && src->arrays ) {
+ if( (sa = idb_get(src->arrays, script_getvarid(uid)) ) ) {
+ unsigned int i;
+
+ ARR_FIND(0, sa->size, i, sa->members[i] == 0);
+ if( i != sa->size ) {
+ if( !insert )
+ script->array_remove_member(src,sa,i);
+ return;
+ }
+
+ script->array_add_member(sa,0);
+ } else if( insert ) {
+ script->array_update(src,reference_uid(script_getvarid(uid), 0),false);
+ }
+ }
+}
+/**
+ * Returns array size by ID
+ **/
+unsigned int script_array_size(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) {
+ struct script_array *sa = NULL;
+ struct reg_db *src = script->array_src(st, sd, name, ref);
+
+ if( src && src->arrays )
+ sa = idb_get(src->arrays, script->search_str(name));
+
+ return sa ? sa->size : 0;
+}
+/**
+ * Returns array's highest key (for that awful getarraysize implementation that doesn't really gets the array size)
+ **/
+unsigned int script_array_highest_key(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) {
+ struct script_array *sa = NULL;
+ struct reg_db *src = script->array_src(st, sd, name, ref);
+
+
+ if( src && src->arrays ) {
+ int key = script->add_word(name);
+
+ script->array_ensure_zero(st,sd,reference_uid(key, 0),ref);
+
+ if( ( sa = idb_get(src->arrays, key) ) ) {
+ unsigned int i, highest_key = 0;
+
+ for(i = 0; i < sa->size; i++) {
+ if( sa->members[i] > highest_key )
+ highest_key = sa->members[i];
+ }
+
+ return sa->size ? highest_key + 1 : 0;
+ }
+ }
+
+ return 0;
+}
+int script_free_array_db(DBKey key, DBData *data, va_list ap) {
+ struct script_array *sa = DB->data2ptr(data);
+ aFree(sa->members);
+ ers_free(script->array_ers, sa);
+ return 0;
+}
+/**
+ * Clears script_array and removes it from script->array_db
+ **/
+void script_array_delete(struct reg_db *src, struct script_array *sa) {
+ aFree(sa->members);
+ idb_remove(src->arrays, sa->id);
+ ers_free(script->array_ers, sa);
+}
+/**
+ * Removes a member from a script_array list
+ *
+ * @param idx the index of the member in script_array struct list, not of the actual array member
+ **/
+void script_array_remove_member(struct reg_db *src, struct script_array *sa, unsigned int idx) {
+ unsigned int i, cursor;
+
+ /* its the only member left, no need to do anything other than delete the array data */
+ if( sa->size == 1 ) {
+ script->array_delete(src,sa);
+ return;
+ }
+
+ sa->members[idx] = UINT_MAX;
+
+ for(i = 0, cursor = 0; i < sa->size; i++) {
+ if( sa->members[i] == UINT_MAX )
+ continue;
+ if( i != cursor )
+ sa->members[cursor] = sa->members[i];
+ cursor++;
+ }
+
+ sa->size = cursor;
}
+/**
+ * Appends a new array index to the list in script_array
+ *
+ * @param idx the index of the array member being inserted
+ **/
+void script_array_add_member(struct script_array *sa, unsigned int idx) {
+
+ RECREATE(sa->members, unsigned int, ++sa->size);
+
+ sa->members[sa->size - 1] = idx;
-/*==========================================
+}
+/**
+ * Obtains the source of the array database for this type and scenario
+ * Initializes such database when not yet initialized.
+ **/
+struct reg_db *script_array_src(struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref) {
+ struct reg_db *src = NULL;
+
+ switch( name[0] ) {
+ /* from player */
+ default: /* char reg */
+ case '@':/* temp char reg */
+ case '#':/* account reg */
+ src = &sd->regs;
+ break;
+ case '$':/* map reg */
+ src = &mapreg->regs;
+ break;
+ case '.':/* npc/script */
+ if( ref )
+ src = ref;
+ else
+ src = (name[1] == '@') ? &st->stack->scope : &st->script->local;
+ break;
+ case '\'':/* instance */
+ if( st->instance_id >= 0 ) {
+ src = &instance->list[st->instance_id].regs;
+ }
+ break;
+ }
+
+ if( src ) {
+ if( !src->arrays )
+ src->arrays = idb_alloc(DB_OPT_BASE);
+ return src;
+ }
+
+ return NULL;
+}
+
+/**
+ * Processes a array member modification, and update data accordingly
+ *
+ * @param src[in,out] Variable source database. If the array database doesn't exist, it is created.
+ * @param num[in] Variable ID
+ * @param empty[in] Whether the modified member is empty (needs to be removed)
+ **/
+void script_array_update(struct reg_db *src, int64 num, bool empty) {
+ struct script_array *sa = NULL;
+ int id = script_getvarid(num);
+ unsigned int index = script_getvaridx(num);
+
+ if (!src->arrays) {
+ src->arrays = idb_alloc(DB_OPT_BASE);
+ } else {
+ sa = idb_get(src->arrays, id);
+ }
+
+ if( sa ) {
+ unsigned int i;
+
+ /* search */
+ for(i = 0; i < sa->size; i++) {
+ if( sa->members[i] == index )
+ break;
+ }
+
+ /* if existent */
+ if( i != sa->size ) {
+ /* if empty, we gotta remove it */
+ if( empty ) {
+ script->array_remove_member(src, sa, i);
+ }
+ } else if( !empty ) { /* new entry */
+ script->array_add_member(sa,index);
+ /* we do nothing if its empty, no point in modifying array data for a new empty member */
+ }
+ } else if ( !empty ) {/* we only move to create if not empty */
+ sa = ers_alloc(script->array_ers, struct script_array);
+ sa->id = id;
+ sa->members = NULL;
+ sa->size = 0;
+ script->array_add_member(sa,index);
+ idb_put(src->arrays, id, sa);
+ }
+}
+
+/**
* Stores the value of a script variable
- * Return value is 0 on fail, 1 on success.
+ *
+ * @param st current script state.
+ * @param sd current character data.
+ * @param num variable identifier.
+ * @param name variable name.
+ * @param value new value.
+ * @param ref variable container, in case of a npc/scope variable reference outside the current scope.
+ * @retval 0 failure.
+ * @retval 1 success.
+ *
+ * TODO: return values are screwed up, have been for some time (reaad: years), e.g. some functions return 1 failure and success.
*------------------------------------------*/
-static int set_reg(struct script_state* st, TBL_PC* sd, int num, const char* name, const void* value, struct DBMap** ref)
-{
+int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, const void* value, struct reg_db *ref) {
char prefix = name[0];
+
+ if( is_string_variable(name) ) {// string variable
+ const char *str = (const char*)value;
- if( is_string_variable(name) )
- {// string variable
- const char* str = (const char*)value;
switch (prefix) {
- case '@':
- return pc->setregstr(sd, num, str);
- case '$':
- return mapreg_setregstr(num, str);
- case '#':
- return (name[1] == '#') ?
- pc_setaccountreg2str(sd, name, str) :
- pc_setaccountregstr(sd, name, str);
- case '.':
- {
- struct DBMap* n;
- n = (ref) ? *ref : (name[1] == '@') ? st->stack->var_function : st->script->script_vars;
- if( n ) {
- idb_remove(n, num);
- if (str[0]) idb_put(n, num, aStrdup(str));
+ case '@':
+ pc->setregstr(sd, num, str);
+ return 1;
+ case '$':
+ return mapreg->setregstr(num, str);
+ case '#':
+ return (name[1] == '#') ?
+ pc_setaccountreg2str(sd, num, str) :
+ pc_setaccountregstr(sd, num, str);
+ case '.':
+ {
+ struct reg_db *n = (ref) ? ref : (name[1] == '@') ? &st->stack->scope : &st->script->local;
+ if( n ) {
+ if (str[0]) {
+ i64db_put(n->vars, num, aStrdup(str));
+ if( script_getvaridx(num) )
+ script->array_update(n, num, false);
+ } else {
+ i64db_remove(n->vars, num);
+ if( script_getvaridx(num) )
+ script->array_update(n, num, true);
+ }
+ }
}
- }
- return 1;
- case '\'':
- if( st->instance_id >= 0 ) {
- idb_remove(instances[st->instance_id].vars, num);
- if( str[0] ) idb_put(instances[st->instance_id].vars, num, aStrdup(str));
- }
- return 1;
- default:
- return pc_setglobalreg_str(sd, name, str);
+ return 1;
+ case '\'':
+ if( st->instance_id >= 0 ) {
+ if( str[0] ) {
+ i64db_put(instance->list[st->instance_id].regs.vars, num, aStrdup(str));
+ if( script_getvaridx(num) )
+ script->array_update(&instance->list[st->instance_id].regs, num, false);
+ } else {
+ i64db_remove(instance->list[st->instance_id].regs.vars, num);
+ if( script_getvaridx(num) )
+ script->array_update(&instance->list[st->instance_id].regs, num, true);
+ }
+ } else {
+ ShowError("script_set_reg: cannot write instance variable '%s', NPC not in a instance!\n", name);
+ script_reportsrc(st);
+ }
+ return 1;
+ default:
+ return pc_setglobalreg_str(sd, num, str);
}
- }
- else
- {// integer variable
- int val = (int)__64BPTRSIZE(value);
- if(script->str_data[num&0x00ffffff].type == C_PARAM)
- {
- if( pc->setparam(sd, script->str_data[num&0x00ffffff].val, val) == 0 )
- {
- if( st != NULL )
- {
+ } else {// integer variable
+ // FIXME: This isn't safe, in 32bits systems we're converting a 64bit pointer
+ // to a 32bit int, this will lead to overflows! [Panikon]
+ int val = (int)h64BPTRSIZE(value);
+
+ if(script->str_data[script_getvarid(num)].type == C_PARAM) {
+ if( pc->setparam(sd, script->str_data[script_getvarid(num)].val, val) == 0 ) {
+ if( st != NULL ) {
ShowError("script:set_reg: failed to set param '%s' to %d.\n", name, val);
- script_reportsrc(st);
- st->state = END;
+ script->reportsrc(st);
+ // Instead of just stop the script execution we let the character close
+ // the window if it was open.
+ st->state = (sd->state.dialog) ? CLOSE : END;
+ if( st->state == CLOSE )
+ clif->scriptclose(sd, st->oid);
}
return 0;
}
@@ -2464,46 +2936,59 @@ static int set_reg(struct script_state* st, TBL_PC* sd, int num, const char* nam
}
switch (prefix) {
- case '@':
- return pc->setreg(sd, num, val);
- case '$':
- return mapreg_setreg(num, val);
- case '#':
- return (name[1] == '#') ?
- pc_setaccountreg2(sd, name, val) :
- pc_setaccountreg(sd, name, val);
- case '.':
- {
- struct DBMap* n;
- n = (ref) ? *ref : (name[1] == '@') ? st->stack->var_function : st->script->script_vars;
- if( n ) {
- idb_remove(n, num);
- if( val != 0 )
- idb_iput(n, num, val);
+ case '@':
+ pc->setreg(sd, num, val);
+ return 1;
+ case '$':
+ return mapreg->setreg(num, val);
+ case '#':
+ return (name[1] == '#') ?
+ pc_setaccountreg2(sd, num, val) :
+ pc_setaccountreg(sd, num, val);
+ case '.':
+ {
+ struct reg_db *n = (ref) ? ref : (name[1] == '@') ? &st->stack->scope : &st->script->local;
+ if( n ) {
+ if( val != 0 ) {
+ i64db_iput(n->vars, num, val);
+ if( script_getvaridx(num) )
+ script->array_update(n, num, false);
+ } else {
+ i64db_remove(n->vars, num);
+ if( script_getvaridx(num) )
+ script->array_update(n, num, true);
+ }
+ }
}
- }
- return 1;
- case '\'':
- if( st->instance_id >= 0 ) {
- idb_remove(instances[st->instance_id].vars, num);
- if( val != 0 )
- idb_iput(instances[st->instance_id].vars, num, val);
- }
- return 1;
- default:
- return pc_setglobalreg(sd, name, val);
+ return 1;
+ case '\'':
+ if( st->instance_id >= 0 ) {
+ if( val != 0 ) {
+ i64db_iput(instance->list[st->instance_id].regs.vars, num, val);
+ if( script_getvaridx(num) )
+ script->array_update(&instance->list[st->instance_id].regs, num, false);
+ } else {
+ i64db_remove(instance->list[st->instance_id].regs.vars, num);
+ if( script_getvaridx(num) )
+ script->array_update(&instance->list[st->instance_id].regs, num, true);
+ }
+ } else {
+ ShowError("script_set_reg: cannot write instance variable '%s', NPC not in a instance!\n", name);
+ script_reportsrc(st);
+ }
+ return 1;
+ default:
+ return pc_setglobalreg(sd, num, val);
}
}
}
-int set_var(TBL_PC* sd, char* name, void* val)
-{
- return set_reg(NULL, sd, reference_uid(add_str(name),0), name, val, NULL);
+int set_var(TBL_PC* sd, char* name, void* val) {
+ return script->set_reg(NULL, sd, reference_uid(script->add_str(name),0), name, val, NULL);
}
-void setd_sub(struct script_state *st, TBL_PC *sd, const char *varname, int elem, void *value, struct DBMap **ref)
-{
- set_reg(st, sd, reference_uid(add_str(varname),elem), varname, value, ref);
+void setd_sub(struct script_state *st, TBL_PC *sd, const char *varname, int elem, void *value, struct reg_db *ref) {
+ script->set_reg(st, sd, reference_uid(script->add_str(varname),elem), varname, value, ref);
}
/// Converts the data to a string
@@ -2518,7 +3003,7 @@ const char* conv_str(struct script_state* st, struct script_data* data)
else if( data_isint(data) )
{// int -> string
CREATE(p, char, ITEM_NAME_LENGTH);
- snprintf(p, ITEM_NAME_LENGTH, "%d", data->u.num);
+ snprintf(p, ITEM_NAME_LENGTH, "%"PRId64"", data->u.num);
p[ITEM_NAME_LENGTH-1] = '\0';
data->type = C_STR;
data->u.str = p;
@@ -2532,8 +3017,8 @@ const char* conv_str(struct script_state* st, struct script_data* data)
else
{// unsupported data type
ShowError("script:conv_str: cannot convert to string, defaulting to \"\"\n");
- script_reportdata(data);
- script_reportsrc(st);
+ script->reportdata(data);
+ script->reportsrc(st);
data->type = C_CONSTSTR;
data->u.str = "";
}
@@ -2572,8 +3057,8 @@ int conv_num(struct script_state* st, struct script_data* data) {
num = INT_MAX;
ShowError("script:conv_num: overflow detected, capping to %ld\n", num);
}
- script_reportdata(data);
- script_reportsrc(st);
+ script->reportdata(data);
+ script->reportsrc(st);
}
if( data->type == C_STR )
aFree(p);
@@ -2586,13 +3071,13 @@ int conv_num(struct script_state* st, struct script_data* data) {
else
{// unsupported data type
ShowError("script:conv_num: cannot convert to number, defaulting to 0\n");
- script_reportdata(data);
- script_reportsrc(st);
+ script->reportdata(data);
+ script->reportsrc(st);
data->type = C_INT;
data->u.num = 0;
}
#endif
- return data->u.num;
+ return (int)data->u.num;
}
//
@@ -2609,9 +3094,9 @@ void stack_expand(struct script_stack* stack) {
}
/// Pushes a value into the stack (with reference)
-struct script_data* push_val(struct script_stack* stack, enum c_op type, int val, struct DBMap** ref) {
+struct script_data* push_val(struct script_stack* stack, enum c_op type, int64 val, struct reg_db *ref) {
if( stack->sp >= stack->sp_max )
- stack_expand(stack);
+ script->stack_expand(stack);
stack->stack_data[stack->sp].type = type;
stack->stack_data[stack->sp].u.num = val;
stack->stack_data[stack->sp].ref = ref;
@@ -2623,7 +3108,7 @@ struct script_data* push_val(struct script_stack* stack, enum c_op type, int val
struct script_data* push_str(struct script_stack* stack, enum c_op type, char* str)
{
if( stack->sp >= stack->sp_max )
- stack_expand(stack);
+ script->stack_expand(stack);
stack->stack_data[stack->sp].type = type;
stack->stack_data[stack->sp].u.str = str;
stack->stack_data[stack->sp].ref = NULL;
@@ -2632,10 +3117,9 @@ struct script_data* push_str(struct script_stack* stack, enum c_op type, char* s
}
/// Pushes a retinfo into the stack
-struct script_data* push_retinfo(struct script_stack* stack, struct script_retinfo* ri, DBMap **ref)
-{
+struct script_data* push_retinfo(struct script_stack* stack, struct script_retinfo* ri, struct reg_db *ref) {
if( stack->sp >= stack->sp_max )
- stack_expand(stack);
+ script->stack_expand(stack);
stack->stack_data[stack->sp].type = C_RETINFO;
stack->stack_data[stack->sp].u.ri = ri;
stack->stack_data[stack->sp].ref = ref;
@@ -2668,8 +3152,7 @@ struct script_data* push_copy(struct script_stack* stack, int pos) {
/// Removes the values in indexes [start,end[ from the stack.
/// Adjusts all stack pointers.
-void pop_stack(struct script_state* st, int start, int end)
-{
+void pop_stack(struct script_state* st, int start, int end) {
struct script_stack* stack = st->stack;
struct script_data* data;
int i;
@@ -2690,8 +3173,18 @@ void pop_stack(struct script_state* st, int start, int end)
if( data->type == C_RETINFO )
{
struct script_retinfo* ri = data->u.ri;
- if( ri->var_function )
- script_free_vars(ri->var_function);
+ if( ri->scope.vars ) {
+ // Note: This is necessary evern if we're also doing it in run_func
+ // (in the RETFUNC block) because not all functions return. If a
+ // function (or a sub) has an 'end' or a 'close', it'll reach this
+ // block with its scope vars still to be freed.
+ script->free_vars(ri->scope.vars);
+ ri->scope.vars = NULL;
+ }
+ if( ri->scope.arrays ) {
+ ri->scope.arrays->destroy(ri->scope.arrays,script->array_free_db);
+ ri->scope.arrays = NULL;
+ }
if( data->ref )
aFree(data->ref);
aFree(ri);
@@ -2706,12 +3199,18 @@ void pop_stack(struct script_state* st, int start, int end)
stack->stack_data[i].type = C_NOP;
}
// adjust stack pointers
- if( st->start > end ) st->start -= end - start;
- else if( st->start > start ) st->start = start;
- if( st->end > end ) st->end -= end - start;
- else if( st->end > start ) st->end = start;
- if( stack->defsp > end ) stack->defsp -= end - start;
- else if( stack->defsp > start ) stack->defsp = start;
+ if( st->start > end )
+ st->start -= end - start;
+ else if( st->start > start )
+ st->start = start;
+ if( st->end > end )
+ st->end -= end - start;
+ else if( st->end > start )
+ st->end = start;
+ if( stack->defsp > end )
+ stack->defsp -= end - start;
+ else if( stack->defsp > start )
+ stack->defsp = start;
stack->sp -= end - start;
}
@@ -2722,17 +3221,24 @@ void pop_stack(struct script_state* st, int start, int end)
/*==========================================
* Release script dependent variable, dependent variable of function
*------------------------------------------*/
-void script_free_vars(struct DBMap* storage)
-{
- if( storage )
- {// destroy the storage construct containing the variables
- db_destroy(storage);
+void script_free_vars(struct DBMap* var_storage) {
+ if( var_storage ) {
+ // destroy the storage construct containing the variables
+ db_destroy(var_storage);
}
}
void script_free_code(struct script_code* code)
{
- script_free_vars( code->script_vars );
+ nullpo_retv(code);
+
+ if( code->instances )
+ script->stop_instances(code);
+ else {
+ script->free_vars(code->local.vars);
+ if( code->local.arrays )
+ code->local.arrays->destroy(code->local.arrays,script->array_free_db);
+ }
aFree( code->script_buf );
aFree( code );
}
@@ -2746,14 +3252,17 @@ void script_free_code(struct script_code* code)
/// @return Script state
struct script_state* script_alloc_state(struct script_code* rootscript, int pos, int rid, int oid) {
struct script_state* st;
-
+
st = ers_alloc(script->st_ers, struct script_state);
st->stack = ers_alloc(script->stack_ers, struct script_stack);
+ st->pending_refs = NULL;
+ st->pending_ref_count = 0;
st->stack->sp = 0;
st->stack->sp_max = 64;
CREATE(st->stack->stack_data, struct script_data, st->stack->sp_max);
st->stack->defsp = st->stack->sp;
- st->stack->var_function = idb_alloc(DB_OPT_RELEASE_DATA);
+ st->stack->scope.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+ st->stack->scope.arrays = NULL;
st->state = RUN;
st->script = rootscript;
st->pos = pos;
@@ -2762,91 +3271,125 @@ struct script_state* script_alloc_state(struct script_code* rootscript, int pos,
st->sleep.timer = INVALID_TIMER;
st->npc_item_flag = battle_config.item_enabled_npc;
- if( !st->script->script_vars )
- st->script->script_vars = idb_alloc(DB_OPT_RELEASE_DATA);
-
+ if( st->script->instances != USHRT_MAX )
+ st->script->instances++;
+ else {
+ struct npc_data *nd = map->id2nd(oid);
+ ShowError("over 65k instances of '%s' script are being run\n",nd ? nd->name : "unknown");
+ }
+
+ if( !st->script->local.vars )
+ st->script->local.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+
st->id = script->next_id++;
script->active_scripts++;
idb_put(script->st_db, st->id, st);
-
+
return st;
}
/// Frees a script state.
///
/// @param st Script state
-void script_free_state(struct script_state* st)
-{
- if(st->bk_st) {// backup was not restored
- ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid);
- }
+void script_free_state(struct script_state* st) {
+ if( idb_exists(script->st_db,st->id) ) {
+ struct map_session_data *sd = st->rid ? map->id2sd(st->rid) : NULL;
+
+ if(st->bk_st) {// backup was not restored
+ ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid);
+ }
+
+ if(sd && sd->st == st) { //Current script is aborted.
+ if(sd->state.using_fake_npc){
+ clif->clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
+ sd->state.using_fake_npc = 0;
+ }
+ sd->st = NULL;
+ sd->npc_id = 0;
+ }
- if( st->sleep.timer != INVALID_TIMER )
- iTimer->delete_timer(st->sleep.timer, run_script_timer);
- script_free_vars(st->stack->var_function);
- script->pop_stack(st, 0, st->stack->sp);
- aFree(st->stack->stack_data);
- ers_free(script->stack_ers, st->stack);
- if( st->script && st->script->script_vars && !db_size(st->script->script_vars) ) {
- script_free_vars(st->script->script_vars);
- st->script->script_vars = NULL;
- }
- st->stack = NULL;
- st->pos = -1;
- idb_remove(script->st_db, st->id);
- ers_free(script->st_ers, st);
- if( --script->active_scripts == 0 ) {
- script->next_id = 0;
+ if( st->sleep.timer != INVALID_TIMER )
+ timer->delete(st->sleep.timer, script->run_timer);
+ if( st->stack ) {
+ script->free_vars(st->stack->scope.vars);
+ if( st->stack->scope.arrays )
+ st->stack->scope.arrays->destroy(st->stack->scope.arrays,script->array_free_db);
+ script->pop_stack(st, 0, st->stack->sp);
+ aFree(st->stack->stack_data);
+ ers_free(script->stack_ers, st->stack);
+ st->stack = NULL;
+ }
+ if( st->script && st->script->instances != USHRT_MAX && --st->script->instances == 0 ) {
+ if( st->script->local.vars && !db_size(st->script->local.vars) ) {
+ script->free_vars(st->script->local.vars);
+ st->script->local.vars = NULL;
+ }
+ if( st->script->local.arrays && !db_size(st->script->local.arrays) ) {
+ st->script->local.arrays->destroy(st->script->local.arrays,script->array_free_db);
+ st->script->local.arrays = NULL;
+ }
+ }
+ st->pos = -1;
+ if (st->pending_ref_count > 0) {
+ while (st->pending_ref_count > 0)
+ aFree(st->pending_refs[--st->pending_ref_count]);
+ aFree(st->pending_refs);
+ st->pending_refs = NULL;
+ }
+ idb_remove(script->st_db, st->id);
+ ers_free(script->st_ers, st);
+ if( --script->active_scripts == 0 ) {
+ script->next_id = 0;
+ }
}
}
+/**
+ * Adds a pending reference entry to the current script.
+ *
+ * @see struct script_state::pending_refs
+ *
+ * @param st[in] Script state.
+ * @param ref[in] Reference to be added.
+ */
+void script_add_pending_ref(struct script_state *st, struct reg_db *ref) {
+ RECREATE(st->pending_refs, struct reg_db*, ++st->pending_ref_count);
+ st->pending_refs[st->pending_ref_count-1] = ref;
+}
+
//
// Main execution unit
//
/*==========================================
* Read command
*------------------------------------------*/
-c_op get_com(unsigned char *script,int *pos)
+c_op get_com(unsigned char *scriptbuf,int *pos)
{
int i = 0, j = 0;
- if(script[*pos]>=0x80){
+ if(scriptbuf[*pos]>=0x80) {
return C_INT;
}
- while(script[*pos]>=0x40){
- i=script[(*pos)++]<<j;
+ while(scriptbuf[*pos]>=0x40) {
+ i=scriptbuf[(*pos)++]<<j;
j+=6;
}
- return (c_op)(i+(script[(*pos)++]<<j));
+ return (c_op)(i+(scriptbuf[(*pos)++]<<j));
}
/*==========================================
* Income figures
*------------------------------------------*/
-int get_num(unsigned char *script,int *pos)
+int get_num(unsigned char *scriptbuf,int *pos)
{
int i,j;
i=0; j=0;
- while(script[*pos]>=0xc0){
- i+=(script[(*pos)++]&0x7f)<<j;
+ while(scriptbuf[*pos]>=0xc0) {
+ i+=(scriptbuf[(*pos)++]&0x7f)<<j;
j+=6;
}
- return i+((script[(*pos)++]&0x7f)<<j);
-}
-
-/*==========================================
- * Remove the value from the stack
- *------------------------------------------*/
-int pop_val(struct script_state* st)
-{
- if(st->stack->sp<=0)
- return 0;
- st->stack->sp--;
- script->get_val(st,&(st->stack->stack_data[st->stack->sp]));
- if(st->stack->stack_data[st->stack->sp].type==C_INT)
- return st->stack->stack_data[st->stack->sp].u.num;
- return 0;
+ return i+((scriptbuf[(*pos)++]&0x7f)<<j);
}
/// Ternary operators
@@ -2862,12 +3405,12 @@ void op_3(struct script_state* st, int op)
if( data_isstring(data) )
flag = data->u.str[0];// "" -> false
else if( data_isint(data) )
- flag = data->u.num;// 0 -> false
+ flag = data->u.num == 0 ? 0 : 1;// 0 -> false
else
{
ShowError("script:op_3: invalid data for the ternary operator test\n");
- script_reportdata(data);
- script_reportsrc(st);
+ script->reportdata(data);
+ script->reportsrc(st);
script_removetop(st, -3, 0);
script_pushnil(st);
return;
@@ -2886,18 +3429,86 @@ void op_3(struct script_state* st, int op)
/// s1 GE s2 -> i
/// s1 LT s2 -> i
/// s1 LE s2 -> i
+/// s1 RE_EQ s2 -> i
+/// s1 RE_NE s2 -> i
/// s1 ADD s2 -> s
void op_2str(struct script_state* st, int op, const char* s1, const char* s2)
{
int a = 0;
- switch(op){
+ switch(op) {
case C_EQ: a = (strcmp(s1,s2) == 0); break;
case C_NE: a = (strcmp(s1,s2) != 0); break;
case C_GT: a = (strcmp(s1,s2) > 0); break;
case C_GE: a = (strcmp(s1,s2) >= 0); break;
case C_LT: a = (strcmp(s1,s2) < 0); break;
case C_LE: a = (strcmp(s1,s2) <= 0); break;
+#ifdef PCRE_SUPPORT
+ case C_RE_EQ:
+ case C_RE_NE:
+ {
+ int inputlen = (int)strlen(s1);
+ pcre *compiled_regex;
+ pcre_extra *extra_regex;
+ const char *pcre_error, *pcre_match;
+ int pcre_erroroffset, offsetcount, i;
+ int offsets[256*3]; // (max_capturing_groups+1)*3
+
+ compiled_regex = libpcre->compile(s2, 0, &pcre_error, &pcre_erroroffset, NULL);
+
+ if( compiled_regex == NULL ) {
+ ShowError("script:op2_str: Invalid regex '%s'.\n", s2);
+ script->reportsrc(st);
+ script_pushnil(st);
+ st->state = END;
+ return;
+ }
+
+ extra_regex = libpcre->study(compiled_regex, 0, &pcre_error);
+
+ if( pcre_error != NULL ) {
+ libpcre->free(compiled_regex);
+ ShowError("script:op2_str: Unable to optimize the regex '%s': %s\n", s2, pcre_error);
+ script->reportsrc(st);
+ script_pushnil(st);
+ st->state = END;
+ return;
+ }
+
+ offsetcount = libpcre->exec(compiled_regex, extra_regex, s1, inputlen, 0, 0, offsets, 256*3);
+
+ if( offsetcount == 0 ) {
+ offsetcount = 256;
+ } else if( offsetcount == PCRE_ERROR_NOMATCH ) {
+ offsetcount = 0;
+ } else if( offsetcount < 0 ) {
+ libpcre->free(compiled_regex);
+ if( extra_regex != NULL )
+ libpcre->free(extra_regex);
+ ShowWarning("script:op2_str: Unable to process the regex '%s'.\n", s2);
+ script->reportsrc(st);
+ script_pushnil(st);
+ st->state = END;
+ return;
+ }
+
+ if( op == C_RE_EQ ) {
+ for( i = 0; i < offsetcount; i++ ) {
+ libpcre->get_substring(s1, offsets, offsetcount, i, &pcre_match);
+ mapreg->setregstr(reference_uid(script->add_str("$@regexmatch$"), i), pcre_match);
+ libpcre->free_substring(pcre_match);
+ }
+ mapreg->setreg(script->add_str("$@regexmatchcount"), i);
+ a = offsetcount;
+ } else { // C_RE_NE
+ a = (offsetcount == 0);
+ }
+ libpcre->free(compiled_regex);
+ if( extra_regex != NULL )
+ libpcre->free(extra_regex);
+ }
+ break;
+#endif // PCRE_SUPPORT
case C_ADD:
{
char* buf = (char *)aMalloc((strlen(s1)+strlen(s2)+1)*sizeof(char));
@@ -2907,8 +3518,8 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2)
return;
}
default:
- ShowError("script:op2_str: unexpected string operator %s\n", script_op2name(op));
- script_reportsrc(st);
+ ShowError("script:op2_str: unexpected string operator %s\n", script->op2name(op));
+ script->reportsrc(st);
script_pushnil(st);
st->state = END;
return;
@@ -2924,27 +3535,26 @@ void op_2num(struct script_state* st, int op, int i1, int i2)
int ret;
double ret_double;
- switch( op )
- {
- case C_AND: ret = i1 & i2; break;
- case C_OR: ret = i1 | i2; break;
- case C_XOR: ret = i1 ^ i2; break;
- case C_LAND: ret = (i1 && i2); break;
- case C_LOR: ret = (i1 || i2); break;
- case C_EQ: ret = (i1 == i2); break;
- case C_NE: ret = (i1 != i2); break;
- case C_GT: ret = (i1 > i2); break;
- case C_GE: ret = (i1 >= i2); break;
- case C_LT: ret = (i1 < i2); break;
- case C_LE: ret = (i1 <= i2); break;
- case C_R_SHIFT: ret = i1>>i2; break;
- case C_L_SHIFT: ret = i1<<i2; break;
+ switch( op ) {
+ case C_AND: ret = i1 & i2; break;
+ case C_OR: ret = i1 | i2; break;
+ case C_XOR: ret = i1 ^ i2; break;
+ case C_LAND: ret = (i1 && i2); break;
+ case C_LOR: ret = (i1 || i2); break;
+ case C_EQ: ret = (i1 == i2); break;
+ case C_NE: ret = (i1 != i2); break;
+ case C_GT: ret = (i1 > i2); break;
+ case C_GE: ret = (i1 >= i2); break;
+ case C_LT: ret = (i1 < i2); break;
+ case C_LE: ret = (i1 <= i2); break;
+ case C_R_SHIFT: ret = i1>>i2; break;
+ case C_L_SHIFT: ret = i1<<i2; break;
case C_DIV:
case C_MOD:
if( i2 == 0 )
{
- ShowError("script:op_2num: division by zero detected op=%s i1=%d i2=%d\n", script_op2name(op), i1, i2);
- script_reportsrc(st);
+ ShowError("script:op_2num: division by zero detected op=%s i1=%d i2=%d\n", script->op2name(op), i1, i2);
+ script->reportsrc(st);
script_pushnil(st);
st->state = END;
return;
@@ -2961,21 +3571,21 @@ void op_2num(struct script_state* st, int op, int i1, int i2)
case C_SUB: ret = i1 - i2; ret_double = (double)i1 - (double)i2; break;
case C_MUL: ret = i1 * i2; ret_double = (double)i1 * (double)i2; break;
default:
- ShowError("script:op_2num: unexpected number operator %s i1=%d i2=%d\n", script_op2name(op), i1, i2);
- script_reportsrc(st);
+ ShowError("script:op_2num: unexpected number operator %s i1=%d i2=%d\n", script->op2name(op), i1, i2);
+ script->reportsrc(st);
script_pushnil(st);
return;
}
if( ret_double < (double)INT_MIN )
{
- ShowWarning("script:op_2num: underflow detected op=%s i1=%d i2=%d\n", script_op2name(op), i1, i2);
- script_reportsrc(st);
+ ShowWarning("script:op_2num: underflow detected op=%s i1=%d i2=%d\n", script->op2name(op), i1, i2);
+ script->reportsrc(st);
ret = INT_MIN;
}
else if( ret_double > (double)INT_MAX )
{
- ShowWarning("script:op_2num: overflow detected op=%s i1=%d i2=%d\n", script_op2name(op), i1, i2);
- script_reportsrc(st);
+ ShowWarning("script:op_2num: overflow detected op=%s i1=%d i2=%d\n", script->op2name(op), i1, i2);
+ script->reportsrc(st);
ret = INT_MAX;
}
}
@@ -3021,32 +3631,33 @@ void op_2(struct script_state *st, int op)
if( data_isstring(left) && data_isstring(right) )
{// ss => op_2str
- op_2str(st, op, left->u.str, right->u.str);
+ script->op_2str(st, op, left->u.str, right->u.str);
script_removetop(st, leftref.type == C_NOP ? -3 : -2, -1);// pop the two values before the top one
if (leftref.type != C_NOP)
{
- aFree(left->u.str);
+ if (left->type == C_STR) // don't free C_CONSTSTR
+ aFree(left->u.str);
*left = leftref;
}
}
else if( data_isint(left) && data_isint(right) )
{// ii => op_2num
- int i1 = left->u.num;
- int i2 = right->u.num;
+ int i1 = (int)left->u.num;
+ int i2 = (int)right->u.num;
script_removetop(st, leftref.type == C_NOP ? -2 : -1, 0);
- op_2num(st, op, i1, i2);
+ script->op_2num(st, op, i1, i2);
if (leftref.type != C_NOP)
*left = leftref;
}
else
{// invalid argument
- ShowError("script:op_2: invalid data for operator %s\n", script_op2name(op));
- script_reportdata(left);
- script_reportdata(right);
- script_reportsrc(st);
+ ShowError("script:op_2: invalid data for operator %s\n", script->op2name(op));
+ script->reportdata(left);
+ script->reportdata(right);
+ script->reportsrc(st);
script_removetop(st, -2, 0);
script_pushnil(st);
st->state = END;
@@ -3067,27 +3678,26 @@ void op_1(struct script_state* st, int op)
if( !data_isint(data) )
{// not a number
- ShowError("script:op_1: argument is not a number (op=%s)\n", script_op2name(op));
- script_reportdata(data);
- script_reportsrc(st);
+ ShowError("script:op_1: argument is not a number (op=%s)\n", script->op2name(op));
+ script->reportdata(data);
+ script->reportsrc(st);
script_pushnil(st);
st->state = END;
return;
}
- i1 = data->u.num;
+ i1 = (int)data->u.num;
script_removetop(st, -1, 0);
- switch( op )
- {
- case C_NEG: i1 = -i1; break;
- case C_NOT: i1 = ~i1; break;
- case C_LNOT: i1 = !i1; break;
- default:
- ShowError("script:op_1: unexpected operator %s i1=%d\n", script_op2name(op), i1);
- script_reportsrc(st);
- script_pushnil(st);
- st->state = END;
- return;
+ switch( op ) {
+ case C_NEG: i1 = -i1; break;
+ case C_NOT: i1 = ~i1; break;
+ case C_LNOT: i1 = !i1; break;
+ default:
+ ShowError("script:op_1: unexpected operator %s i1=%d\n", script->op2name(op), i1);
+ script->reportsrc(st);
+ script_pushnil(st);
+ st->state = END;
+ return;
}
script_pushint(st, i1);
}
@@ -3097,7 +3707,7 @@ void op_1(struct script_state* st, int op)
///
/// @param st Script state whose stack arguments should be inspected.
/// @param func Built-in function for which the arguments are intended.
-static void script_check_buildin_argtype(struct script_state* st, int func)
+void script_check_buildin_argtype(struct script_state* st, int func)
{
char type;
int idx, invalid = 0;
@@ -3107,11 +3717,11 @@ static void script_check_buildin_argtype(struct script_state* st, int func)
struct script_data* data = script_getdata(st, idx);
type = sf[idx-2];
-
+
if( type == '?' || type == '*' ) {// optional argument or unknown number of optional parameters ( no types are after this )
break;
} else if( type == 0 ) {// more arguments than necessary ( should not happen, as it is checked before )
- ShowWarning("Found more arguments than necessary. unexpected arg type %s\n",script_op2name(data->type));
+ ShowWarning("Found more arguments than necessary. unexpected arg type %s\n",script->op2name(data->type));
invalid++;
break;
} else {
@@ -3127,7 +3737,7 @@ static void script_check_buildin_argtype(struct script_state* st, int func)
if( !data_isstring(data) && !data_isint(data) && !data_isreference(data) )
{// variant
ShowWarning("Unexpected type for argument %d. Expected string, number or variable.\n", idx-1);
- script_reportdata(data);
+ script->reportdata(data);
invalid++;
}
break;
@@ -3135,7 +3745,7 @@ static void script_check_buildin_argtype(struct script_state* st, int func)
if( !data_isstring(data) && !( data_isreference(data) && is_string_variable(name) ) )
{// string
ShowWarning("Unexpected type for argument %d. Expected string.\n", idx-1);
- script_reportdata(data);
+ script->reportdata(data);
invalid++;
}
break;
@@ -3143,23 +3753,23 @@ static void script_check_buildin_argtype(struct script_state* st, int func)
if( !data_isint(data) && !( data_isreference(data) && ( reference_toparam(data) || reference_toconstant(data) || !is_string_variable(name) ) ) )
{// int ( params and constants are always int )
ShowWarning("Unexpected type for argument %d. Expected number.\n", idx-1);
- script_reportdata(data);
+ script->reportdata(data);
invalid++;
}
break;
case 'r':
- if( !data_isreference(data) )
+ if( !data_isreference(data) || reference_toconstant(data) )
{// variables
- ShowWarning("Unexpected type for argument %d. Expected variable, got %s.\n", idx-1,script_op2name(data->type));
- script_reportdata(data);
+ ShowWarning("Unexpected type for argument %d. Expected variable, got %s.\n", idx-1,script->op2name(data->type));
+ script->reportdata(data);
invalid++;
}
break;
case 'l':
if( !data_islabel(data) && !data_isfunclabel(data) )
{// label
- ShowWarning("Unexpected type for argument %d. Expected label, got %s\n", idx-1,script_op2name(data->type));
- script_reportdata(data);
+ ShowWarning("Unexpected type for argument %d. Expected label, got %s\n", idx-1,script->op2name(data->type));
+ script->reportdata(data);
invalid++;
}
break;
@@ -3168,8 +3778,8 @@ static void script_check_buildin_argtype(struct script_state* st, int func)
}
if(invalid) {
- ShowDebug("Function: %s\n", get_str(func));
- script_reportsrc(st);
+ ShowDebug("Function: %s\n", script->get_str(func));
+ script->reportsrc(st);
}
}
@@ -3189,7 +3799,7 @@ int run_func(struct script_state *st)
{
ShowError("script:run_func: C_ARG not found. please report this!!!\n");
st->state = END;
- script_reportsrc(st);
+ script->reportsrc(st);
return 1;
}
start_sp = i-1;// C_NAME of the command
@@ -3198,27 +3808,27 @@ int run_func(struct script_state *st)
data = &st->stack->stack_data[st->start];
if( data->type == C_NAME && script->str_data[data->u.num].type == C_FUNC )
- func = data->u.num;
+ func = (int)data->u.num;
else
{
ShowError("script:run_func: not a buildin command.\n");
- script_reportdata(data);
- script_reportsrc(st);
+ script->reportdata(data);
+ script->reportsrc(st);
st->state = END;
return 1;
}
- if( script_config.warn_func_mismatch_argtypes )
- {
- script_check_buildin_argtype(st, func);
+ if( script->config.warn_func_mismatch_argtypes ) {
+ script->check_buildin_argtype(st, func);
}
- if(script->str_data[func].func){
+ if(script->str_data[func].func) {
if (!(script->str_data[func].func(st))) //Report error
- script_reportsrc(st);
+ script->reportsrc(st);
} else {
- ShowError("script:run_func: '%s' (id=%d type=%s) has no C function. please report this!!!\n", get_str(func), func, script_op2name(script->str_data[func].type));
- script_reportsrc(st);
+ ShowError("script:run_func: '%s' (id=%d type=%s) has no C function. please report this!!!\n",
+ script->get_str(func), func, script->op2name(script->str_data[func].type));
+ script->reportsrc(st);
st->state = END;
}
@@ -3237,17 +3847,19 @@ int run_func(struct script_state *st)
if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp-1].type != C_RETINFO )
{
ShowWarning("script:run_func: return without callfunc or callsub!\n");
- script_reportsrc(st);
+ script->reportsrc(st);
st->state = END;
return 1;
}
- script_free_vars( st->stack->var_function );
+ script->free_vars(st->stack->scope.vars);
+ st->stack->scope.arrays->destroy(st->stack->scope.arrays,script->array_free_db);
ri = st->stack->stack_data[st->stack->defsp-1].u.ri;
nargs = ri->nargs;
st->pos = ri->pos;
st->script = ri->script;
- st->stack->var_function = ri->var_function;
+ st->stack->scope.vars = ri->scope.vars;
+ st->stack->scope.arrays = ri->scope.arrays;
st->stack->defsp = ri->defsp;
memset(ri, 0, sizeof(struct script_retinfo));
@@ -3267,48 +3879,50 @@ void run_script(struct script_code *rootscript,int pos,int rid,int oid) {
if( rootscript == NULL || pos < 0 )
return;
-
+
// TODO In jAthena, this function can take over the pending script in the player. [FlavioJS]
// It is unclear how that can be triggered, so it needs the be traced/checked in more detail.
// NOTE At the time of this change, this function wasn't capable of taking over the script state because st->scriptroot was never set.
- st = script_alloc_state(rootscript, pos, rid, oid);
-
- run_script_main(st);
+ st = script->alloc_state(rootscript, pos, rid, oid);
+
+ script->run_main(st);
}
-void script_stop_instances(int id) {
+void script_stop_instances(struct script_code *code) {
DBIterator *iter;
struct script_state* st;
-
+
if( !script->active_scripts )
return;//dont even bother.
-
+
iter = db_iterator(script->st_db);
-
+
for( st = dbi_first(iter); dbi_exists(iter); st = dbi_next(iter) ) {
- if( st->oid == id ) {
- script_free_state(st);
+ if( st->script == code ) {
+ script->free_state(st);
}
}
-
+
dbi_destroy(iter);
}
/*==========================================
* Timer function for sleep
*------------------------------------------*/
-int run_script_timer(int tid, unsigned int tick, int id, intptr_t data) {
- struct script_state *st = (struct script_state *)data;
- TBL_PC *sd = iMap->id2sd(st->rid);
+int run_script_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct script_state *st = idb_get(script->st_db,(int)data);
+ if( st ) {
+ TBL_PC *sd = map->id2sd(st->rid);
- if((sd && sd->status.char_id != id) || (st->rid && !sd)) { //Character mismatch. Cancel execution.
- st->rid = 0;
- st->state = END;
+ if((sd && sd->status.char_id != id) || (st->rid && !sd)) { //Character mismatch. Cancel execution.
+ st->rid = 0;
+ st->state = END;
+ }
+ st->sleep.timer = INVALID_TIMER;
+ if(st->state != RERUNLINE)
+ st->sleep.tick = 0;
+ script->run_main(st);
}
- st->sleep.timer = INVALID_TIMER;
- if(st->state != RERUNLINE)
- st->sleep.tick = 0;
- run_script_main(st);
return 0;
}
@@ -3316,11 +3930,10 @@ int run_script_timer(int tid, unsigned int tick, int id, intptr_t data) {
///
/// @param st Script state to detach.
/// @param dequeue_event Whether to schedule any queued events, when there was no previous script.
-static void script_detach_state(struct script_state* st, bool dequeue_event)
-{
+void script_detach_state(struct script_state* st, bool dequeue_event) {
struct map_session_data* sd;
- if(st->rid && (sd = iMap->id2sd(st->rid))!=NULL) {
+ if(st->rid && (sd = map->id2sd(st->rid))!=NULL) {
sd->st = st->bk_st;
sd->npc_id = st->bk_npcid;
sd->state.dialog = 0;
@@ -3329,25 +3942,21 @@ static void script_detach_state(struct script_state* st, bool dequeue_event)
st->bk_st = NULL;
st->bk_npcid = 0;
} else if(dequeue_event) {
- /**
- * For the Secure NPC Timeout option (check config/Secure.h) [RR]
- **/
+ // For the Secure NPC Timeout option (check config/Secure.h) [RR]
#ifdef SECURE_NPCTIMEOUT
- /**
- * We're done with this NPC session, so we cancel the timer (if existent) and move on
- **/
+ // We're done with this NPC session, so we cancel the timer (if existent) and move on
if( sd->npc_idle_timer != INVALID_TIMER ) {
- iTimer->delete_timer(sd->npc_idle_timer,npc_rr_secure_timeout_timer);
+ timer->delete(sd->npc_idle_timer,npc->secure_timeout_timer);
sd->npc_idle_timer = INVALID_TIMER;
}
#endif
- npc_event_dequeue(sd);
+ npc->event_dequeue(sd);
}
} else if(st->bk_st) { // rid was set to 0, before detaching the script state
ShowError("script_detach_state: Found previous script state without attached player (rid=%d, oid=%d, state=%d, bk_npcid=%d)\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid);
- script_reportsrc(st->bk_st);
+ script->reportsrc(st->bk_st);
- script_free_state(st->bk_st);
+ script->free_state(st->bk_st);
st->bk_st = NULL;
}
}
@@ -3355,11 +3964,10 @@ static void script_detach_state(struct script_state* st, bool dequeue_event)
/// Attaches script state to possibly attached character and backups it's previous script, if any.
///
/// @param st Script state to attach.
-static void script_attach_state(struct script_state* st)
-{
+void script_attach_state(struct script_state* st) {
struct map_session_data* sd;
- if(st->rid && (sd = iMap->id2sd(st->rid))!=NULL)
+ if(st->rid && (sd = map->id2sd(st->rid))!=NULL)
{
if(st!=sd->st)
{
@@ -3378,8 +3986,8 @@ static void script_attach_state(struct script_state* st)
**/
#ifdef SECURE_NPCTIMEOUT
if( sd->npc_idle_timer == INVALID_TIMER )
- sd->npc_idle_timer = iTimer->add_timer(iTimer->gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc_rr_secure_timeout_timer,sd->bl.id,0);
- sd->npc_idle_tick = iTimer->gettick();
+ sd->npc_idle_timer = timer->add(timer->gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc->secure_timeout_timer,sd->bl.id,0);
+ sd->npc_idle_tick = timer->gettick();
#endif
}
}
@@ -3387,32 +3995,31 @@ static void script_attach_state(struct script_state* st)
/*==========================================
* The main part of the script execution
*------------------------------------------*/
-void run_script_main(struct script_state *st)
-{
- int cmdcount = script_config.check_cmdcount;
- int gotocount = script_config.check_gotocount;
+void run_script_main(struct script_state *st) {
+ int cmdcount = script->config.check_cmdcount;
+ int gotocount = script->config.check_gotocount;
TBL_PC *sd;
struct script_stack *stack = st->stack;
struct npc_data *nd;
- script_attach_state(st);
+ script->attach_state(st);
- nd = iMap->id2nd(st->oid);
+ nd = map->id2nd(st->oid);
if( nd && nd->bl.m >= 0 )
- st->instance_id = map[nd->bl.m].instance_id;
+ st->instance_id = map->list[nd->bl.m].instance_id;
else
st->instance_id = -1;
if(st->state == RERUNLINE) {
- run_func(st);
+ script->run_func(st);
if(st->state == GOTO)
st->state = RUN;
} else if(st->state != END)
st->state = RUN;
- while( st->state == RUN ){
- enum c_op c = get_com(st->script->script_buf,&st->pos);
- switch(c){
+ while( st->state == RUN ) {
+ enum c_op c = script->get_com(st->script->script_buf,&st->pos);
+ switch(c) {
case C_EOL:
if( stack->defsp > stack->sp )
ShowError("script:run_script_main: unexpected stack position (defsp=%d sp=%d). please report this!!!\n", stack->defsp, stack->sp);
@@ -3420,7 +4027,7 @@ void run_script_main(struct script_state *st)
script->pop_stack(st, stack->defsp, stack->sp);// pop unused stack data. (unused return value)
break;
case C_INT:
- script->push_val(stack,C_INT,get_num(st->script->script_buf,&st->pos),NULL);
+ script->push_val(stack,C_INT,script->get_num(st->script->script_buf,&st->pos),NULL);
break;
case C_POS:
case C_NAME:
@@ -3435,12 +4042,12 @@ void run_script_main(struct script_state *st)
while(st->script->script_buf[st->pos++]);
break;
case C_FUNC:
- run_func(st);
- if(st->state==GOTO){
+ script->run_func(st);
+ if(st->state==GOTO) {
st->state = RUN;
- if( !st->freeloop && gotocount>0 && (--gotocount)<=0 ){
+ if( !st->freeloop && gotocount>0 && (--gotocount)<=0 ) {
ShowError("run_script: infinity loop !\n");
- script_reportsrc(st);
+ script->reportsrc(st);
st->state=END;
}
}
@@ -3453,7 +4060,7 @@ void run_script_main(struct script_state *st)
case C_NEG:
case C_NOT:
case C_LNOT:
- op_1(st ,c);
+ script->op_1(st ,c);
break;
case C_ADD:
@@ -3474,11 +4081,15 @@ void run_script_main(struct script_state *st)
case C_LOR:
case C_R_SHIFT:
case C_L_SHIFT:
- op_2(st, c);
+#ifdef PCRE_SUPPORT
+ case C_RE_EQ:
+ case C_RE_NE:
+#endif // PCRE_SUPPORT
+ script->op_2(st, c);
break;
case C_OP3:
- op_3(st, c);
+ script->op_3(st, c);
break;
case C_NOP:
@@ -3490,93 +4101,88 @@ void run_script_main(struct script_state *st)
st->state=END;
break;
}
- if( !st->freeloop && cmdcount>0 && (--cmdcount)<=0 ){
- ShowError("run_script: infinity loop !\n");
- script_reportsrc(st);
+ if( !st->freeloop && cmdcount>0 && (--cmdcount)<=0 ) {
+ ShowError("run_script: too many opeartions being processed non-stop !\n");
+ script->reportsrc(st);
st->state=END;
}
}
if(st->sleep.tick > 0) {
//Restore previous script
- script_detach_state(st, false);
+ script->detach_state(st, false);
//Delay execution
- sd = iMap->id2sd(st->rid); // Get sd since script might have attached someone while running. [Inkfish]
+ sd = map->id2sd(st->rid); // Get sd since script might have attached someone while running. [Inkfish]
st->sleep.charid = sd?sd->status.char_id:0;
- st->sleep.timer = iTimer->add_timer(iTimer->gettick()+st->sleep.tick,
- run_script_timer, st->sleep.charid, (intptr_t)st);
- } else if(st->state != END && st->rid){
+ st->sleep.timer = timer->add(timer->gettick()+st->sleep.tick,
+ script->run_timer, st->sleep.charid, (intptr_t)st->id);
+ } else if(st->state != END && st->rid) {
//Resume later (st is already attached to player).
if(st->bk_st) {
ShowWarning("Unable to restore stack! Double continuation!\n");
//Report BOTH scripts to see if that can help somehow.
ShowDebug("Previous script (lost):\n");
- script_reportsrc(st->bk_st);
+ script->reportsrc(st->bk_st);
ShowDebug("Current script:\n");
- script_reportsrc(st);
+ script->reportsrc(st);
- script_free_state(st->bk_st);
+ script->free_state(st->bk_st);
st->bk_st = NULL;
}
} else {
//Dispose of script.
- if ((sd = iMap->id2sd(st->rid))!=NULL) { //Restore previous stack and save char.
- if(sd->state.using_fake_npc){
+ if ((sd = map->id2sd(st->rid))!=NULL) { //Restore previous stack and save char.
+ if(sd->state.using_fake_npc) {
clif->clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
sd->state.using_fake_npc = 0;
}
//Restore previous script if any.
- script_detach_state(st, true);
- if (sd->state.reg_dirty&2)
- intif_saveregistry(sd,2);
- if (sd->state.reg_dirty&1)
- intif_saveregistry(sd,1);
+ script->detach_state(st, true);
+ if (sd->vars_dirty)
+ intif->saveregistry(sd);
}
- script_free_state(st);
+ script->free_state(st);
st = NULL;
}
}
-int script_config_read(char *cfgName)
-{
+int script_config_read(char *cfgName) {
int i;
char line[1024],w1[1024],w2[1024];
FILE *fp;
- fp=fopen(cfgName,"r");
- if(fp==NULL){
+ if( !( fp = fopen(cfgName,"r") ) ) {
ShowError("File not found: %s\n", cfgName);
return 1;
}
- while(fgets(line, sizeof(line), fp))
- {
- if(line[0] == '/' && line[1] == '/')
+ while (fgets(line, sizeof(line), fp)) {
+ if (line[0] == '/' && line[1] == '/')
continue;
- i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
+ i = sscanf(line,"%1023[^:]: %1023[^\r\n]", w1, w2);
if(i!=2)
continue;
if(strcmpi(w1,"warn_func_mismatch_paramnum")==0) {
- script_config.warn_func_mismatch_paramnum = config_switch(w2);
+ script->config.warn_func_mismatch_paramnum = config_switch(w2);
}
else if(strcmpi(w1,"check_cmdcount")==0) {
- script_config.check_cmdcount = config_switch(w2);
+ script->config.check_cmdcount = config_switch(w2);
}
else if(strcmpi(w1,"check_gotocount")==0) {
- script_config.check_gotocount = config_switch(w2);
+ script->config.check_gotocount = config_switch(w2);
}
else if(strcmpi(w1,"input_min_value")==0) {
- script_config.input_min_value = config_switch(w2);
+ script->config.input_min_value = config_switch(w2);
}
else if(strcmpi(w1,"input_max_value")==0) {
- script_config.input_max_value = config_switch(w2);
+ script->config.input_max_value = config_switch(w2);
}
else if(strcmpi(w1,"warn_func_mismatch_argtypes")==0) {
- script_config.warn_func_mismatch_argtypes = config_switch(w2);
+ script->config.warn_func_mismatch_argtypes = config_switch(w2);
}
- else if(strcmpi(w1,"import")==0){
- script_config_read(w2);
+ else if(strcmpi(w1,"import")==0) {
+ script->config_read(w2);
}
else {
ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
@@ -3590,102 +4196,132 @@ int script_config_read(char *cfgName)
/**
* @see DBApply
*/
-static int db_script_free_code_sub(DBKey key, DBData *data, va_list ap)
+int db_script_free_code_sub(DBKey key, DBData *data, va_list ap)
{
struct script_code *code = DB->data2ptr(data);
if (code)
- script_free_code(code);
+ script->free_code(code);
return 0;
}
void script_run_autobonus(const char *autobonus, int id, int pos)
{
- struct script_code *script = (struct script_code *)strdb_get(autobonus_db, autobonus);
+ struct script_code *scriptroot = (struct script_code *)strdb_get(script->autobonus_db, autobonus);
- if( script )
- {
- current_equip_item_index = pos;
- run_script(script,0,id,0);
+ if( scriptroot ) {
+ status->current_equip_item_index = pos;
+ script->run(scriptroot,0,id,0);
}
}
void script_add_autobonus(const char *autobonus)
{
- if( strdb_get(autobonus_db, autobonus) == NULL )
- {
- struct script_code *script = parse_script(autobonus, "autobonus", 0, 0);
+ if( strdb_get(script->autobonus_db, autobonus) == NULL ) {
+ struct script_code *scriptroot = script->parse(autobonus, "autobonus", 0, 0, NULL);
- if( script )
- strdb_put(autobonus_db, autobonus, script);
+ if( scriptroot )
+ strdb_put(script->autobonus_db, autobonus, scriptroot);
}
}
/// resets a temporary character array variable to given value
-void script_cleararray_pc(struct map_session_data* sd, const char* varname, void* value)
-{
+void script_cleararray_pc(struct map_session_data* sd, const char* varname, void* value) {
+ struct script_array *sa = NULL;
+ struct reg_db *src = NULL;
+ unsigned int i, *list = NULL, size = 0;
int key;
- uint8 idx;
- if( not_array_variable(varname[0]) || !not_server_variable(varname[0]) )
- {
- ShowError("script_cleararray_pc: Variable '%s' has invalid scope (char_id=%d).\n", varname, sd->status.char_id);
+ key = script->add_str(varname);
+
+ if( !(src = script->array_src(NULL,sd,varname,NULL) ) )
return;
- }
-
- key = add_str(varname);
-
- if( is_string_variable(varname) )
- {
- for( idx = 0; idx < SCRIPT_MAX_ARRAYSIZE; idx++ )
- {
- pc->setregstr(sd, reference_uid(key, idx), (const char*)value);
- }
- }
- else
- {
- for( idx = 0; idx < SCRIPT_MAX_ARRAYSIZE; idx++ )
- {
- pc->setreg(sd, reference_uid(key, idx), (int)__64BPTRSIZE(value));
- }
+
+ if( value )
+ script->array_ensure_zero(NULL,sd,reference_uid(key,0),NULL);
+
+ if( !(sa = idb_get(src->arrays, key)) ) /* non-existent array, nothing to empty */
+ return;
+
+ size = sa->size;
+ list = script->array_cpy_list(sa);
+
+ for(i = 0; i < size; i++) {
+ script->set_reg(NULL,sd,reference_uid(key, list[i]),varname,value,NULL);
}
}
/// sets a temporary character array variable element idx to given value
/// @param refcache Pointer to an int variable, which keeps a copy of the reference to varname and must be initialized to 0. Can be NULL if only one element is set.
-void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8 idx, void* value, int* refcache)
-{
+void script_setarray_pc(struct map_session_data* sd, const char* varname, uint32 idx, void* value, int* refcache) {
int key;
-
- if( not_array_variable(varname[0]) || !not_server_variable(varname[0]) )
- {
- ShowError("script_setarray_pc: Variable '%s' has invalid scope (char_id=%d).\n", varname, sd->status.char_id);
- return;
- }
-
- if( idx >= SCRIPT_MAX_ARRAYSIZE )
- {
- ShowError("script_setarray_pc: Variable '%s' has invalid index '%d' (char_id=%d).\n", varname, (int)idx, sd->status.char_id);
+
+ if( idx >= SCRIPT_MAX_ARRAYSIZE ) {
+ ShowError("script_setarray_pc: Variable '%s' has invalid index '%u' (char_id=%d).\n", varname, idx, sd->status.char_id);
return;
}
- key = ( refcache && refcache[0] ) ? refcache[0] : add_str(varname);
-
- if( is_string_variable(varname) )
- {
- pc->setregstr(sd, reference_uid(key, idx), (const char*)value);
+ key = ( refcache && refcache[0] ) ? refcache[0] : script->add_str(varname);
+
+ script->set_reg(NULL,sd,reference_uid(key, idx),varname,value,NULL);
+
+ if( refcache )
+ {// save to avoid repeated script->add_str calls
+ refcache[0] = key;
}
- else
- {
- pc->setreg(sd, reference_uid(key, idx), (int)__64BPTRSIZE(value));
+}
+/**
+ * Clears persistent variables from memory
+ **/
+int script_reg_destroy(DBKey key, DBData *data, va_list ap) {
+ struct script_reg_state *src;
+
+ if( data->type != DB_DATA_PTR )/* got no need for those! */
+ return 0;
+
+ src = DB->data2ptr(data);
+
+ if( src->type ) {
+ struct script_reg_str *p = (struct script_reg_str *)src;
+
+ if( p->value )
+ aFree(p->value);
+
+ ers_free(pc->str_reg_ers,p);
+ } else {
+ ers_free(pc->num_reg_ers,(struct script_reg_num*)src);
}
+
+ return 0;
+}
+/**
+ * Clears a single persistent variable
+ **/
+void script_reg_destroy_single(struct map_session_data *sd, int64 reg, struct script_reg_state *data) {
+ i64db_remove(sd->regs.vars, reg);
- if( refcache )
- {// save to avoid repeated add_str calls
- refcache[0] = key;
+ if( data->type ) {
+ struct script_reg_str *p = (struct script_reg_str*)data;
+
+ if( p->value )
+ aFree(p->value);
+
+ ers_free(pc->str_reg_ers,p);
+ } else {
+ ers_free(pc->num_reg_ers,(struct script_reg_num*)data);
}
}
+unsigned int *script_array_cpy_list(struct script_array *sa) {
+ if( sa->size > script->generic_ui_array_size )
+ script->generic_ui_array_expand(sa->size);
+ memcpy(script->generic_ui_array, sa->members, sizeof(unsigned int)*sa->size);
+ return script->generic_ui_array;
+}
+void script_generic_ui_array_expand (unsigned int plus) {
+ script->generic_ui_array_size += plus + 100;
+ RECREATE(script->generic_ui_array, unsigned int, script->generic_ui_array_size);
+}
/*==========================================
* Destructor
*------------------------------------------*/
@@ -3693,8 +4329,8 @@ void do_final_script(void) {
int i;
DBIterator *iter;
struct script_state *st;
-
-#ifdef DEBUG_HASH
+
+#ifdef SCRIPT_DEBUG_HASH
if (battle_config.etc_log)
{
FILE *fp = fopen("hash_dump.txt","wt");
@@ -3711,8 +4347,8 @@ void do_final_script(void) {
fprintf(fp,"num : hash : data_name\n");
fprintf(fp,"---------------------------------------------------------------\n");
for(i=LABEL_START; i<script->str_num; i++) {
- unsigned int h = calc_hash(get_str(i));
- fprintf(fp,"%04d : %4u : %s\n",i,h, get_str(i));
+ unsigned int h = script->calc_hash(script->get_str(i));
+ fprintf(fp,"%04d : %4u : %s\n",i,h, script->get_str(i));
++count[h];
}
fprintf(fp,"--------------------\n\n");
@@ -3720,19 +4356,19 @@ void do_final_script(void) {
for(i=0; i<SCRIPT_HASH_SIZE; i++) {
fprintf(fp," hash %3d = %d\n",i,count[i]);
if(min > count[i])
- min = count[i]; // minimun count of collision
+ min = count[i]; // minimun count of collision
if(max < count[i])
- max = count[i]; // maximun count of collision
+ max = count[i]; // maximun count of collision
if(count[i] == 0)
zero++;
++count2[count[i]];
}
fprintf(fp,"\n--------------------\n items : buckets\n--------------------\n");
- for( i=min; i <= max; ++i ){
+ for( i=min; i <= max; ++i ) {
fprintf(fp," %5d : %7d\n",i,count2[i]);
mean += 1.0f*i*count2[i]/SCRIPT_HASH_SIZE; // Note: this will always result in <nr labels>/<nr buckets>
}
- for( i=min; i <= max; ++i ){
+ for( i=min; i <= max; ++i ) {
n += count2[i];
if( n*2 >= SCRIPT_HASH_SIZE )
{
@@ -3749,20 +4385,19 @@ void do_final_script(void) {
}
#endif
- mapreg_final();
-
- db_destroy(scriptlabel_db);
- userfunc_db->destroy(userfunc_db, db_script_free_code_sub);
- autobonus_db->destroy(autobonus_db, db_script_free_code_sub);
-
iter = db_iterator(script->st_db);
-
+
for( st = dbi_first(iter); dbi_exists(iter); st = dbi_next(iter) ) {
- script_free_state(st);
+ script->free_state(st);
}
-
+
dbi_destroy(iter);
-
+
+ mapreg->final();
+
+ script->userfunc_db->destroy(script->userfunc_db, script->db_free_code_sub);
+ script->autobonus_db->destroy(script->autobonus_db, script->db_free_code_sub);
+
if (script->str_data)
aFree(script->str_data);
if (script->str_buf)
@@ -3774,7 +4409,7 @@ void do_final_script(void) {
if( atcommand->binding_count != 0 )
aFree(atcommand->binding);
-
+
for( i = 0; i < script->buildin_count; i++) {
if( script->buildin[i] ) {
aFree(script->buildin[i]);
@@ -3783,7 +4418,7 @@ void do_final_script(void) {
}
aFree(script->buildin);
-
+
if( script->hqs ) {
for( i = 0; i < script->hqs; i++ ) {
if( script->hq[i].item != NULL )
@@ -3802,39 +4437,69 @@ void do_final_script(void) {
aFree(script->hqi);
if( script->word_buf != NULL )
aFree(script->word_buf);
-
+
+#ifdef ENABLE_CASE_CHECK
+ script->global_casecheck.clear();
+ script->local_casecheck.clear();
+#endif // ENABLE_CASE_CHECK
+
ers_destroy(script->st_ers);
ers_destroy(script->stack_ers);
-
+
db_destroy(script->st_db);
+
+ if( script->labels != NULL )
+ aFree(script->labels);
+
+ ers_destroy(script->array_ers);
+
+ if( script->generic_ui_array )
+ aFree(script->generic_ui_array);
}
/*==========================================
* Initialization
*------------------------------------------*/
-void do_init_script(void) {
+void do_init_script(bool minimal) {
script->st_db = idb_alloc(DB_OPT_BASE);
- userfunc_db = strdb_alloc(DB_OPT_DUP_KEY,0);
- scriptlabel_db = strdb_alloc(DB_OPT_DUP_KEY,50);
- autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0);
+ script->userfunc_db = strdb_alloc(DB_OPT_DUP_KEY,0);
+ script->autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0);
- script->st_ers = ers_new(sizeof(struct script_state), "script.c::st_ers", ERS_OPT_NONE);
- script->stack_ers = ers_new(sizeof(struct script_stack), "script.c::script_stack", ERS_OPT_NONE);
+ script->st_ers = ers_new(sizeof(struct script_state), "script.c::st_ers", ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
+ script->stack_ers = ers_new(sizeof(struct script_stack), "script.c::script_stack", ERS_OPT_NONE|ERS_OPT_FLEX_CHUNK);
+ script->array_ers = ers_new(sizeof(struct script_array), "script.c::array_ers", ERS_OPT_CLEAN|ERS_OPT_CLEAR);
ers_chunk_size(script->st_ers, 10);
ers_chunk_size(script->stack_ers, 10);
-
+
script->parse_builtin();
- read_constdb();
- mapreg_init();
+ script->read_constdb();
+ script->hardcoded_constants();
+
+ if (minimal)
+ return;
+
+ mapreg->init();
}
-int script_reload() {
+int script_reload(void) {
int i;
DBIterator *iter;
struct script_state *st;
- userfunc_db->clear(userfunc_db, db_script_free_code_sub);
- db_clear(scriptlabel_db);
+#ifdef ENABLE_CASE_CHECK
+ script->global_casecheck.clear();
+#endif // ENABLE_CASE_CHECK
+
+ iter = db_iterator(script->st_db);
+
+ for( st = dbi_first(iter); dbi_exists(iter); st = dbi_next(iter) ) {
+ script->free_state(st);
+ }
+
+ dbi_destroy(iter);
+
+ script->userfunc_db->clear(script->userfunc_db, script->db_free_code_sub);
+ script->label_count = 0;
for( i = 0; i < atcommand->binding_count; i++ ) {
aFree(atcommand->binding[i]);
@@ -3845,27 +4510,32 @@ int script_reload() {
atcommand->binding_count = 0;
- iter = db_iterator(script->st_db);
-
- for( st = dbi_first(iter); dbi_exists(iter); st = dbi_next(iter) ) {
- script_free_state(st);
- }
-
- dbi_destroy(iter);
-
db_clear(script->st_db);
-
- mapreg_reload();
+
+ mapreg->reload();
+
+ itemdb->name_constants();
+
+ sysinfo->vcsrevision_reload();
+
return 0;
}
+/* returns name of current function being run, from within the stack [Ind/Hercules] */
+const char *script_getfuncname(struct script_state *st) {
+ struct script_data *data;
+
+ data = &st->stack->stack_data[st->start];
+
+ if( data->type == C_NAME && script->str_data[data->u.num].type == C_FUNC )
+ return script->get_str(script_getvarid(data->u.num));
+
+ return NULL;
+}
//-----------------------------------------------------------------------------
// buildin functions
//
-#define BUILDIN_DEF(x,args) { buildin_ ## x , #x , args }
-#define BUILDIN_DEF2(x,x2,args) { buildin_ ## x , x2 , args }
-
/////////////////////////////////////////////////////////////////////
// NPC interaction
//
@@ -3875,21 +4545,21 @@ int script_reload() {
///
/// mes "<message>";
BUILDIN(mes) {
- TBL_PC* sd = script_rid2sd(st);
+ TBL_PC* sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
if( !script_hasdata(st, 3) ) {// only a single line detected in the script
clif->scriptmes(sd, st->oid, script_getstr(st, 2));
} else {// parse multiple lines as they exist
int i;
-
+
for( i = 2; script_hasdata(st, i); i++ ) {
// send the message to the client
clif->scriptmes(sd, st->oid, script_getstr(st, i));
}
}
-
+
return true;
}
@@ -3900,8 +4570,8 @@ BUILDIN(mes) {
BUILDIN(next)
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
#ifdef SECURE_NPCTIMEOUT
@@ -3918,11 +4588,11 @@ BUILDIN(next)
/// close;
BUILDIN(close) {
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
st->state = sd->state.dialog == 1 ? CLOSE : END;
clif->scriptclose(sd, st->oid);
return true;
@@ -3934,12 +4604,18 @@ BUILDIN(close) {
/// close2;
BUILDIN(close2) {
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- st->state = STOP;
+
+ if( sd->state.dialog == 1 )
+ st->state = STOP;
+ else {
+ ShowWarning("misuse of 'close2'! trying to use it without prior dialog! skipping...\n");
+ script->reportsrc(st);
+ }
+
clif->scriptclose(sd, st->oid);
return true;
}
@@ -3947,15 +4623,15 @@ BUILDIN(close2) {
/// Counts the number of valid and total number of options in 'str'
/// If max_count > 0 the counting stops when that valid option is reached
/// total is incremented for each option (NULL is supported)
-static int menu_countoptions(const char* str, int max_count, int* total)
+int menu_countoptions(const char* str, int max_count, int* total)
{
int count = 0;
int bogus_total;
-
+
if( total == NULL )
total = &bogus_total;
++(*total);
-
+
// initial empty options
while( *str == ':' )
{
@@ -4001,62 +4677,60 @@ BUILDIN(menu)
int i;
const char* text;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
#ifdef SECURE_NPCTIMEOUT
sd->npc_idle_type = NPCT_MENU;
#endif
-
+
// TODO detect multiple scripts waiting for input at the same time, and what to do when that happens
if( sd->state.menu_or_input == 0 )
{
struct StringBuf buf;
struct script_data* data;
-
+
if( script_lastdata(st) % 2 == 0 )
{// argument count is not even (1st argument is at index 2)
ShowError("script:menu: illegal number of arguments (%d).\n", (script_lastdata(st) - 1));
st->state = END;
return false;
}
-
+
StrBuf->Init(&buf);
sd->npc_menu = 0;
for( i = 2; i < script_lastdata(st); i += 2 )
{
// menu options
text = script_getstr(st, i);
-
+
// target label
data = script_getdata(st, i+1);
if( !data_islabel(data) )
{// not a label
StrBuf->Destroy(&buf);
ShowError("script:menu: argument #%d (from 1) is not a label or label not found.\n", i);
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;
}
-
+
// append option(s)
if( text[0] == '\0' )
continue;// empty string, ignore
if( sd->npc_menu > 0 )
StrBuf->AppendStr(&buf, ":");
StrBuf->AppendStr(&buf, text);
- sd->npc_menu += menu_countoptions(text, 0, NULL);
+ sd->npc_menu += script->menu_countoptions(text, 0, NULL);
}
st->state = RERUNLINE;
sd->state.menu_or_input = 1;
-
- /**
- * menus beyond this length crash the client (see bugreport:6402)
- **/
+
+ /* menus beyond this length crash the client (see bugreport:6402) */
if( StrBuf->Length(&buf) >= 2047 ) {
- struct npc_data * nd = iMap->id2nd(st->oid);
+ struct npc_data * nd = map->id2nd(st->oid);
char* menu;
CREATE(menu, char, 2048);
safestrncpy(menu, StrBuf->Value(&buf), 2047);
@@ -4065,13 +4739,13 @@ BUILDIN(menu)
aFree(menu);
} else
clif->scriptmenu(sd, st->oid, StrBuf->Value(&buf));
-
+
StrBuf->Destroy(&buf);
-
+
if( sd->npc_menu >= 0xff )
{// client supports only up to 254 entries; 0 is not used and 255 is reserved for cancel; excess entries are displayed but cause 'uint8' overflow
ShowWarning("buildin_menu: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
- script_reportsrc(st);
+ script->reportsrc(st);
}
}
else if( sd->npc_menu == 0xff )
@@ -4082,7 +4756,7 @@ BUILDIN(menu)
else
{// goto target label
int menu = 0;
-
+
sd->state.menu_or_input = 0;
if( sd->npc_menu <= 0 )
{
@@ -4090,12 +4764,12 @@ BUILDIN(menu)
st->state = END;
return false;
}
-
+
// get target label
for( i = 2; i < script_lastdata(st); i += 2 )
{
text = script_getstr(st, i);
- sd->npc_menu -= menu_countoptions(text, sd->npc_menu, &menu);
+ sd->npc_menu -= script->menu_countoptions(text, sd->npc_menu, &menu);
if( sd->npc_menu <= 0 )
break;// entry found
}
@@ -4108,11 +4782,11 @@ BUILDIN(menu)
if( !data_islabel(script_getdata(st, i + 1)) )
{// TODO remove this temporary crash-prevention code (fallback for multiple scripts requesting user input)
ShowError("script:menu: unexpected data in label argument\n");
- script_reportdata(script_getdata(st, i + 1));
+ script->reportdata(script_getdata(st, i + 1));
st->state = END;
return false;
}
- pc->setreg(sd, add_str("@menu"), menu);
+ pc->setreg(sd, script->add_str("@menu"), menu);
st->pos = script_getnum(st, i + 1);
st->state = GOTO;
}
@@ -4130,38 +4804,36 @@ BUILDIN(select)
int i;
const char* text;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
#ifdef SECURE_NPCTIMEOUT
sd->npc_idle_type = NPCT_MENU;
#endif
-
+
if( sd->state.menu_or_input == 0 ) {
struct StringBuf buf;
-
+
StrBuf->Init(&buf);
sd->npc_menu = 0;
for( i = 2; i <= script_lastdata(st); ++i ) {
text = script_getstr(st, i);
-
+
if( sd->npc_menu > 0 )
StrBuf->AppendStr(&buf, ":");
-
+
StrBuf->AppendStr(&buf, text);
- sd->npc_menu += menu_countoptions(text, 0, NULL);
+ sd->npc_menu += script->menu_countoptions(text, 0, NULL);
}
-
+
st->state = RERUNLINE;
sd->state.menu_or_input = 1;
-
- /**
- * menus beyond this length crash the client (see bugreport:6402)
- **/
+
+ /* menus beyond this length crash the client (see bugreport:6402) */
if( StrBuf->Length(&buf) >= 2047 ) {
- struct npc_data * nd = iMap->id2nd(st->oid);
+ struct npc_data * nd = map->id2nd(st->oid);
char* menu;
CREATE(menu, char, 2048);
safestrncpy(menu, StrBuf->Value(&buf), 2047);
@@ -4171,25 +4843,25 @@ BUILDIN(select)
} else
clif->scriptmenu(sd, st->oid, StrBuf->Value(&buf));
StrBuf->Destroy(&buf);
-
+
if( sd->npc_menu >= 0xff ) {
ShowWarning("buildin_select: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
- script_reportsrc(st);
+ script->reportsrc(st);
}
} else if( sd->npc_menu == 0xff ) {// Cancel was pressed
sd->state.menu_or_input = 0;
st->state = END;
} else {// return selected option
int menu = 0;
-
+
sd->state.menu_or_input = 0;
for( i = 2; i <= script_lastdata(st); ++i ) {
text = script_getstr(st, i);
- sd->npc_menu -= menu_countoptions(text, sd->npc_menu, &menu);
+ sd->npc_menu -= script->menu_countoptions(text, sd->npc_menu, &menu);
if( sd->npc_menu <= 0 )
break;// entry found
}
- pc->setreg(sd, add_str("@menu"), menu);
+ pc->setreg(sd, script->add_str("@menu"), menu);
script_pushint(st, menu);
st->state = RUN;
}
@@ -4209,19 +4881,19 @@ BUILDIN(prompt)
int i;
const char *text;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
#ifdef SECURE_NPCTIMEOUT
sd->npc_idle_type = NPCT_MENU;
#endif
-
+
if( sd->state.menu_or_input == 0 )
{
struct StringBuf buf;
-
+
StrBuf->Init(&buf);
sd->npc_menu = 0;
for( i = 2; i <= script_lastdata(st); ++i )
@@ -4230,17 +4902,15 @@ BUILDIN(prompt)
if( sd->npc_menu > 0 )
StrBuf->AppendStr(&buf, ":");
StrBuf->AppendStr(&buf, text);
- sd->npc_menu += menu_countoptions(text, 0, NULL);
+ sd->npc_menu += script->menu_countoptions(text, 0, NULL);
}
-
+
st->state = RERUNLINE;
sd->state.menu_or_input = 1;
-
- /**
- * menus beyond this length crash the client (see bugreport:6402)
- **/
+
+ /* menus beyond this length crash the client (see bugreport:6402) */
if( StrBuf->Length(&buf) >= 2047 ) {
- struct npc_data * nd = iMap->id2nd(st->oid);
+ struct npc_data * nd = map->id2nd(st->oid);
char* menu;
CREATE(menu, char, 2048);
safestrncpy(menu, StrBuf->Value(&buf), 2047);
@@ -4250,33 +4920,33 @@ BUILDIN(prompt)
} else
clif->scriptmenu(sd, st->oid, StrBuf->Value(&buf));
StrBuf->Destroy(&buf);
-
+
if( sd->npc_menu >= 0xff )
{
ShowWarning("buildin_prompt: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
- script_reportsrc(st);
+ script->reportsrc(st);
}
}
else if( sd->npc_menu == 0xff )
{// Cancel was pressed
sd->state.menu_or_input = 0;
- pc->setreg(sd, add_str("@menu"), 0xff);
+ pc->setreg(sd, script->add_str("@menu"), 0xff);
script_pushint(st, 0xff);
st->state = RUN;
}
else
{// return selected option
int menu = 0;
-
+
sd->state.menu_or_input = 0;
for( i = 2; i <= script_lastdata(st); ++i )
{
text = script_getstr(st, i);
- sd->npc_menu -= menu_countoptions(text, sd->npc_menu, &menu);
+ sd->npc_menu -= script->menu_countoptions(text, sd->npc_menu, &menu);
if( sd->npc_menu <= 0 )
break;// entry found
}
- pc->setreg(sd, add_str("@menu"), menu);
+ pc->setreg(sd, script->add_str("@menu"), menu);
script_pushint(st, menu);
st->state = RUN;
}
@@ -4295,11 +4965,11 @@ BUILDIN(goto)
if( !data_islabel(script_getdata(st,2)) )
{
ShowError("script:goto: not a label\n");
- script_reportdata(script_getdata(st,2));
+ script->reportdata(script_getdata(st,2));
st->state = END;
return false;
}
-
+
st->pos = script_getnum(st,2);
st->state = GOTO;
return true;
@@ -4314,44 +4984,55 @@ BUILDIN(callfunc)
struct script_retinfo* ri;
struct script_code* scr;
const char* str = script_getstr(st,2);
- DBMap **ref = NULL;
-
- scr = (struct script_code*)strdb_get(userfunc_db, str);
+ struct reg_db *ref = NULL;
+
+ scr = (struct script_code*)strdb_get(script->userfunc_db, str);
if( !scr )
{
ShowError("script:callfunc: function not found! [%s]\n", str);
st->state = END;
return false;
}
-
- for( i = st->start+3, j = 0; i < st->end; i++, j++ )
- {
+
+ ref = (struct reg_db *)aCalloc(sizeof(struct reg_db), 2);
+ ref[0].vars = st->stack->scope.vars;
+ if (!st->stack->scope.arrays)
+ st->stack->scope.arrays = idb_alloc(DB_OPT_BASE); // TODO: Can this happen? when?
+ ref[0].arrays = st->stack->scope.arrays;
+ ref[1].vars = st->script->local.vars;
+ if (!st->script->local.arrays)
+ st->script->local.arrays = idb_alloc(DB_OPT_BASE); // TODO: Can this happen? when?
+ ref[1].arrays = st->script->local.arrays;
+
+ for( i = st->start+3, j = 0; i < st->end; i++, j++ ) {
struct script_data* data = script->push_copy(st->stack,i);
- if( data_isreference(data) && !data->ref )
- {
+ if( data_isreference(data) && !data->ref ) {
const char* name = reference_getname(data);
if( name[0] == '.' ) {
- ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 1);
- ref[0] = (name[1] == '@' ? st->stack->var_function : st->script->script_vars);
- data->ref = ref;
+ data->ref = (name[1] == '@' ? &ref[0] : &ref[1]);
}
}
}
-
+
CREATE(ri, struct script_retinfo, 1);
- ri->script = st->script;// script code
- ri->var_function = st->stack->var_function;// scope variables
- ri->pos = st->pos;// script location
- ri->nargs = j;// argument count
- ri->defsp = st->stack->defsp;// default stack pointer
- push_retinfo(st->stack, ri, ref);
-
+ ri->script = st->script; // script code
+ ri->scope.vars = st->stack->scope.vars; // scope variables
+ ri->scope.arrays = st->stack->scope.arrays; // scope arrays
+ ri->pos = st->pos; // script location
+ ri->nargs = j; // argument count
+ ri->defsp = st->stack->defsp; // default stack pointer
+ script->push_retinfo(st->stack, ri, ref);
+
st->pos = 0;
st->script = scr;
st->stack->defsp = st->stack->sp;
st->state = GOTO;
- st->stack->var_function = idb_alloc(DB_OPT_RELEASE_DATA);
-
+ st->stack->scope.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+ st->stack->scope.arrays = idb_alloc(DB_OPT_BASE);
+
+ if( !st->script->local.vars )
+ st->script->local.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+
return true;
}
/*==========================================
@@ -4362,45 +5043,47 @@ BUILDIN(callsub)
int i,j;
struct script_retinfo* ri;
int pos = script_getnum(st,2);
- DBMap **ref = NULL;
-
+ struct reg_db *ref = NULL;
+
if( !data_islabel(script_getdata(st,2)) && !data_isfunclabel(script_getdata(st,2)) )
{
ShowError("script:callsub: argument is not a label\n");
- script_reportdata(script_getdata(st,2));
+ script->reportdata(script_getdata(st,2));
st->state = END;
return false;
}
-
- for( i = st->start+3, j = 0; i < st->end; i++, j++ )
- {
+
+ ref = (struct reg_db *)aCalloc(sizeof(struct reg_db), 1);
+ ref[0].vars = st->stack->scope.vars;
+ if (!st->stack->scope.arrays)
+ st->stack->scope.arrays = idb_alloc(DB_OPT_BASE); // TODO: Can this happen? when?
+ ref[0].arrays = st->stack->scope.arrays;
+
+ for( i = st->start+3, j = 0; i < st->end; i++, j++ ) {
struct script_data* data = script->push_copy(st->stack,i);
- if( data_isreference(data) && !data->ref )
- {
+ if( data_isreference(data) && !data->ref ) {
const char* name = reference_getname(data);
if( name[0] == '.' && name[1] == '@' ) {
- if ( !ref ) {
- ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 1);
- ref[0] = st->stack->var_function;
- }
- data->ref = ref;
+ data->ref = &ref[0];
}
}
}
-
+
CREATE(ri, struct script_retinfo, 1);
- ri->script = st->script;// script code
- ri->var_function = st->stack->var_function;// scope variables
- ri->pos = st->pos;// script location
- ri->nargs = j;// argument count
- ri->defsp = st->stack->defsp;// default stack pointer
- push_retinfo(st->stack, ri, ref);
-
+ ri->script = st->script; // script code
+ ri->scope.vars = st->stack->scope.vars; // scope variables
+ ri->scope.arrays = st->stack->scope.arrays; // scope arrays
+ ri->pos = st->pos; // script location
+ ri->nargs = j; // argument count
+ ri->defsp = st->stack->defsp; // default stack pointer
+ script->push_retinfo(st->stack, ri, ref);
+
st->pos = pos;
st->stack->defsp = st->stack->sp;
st->state = GOTO;
- st->stack->var_function = idb_alloc(DB_OPT_RELEASE_DATA);
-
+ st->stack->scope.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+ st->stack->scope.arrays = idb_alloc(DB_OPT_BASE);
+
return true;
}
@@ -4412,7 +5095,7 @@ BUILDIN(getarg)
{
struct script_retinfo* ri;
int idx;
-
+
if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp - 1].type != C_RETINFO )
{
ShowError("script:getarg: no callfunc or callsub!\n");
@@ -4420,9 +5103,9 @@ BUILDIN(getarg)
return false;
}
ri = st->stack->stack_data[st->stack->defsp - 1].u.ri;
-
+
idx = script_getnum(st,2);
-
+
if( idx >= 0 && idx < ri->nargs )
script->push_copy(st->stack, st->stack->defsp - 1 - ri->nargs + idx);
else if( script_hasdata(st,3) )
@@ -4433,7 +5116,7 @@ BUILDIN(getarg)
st->state = END;
return false;
}
-
+
return true;
}
@@ -4442,24 +5125,30 @@ BUILDIN(getarg)
///
/// return;
/// return <value>;
-BUILDIN(return)
-{
+BUILDIN(return) {
if( script_hasdata(st,2) )
{// return value
struct script_data* data;
script_pushcopy(st, 2);
data = script_getdatatop(st, -1);
- if( data_isreference(data) )
- {
+ if( data_isreference(data) ) {
const char* name = reference_getname(data);
- if( name[0] == '.' && name[1] == '@' )
- {// scope variable
- if( !data->ref || data->ref == (DBMap**)&st->stack->var_function )
+ if( name[0] == '.' && name[1] == '@' ) {
+ // scope variable
+ if( !data->ref || data->ref->vars == st->stack->scope.vars )
script->get_val(st, data);// current scope, convert to value
- }
- else if( name[0] == '.' && !data->ref )
- {// script variable, link to current script
- data->ref = &st->script->script_vars;
+ if( data->ref && data->ref->vars == st->stack->stack_data[st->stack->defsp-1].u.ri->scope.vars )
+ data->ref = NULL; // Reference to the parent scope, remove reference pointer
+ } else if( name[0] == '.' && !data->ref ) {
+ // script variable without a reference set, link to current script
+ data->ref = (struct reg_db *)aCalloc(sizeof(struct reg_db), 1);
+ script->add_pending_ref(st, data->ref);
+ data->ref->vars = st->script->local.vars;
+ if( !st->script->local.arrays )
+ st->script->local.arrays = idb_alloc(DB_OPT_BASE);
+ data->ref->arrays = st->script->local.arrays;
+ } else if ( name[0] == '.' /* && data->ref != NULL */ ) {
+ data->ref = NULL; // Reference to the parent scope's script, remove reference pointer.
}
}
}
@@ -4481,7 +5170,7 @@ BUILDIN(rand)
int range;
int min;
int max;
-
+
if( script_hasdata(st,3) )
{// min,max
min = script_getnum(st,2);
@@ -4499,7 +5188,7 @@ BUILDIN(rand)
script_pushint(st, min);
else
script_pushint(st, rnd()%range + min);
-
+
return true;
}
@@ -4512,59 +5201,59 @@ BUILDIN(warp)
int x,y;
const char* str;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
str = script_getstr(st,2);
x = script_getnum(st,3);
y = script_getnum(st,4);
-
+
if(strcmp(str,"Random")==0)
ret = pc->randomwarp(sd,CLR_TELEPORT);
else if(strcmp(str,"SavePoint")==0 || strcmp(str,"Save")==0)
ret = pc->setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
else
- ret = pc->setpos(sd,mapindex_name2id(str),x,y,CLR_OUTSIGHT);
-
+ ret = pc->setpos(sd,script->mapindexname2id(st,str),x,y,CLR_OUTSIGHT);
+
if( ret ) {
ShowError("buildin_warp: moving player '%s' to \"%s\",%d,%d failed.\n", sd->status.name, str, x, y);
- script_reportsrc(st);
+ script->reportsrc(st);
}
-
+
return true;
}
/*==========================================
* Warp a specified area
*------------------------------------------*/
-static int buildin_areawarp_sub(struct block_list *bl,va_list ap)
+int buildin_areawarp_sub(struct block_list *bl,va_list ap)
{
int x2,y2,x3,y3;
unsigned int index;
-
+
index = va_arg(ap,unsigned int);
x2 = va_arg(ap,int);
y2 = va_arg(ap,int);
x3 = va_arg(ap,int);
y3 = va_arg(ap,int);
-
+
if(index == 0)
pc->randomwarp((TBL_PC *)bl,CLR_TELEPORT);
else if(x3 && y3) {
int max, tx, ty, j = 0;
-
+
// choose a suitable max number of attempts
if( (max = (y3-y2+1)*(x3-x2+1)*3) > 1000 )
max = 1000;
-
+
// find a suitable map cell
do {
tx = rnd()%(x3-x2+1)+x2;
ty = rnd()%(y3-y2+1)+y2;
j++;
- } while( iMap->getcell(index,tx,ty,CELL_CHKNOPASS) && j < max );
-
+ } while( map->getcell(index,tx,ty,CELL_CHKNOPASS) && j < max );
+
pc->setpos((TBL_PC *)bl,index,tx,ty,CLR_OUTSIGHT);
}
else
@@ -4577,7 +5266,7 @@ BUILDIN(areawarp)
unsigned int index;
const char *str;
const char *mapname;
-
+
mapname = script_getstr(st,2);
x0 = script_getnum(st,3);
y0 = script_getnum(st,4);
@@ -4586,9 +5275,9 @@ BUILDIN(areawarp)
str = script_getstr(st,7);
x2 = script_getnum(st,8);
y2 = script_getnum(st,9);
-
+
if( script_hasdata(st,10) && script_hasdata(st,11) ) { // Warp area to area
- if( (x3 = script_getnum(st,10)) < 0 || (y3 = script_getnum(st,11)) < 0 ){
+ if( (x3 = script_getnum(st,10)) < 0 || (y3 = script_getnum(st,11)) < 0 ) {
x3 = 0;
y3 = 0;
} else if( x3 && y3 ) {
@@ -4597,23 +5286,23 @@ BUILDIN(areawarp)
if( y3 < y2 ) swap(y3,y2);
}
}
-
- if( (m = iMap->mapname2mapid(mapname)) < 0 )
+
+ if( (m = map->mapname2mapid(mapname)) < 0 )
return true;
-
+
if( strcmp(str,"Random") == 0 )
index = 0;
- else if( !(index=mapindex_name2id(str)) )
+ else if( !(index=script->mapindexname2id(st,str)) )
return true;
-
- iMap->foreachinarea(buildin_areawarp_sub, m,x0,y0,x1,y1, BL_PC, index,x2,y2,x3,y3);
+
+ map->foreachinarea(script->buildin_areawarp_sub, m,x0,y0,x1,y1, BL_PC, index,x2,y2,x3,y3);
return true;
}
/*==========================================
* areapercentheal <map>,<x1>,<y1>,<x2>,<y2>,<hp>,<sp>
*------------------------------------------*/
-static int buildin_areapercentheal_sub(struct block_list *bl,va_list ap)
+int buildin_areapercentheal_sub(struct block_list *bl,va_list ap)
{
int hp, sp;
hp = va_arg(ap, int);
@@ -4621,12 +5310,11 @@ static int buildin_areapercentheal_sub(struct block_list *bl,va_list ap)
pc->percentheal((TBL_PC *)bl,hp,sp);
return 0;
}
-BUILDIN(areapercentheal)
-{
+BUILDIN(areapercentheal) {
int hp,sp,m;
const char *mapname;
int x0,y0,x1,y1;
-
+
mapname=script_getstr(st,2);
x0=script_getnum(st,3);
y0=script_getnum(st,4);
@@ -4634,11 +5322,11 @@ BUILDIN(areapercentheal)
y1=script_getnum(st,6);
hp=script_getnum(st,7);
sp=script_getnum(st,8);
-
- if( (m=iMap->mapname2mapid(mapname))< 0)
+
+ if( (m=map->mapname2mapid(mapname))< 0)
return true;
-
- iMap->foreachinarea(buildin_areapercentheal_sub,m,x0,y0,x1,y1,BL_PC,hp,sp);
+
+ map->foreachinarea(script->buildin_areapercentheal_sub,m,x0,y0,x1,y1,BL_PC,hp,sp);
return true;
}
@@ -4648,29 +5336,28 @@ BUILDIN(areapercentheal)
* another player npc-session.
* Using: warpchar "mapname",x,y,Char_ID;
*------------------------------------------*/
-BUILDIN(warpchar)
-{
+BUILDIN(warpchar) {
int x,y,a;
const char *str;
TBL_PC *sd;
-
+
str=script_getstr(st,2);
x=script_getnum(st,3);
y=script_getnum(st,4);
a=script_getnum(st,5);
-
- sd = iMap->charid2sd(a);
+
+ sd = map->charid2sd(a);
if( sd == NULL )
return true;
-
+
if(strcmp(str, "Random") == 0)
pc->randomwarp(sd, CLR_TELEPORT);
else
if(strcmp(str, "SavePoint") == 0)
pc->setpos(sd, sd->status.save_point.map,sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
else
- pc->setpos(sd, mapindex_name2id(str), x, y, CLR_TELEPORT);
-
+ pc->setpos(sd, script->mapindexname2id(st,str), x, y, CLR_TELEPORT);
+
return true;
}
/*==========================================
@@ -4684,9 +5371,9 @@ BUILDIN(warpparty)
TBL_PC *pl_sd;
struct party_data* p;
int type;
- int mapindex;
+ int map_index;
int i;
-
+
const char* str = script_getstr(st,2);
int x = script_getnum(st,3);
int y = script_getnum(st,4);
@@ -4694,17 +5381,17 @@ BUILDIN(warpparty)
const char* str2 = NULL;
if ( script_hasdata(st,6) )
str2 = script_getstr(st,6);
-
+
p = party->search(p_id);
if(!p)
return true;
-
+
type = ( strcmp(str,"Random")==0 ) ? 0
: ( strcmp(str,"SavePointAll")==0 ) ? 1
: ( strcmp(str,"SavePoint")==0 ) ? 2
: ( strcmp(str,"Leader")==0 ) ? 3
: 4;
-
+
switch (type)
{
case 3:
@@ -4712,55 +5399,54 @@ BUILDIN(warpparty)
if (i == MAX_PARTY || !p->data[i].sd) //Leader not found / not online
return true;
pl_sd = p->data[i].sd;
- mapindex = pl_sd->mapindex;
+ map_index = pl_sd->mapindex;
x = pl_sd->bl.x;
y = pl_sd->bl.y;
break;
case 4:
- mapindex = mapindex_name2id(str);
+ map_index = script->mapindexname2id(st,str);
break;
case 2:
//"SavePoint" uses save point of the currently attached player
- if (( sd = script_rid2sd(st) ) == NULL )
+ if (( sd = script->rid2sd(st) ) == NULL )
return true;
default:
- mapindex = 0;
+ map_index = 0;
break;
}
-
- for (i = 0; i < MAX_PARTY; i++)
- {
+
+ for (i = 0; i < MAX_PARTY; i++) {
if( !(pl_sd = p->data[i].sd) || pl_sd->status.party_id != p_id )
continue;
-
- if( str2 && strcmp(str2, map[pl_sd->bl.m].name) != 0 )
+
+ if( str2 && strcmp(str2, map->list[pl_sd->bl.m].name) != 0 )
continue;
-
+
if( pc_isdead(pl_sd) )
continue;
-
+
switch( type )
{
case 0: // Random
- if(!map[pl_sd->bl.m].flag.nowarp)
+ if(!map->list[pl_sd->bl.m].flag.nowarp)
pc->randomwarp(pl_sd,CLR_TELEPORT);
break;
case 1: // SavePointAll
- if(!map[pl_sd->bl.m].flag.noreturn)
+ if(!map->list[pl_sd->bl.m].flag.noreturn)
pc->setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT);
break;
case 2: // SavePoint
- if(!map[pl_sd->bl.m].flag.noreturn)
+ if(!map->list[pl_sd->bl.m].flag.noreturn)
pc->setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
break;
case 3: // Leader
case 4: // m,x,y
- if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp)
- pc->setpos(pl_sd,mapindex,x,y,CLR_TELEPORT);
+ if(!map->list[pl_sd->bl.m].flag.noreturn && !map->list[pl_sd->bl.m].flag.nowarp)
+ pc->setpos(pl_sd,map_index,x,y,CLR_TELEPORT);
break;
}
}
-
+
return true;
}
/*==========================================
@@ -4774,70 +5460,69 @@ BUILDIN(warpguild)
struct guild* g;
struct s_mapiterator* iter;
int type;
-
+
const char* str = script_getstr(st,2);
int x = script_getnum(st,3);
int y = script_getnum(st,4);
int gid = script_getnum(st,5);
-
+
g = guild->search(gid);
if( g == NULL )
return true;
-
+
type = ( strcmp(str,"Random")==0 ) ? 0
: ( strcmp(str,"SavePointAll")==0 ) ? 1
: ( strcmp(str,"SavePoint")==0 ) ? 2
: 3;
-
- if( type == 2 && ( sd = script_rid2sd(st) ) == NULL )
+
+ if( type == 2 && ( sd = script->rid2sd(st) ) == NULL )
{// "SavePoint" uses save point of the currently attached player
return true;
}
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
if( pl_sd->status.guild_id != gid )
continue;
-
+
switch( type )
{
case 0: // Random
- if(!map[pl_sd->bl.m].flag.nowarp)
+ if(!map->list[pl_sd->bl.m].flag.nowarp)
pc->randomwarp(pl_sd,CLR_TELEPORT);
break;
case 1: // SavePointAll
- if(!map[pl_sd->bl.m].flag.noreturn)
+ if(!map->list[pl_sd->bl.m].flag.noreturn)
pc->setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT);
break;
case 2: // SavePoint
- if(!map[pl_sd->bl.m].flag.noreturn)
+ if(!map->list[pl_sd->bl.m].flag.noreturn)
pc->setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
break;
case 3: // m,x,y
- if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp)
- pc->setpos(pl_sd,mapindex_name2id(str),x,y,CLR_TELEPORT);
+ if(!map->list[pl_sd->bl.m].flag.noreturn && !map->list[pl_sd->bl.m].flag.nowarp)
+ pc->setpos(pl_sd,script->mapindexname2id(st,str),x,y,CLR_TELEPORT);
break;
}
}
mapit->free(iter);
-
+
return true;
}
/*==========================================
* Force Heal a player (hp and sp)
*------------------------------------------*/
-BUILDIN(heal)
-{
+BUILDIN(heal) {
TBL_PC *sd;
int hp,sp;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if (!sd) return true;
-
+
hp=script_getnum(st,2);
sp=script_getnum(st,3);
- status_heal(&sd->bl, hp, sp, 1);
+ status->heal(&sd->bl, hp, sp, 1);
return true;
}
/*==========================================
@@ -4847,17 +5532,17 @@ BUILDIN(itemheal)
{
TBL_PC *sd;
int hp,sp;
-
+
hp=script_getnum(st,2);
sp=script_getnum(st,3);
-
- if(potion_flag==1) {
- potion_hp = hp;
- potion_sp = sp;
+
+ if(script->potion_flag==1) {
+ script->potion_hp = hp;
+ script->potion_sp = sp;
return true;
}
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if (!sd) return true;
pc->itemheal(sd,sd->itemid,hp,sp);
return true;
@@ -4869,17 +5554,17 @@ BUILDIN(percentheal)
{
int hp,sp;
TBL_PC* sd;
-
+
hp=script_getnum(st,2);
sp=script_getnum(st,3);
-
- if(potion_flag==1) {
- potion_per_hp = hp;
- potion_per_sp = sp;
+
+ if(script->potion_flag==1) {
+ script->potion_per_hp = hp;
+ script->potion_per_sp = sp;
return true;
}
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
#ifdef RENEWAL
@@ -4896,22 +5581,22 @@ BUILDIN(percentheal)
BUILDIN(jobchange)
{
int job, upper=-1;
-
+
job=script_getnum(st,2);
if( script_hasdata(st,3) )
upper=script_getnum(st,3);
-
+
if (pcdb_checkid(job))
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
pc->jobchange(sd, job, upper);
}
-
+
return true;
}
@@ -4936,53 +5621,52 @@ BUILDIN(input)
{
TBL_PC* sd;
struct script_data* data;
- int uid;
+ int64 uid;
const char* name;
int min;
int max;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
data = script_getdata(st,2);
- if( !data_isreference(data) ){
+ if( !data_isreference(data) ) {
ShowError("script:input: not a variable\n");
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;
}
uid = reference_getuid(data);
name = reference_getname(data);
- min = (script_hasdata(st,3) ? script_getnum(st,3) : script_config.input_min_value);
- max = (script_hasdata(st,4) ? script_getnum(st,4) : script_config.input_max_value);
-
+ min = (script_hasdata(st,3) ? script_getnum(st,3) : script->config.input_min_value);
+ max = (script_hasdata(st,4) ? script_getnum(st,4) : script->config.input_max_value);
+
#ifdef SECURE_NPCTIMEOUT
sd->npc_idle_type = NPCT_WAIT;
#endif
-
- if( !sd->state.menu_or_input )
- { // first invocation, display npc input box
+
+ if( !sd->state.menu_or_input ) {
+ // first invocation, display npc input box
sd->state.menu_or_input = 1;
st->state = RERUNLINE;
if( is_string_variable(name) )
clif->scriptinputstr(sd,st->oid);
else
clif->scriptinput(sd,st->oid);
- }
- else
- { // take received text/value and store it in the designated variable
+ } else {
+ // take received text/value and store it in the designated variable
sd->state.menu_or_input = 0;
if( is_string_variable(name) )
{
int len = (int)strlen(sd->npc_str);
- set_reg(st, sd, uid, name, (void*)sd->npc_str, script_getref(st,2));
+ script->set_reg(st, sd, uid, name, (void*)sd->npc_str, script_getref(st,2));
script_pushint(st, (len > max ? 1 : len < min ? -1 : 0));
}
else
{
int amount = sd->npc_amount;
- set_reg(st, sd, uid, name, (void*)__64BPTRSIZE(cap_value(amount,min,max)), script_getref(st,2));
+ script->set_reg(st, sd, uid, name, (void*)h64BPTRSIZE(cap_value(amount,min,max)), script_getref(st,2));
script_pushint(st, (amount > max ? 1 : amount < min ? -1 : 0));
}
st->state = RUN;
@@ -4997,75 +5681,81 @@ BUILDIN(copyarray);
/// The value is converted to the type of the variable.
///
/// set(<variable>,<value>) -> <variable>
-BUILDIN(set)
-{
+BUILDIN(setr) {
TBL_PC* sd = NULL;
struct script_data* data;
//struct script_data* datavalue;
- int num;
+ int64 num;
const char* name;
char prefix;
-
+
data = script_getdata(st,2);
//datavalue = script_getdata(st,3);
- if( !data_isreference(data) )
- {
+ if( !data_isreference(data) || reference_toconstant(data) ) {
ShowError("script:set: not a variable\n");
- script_reportdata(script_getdata(st,2));
+ script->reportdata(script_getdata(st,2));
st->state = END;
return false;
}
-
+
num = reference_getuid(data);
name = reference_getname(data);
prefix = *name;
-
- if( not_server_variable(prefix) )
- {
- sd = script_rid2sd(st);
- if( sd == NULL )
- {
+
+ if( not_server_variable(prefix) ) {
+ sd = script->rid2sd(st);
+ if( sd == NULL ) {
ShowError("script:set: no player attached for player variable '%s'\n", name);
return true;
}
}
-
+
#if 0
- if( data_isreference(datavalue) )
- {// the value being referenced is a variable
+ // TODO: see de43fa0f73be01080bd11c08adbfb7c158324c81
+ if( data_isreference(datavalue) ) {
+ // the value being referenced is a variable
const char* namevalue = reference_getname(datavalue);
-
- if( !not_array_variable(*namevalue) )
- {// array variable being copied into another array variable
- if( sd == NULL && not_server_variable(*namevalue) && !(sd = script_rid2sd(st)) )
- {// player must be attached in order to copy a player variable
+
+ if( !not_array_variable(*namevalue) ) {
+ // array variable being copied into another array variable
+ if( sd == NULL && not_server_variable(*namevalue) && !(sd = script->rid2sd(st)) ) {
+ // player must be attached in order to copy a player variable
ShowError("script:set: no player attached for player variable '%s'\n", namevalue);
return true;
}
-
- if( is_string_variable(namevalue) != is_string_variable(name) )
- {// non-matching array value types
+
+ if( is_string_variable(namevalue) != is_string_variable(name) ) {
+ // non-matching array value types
ShowWarning("script:set: two array variables do not match in type.\n");
return true;
}
-
+
// push the maximum number of array values to the stack
script->push_val(st->stack, C_INT, SCRIPT_MAX_ARRAYSIZE,NULL);
-
+
// call the copy array method directly
return buildin_copyarray(st);
}
}
#endif
-
+
+ if( script_hasdata(st, 4) ) {
+ // Optional argument used by post-increment/post-decrement constructs to return the previous value
+ if( is_string_variable(name) ) {
+ script_pushstrcopy(st, script_getstr(st, 4));
+ } else {
+ script_pushint(st, script_getnum(st, 4));
+ }
+ } else {
+ // return a copy of the variable reference
+ script_pushcopy(st,2);
+ }
+
if( is_string_variable(name) )
- set_reg(st,sd,num,name,(void*)script_getstr(st,3),script_getref(st,2));
+ script->set_reg(st,sd,num,name,(void*)script_getstr(st,3),script_getref(st,2));
else
- set_reg(st,sd,num,name,(void*)__64BPTRSIZE(script_getnum(st,3)),script_getref(st,2));
-
- // return a copy of the variable reference
- script_pushcopy(st,2);
-
+ script->set_reg(st,sd,num,name,(void*)h64BPTRSIZE(script_getnum(st,3)),script_getref(st,2));
+
return true;
}
@@ -5073,34 +5763,6 @@ BUILDIN(set)
/// Array variables
///
-/// Returns the size of the specified array
-static int32 getarraysize(struct script_state* st, int32 id, int32 idx, int isstring, struct DBMap** ref)
-{
- int32 ret = idx;
-
- if( isstring )
- {
- for( ; idx < SCRIPT_MAX_ARRAYSIZE; ++idx )
- {
- char* str = (char*)script->get_val2(st, reference_uid(id, idx), ref);
- if( str && *str )
- ret = idx + 1;
- script_removetop(st, -1, 0);
- }
- }
- else
- {
- for( ; idx < SCRIPT_MAX_ARRAYSIZE; ++idx )
- {
- int32 num = (int32)__64BPTRSIZE(script->get_val2(st, reference_uid(id, idx), ref));
- if( num )
- ret = idx + 1;
- script_removetop(st, -1, 0);
- }
- }
- return ret;
-}
-
/// Sets values of an array, from the starting index.
/// ex: setarray arr[1],1,2,3;
///
@@ -5109,52 +5771,45 @@ BUILDIN(setarray)
{
struct script_data* data;
const char* name;
- int32 start;
- int32 end;
+ uint32 start;
+ uint32 end;
int32 id;
int32 i;
TBL_PC* sd = NULL;
-
+
data = script_getdata(st, 2);
- if( !data_isreference(data) )
+ if( !data_isreference(data) || reference_toconstant(data) )
{
ShowError("script:setarray: not a variable\n");
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;// not a variable
}
-
+
id = reference_getid(data);
start = reference_getindex(data);
name = reference_getname(data);
- if( not_array_variable(*name) )
- {
- ShowError("script:setarray: illegal scope\n");
- script_reportdata(data);
- st->state = END;
- return false;// not supported
- }
-
+
if( not_server_variable(*name) )
{
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached
}
-
+
end = start + script_lastdata(st) - 2;
if( end > SCRIPT_MAX_ARRAYSIZE )
end = SCRIPT_MAX_ARRAYSIZE;
-
+
if( is_string_variable(name) )
{// string array
for( i = 3; start < end; ++start, ++i )
- set_reg(st, sd, reference_uid(id, start), name, (void*)script_getstr(st,i), reference_getref(data));
+ script->set_reg(st, sd, reference_uid(id, start), name, (void*)script_getstr(st,i), reference_getref(data));
}
else
{// int array
for( i = 3; start < end; ++start, ++i )
- set_reg(st, sd, reference_uid(id, start), name, (void*)__64BPTRSIZE(script_getnum(st,i)), reference_getref(data));
+ script->set_reg(st, sd, reference_uid(id, start), name, (void*)h64BPTRSIZE(script_getnum(st,i)), reference_getref(data));
}
return true;
}
@@ -5167,50 +5822,43 @@ BUILDIN(cleararray)
{
struct script_data* data;
const char* name;
- int32 start;
- int32 end;
+ uint32 start;
+ uint32 end;
int32 id;
void* v;
TBL_PC* sd = NULL;
-
+
data = script_getdata(st, 2);
if( !data_isreference(data) )
{
ShowError("script:cleararray: not a variable\n");
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;// not a variable
}
-
+
id = reference_getid(data);
start = reference_getindex(data);
name = reference_getname(data);
- if( not_array_variable(*name) )
- {
- ShowError("script:cleararray: illegal scope\n");
- script_reportdata(data);
- st->state = END;
- return false;// not supported
- }
-
+
if( not_server_variable(*name) )
{
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached
}
-
+
if( is_string_variable(name) )
v = (void*)script_getstr(st, 3);
else
- v = (void*)__64BPTRSIZE(script_getnum(st, 3));
-
+ v = (void*)h64BPTRSIZE(script_getnum(st, 3));
+
end = start + script_getnum(st, 4);
if( end > SCRIPT_MAX_ARRAYSIZE )
end = SCRIPT_MAX_ARRAYSIZE;
-
+
for( ; start < end; ++start )
- set_reg(st, sd, reference_uid(id, start), name, v, script_getref(st,2));
+ script->set_reg(st, sd, reference_uid(id, start), name, v, script_getref(st,2));
return true;
}
@@ -5230,78 +5878,67 @@ BUILDIN(copyarray)
int32 id2;
void* v;
int32 i;
- int32 count;
+ uint32 count;
TBL_PC* sd = NULL;
-
+
data1 = script_getdata(st, 2);
data2 = script_getdata(st, 3);
if( !data_isreference(data1) || !data_isreference(data2) )
{
ShowError("script:copyarray: not a variable\n");
- script_reportdata(data1);
- script_reportdata(data2);
+ script->reportdata(data1);
+ script->reportdata(data2);
st->state = END;
return false;// not a variable
}
-
+
id1 = reference_getid(data1);
id2 = reference_getid(data2);
idx1 = reference_getindex(data1);
idx2 = reference_getindex(data2);
name1 = reference_getname(data1);
name2 = reference_getname(data2);
- if( not_array_variable(*name1) || not_array_variable(*name2) )
- {
- ShowError("script:copyarray: illegal scope\n");
- script_reportdata(data1);
- script_reportdata(data2);
- st->state = END;
- return false;// not supported
- }
-
+
if( is_string_variable(name1) != is_string_variable(name2) )
{
ShowError("script:copyarray: type mismatch\n");
- script_reportdata(data1);
- script_reportdata(data2);
+ script->reportdata(data1);
+ script->reportdata(data2);
st->state = END;
return false;// data type mismatch
}
-
+
if( not_server_variable(*name1) || not_server_variable(*name2) )
{
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached
}
-
+
count = script_getnum(st, 4);
if( count > SCRIPT_MAX_ARRAYSIZE - idx1 )
count = SCRIPT_MAX_ARRAYSIZE - idx1;
- if( count <= 0 || (id1 == id2 && idx1 == idx2) )
+ if( count <= 0 || (idx1 == idx2 && is_same_reference(data1, data2)) )
return true;// nothing to copy
-
- if( id1 == id2 && idx1 > idx2 )
- {// destination might be overlapping the source - copy in reverse order
- for( i = count - 1; i >= 0; --i )
- {
+
+ if( is_same_reference(data1, data2) && idx1 > idx2 ) {
+ // destination might be overlapping the source - copy in reverse order
+ for( i = count - 1; i >= 0; --i ) {
v = script->get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2));
- set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1));
+ script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1));
script_removetop(st, -1, 0);
}
- }
- else
- {// normal copy
- for( i = 0; i < count; ++i )
- {
- if( idx2 + i < SCRIPT_MAX_ARRAYSIZE )
- {
+ } else {
+ // normal copy
+ for( i = 0; i < count; ++i ) {
+ if( idx2 + i < SCRIPT_MAX_ARRAYSIZE ) {
v = script->get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2));
- set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1));
+ script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1));
script_removetop(st, -1, 0);
+ } else {
+ // out of range - assume ""/0
+ script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, (is_string_variable(name1)?(void*)"":(void*)0), reference_getref(data1));
}
- else// out of range - assume ""/0
- set_reg(st, sd, reference_uid(id1, idx1 + i), name1, (is_string_variable(name1)?(void*)"":(void*)0), reference_getref(data1));
}
}
return true;
@@ -5315,31 +5952,23 @@ BUILDIN(copyarray)
BUILDIN(getarraysize)
{
struct script_data* data;
- const char* name;
-
+
data = script_getdata(st, 2);
if( !data_isreference(data) )
{
ShowError("script:getarraysize: not a variable\n");
- script_reportdata(data);
+ script->reportdata(data);
script_pushnil(st);
st->state = END;
return false;// not a variable
}
-
- name = reference_getname(data);
- if( not_array_variable(*name) )
- {
- ShowError("script:getarraysize: illegal scope\n");
- script_reportdata(data);
- script_pushnil(st);
- st->state = END;
- return false;// not supported
- }
-
- script_pushint(st, getarraysize(st, reference_getid(data), reference_getindex(data), is_string_variable(name), reference_getref(data)));
+
+ script_pushint(st, script->array_highest_key(st,st->rid ? script->rid2sd(st) : NULL,reference_getname(data),reference_getref(data)));
return true;
}
+int script_array_index_cmp(const void *a, const void *b) {
+ return ( *(unsigned int*)a - *(unsigned int*)b );
+}
/// Deletes count or all the elements in an array, from the starting index.
/// ex: deletearray arr[4],2;
@@ -5350,71 +5979,109 @@ BUILDIN(deletearray)
{
struct script_data* data;
const char* name;
- int start;
- int end;
+ unsigned int start, end, i;
int id;
TBL_PC *sd = NULL;
-
+ struct script_array *sa = NULL;
+ struct reg_db *src = NULL;
+ void *value;
+
data = script_getdata(st, 2);
if( !data_isreference(data) )
{
ShowError("script:deletearray: not a variable\n");
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;// not a variable
}
-
+
id = reference_getid(data);
start = reference_getindex(data);
name = reference_getname(data);
- if( not_array_variable(*name) )
- {
- ShowError("script:deletearray: illegal scope\n");
- script_reportdata(data);
- st->state = END;
- return false;// not supported
- }
-
+
if( not_server_variable(*name) )
{
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached
}
+
+ if( !(src = script->array_src(st,sd,name, reference_getref(data)) ) ) {
+ ShowError("script:deletearray: not a array\n");
+ script->reportdata(data);
+ st->state = END;
+ return false;// not a variable
+ }
- end = SCRIPT_MAX_ARRAYSIZE;
+ script->array_ensure_zero(st,NULL,data->u.num,reference_getref(data));
+
+ if ( !(sa = idb_get(src->arrays, id)) ) { /* non-existent array, nothing to empty */
+ return true;// not a variable
+ }
+
+ end = script->array_highest_key(st,sd,name,reference_getref(data));
if( start >= end )
return true;// nothing to free
+
+ if( is_string_variable(name) )
+ value = (void *)"";
+ else
+ value = (void *)0;
- if( script_hasdata(st,3) )
- {
- int count = script_getnum(st, 3);
+ if( script_hasdata(st,3) ) {
+ unsigned int count = script_getnum(st, 3);
if( count > end - start )
count = end - start;
if( count <= 0 )
return true;// nothing to free
+
+ if( end - start < sa->size ) {
+ // Better to iterate directly on the array, no speed-up from using sa
+ for( ; start + count < end; ++start ) {
+ // Compact and overwrite
+ void* v = script->get_val2(st, reference_uid(id, start + count), reference_getref(data));
+ script->set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data));
+ script_removetop(st, -1, 0);
+ }
+ for( ; start < end; start++ ) {
+ // Clean up any leftovers that weren't overwritten
+ script->set_reg(st, sd, reference_uid(id, start), name, value, reference_getref(data));
+ }
+ } else {
+ // using sa to speed up
+ unsigned int *list = NULL, size = 0;
+ list = script->array_cpy_list(sa);
+ size = sa->size;
+ qsort(list, size, sizeof(unsigned int), script_array_index_cmp);
+
+ ARR_FIND(0, size, i, list[i] >= start);
+
+ for( ; i < size && list[i] < start + count; i++ ) {
+ // Clear any entries between start and start+count, if they exist
+ script->set_reg(st, sd, reference_uid(id, list[i]), name, value, reference_getref(data));
+ }
+
+ for( ; i < size && list[i] < end; i++ ) {
+ // Move back count positions any entries between start+count to fill the gaps
+ void* v = script->get_val2(st, reference_uid(id, list[i]), reference_getref(data));
+ script->set_reg(st, sd, reference_uid(id, list[i]-count), name, v, reference_getref(data));
+ script_removetop(st, -1, 0);
+ // Clear their originals
+ script->set_reg(st, sd, reference_uid(id, list[i]), name, value, reference_getref(data));
+ }
+ }
+ } else {
+ unsigned int *list = NULL, size = 0;
+ list = script->array_cpy_list(sa);
+ size = sa->size;
- // move rest of the elements backward
- for( ; start + count < end; ++start )
- {
- void* v = script->get_val2(st, reference_uid(id, start + count), reference_getref(data));
- set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data));
- script_removetop(st, -1, 0);
+ for(i = 0; i < size; i++) {
+ if( list[i] >= start ) // Less expensive than sorting it, most likely
+ script->set_reg(st, sd, reference_uid(id, list[i]), name, value, reference_getref(data));
}
}
-
- // clear the rest of the array
- if( is_string_variable(name) )
- {
- for( ; start < end; ++start )
- set_reg(st, sd, reference_uid(id, start), name, (void *)"", reference_getref(data));
- }
- else
- {
- for( ; start < end; ++start )
- set_reg(st, sd, reference_uid(id, start), name, (void*)0, reference_getref(data));
- }
+
return true;
}
@@ -5425,42 +6092,31 @@ BUILDIN(deletearray)
BUILDIN(getelementofarray)
{
struct script_data* data;
- const char* name;
int32 id;
- int i;
-
+ int64 i;
+
data = script_getdata(st, 2);
if( !data_isreference(data) )
{
ShowError("script:getelementofarray: not a variable\n");
- script_reportdata(data);
+ script->reportdata(data);
script_pushnil(st);
st->state = END;
return false;// not a variable
}
-
+
id = reference_getid(data);
- name = reference_getname(data);
- if( not_array_variable(*name) )
- {
- ShowError("script:getelementofarray: illegal scope\n");
- script_reportdata(data);
- script_pushnil(st);
- st->state = END;
- return false;// not supported
- }
-
+
i = script_getnum(st, 3);
- if( i < 0 || i >= SCRIPT_MAX_ARRAYSIZE )
- {
- ShowWarning("script:getelementofarray: index out of range (%d)\n", i);
- script_reportdata(data);
+ if (i < 0 || i >= SCRIPT_MAX_ARRAYSIZE) {
+ ShowWarning("script:getelementofarray: index out of range (%"PRId64")\n", i);
+ script->reportdata(data);
script_pushnil(st);
st->state = END;
return false;// out of range
}
-
- script->push_val(st->stack, C_NAME, reference_uid(id, i), reference_getref(data));
+
+ script->push_val(st->stack, C_NAME, reference_uid(id, (unsigned int)i), reference_getref(data));
return true;
}
@@ -5475,16 +6131,16 @@ BUILDIN(setlook)
{
int type,val;
TBL_PC* sd;
-
+
type=script_getnum(st,2);
val=script_getnum(st,3);
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
pc->changelook(sd,type,val);
-
+
return true;
}
@@ -5492,16 +6148,16 @@ BUILDIN(changelook)
{ // As setlook but only client side
int type,val;
TBL_PC* sd;
-
+
type=script_getnum(st,2);
val=script_getnum(st,3);
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
clif->changelook(&sd->bl,type,val);
-
+
return true;
}
@@ -5511,11 +6167,11 @@ BUILDIN(changelook)
BUILDIN(cutin)
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
clif->cutin(sd,script_getstr(st,2),script_getnum(st,3));
return true;
}
@@ -5527,104 +6183,86 @@ BUILDIN(viewpoint)
{
int type,x,y,id,color;
TBL_PC* sd;
-
+
type=script_getnum(st,2);
x=script_getnum(st,3);
y=script_getnum(st,4);
id=script_getnum(st,5);
color=script_getnum(st,6);
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
clif->viewpoint(sd,st->oid,type,x,y,id,color);
-
+
return true;
}
/*==========================================
*
*------------------------------------------*/
-BUILDIN(countitem)
-{
+BUILDIN(countitem) {
int nameid, i;
int count = 0;
struct item_data* id = NULL;
- struct script_data* data;
-
- TBL_PC* sd = script_rid2sd(st);
- if (!sd) {
- script_pushint(st,0);
+
+ TBL_PC* sd = script->rid2sd(st);
+ if( !sd )
return true;
+
+ if( script_isstringtype(st, 2) ) {
+ // item name
+ id = itemdb->search_name(script_getstr(st, 2));
+ } else {
+ // item id
+ id = itemdb->exists(script_getnum(st, 2));
}
-
- data = script_getdata(st,2);
- script->get_val(st, data); // convert into value in case of a variable
-
- if( data_isstring(data) )
- {// item name
- id = itemdb_searchname(script->conv_str(st, data));
- }
- else
- {// item id
- id = itemdb_exists(script->conv_num(st, data));
- }
-
- if( id == NULL )
- {
+
+ if( id == NULL ) {
ShowError("buildin_countitem: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was
script_pushint(st,0);
return false;
}
-
+
nameid = id->nameid;
-
+
for(i = 0; i < MAX_INVENTORY; i++)
if(sd->status.inventory[i].nameid == nameid)
count += sd->status.inventory[i].amount;
-
+
script_pushint(st,count);
return true;
}
/*==========================================
- * countitem2(nameID,Identified,Refine,Attribute,Card0,Card1,Card2,Card3) [Lupus]
- * returns number of items that meet the conditions
+ * countitem2(nameID,Identified,Refine,Attribute,Card0,Card1,Card2,Card3) [Lupus]
+ * returns number of items that meet the conditions
*------------------------------------------*/
-BUILDIN(countitem2)
-{
+BUILDIN(countitem2) {
int nameid, iden, ref, attr, c1, c2, c3, c4;
int count = 0;
int i;
struct item_data* id = NULL;
- struct script_data* data;
-
- TBL_PC* sd = script_rid2sd(st);
- if (!sd) {
- script_pushint(st,0);
+
+ TBL_PC* sd = script->rid2sd(st);
+ if( !sd )
return true;
+
+ if( script_isstringtype(st, 2) ) {
+ // item name
+ id = itemdb->search_name(script_getstr(st, 2));
+ } else {
+ // item id
+ id = itemdb->exists(script_getnum(st, 2));
}
-
- data = script_getdata(st,2);
- script->get_val(st, data); // convert into value in case of a variable
-
- if( data_isstring(data) )
- {// item name
- id = itemdb_searchname(script->conv_str(st, data));
- }
- else
- {// item id
- id = itemdb_exists(script->conv_num(st, data));
- }
-
- if( id == NULL )
- {
+
+ if( id == NULL ) {
ShowError("buildin_countitem2: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was
script_pushint(st,0);
return false;
}
-
+
nameid = id->nameid;
iden = script_getnum(st,3);
ref = script_getnum(st,4);
@@ -5633,7 +6271,7 @@ BUILDIN(countitem2)
c2 = (short)script_getnum(st,7);
c3 = (short)script_getnum(st,8);
c4 = (short)script_getnum(st,9);
-
+
for(i = 0; i < MAX_INVENTORY; i++)
if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] != NULL &&
sd->status.inventory[i].amount > 0 && sd->status.inventory[i].nameid == nameid &&
@@ -5643,7 +6281,7 @@ BUILDIN(countitem2)
sd->status.inventory[i].card[3] == c4
)
count += sd->status.inventory[i].amount;
-
+
script_pushint(st,count);
return true;
}
@@ -5652,8 +6290,8 @@ BUILDIN(countitem2)
* Check if item with this amount can fit in inventory
* Checking : weight, stack amount >32k, slots amount >(MAX_INVENTORY)
* Return
- * 0 : fail
- * 1 : success (npc side only)
+ * 0 : fail
+ * 1 : success (npc side only)
*------------------------------------------*/
BUILDIN(checkweight)
{
@@ -5661,73 +6299,76 @@ BUILDIN(checkweight)
unsigned int weight=0, i, nbargs;
struct item_data* id = NULL;
struct map_session_data* sd;
- struct script_data* data;
-
- if( ( sd = script_rid2sd(st) ) == NULL ){
+
+ if( ( sd = script->rid2sd(st) ) == NULL ) {
return true;
}
nbargs = script_lastdata(st)+1;
- if(nbargs%2){
- ShowError("buildin_checkweight: Invalid nb of args should be a multiple of 2.\n");
- script_pushint(st,0);
- return false;
+ if(nbargs%2) {
+ ShowError("buildin_checkweight: Invalid nb of args should be a multiple of 2.\n");
+ script_pushint(st,0);
+ return false;
}
slots = pc->inventoryblank(sd); //nb of empty slot
-
- for(i=2; i<nbargs; i=i+2){
- data = script_getdata(st,i);
- script->get_val(st, data); // convert into value in case of a variable
- if( data_isstring(data) ){// item name
- id = itemdb_searchname(script->conv_str(st, data));
- } else {// item id
- id = itemdb_exists(script->conv_num(st, data));
- }
- if( id == NULL ) {
- ShowError("buildin_checkweight: Invalid item '%s'.\n", script_getstr(st,i)); // returns string, regardless of what it was
- script_pushint(st,0);
- return false;
- }
- nameid = id->nameid;
-
- amount = script_getnum(st,i+1);
- if( amount < 1 ) {
- ShowError("buildin_checkweight: Invalid amount '%d'.\n", amount);
- script_pushint(st,0);
- return false;
- }
-
- weight += itemdb_weight(nameid)*amount; //total weight for all chk
- if( weight + sd->weight > sd->max_weight )
- {// too heavy
- script_pushint(st,0);
- return true;
- }
-
- switch( pc->checkadditem(sd, nameid, amount) )
- {
- case ADDITEM_EXIST:
- // item is already in inventory, but there is still space for the requested amount
- break;
- case ADDITEM_NEW:
- if( itemdb_isstackable(nameid) ) {// stackable
- amount2++;
- if( slots < amount2 ) {
- script_pushint(st,0);
- return true;
- }
- }
- else {// non-stackable
- amount2 += amount;
- if( slots < amount2){
- script_pushint(st,0);
- return true;
- }
- }
- break;
- case ADDITEM_OVERAMOUNT:
- script_pushint(st,0);
- return true;
- }
+
+ for( i = 2; i < nbargs; i += 2 ) {
+ if( script_isstringtype(st, i) ) {
+ // item name
+ id = itemdb->search_name(script_getstr(st, i));
+ } else if ( script_isinttype(st, i) ) {
+ // item id
+ id = itemdb->exists(script_getnum(st, i));
+ } else {
+ ShowError("buildin_checkweight: invalid type for argument '%d'.\n", i);
+ script_pushint(st,0);
+ return false;
+ }
+ if( id == NULL ) {
+ ShowError("buildin_checkweight: Invalid item '%s'.\n", script_getstr(st,i)); // returns string, regardless of what it was
+ script_pushint(st,0);
+ return false;
+ }
+ nameid = id->nameid;
+
+ amount = script_getnum(st,i+1);
+ if( amount < 1 ) {
+ ShowError("buildin_checkweight: Invalid amount '%d'.\n", amount);
+ script_pushint(st,0);
+ return false;
+ }
+
+ weight += itemdb_weight(nameid)*amount; //total weight for all chk
+ if( weight + sd->weight > sd->max_weight )
+ {// too heavy
+ script_pushint(st,0);
+ return true;
+ }
+
+ switch( pc->checkadditem(sd, nameid, amount) ) {
+ case ADDITEM_EXIST:
+ // item is already in inventory, but there is still space for the requested amount
+ break;
+ case ADDITEM_NEW:
+ if( itemdb->isstackable(nameid) ) {
+ // stackable
+ amount2++;
+ if( slots < amount2 ) {
+ script_pushint(st,0);
+ return true;
+ }
+ } else {
+ // non-stackable
+ amount2 += amount;
+ if( slots < amount2) {
+ script_pushint(st,0);
+ return true;
+ }
+ }
+ break;
+ case ADDITEM_OVERAMOUNT:
+ script_pushint(st,0);
+ return true;
+ }
}
script_pushint(st,1);
return true;
@@ -5739,7 +6380,7 @@ BUILDIN(checkweight2)
int32 nameid=-1, amount=-1;
int i=0, amount2=0, slots=0, weight=0;
short fail=0;
-
+
//variable for array parsing
struct script_data* data_it;
struct script_data* data_nb;
@@ -5748,13 +6389,15 @@ BUILDIN(checkweight2)
int32 id_it, id_nb;
int32 idx_it, idx_nb;
int nb_it, nb_nb; //array size
-
- TBL_PC *sd = script_rid2sd(st);
- nullpo_retr(1,sd);
-
+
+ TBL_PC *sd = script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
data_it = script_getdata(st, 2);
data_nb = script_getdata(st, 3);
-
+
if( !data_isreference(data_it) || !data_isreference(data_nb))
{
ShowError("script:checkweight2: parameter not a variable\n");
@@ -5767,70 +6410,64 @@ BUILDIN(checkweight2)
idx_nb = reference_getindex(data_nb);
name_it = reference_getname(data_it);
name_nb = reference_getname(data_nb);
-
- if( not_array_variable(*name_it) || not_array_variable(*name_nb))
- {
- ShowError("script:checkweight2: illegal scope\n");
- script_pushint(st,0);
- return false;// not supported
- }
- if(is_string_variable(name_it) || is_string_variable(name_nb)){
+
+ if(is_string_variable(name_it) || is_string_variable(name_nb)) {
ShowError("script:checkweight2: illegal type, need int\n");
script_pushint(st,0);
return false;// not supported
}
- nb_it = getarraysize(st, id_it, idx_it, 0, reference_getref(data_it));
- nb_nb = getarraysize(st, id_nb, idx_nb, 0, reference_getref(data_nb));
- if(nb_it != nb_nb){
+ nb_it = script->array_highest_key(st,sd,reference_getname(data_it),reference_getref(data_it));
+ nb_nb = script->array_highest_key(st,sd,reference_getname(data_nb),reference_getref(data_nb));
+ if(nb_it != nb_nb) {
ShowError("Size mistmatch: nb_it=%d, nb_nb=%d\n",nb_it,nb_nb);
fail = 1;
}
-
+
slots = pc->inventoryblank(sd);
- for(i=0; i<nb_it; i++){
- nameid = (int32)__64BPTRSIZE(script->get_val2(st,reference_uid(id_it,idx_it+i),reference_getref(data_it)));
- script_removetop(st, -1, 0);
- amount = (int32)__64BPTRSIZE(script->get_val2(st,reference_uid(id_nb,idx_nb+i),reference_getref(data_nb)));
- script_removetop(st, -1, 0);
- if(fail) continue; //cpntonie to depop rest
-
- if(itemdb_exists(nameid) == NULL ){
+ for(i=0; i<nb_it; i++) {
+ nameid = (int32)h64BPTRSIZE(script->get_val2(st,reference_uid(id_it,idx_it+i),reference_getref(data_it)));
+ script_removetop(st, -1, 0);
+ amount = (int32)h64BPTRSIZE(script->get_val2(st,reference_uid(id_nb,idx_nb+i),reference_getref(data_nb)));
+ script_removetop(st, -1, 0);
+ if(fail) continue; //cpntonie to depop rest
+
+ if(itemdb->exists(nameid) == NULL ) {
ShowError("buildin_checkweight2: Invalid item '%d'.\n", nameid);
fail=1;
continue;
}
- if(amount < 0 ){
+ if(amount < 0 ) {
ShowError("buildin_checkweight2: Invalid amount '%d'.\n", amount);
fail = 1;
continue;
}
- weight += itemdb_weight(nameid)*amount;
- if( weight + sd->weight > sd->max_weight ){
+ weight += itemdb_weight(nameid)*amount;
+ if( weight + sd->weight > sd->max_weight ) {
fail = 1;
continue;
- }
- switch( pc->checkadditem(sd, nameid, amount) ) {
- case ADDITEM_EXIST:
+ }
+ switch( pc->checkadditem(sd, nameid, amount) ) {
+ case ADDITEM_EXIST:
// item is already in inventory, but there is still space for the requested amount
- break;
- case ADDITEM_NEW:
- if( itemdb_isstackable(nameid) ){// stackable
- amount2++;
- if( slots < amount2 )
- fail = 1;
- }
- else {// non-stackable
- amount2 += amount;
- if( slots < amount2 ){
- fail = 1;
- }
- }
- break;
- case ADDITEM_OVERAMOUNT:
- fail = 1;
- } //end switch
+ break;
+ case ADDITEM_NEW:
+ if( itemdb->isstackable(nameid) ) {// stackable
+ amount2++;
+ if( slots < amount2 )
+ fail = 1;
+ }
+ else {// non-stackable
+ amount2 += amount;
+ if( slots < amount2 ) {
+ fail = 1;
+ }
+ }
+ break;
+ case ADDITEM_OVERAMOUNT:
+ fail = 1;
+ } //end switch
} //end loop DO NOT break it prematurly we need to depop all stack
-
+
fail?script_pushint(st,0):script_pushint(st,1);
return true;
}
@@ -5838,115 +6475,128 @@ BUILDIN(checkweight2)
/*==========================================
* getitem <item id>,<amount>{,<account ID>};
* getitem "<item name>",<amount>{,<account ID>};
+ *
+ * getitembound <item id>,<amount>,<type>{,<account ID>};
+ * getitembound "<item id>",<amount>,<type>{,<account ID>};
*------------------------------------------*/
-BUILDIN(getitem)
-{
- int nameid,amount,get_count,i,flag = 0;
+BUILDIN(getitem) {
+ int nameid,amount,get_count,i,flag = 0, offset = 0;
struct item it;
TBL_PC *sd;
- struct script_data *data;
struct item_data *item_data;
-
- data=script_getdata(st,2);
- script->get_val(st,data);
- if( data_isstring(data) )
- {// "<item name>"
- const char *name=script->conv_str(st,data);
- if( (item_data = itemdb_searchname(name)) == NULL ){
- ShowError("buildin_getitem: Nonexistant item %s requested.\n", name);
+
+ if( script_isstringtype(st, 2) ) {
+ // "<item name>"
+ const char *name = script_getstr(st, 2);
+ if( (item_data = itemdb->search_name(name)) == NULL ) {
+ ShowError("buildin_%s: Nonexistant item %s requested.\n", script->getfuncname(st), name);
return false; //No item created.
}
nameid=item_data->nameid;
- } else if( data_isint(data) ) {// <item id>
- nameid=script->conv_num(st,data);
+ } else {
+ // <item id>
+ nameid = script_getnum(st, 2);
//Violet Box, Blue Box, etc - random item pick
if( nameid < 0 ) {
nameid = -nameid;
flag = 1;
}
- if( nameid <= 0 || !(item_data = itemdb_exists(nameid)) ){
- ShowError("buildin_getitem: Nonexistant item %d requested.\n", nameid);
+ if( nameid <= 0 || !(item_data = itemdb->exists(nameid)) ) {
+ ShowError("buildin_%s: Nonexistant item %d requested.\n", script->getfuncname(st), nameid);
return false; //No item created.
}
- } else {
- ShowError("buildin_getitem: invalid data type for argument #1 (%d).", data->type);
- return false;
}
-
+
// <amount>
if( (amount=script_getnum(st,3)) <= 0)
return true; //return if amount <=0, skip the useles iteration
-
+
memset(&it,0,sizeof(it));
it.nameid=nameid;
+
if(!flag)
it.identify=1;
else
- it.identify=itemdb_isidentified2(item_data);
-
- if( script_hasdata(st,4) )
- sd=iMap->id2sd(script_getnum(st,4)); // <Account ID>
+ it.identify=itemdb->isidentified2(item_data);
+
+ if( !strcmp(script->getfuncname(st),"getitembound") ) {
+ int bound = script_getnum(st,4);
+ if( bound < IBT_MIN || bound > IBT_MAX ) { //Not a correct bound type
+ ShowError("script_getitembound: Not a correct bound type! Type=%d\n",bound);
+ return false;
+ }
+ if( item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR ) {
+ ShowError("script_getitembound: can't bind a pet egg/armor! Type=%d\n",bound);
+ return false;
+ }
+ it.bound = (unsigned char)bound;
+ offset += 1;
+ }
+
+ if( script_hasdata(st,4+offset) )
+ sd=map->id2sd(script_getnum(st,4+offset)); // <Account ID>
else
- sd=script_rid2sd(st); // Attached player
-
+ sd=script->rid2sd(st); // Attached player
+
if( sd == NULL ) // no target
return true;
-
+
//Check if it's stackable.
- if (!itemdb_isstackable(nameid))
+ if (!itemdb->isstackable(nameid))
get_count = 1;
else
get_count = amount;
-
- for (i = 0; i < amount; i += get_count)
- {
+
+ for (i = 0; i < amount; i += get_count) {
// if not pet egg
- if (!pet_create_egg(sd, nameid))
- {
- if ((flag = pc->additem(sd, &it, get_count, LOG_TYPE_SCRIPT)))
- {
+ if (!pet->create_egg(sd, nameid)) {
+ if ((flag = pc->additem(sd, &it, get_count, LOG_TYPE_SCRIPT))) {
clif->additem(sd, 0, 0, flag);
if( pc->candrop(sd,&it) )
- iMap->addflooritem(&it,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&it,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
}
-
+
return true;
}
/*==========================================
*
*------------------------------------------*/
-BUILDIN(getitem2)
-{
- int nameid,amount,get_count,i,flag = 0;
- int iden,ref,attr,c1,c2,c3,c4;
- struct item_data *item_data;
- struct item item_tmp;
+BUILDIN(getitem2) {
+ int nameid,amount,i,flag = 0, offset = 0;
+ int iden,ref,attr,c1,c2,c3,c4, bound = 0;
TBL_PC *sd;
- struct script_data *data;
-
- if( script_hasdata(st,11) )
- sd=iMap->id2sd(script_getnum(st,11)); // <Account ID>
+
+ if( !strcmp(script->getfuncname(st),"getitembound2") ) {
+ bound = script_getnum(st,11);
+ if( bound < IBT_MIN || bound > IBT_MAX ) { //Not a correct bound type
+ ShowError("script_getitembound2: Not a correct bound type! Type=%d\n",bound);
+ return false;
+ }
+ offset += 1;
+ }
+
+ if( script_hasdata(st,11+offset) )
+ sd=map->id2sd(script_getnum(st,11+offset)); // <Account ID>
else
- sd=script_rid2sd(st); // Attached player
-
+ sd=script->rid2sd(st); // Attached player
+
if( sd == NULL ) // no target
return true;
-
- data=script_getdata(st,2);
- script->get_val(st,data);
- if( data_isstring(data) ){
- const char *name=script->conv_str(st,data);
- struct item_data *item_data = itemdb_searchname(name);
+
+ if( script_isstringtype(st, 2) ) {
+ const char *name = script_getstr(st, 2);
+ struct item_data *item_data = itemdb->search_name(name);
if( item_data )
nameid=item_data->nameid;
else
nameid=UNKNOWN_ITEM_ID;
- }else
- nameid=script->conv_num(st,data);
-
+ } else {
+ nameid = script_getnum(st, 2);
+ }
+
amount=script_getnum(st,3);
iden=script_getnum(st,4);
ref=script_getnum(st,5);
@@ -5955,18 +6605,25 @@ BUILDIN(getitem2)
c2=(short)script_getnum(st,8);
c3=(short)script_getnum(st,9);
c4=(short)script_getnum(st,10);
-
+
+ if (bound && (itemdb_type(nameid) == IT_PETEGG || itemdb_type(nameid) == IT_PETARMOR)) {
+ ShowError("script_getitembound2: can't bind a pet egg/armor! Type=%d\n",bound);
+ return false;
+ }
+
if(nameid<0) { // Invalide nameid
nameid = -nameid;
flag = 1;
}
-
+
if(nameid > 0) {
+ struct item item_tmp;
+ struct item_data *item_data = itemdb->exists(nameid);
+ int get_count;
memset(&item_tmp,0,sizeof(item_tmp));
- item_data=itemdb_exists(nameid);
if (item_data == NULL)
return -1;
- if(item_data->type==IT_WEAPON || item_data->type==IT_ARMOR){
+ if(item_data->type==IT_WEAPON || item_data->type==IT_ARMOR) {
if(ref > MAX_REFINE) ref = MAX_REFINE;
}
else if(item_data->type==IT_PETEGG) {
@@ -5977,7 +6634,7 @@ BUILDIN(getitem2)
iden = 1;
ref = attr = 0;
}
-
+
item_tmp.nameid=nameid;
if(!flag)
item_tmp.identify=iden;
@@ -5985,32 +6642,30 @@ BUILDIN(getitem2)
item_tmp.identify=0;
item_tmp.refine=ref;
item_tmp.attribute=attr;
+ item_tmp.bound=(unsigned char)bound;
item_tmp.card[0]=(short)c1;
item_tmp.card[1]=(short)c2;
item_tmp.card[2]=(short)c3;
item_tmp.card[3]=(short)c4;
-
+
//Check if it's stackable.
- if (!itemdb_isstackable(nameid))
+ if (!itemdb->isstackable(nameid))
get_count = 1;
else
get_count = amount;
-
- for (i = 0; i < amount; i += get_count)
- {
+
+ for (i = 0; i < amount; i += get_count) {
// if not pet egg
- if (!pet_create_egg(sd, nameid))
- {
- if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT)))
- {
+ if (!pet->create_egg(sd, nameid)) {
+ if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) {
clif->additem(sd, 0, 0, flag);
if( pc->candrop(sd,&item_tmp) )
- iMap->addflooritem(&item_tmp,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&item_tmp,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
}
}
-
+
return true;
}
@@ -6018,58 +6673,45 @@ BUILDIN(getitem2)
* rentitem <item id>,<seconds>
* rentitem "<item name>",<seconds>
*------------------------------------------*/
-BUILDIN(rentitem)
-{
+BUILDIN(rentitem) {
struct map_session_data *sd;
- struct script_data *data;
struct item it;
int seconds;
int nameid = 0, flag;
-
- data = script_getdata(st,2);
- script->get_val(st,data);
-
- if( (sd = script_rid2sd(st)) == NULL )
+
+ if( (sd = script->rid2sd(st)) == NULL )
return true;
-
- if( data_isstring(data) )
- {
- const char *name = script->conv_str(st,data);
- struct item_data *itd = itemdb_searchname(name);
+
+ if( script_isstringtype(st, 2) ) {
+ const char *name = script_getstr(st, 2);
+ struct item_data *itd = itemdb->search_name(name);
if( itd == NULL )
{
ShowError("buildin_rentitem: Nonexistant item %s requested.\n", name);
return false;
}
nameid = itd->nameid;
- }
- else if( data_isint(data) )
- {
- nameid = script->conv_num(st,data);
- if( nameid <= 0 || !itemdb_exists(nameid) )
- {
+ } else {
+ nameid = script_getnum(st, 2);
+ if( nameid <= 0 || !itemdb->exists(nameid) ) {
ShowError("buildin_rentitem: Nonexistant item %d requested.\n", nameid);
return false;
}
}
- else
- {
- ShowError("buildin_rentitem: invalid data type for argument #1 (%d).\n", data->type);
- return false;
- }
-
+
seconds = script_getnum(st,3);
memset(&it, 0, sizeof(it));
it.nameid = nameid;
it.identify = 1;
it.expire_time = (unsigned int)(time(NULL) + seconds);
-
+ it.bound = 0;
+
if( (flag = pc->additem(sd, &it, 1, LOG_TYPE_SCRIPT)) )
{
clif->additem(sd, 0, 0, flag);
return false;
}
-
+
return true;
}
@@ -6079,53 +6721,45 @@ BUILDIN(rentitem)
* Returned Qty is always 1, only works on equip-able
* equipment
*------------------------------------------*/
-BUILDIN(getnameditem)
-{
+BUILDIN(getnameditem) {
int nameid;
struct item item_tmp;
TBL_PC *sd, *tsd;
- struct script_data *data;
-
- sd = script_rid2sd(st);
- if (sd == NULL)
- { //Player not attached!
- script_pushint(st,0);
+
+ sd = script->rid2sd(st);
+ if (sd == NULL) // Player not attached!
return true;
- }
-
- data=script_getdata(st,2);
- script->get_val(st,data);
- if( data_isstring(data) ){
- const char *name=script->conv_str(st,data);
- struct item_data *item_data = itemdb_searchname(name);
- if( item_data == NULL)
- { //Failed
+
+ if( script_isstringtype(st, 2) ) {
+ const char *name = script_getstr(st, 2);
+ struct item_data *item_data = itemdb->search_name(name);
+ if( item_data == NULL) {
+ //Failed
script_pushint(st,0);
return true;
}
nameid = item_data->nameid;
- }else
- nameid = script->conv_num(st,data);
-
- if(!itemdb_exists(nameid)/* || itemdb_isstackable(nameid)*/)
- { //Even though named stackable items "could" be risky, they are required for certain quests.
+ } else {
+ nameid = script_getnum(st, 2);
+ }
+
+ if(!itemdb->exists(nameid)/* || itemdb->isstackable(nameid)*/) {
+ //Even though named stackable items "could" be risky, they are required for certain quests.
script_pushint(st,0);
return true;
}
-
- data=script_getdata(st,3);
- script->get_val(st,data);
- if( data_isstring(data) ) //Char Name
- tsd=iMap->nick2sd(script->conv_str(st,data));
- else //Char Id was given
- tsd=iMap->charid2sd(script->conv_num(st,data));
-
- if( tsd == NULL )
- { //Failed
+
+ if( script_isstringtype(st, 3) ) //Char Name
+ tsd=map->nick2sd(script_getstr(st, 3));
+ else //Char Id was given
+ tsd=map->charid2sd(script_getnum(st, 3));
+
+ if( tsd == NULL ) {
+ //Failed
script_pushint(st,0);
return true;
}
-
+
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid=nameid;
item_tmp.amount=1;
@@ -6135,9 +6769,9 @@ BUILDIN(getnameditem)
item_tmp.card[3]=tsd->status.char_id >> 16;
if(pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT)) {
script_pushint(st,0);
- return true; //Failed to add item, we will not drop if they don't fit
+ return true; //Failed to add item, we will not drop if they don't fit
}
-
+
script_pushint(st,1);
return true;
}
@@ -6146,12 +6780,30 @@ BUILDIN(getnameditem)
* gets a random item ID from an item group [Skotlex]
* groupranditem group_num
*------------------------------------------*/
-BUILDIN(grouprandomitem)
-{
- int group;
-
- group = script_getnum(st,2);
- script_pushint(st,itemdb_searchrandomid(group));
+BUILDIN(grouprandomitem) {
+ struct item_data *data;
+ int nameid;
+
+ if( script_hasdata(st, 2) )
+ nameid = script_getnum(st, 2);
+ else if ( script->current_item_id )
+ nameid = script->current_item_id;
+ else {
+ ShowWarning("buildin_grouprandomitem: no item id provided and no item attached\n");
+ script_pushint(st, 0);
+ return true;
+ }
+
+ if( !(data = itemdb->exists(nameid)) ) {
+ ShowWarning("buildin_grouprandomitem: unknown item id %d\n",nameid);
+ script_pushint(st, 0);
+ } else if ( !data->group ) {
+ ShowWarning("buildin_grouprandomitem: item '%s' (%d) isn't a group!\n",data->name,nameid);
+ script_pushint(st, 0);
+ } else {
+ script_pushint(st, itemdb->group_item(data->group));
+ }
+
return true;
}
@@ -6164,47 +6816,49 @@ BUILDIN(makeitem)
int x,y,m;
const char *mapname;
struct item item_tmp;
- struct script_data *data;
struct item_data *item_data;
- data=script_getdata(st,2);
- script->get_val(st,data);
- if( data_isstring(data) ){
- const char *name=script->conv_str(st,data);
- if( (item_data = itemdb_searchname(name)) )
+ if( script_isstringtype(st, 2) ) {
+ const char *name = script_getstr(st, 2);
+ if( (item_data = itemdb->search_name(name)) )
nameid=item_data->nameid;
else
nameid=UNKNOWN_ITEM_ID;
} else {
- nameid=script->conv_num(st,data);
- if( nameid <= 0 || !(item_data = itemdb_exists(nameid)) ){
+ nameid = script_getnum(st, 2);
+ if( nameid <= 0 || !(item_data = itemdb->exists(nameid)) ) {
ShowError("makeitem: Nonexistant item %d requested.\n", nameid);
return false; //No item created.
}
}
- amount=script_getnum(st,3);
- mapname =script_getstr(st,4);
- x =script_getnum(st,5);
- y =script_getnum(st,6);
-
- if(strcmp(mapname,"this")==0)
- {
+ amount = script_getnum(st,3);
+ mapname = script_getstr(st,4);
+ x = script_getnum(st,5);
+ y = script_getnum(st,6);
+
+ if(strcmp(mapname,"this")==0) {
TBL_PC *sd;
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if (!sd) return true; //Failed...
m=sd->bl.m;
} else
- m=iMap->mapname2mapid(mapname);
-
+ m=map->mapname2mapid(mapname);
+
+ if( m == -1 ) {
+ ShowError("makeitem: creating map on unexistent map '%s'!\n", mapname);
+ return false;
+ }
+
+
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid=nameid;
if(!flag)
item_tmp.identify=1;
else
- item_tmp.identify=itemdb_isidentified2(item_data);
-
- iMap->addflooritem(&item_tmp,amount,m,x,y,0,0,0,0);
-
+ item_tmp.identify=itemdb->isidentified2(item_data);
+
+ map->addflooritem(&item_tmp,amount,m,x,y,0,0,0,0);
+
return true;
}
@@ -6212,22 +6866,22 @@ BUILDIN(makeitem)
/// Counts / deletes the current item given by idx.
/// Used by buildin_delitem_search
/// Relies on all input data being already fully valid.
-static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* amount, bool delete_items)
+void buildin_delitem_delete(struct map_session_data* sd, int idx, int* amount, bool delete_items)
{
int delamount;
struct item* inv = &sd->status.inventory[idx];
-
+
delamount = ( amount[0] < inv->amount ) ? amount[0] : inv->amount;
-
+
if( delete_items )
{
if( sd->inventory_data[idx]->type == IT_PETEGG && inv->card[0] == CARD0_PET )
{// delete associated pet
- intif_delete_petdata(MakeDWord(inv->card[1], inv->card[2]));
+ intif->delete_petdata(MakeDWord(inv->card[1], inv->card[2]));
}
pc->delitem(sd, idx, delamount, 0, 0, LOG_TYPE_SCRIPT);
}
-
+
amount[0]-= delamount;
}
@@ -6237,15 +6891,15 @@ static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* am
/// Relies on all input data being already fully valid.
/// @param exact_match will also match item attributes and cards, not just name id
/// @return true when all items could be deleted, false when there were not enough items to delete
-static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, bool exact_match)
+bool buildin_delitem_search(struct map_session_data* sd, struct item* it, bool exact_match)
{
bool delete_items = false;
int i, amount, important;
struct item* inv;
-
+
// prefer always non-equipped items
it->equip = 0;
-
+
// when searching for nameid only, prefer additionally
if( !exact_match )
{
@@ -6254,28 +6908,28 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it,
// card-less items
memset(it->card, 0, sizeof(it->card));
}
-
+
for(;;)
{
amount = it->amount;
important = 0;
-
+
// 1st pass -- less important items / exact match
for( i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++ )
{
inv = &sd->status.inventory[i];
-
+
if( !inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid )
{// wrong/invalid item
continue;
}
-
+
if( inv->equip != it->equip || inv->refine != it->refine )
{// not matching attributes
important++;
continue;
}
-
+
if( exact_match )
{
if( inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card)) )
@@ -6287,7 +6941,7 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it,
{
if( sd->inventory_data[i]->type == IT_PETEGG )
{
- if( inv->card[0] == CARD0_PET && CheckForCharServer() )
+ if( inv->card[0] == CARD0_PET && intif->CheckForCharServer() )
{// pet which cannot be deleted
continue;
}
@@ -6298,11 +6952,11 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it,
continue;
}
}
-
+
// count / delete item
- buildin_delitem_delete(sd, i, &amount, delete_items);
+ script->buildin_delitem_delete(sd, i, &amount, delete_items);
}
-
+
// 2nd pass -- any matching item
if( amount == 0 || important == 0 )
{// either everything was already consumed or no items were skipped
@@ -6311,17 +6965,17 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it,
else for( i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++ )
{
inv = &sd->status.inventory[i];
-
+
if( !inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid )
{// wrong/invalid item
continue;
}
-
- if( sd->inventory_data[i]->type == IT_PETEGG && inv->card[0] == CARD0_PET && CheckForCharServer() )
+
+ if( sd->inventory_data[i]->type == IT_PETEGG && inv->card[0] == CARD0_PET && intif->CheckForCharServer() )
{// pet which cannot be deleted
continue;
}
-
+
if( exact_match )
{
if( inv->refine != it->refine || inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card)) )
@@ -6329,11 +6983,11 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it,
continue;
}
}
-
+
// count / delete item
- buildin_delitem_delete(sd, i, &amount, delete_items);
+ script->buildin_delitem_delete(sd, i, &amount, delete_items);
}
-
+
if( amount )
{// not enough items
return false;
@@ -6355,16 +7009,14 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it,
///
/// delitem <item id>,<amount>{,<account id>}
/// delitem "<item name>",<amount>{,<account id>}
-BUILDIN(delitem)
-{
+BUILDIN(delitem) {
TBL_PC *sd;
struct item it;
- struct script_data *data;
-
+
if( script_hasdata(st,4) )
{
int account_id = script_getnum(st,4);
- sd = iMap->id2sd(account_id); // <account id>
+ sd = map->id2sd(account_id); // <account id>
if( sd == NULL )
{
ShowError("script:delitem: player not found (AID=%d).\n", account_id);
@@ -6374,46 +7026,40 @@ BUILDIN(delitem)
}
else
{
- sd = script_rid2sd(st);// attached player
+ sd = script->rid2sd(st);// attached player
if( sd == NULL )
return true;
}
-
- data = script_getdata(st,2);
- script->get_val(st,data);
- if( data_isstring(data) )
- {
- const char* item_name = script->conv_str(st,data);
- struct item_data* id = itemdb_searchname(item_name);
- if( id == NULL )
- {
+
+ if( script_isstringtype(st, 2) ) {
+ const char* item_name = script_getstr(st, 2);
+ struct item_data* id = itemdb->search_name(item_name);
+ if( id == NULL ) {
ShowError("script:delitem: unknown item \"%s\".\n", item_name);
st->state = END;
return false;
}
it.nameid = id->nameid;// "<item name>"
- }
- else
- {
- it.nameid = script->conv_num(st,data);// <item id>
- if( !itemdb_exists( it.nameid ) )
+ } else {
+ it.nameid = script_getnum(st, 2);// <item id>
+ if( !itemdb->exists( it.nameid ) )
{
ShowError("script:delitem: unknown item \"%d\".\n", it.nameid);
st->state = END;
return false;
}
}
-
+
it.amount=script_getnum(st,3);
-
+
if( it.amount <= 0 )
return true;// nothing to do
-
- if( buildin_delitem_search(sd, &it, false) )
+
+ if( script->buildin_delitem_search(sd, &it, false) )
{// success
return true;
}
-
+
ShowError("script:delitem: failed to delete %d items (AID=%d item_id=%d).\n", it.amount, sd->status.account_id, it.nameid);
st->state = END;
clif->scriptclose(sd, st->oid);
@@ -6424,18 +7070,14 @@ BUILDIN(delitem)
///
/// delitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}
/// delitem2 "<Item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}
-BUILDIN(delitem2)
-{
+BUILDIN(delitem2) {
TBL_PC *sd;
struct item it;
- struct script_data *data;
-
- if( script_hasdata(st,11) )
- {
+
+ if( script_hasdata(st,11) ) {
int account_id = script_getnum(st,11);
- sd = iMap->id2sd(account_id); // <account id>
- if( sd == NULL )
- {
+ sd = map->id2sd(account_id); // <account id>
+ if( sd == NULL ) {
ShowError("script:delitem2: player not found (AID=%d).\n", account_id);
st->state = END;
return false;
@@ -6443,36 +7085,29 @@ BUILDIN(delitem2)
}
else
{
- sd = script_rid2sd(st);// attached player
+ sd = script->rid2sd(st);// attached player
if( sd == NULL )
return true;
}
-
- data = script_getdata(st,2);
- script->get_val(st,data);
- if( data_isstring(data) )
- {
- const char* item_name = script->conv_str(st,data);
- struct item_data* id = itemdb_searchname(item_name);
- if( id == NULL )
- {
+
+ if( script_isstringtype(st, 2) ) {
+ const char* item_name = script_getstr(st, 2);
+ struct item_data* id = itemdb->search_name(item_name);
+ if( id == NULL ) {
ShowError("script:delitem2: unknown item \"%s\".\n", item_name);
st->state = END;
return false;
}
it.nameid = id->nameid;// "<item name>"
- }
- else
- {
- it.nameid = script->conv_num(st,data);// <item id>
- if( !itemdb_exists( it.nameid ) )
- {
+ } else {
+ it.nameid = script_getnum(st, 2);// <item id>
+ if( !itemdb->exists( it.nameid ) ) {
ShowError("script:delitem: unknown item \"%d\".\n", it.nameid);
st->state = END;
return false;
}
}
-
+
it.amount=script_getnum(st,3);
it.identify=script_getnum(st,4);
it.refine=script_getnum(st,5);
@@ -6481,15 +7116,15 @@ BUILDIN(delitem2)
it.card[1]=(short)script_getnum(st,8);
it.card[2]=(short)script_getnum(st,9);
it.card[3]=(short)script_getnum(st,10);
-
+
if( it.amount <= 0 )
return true;// nothing to do
-
- if( buildin_delitem_search(sd, &it, true) )
+
+ if( script->buildin_delitem_search(sd, &it, true) )
{// success
return true;
}
-
+
ShowError("script:delitem2: failed to delete %d items (AID=%d item_id=%d).\n", it.amount, sd->status.account_id, it.nameid);
st->state = END;
clif->scriptclose(sd, st->oid);
@@ -6502,7 +7137,7 @@ BUILDIN(delitem2)
BUILDIN(enableitemuse)
{
TBL_PC *sd;
- sd=script_rid2sd(st);
+ sd=script->rid2sd(st);
if (sd)
st->npc_item_flag = sd->npc_item_flag = 1;
return true;
@@ -6511,7 +7146,7 @@ BUILDIN(enableitemuse)
BUILDIN(disableitemuse)
{
TBL_PC *sd;
- sd=script_rid2sd(st);
+ sd=script->rid2sd(st);
if (sd)
st->npc_item_flag = sd->npc_item_flag = 0;
return true;
@@ -6521,52 +7156,50 @@ BUILDIN(disableitemuse)
* return the basic stats of sd
* chk pc->readparam for available type
*------------------------------------------*/
-BUILDIN(readparam)
-{
+BUILDIN(readparam) {
int type;
TBL_PC *sd;
-
+
type=script_getnum(st,2);
if( script_hasdata(st,3) )
- sd=iMap->nick2sd(script_getstr(st,3));
+ sd=map->nick2sd(script_getstr(st,3));
else
- sd=script_rid2sd(st);
-
- if(sd==NULL){
+ sd=script->rid2sd(st);
+
+ if(sd==NULL) {
script_pushint(st,-1);
return true;
}
-
+
script_pushint(st,pc->readparam(sd,type));
-
+
return true;
}
/*==========================================
* Return charid identification
* return by @num :
- * 0 : char_id
- * 1 : party_id
- * 2 : guild_id
- * 3 : account_id
- * 4 : bg_id
+ * 0 : char_id
+ * 1 : party_id
+ * 2 : guild_id
+ * 3 : account_id
+ * 4 : bg_id
*------------------------------------------*/
-BUILDIN(getcharid)
-{
+BUILDIN(getcharid) {
int num;
TBL_PC *sd;
-
+
num = script_getnum(st,2);
if( script_hasdata(st,3) )
- sd=iMap->nick2sd(script_getstr(st,3));
+ sd=map->nick2sd(script_getstr(st,3));
else
- sd=script_rid2sd(st);
-
- if(sd==NULL){
- script_pushint(st,0); //return 0, according docs
+ sd=script->rid2sd(st);
+
+ if(sd==NULL) {
+ script_pushint(st,0); //return 0, according docs
return true;
}
-
+
switch( num ) {
case 0: script_pushint(st,sd->status.char_id); break;
case 1: script_pushint(st,sd->status.party_id); break;
@@ -6578,7 +7211,7 @@ BUILDIN(getcharid)
script_pushint(st,0);
break;
}
-
+
return true;
}
/*==========================================
@@ -6588,17 +7221,17 @@ BUILDIN(getnpcid)
{
int num = script_getnum(st,2);
struct npc_data* nd = NULL;
-
+
if( script_hasdata(st,3) )
{// unique npc name
- if( ( nd = npc_name2id(script_getstr(st,3)) ) == NULL )
+ if( ( nd = npc->name2id(script_getstr(st,3)) ) == NULL )
{
ShowError("buildin_getnpcid: No such NPC '%s'.\n", script_getstr(st,3));
script_pushint(st,0);
return false;
}
}
-
+
switch (num) {
case 0:
script_pushint(st,nd ? nd->bl.id : st->oid);
@@ -6608,7 +7241,7 @@ BUILDIN(getnpcid)
script_pushint(st,0);
return false;
}
-
+
return true;
}
@@ -6620,9 +7253,9 @@ BUILDIN(getpartyname)
{
int party_id;
struct party_data* p;
-
+
party_id = script_getnum(st,2);
-
+
if( ( p = party->search(party_id) ) != NULL )
{
script_pushstrcopy(st,p->party.name);
@@ -6638,39 +7271,39 @@ BUILDIN(getpartyname)
* Get the information of the members of a party by type
* @party_id, @type
* return by @type :
- * - : nom des membres
- * 1 : char_id des membres
- * 2 : account_id des membres
+ * - : nom des membres
+ * 1 : char_id des membres
+ * 2 : account_id des membres
*------------------------------------------*/
BUILDIN(getpartymember)
{
struct party_data *p;
int i,j=0,type=0;
-
+
p=party->search(script_getnum(st,2));
-
+
if( script_hasdata(st,3) )
- type=script_getnum(st,3);
-
- if(p!=NULL){
- for(i=0;i<MAX_PARTY;i++){
- if(p->party.member[i].account_id){
+ type=script_getnum(st,3);
+
+ if(p!=NULL) {
+ for(i=0;i<MAX_PARTY;i++) {
+ if(p->party.member[i].account_id) {
switch (type) {
case 2:
- mapreg_setreg(reference_uid(add_str("$@partymemberaid"), j),p->party.member[i].account_id);
+ mapreg->setreg(reference_uid(script->add_str("$@partymemberaid"), j),p->party.member[i].account_id);
break;
case 1:
- mapreg_setreg(reference_uid(add_str("$@partymembercid"), j),p->party.member[i].char_id);
+ mapreg->setreg(reference_uid(script->add_str("$@partymembercid"), j),p->party.member[i].char_id);
break;
default:
- mapreg_setregstr(reference_uid(add_str("$@partymembername$"), j),p->party.member[i].name);
+ mapreg->setregstr(reference_uid(script->add_str("$@partymembername$"), j),p->party.member[i].name);
}
j++;
}
}
}
- mapreg_setreg(add_str("$@partymembercount"),j);
-
+ mapreg->setreg(script->add_str("$@partymembercount"),j);
+
return true;
}
@@ -6682,16 +7315,16 @@ BUILDIN(getpartyleader)
{
int party_id, type = 0, i=0;
struct party_data *p;
-
+
party_id=script_getnum(st,2);
if( script_hasdata(st,3) )
- type=script_getnum(st,3);
-
+ type=script_getnum(st,3);
+
p=party->search(party_id);
-
+
if (p) //Search leader
for(i = 0; i < MAX_PARTY && !p->party.member[i].leader; i++);
-
+
if (!p || i == MAX_PARTY) { //leader not found
if (type)
script_pushint(st,-1);
@@ -6699,7 +7332,7 @@ BUILDIN(getpartyleader)
script_pushconststr(st,"null");
return true;
}
-
+
switch (type) {
case 1: script_pushint(st,p->party.member[i].account_id); break;
case 2: script_pushint(st,p->party.member[i].char_id); break;
@@ -6719,9 +7352,9 @@ BUILDIN(getguildname)
{
int guild_id;
struct guild* g;
-
+
guild_id = script_getnum(st,2);
-
+
if( ( g = guild->search(guild_id) ) != NULL )
{
script_pushstrcopy(st,g->name);
@@ -6741,9 +7374,9 @@ BUILDIN(getguildmaster)
{
int guild_id;
struct guild* g;
-
+
guild_id = script_getnum(st,2);
-
+
if( ( g = guild->search(guild_id) ) != NULL )
{
script_pushstrcopy(st,g->member[0].name);
@@ -6759,9 +7392,9 @@ BUILDIN(getguildmasterid)
{
int guild_id;
struct guild* g;
-
+
guild_id = script_getnum(st,2);
-
+
if( ( g = guild->search(guild_id) ) != NULL )
{
script_pushint(st,g->member[0].char_id);
@@ -6776,11 +7409,11 @@ BUILDIN(getguildmasterid)
/*==========================================
* Get char string information by type :
* Return by @type :
- * 0 : char_name
- * 1 : party_name or ""
- * 2 : guild_name or ""
- * 3 : map_name
- * - : ""
+ * 0 : char_name
+ * 1 : party_name or ""
+ * 2 : guild_name or ""
+ * 3 : map_name
+ * - : ""
*------------------------------------------*/
BUILDIN(strcharinfo)
{
@@ -6788,14 +7421,13 @@ BUILDIN(strcharinfo)
int num;
struct guild* g;
struct party_data* p;
-
- sd=script_rid2sd(st);
- if (!sd) { //Avoid crashing....
- script_pushconststr(st,"");
+
+ sd=script->rid2sd(st);
+ if (!sd) //Avoid crashing....
return true;
- }
+
num=script_getnum(st,2);
- switch(num){
+ switch(num) {
case 0:
script_pushstrcopy(st,sd->status.name);
break;
@@ -6814,40 +7446,39 @@ BUILDIN(strcharinfo)
}
break;
case 3:
- script_pushconststr(st,map[sd->bl.m].name);
+ script_pushconststr(st,map->list[sd->bl.m].name);
break;
default:
ShowWarning("buildin_strcharinfo: unknown parameter.\n");
script_pushconststr(st,"");
break;
}
-
+
return true;
}
/*==========================================
* Get npc string information by type
* return by @type:
- * 0 : name
- * 1 : str#
- * 2 : #str
- * 3 : ::str
- * 4 : map name
+ * 0 : name
+ * 1 : str#
+ * 2 : #str
+ * 3 : ::str
+ * 4 : map name
*------------------------------------------*/
-BUILDIN(strnpcinfo)
-{
+BUILDIN(strnpcinfo) {
TBL_NPC* nd;
int num;
char *buf,*name=NULL;
-
- nd = iMap->id2nd(st->oid);
+
+ nd = map->id2nd(st->oid);
if (!nd) {
script_pushconststr(st, "");
return true;
}
-
+
num = script_getnum(st,2);
- switch(num){
+ switch(num) {
case 0: // display name
name = aStrdup(nd->name);
break;
@@ -6867,56 +7498,53 @@ BUILDIN(strnpcinfo)
name = aStrdup(nd->exname);
break;
case 4: // map name
- name = aStrdup(map[nd->bl.m].name);
+ if( nd->bl.m >= 0 ) // Only valid map indexes allowed (issue:8034)
+ name = aStrdup(map->list[nd->bl.m].name);
break;
}
-
+
if(name)
script_pushstr(st, name);
else
script_pushconststr(st, "");
-
+
return true;
}
-
-// aegis->athena slot position conversion table
-static unsigned int equip[] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_GARMENT};
-
/*==========================================
- * GetEquipID(Pos); Pos: 1-10
+ * GetEquipID(Pos); Pos: 1-SCRIPT_EQUIP_TABLE_SIZE
*------------------------------------------*/
BUILDIN(getequipid)
{
int i, num;
TBL_PC* sd;
struct item_data* item;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
num = script_getnum(st,2) - 1;
- if( num < 0 || num >= ARRAYLENGTH(equip) )
+ if( num < 0 || num >= ARRAYLENGTH(script->equip) )
{
script_pushint(st,-1);
return true;
}
-
+
// get inventory position of item
- i = pc->checkequip(sd,equip[num]);
+ i = pc->checkequip(sd,script->equip[num]);
if( i < 0 )
{
script_pushint(st,-1);
return true;
}
-
+
item = sd->inventory_data[i];
if( item != 0 )
script_pushint(st,item->nameid);
else
script_pushint(st,0);
-
+
return true;
}
@@ -6929,32 +7557,32 @@ BUILDIN(getequipname)
int i, num;
TBL_PC* sd;
struct item_data* item;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
num = script_getnum(st,2) - 1;
- if( num < 0 || num >= ARRAYLENGTH(equip) )
+ if( num < 0 || num >= ARRAYLENGTH(script->equip) )
{
script_pushconststr(st,"");
return true;
}
-
+
// get inventory position of item
- i = pc->checkequip(sd,equip[num]);
+ i = pc->checkequip(sd,script->equip[num]);
if( i < 0 )
{
script_pushconststr(st,"");
return true;
}
-
+
item = sd->inventory_data[i];
if( item != 0 )
script_pushstrcopy(st,item->jname);
else
script_pushconststr(st,"");
-
+
return true;
}
@@ -6965,24 +7593,24 @@ BUILDIN(getbrokenid)
{
int i,num,id=0,brokencounter=0;
TBL_PC *sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
num=script_getnum(st,2);
for(i=0; i<MAX_INVENTORY; i++) {
- if(sd->status.inventory[i].attribute){
+ if(sd->status.inventory[i].attribute) {
brokencounter++;
- if(num==brokencounter){
+ if(num==brokencounter) {
id=sd->status.inventory[i].nameid;
break;
}
}
}
-
+
script_pushint(st,id);
-
+
return true;
}
@@ -6994,16 +7622,16 @@ BUILDIN(repair)
int i,num;
int repaircounter=0;
TBL_PC *sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
num=script_getnum(st,2);
for(i=0; i<MAX_INVENTORY; i++) {
- if(sd->status.inventory[i].attribute){
+ if(sd->status.inventory[i].attribute) {
repaircounter++;
- if(num==repaircounter){
+ if(num==repaircounter) {
sd->status.inventory[i].attribute=0;
clif->equiplist(sd);
clif->produce_effect(sd, 0, sd->status.inventory[i].nameid);
@@ -7012,7 +7640,7 @@ BUILDIN(repair)
}
}
}
-
+
return true;
}
@@ -7023,11 +7651,11 @@ BUILDIN(repairall)
{
int i, repaircounter = 0;
TBL_PC *sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if(sd == NULL)
return true;
-
+
for(i = 0; i < MAX_INVENTORY; i++)
{
if(sd->status.inventory[i].nameid && sd->status.inventory[i].attribute)
@@ -7037,13 +7665,13 @@ BUILDIN(repairall)
repaircounter++;
}
}
-
+
if(repaircounter)
{
clif->misceffect(&sd->bl, 3);
clif->equiplist(sd);
}
-
+
return true;
}
@@ -7054,15 +7682,15 @@ BUILDIN(getequipisequiped)
{
int i = -1,num;
TBL_PC *sd;
-
+
num = script_getnum(st,2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
-
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
+
if(i >= 0)
script_pushint(st,1);
else
@@ -7074,78 +7702,78 @@ BUILDIN(getequipisequiped)
* Chk if the player have something equiped at pos
* if so chk if this item ain't marked not refinable or rental
* return (npc)
- * 1 : true
- * 0 : false
+ * 1 : true
+ * 0 : false
*------------------------------------------*/
BUILDIN(getequipisenableref)
{
int i = -1,num;
TBL_PC *sd;
-
+
num = script_getnum(st,2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- if( num > 0 && num <= ARRAYLENGTH(equip) )
- i = pc->checkequip(sd,equip[num-1]);
+
+ if( num > 0 && num <= ARRAYLENGTH(script->equip) )
+ i = pc->checkequip(sd,script->equip[num-1]);
if( i >= 0 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_refine && !sd->status.inventory[i].expire_time )
script_pushint(st,1);
else
script_pushint(st,0);
-
+
return true;
}
/*==========================================
* Chk if the item equiped at pos is identify (huh ?)
* return (npc)
- * 1 : true
- * 0 : false
+ * 1 : true
+ * 0 : false
*------------------------------------------*/
BUILDIN(getequipisidentify)
{
int i = -1,num;
TBL_PC *sd;
-
+
num = script_getnum(st,2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
if(i >= 0)
script_pushint(st,sd->status.inventory[i].identify);
else
script_pushint(st,0);
-
+
return true;
}
/*==========================================
* Get the item refined value at pos
* return (npc)
- * x : refine amount
- * 0 : false (not refined)
+ * x : refine amount
+ * 0 : false (not refined)
*------------------------------------------*/
BUILDIN(getequiprefinerycnt)
{
int i = -1,num;
TBL_PC *sd;
-
+
num = script_getnum(st,2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
if(i >= 0)
script_pushint(st,sd->status.inventory[i].refine);
else
script_pushint(st,0);
-
+
return true;
}
@@ -7153,96 +7781,98 @@ BUILDIN(getequiprefinerycnt)
* Get the weapon level value at pos
* (pos should normally only be EQI_HAND_L or EQI_HAND_R)
* return (npc)
- * x : weapon level
- * 0 : false
+ * x : weapon level
+ * 0 : false
*------------------------------------------*/
BUILDIN(getequipweaponlv)
{
int i = -1,num;
TBL_PC *sd;
-
+
num = script_getnum(st,2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
if(i >= 0 && sd->inventory_data[i])
script_pushint(st,sd->inventory_data[i]->wlv);
else
script_pushint(st,0);
-
+
return true;
}
/*==========================================
* Get the item refine chance (from refine.txt) for item at pos
* return (npc)
- * x : refine chance
- * 0 : false (max refine level or unequip..)
+ * x : refine chance
+ * 0 : false (max refine level or unequip..)
*------------------------------------------*/
-BUILDIN(getequippercentrefinery)
-{
+BUILDIN(getequippercentrefinery) {
int i = -1,num;
TBL_PC *sd;
-
+
num = script_getnum(st,2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
if(i >= 0 && sd->status.inventory[i].nameid && sd->status.inventory[i].refine < MAX_REFINE)
- script_pushint(st,status_get_refine_chance(itemdb_wlv(sd->status.inventory[i].nameid), (int)sd->status.inventory[i].refine));
+ script_pushint(st,status->get_refine_chance(itemdb_wlv(sd->status.inventory[i].nameid), (int)sd->status.inventory[i].refine));
else
script_pushint(st,0);
-
+
return true;
}
/*==========================================
* Refine +1 item at pos and log and display refine
*------------------------------------------*/
-BUILDIN(successrefitem)
-{
- int i=-1,num,ep;
+BUILDIN(successrefitem) {
+ int i = -1 , num, ep, up = 1;
TBL_PC *sd;
-
+
num = script_getnum(st,2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
+
+ if( script_hasdata(st, 3) )
+ up = script_getnum(st, 3);
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
if(i >= 0) {
ep=sd->status.inventory[i].equip;
-
+
//Logs items, got from (N)PC scripts [Lupus]
logs->pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i],sd->inventory_data[i]);
-
+
if (sd->status.inventory[i].refine >= MAX_REFINE)
return true;
-
- sd->status.inventory[i].refine++;
+
+ sd->status.inventory[i].refine += up;
+ sd->status.inventory[i].refine = cap_value( sd->status.inventory[i].refine, 0, MAX_REFINE);
pc->unequipitem(sd,i,2); // status calc will happen in pc->equipitem() below
-
+
clif->refine(sd->fd,0,i,sd->status.inventory[i].refine);
clif->delitem(sd,i,1,3);
-
+
//Logs items, got from (N)PC scripts [Lupus]
logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i],sd->inventory_data[i]);
-
+
clif->additem(sd,i,1,0);
pc->equipitem(sd,i,ep);
clif->misceffect(&sd->bl,3);
if(sd->status.inventory[i].refine == 10 &&
sd->status.inventory[i].card[0] == CARD0_FORGE &&
sd->status.char_id == (int)MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3])
- ){ // Fame point system [DracoRPG]
- switch (sd->inventory_data[i]->wlv){
+ ) { // Fame point system [DracoRPG]
+ switch (sd->inventory_data[i]->wlv) {
case 1:
pc->addfame(sd,1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point
break;
@@ -7255,7 +7885,7 @@ BUILDIN(successrefitem)
}
}
}
-
+
return true;
}
@@ -7266,24 +7896,24 @@ BUILDIN(failedrefitem)
{
int i=-1,num;
TBL_PC *sd;
-
+
num = script_getnum(st,2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
if(i >= 0) {
sd->status.inventory[i].refine = 0;
pc->unequipitem(sd,i,3); //recalculate bonus
clif->refine(sd->fd,1,i,sd->status.inventory[i].refine); //notify client of failure
-
+
pc->delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT);
-
- clif->misceffect(&sd->bl,2); // display failure effect
+
+ clif->misceffect(&sd->bl,2); // display failure effect
}
-
+
return true;
}
@@ -7292,36 +7922,39 @@ BUILDIN(failedrefitem)
*------------------------------------------*/
BUILDIN(downrefitem)
{
- int i = -1,num,ep;
+ int i = -1,num,ep, down = 1;
TBL_PC *sd;
-
- num = script_getnum(st,2);
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i = pc->checkequip(sd,equip[num-1]);
+ num = script_getnum(st,2);
+ if( script_hasdata(st, 3) )
+ down = script_getnum(st, 3);
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i = pc->checkequip(sd,script->equip[num-1]);
if(i >= 0) {
ep = sd->status.inventory[i].equip;
-
+
//Logs items, got from (N)PC scripts [Lupus]
logs->pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i],sd->inventory_data[i]);
-
- sd->status.inventory[i].refine++;
+
pc->unequipitem(sd,i,2); // status calc will happen in pc->equipitem() below
-
- clif->refine(sd->fd,2,i,sd->status.inventory[i].refine = sd->status.inventory[i].refine - 2);
+ sd->status.inventory[i].refine -= down;
+ sd->status.inventory[i].refine = cap_value( sd->status.inventory[i].refine, 0, MAX_REFINE);
+
+ clif->refine(sd->fd,2,i,sd->status.inventory[i].refine);
clif->delitem(sd,i,1,3);
-
+
//Logs items, got from (N)PC scripts [Lupus]
logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i],sd->inventory_data[i]);
-
+
clif->additem(sd,i,1,0);
pc->equipitem(sd,i,ep);
clif->misceffect(&sd->bl,2);
}
-
+
return true;
}
@@ -7332,37 +7965,39 @@ BUILDIN(delequip)
{
int i=-1,num;
TBL_PC *sd;
-
+
num = script_getnum(st,2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
if(i >= 0) {
pc->unequipitem(sd,i,3); //recalculate bonus
pc->delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT);
+ script_pushint(st,1);
+ } else {
+ script_pushint(st,0);
}
-
+
return true;
}
/*==========================================
*
*------------------------------------------*/
-BUILDIN(statusup)
-{
+BUILDIN(statusup) {
int type;
TBL_PC *sd;
-
+
type=script_getnum(st,2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- pc->statusup(sd,type);
-
+
+ pc->statusup(sd, type, 1);
+
return true;
}
/*==========================================
@@ -7372,15 +8007,15 @@ BUILDIN(statusup2)
{
int type,val;
TBL_PC *sd;
-
+
type=script_getnum(st,2);
val=script_getnum(st,3);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
pc->statusup2(sd,type,val);
-
+
return true;
}
@@ -7391,8 +8026,7 @@ BUILDIN(statusup2)
/// bonus3 <bonus type>,<val1>,<val2>,<val3>;
/// bonus4 <bonus type>,<val1>,<val2>,<val3>,<val4>;
/// bonus5 <bonus type>,<val1>,<val2>,<val3>,<val4>,<val5>;
-BUILDIN(bonus)
-{
+BUILDIN(bonus) {
int type;
int val1;
int val2 = 0;
@@ -7400,11 +8034,11 @@ BUILDIN(bonus)
int val4 = 0;
int val5 = 0;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true; // no player attached
-
+
type = script_getnum(st,2);
switch( type ) {
case SP_AUTOSPELL:
@@ -7424,13 +8058,16 @@ BUILDIN(bonus)
case SP_FIXCASTRATE:
case SP_SKILL_USE_SP:
// these bonuses support skill names
- val1 = ( script_isstring(st,3) ? skill->name2id(script_getstr(st,3)) : script_getnum(st,3) );
- break;
+ if (script_isstringtype(st, 3)) {
+ val1 = skill->name2id(script_getstr(st, 3));
+ break;
+ }
+ // else fall through
default:
val1 = script_getnum(st,3);
break;
}
-
+
switch( script_lastdata(st)-2 ) {
case 1:
pc->bonus(sd, type, val1);
@@ -7445,21 +8082,21 @@ BUILDIN(bonus)
pc->bonus3(sd, type, val1, val2, val3);
break;
case 4:
- if( type == SP_AUTOSPELL_ONSKILL && script_isstring(st,4) )
+ if( type == SP_AUTOSPELL_ONSKILL && script_isstringtype(st,4) )
val2 = skill->name2id(script_getstr(st,4)); // 2nd value can be skill name
else
val2 = script_getnum(st,4);
-
+
val3 = script_getnum(st,5);
val4 = script_getnum(st,6);
pc->bonus4(sd, type, val1, val2, val3, val4);
break;
case 5:
- if( type == SP_AUTOSPELL_ONSKILL && script_isstring(st,4) )
+ if( type == SP_AUTOSPELL_ONSKILL && script_isstringtype(st,4) )
val2 = skill->name2id(script_getstr(st,4)); // 2nd value can be skill name
else
val2 = script_getnum(st,4);
-
+
val3 = script_getnum(st,5);
val4 = script_getnum(st,6);
val5 = script_getnum(st,7);
@@ -7469,116 +8106,113 @@ BUILDIN(bonus)
ShowDebug("buildin_bonus: unexpected number of arguments (%d)\n", (script_lastdata(st) - 1));
break;
}
-
+
return true;
}
-BUILDIN(autobonus)
-{
+BUILDIN(autobonus) {
unsigned int dur;
short rate;
short atk_type = 0;
TBL_PC* sd;
const char *bonus_script, *other_script = NULL;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true; // no player attached
-
- if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip )
+
+ if( sd->state.autobonus&sd->status.inventory[status->current_equip_item_index].equip )
return true;
-
+
rate = script_getnum(st,3);
dur = script_getnum(st,4);
bonus_script = script_getstr(st,2);
if( !rate || !dur || !bonus_script )
return true;
-
+
if( script_hasdata(st,5) )
atk_type = script_getnum(st,5);
if( script_hasdata(st,6) )
other_script = script_getstr(st,6);
-
- if( pc->addautobonus(sd->autobonus,ARRAYLENGTH(sd->autobonus),
- bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) )
- {
- script_add_autobonus(bonus_script);
+
+ if( pc->addautobonus(sd->autobonus,ARRAYLENGTH(sd->autobonus),bonus_script,rate,dur,atk_type,other_script,
+ sd->status.inventory[status->current_equip_item_index].equip,false)
+ ) {
+ script->add_autobonus(bonus_script);
if( other_script )
- script_add_autobonus(other_script);
+ script->add_autobonus(other_script);
}
-
+
return true;
}
-BUILDIN(autobonus2)
-{
+BUILDIN(autobonus2) {
unsigned int dur;
short rate;
short atk_type = 0;
TBL_PC* sd;
const char *bonus_script, *other_script = NULL;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true; // no player attached
-
- if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip )
+
+ if( sd->state.autobonus&sd->status.inventory[status->current_equip_item_index].equip )
return true;
-
+
rate = script_getnum(st,3);
dur = script_getnum(st,4);
bonus_script = script_getstr(st,2);
if( !rate || !dur || !bonus_script )
return true;
-
+
if( script_hasdata(st,5) )
atk_type = script_getnum(st,5);
if( script_hasdata(st,6) )
other_script = script_getstr(st,6);
-
- if( pc->addautobonus(sd->autobonus2,ARRAYLENGTH(sd->autobonus2),
- bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) )
- {
- script_add_autobonus(bonus_script);
+
+ if( pc->addautobonus(sd->autobonus2,ARRAYLENGTH(sd->autobonus2),bonus_script,rate,dur,atk_type,other_script,
+ sd->status.inventory[status->current_equip_item_index].equip,false)
+ ) {
+ script->add_autobonus(bonus_script);
if( other_script )
- script_add_autobonus(other_script);
+ script->add_autobonus(other_script);
}
-
+
return true;
}
-BUILDIN(autobonus3)
-{
+BUILDIN(autobonus3) {
unsigned int dur;
short rate,atk_type;
TBL_PC* sd;
const char *bonus_script, *other_script = NULL;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true; // no player attached
-
- if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip )
+
+ if( sd->state.autobonus&sd->status.inventory[status->current_equip_item_index].equip )
return true;
-
+
rate = script_getnum(st,3);
dur = script_getnum(st,4);
- atk_type = ( script_isstring(st,5) ? skill->name2id(script_getstr(st,5)) : script_getnum(st,5) );
+ atk_type = ( script_isstringtype(st,5) ? skill->name2id(script_getstr(st,5)) : script_getnum(st,5) );
bonus_script = script_getstr(st,2);
if( !rate || !dur || !atk_type || !bonus_script )
return true;
-
+
if( script_hasdata(st,6) )
other_script = script_getstr(st,6);
-
- if( pc->addautobonus(sd->autobonus3,ARRAYLENGTH(sd->autobonus3),
- bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,true) )
- {
- script_add_autobonus(bonus_script);
+
+ if( pc->addautobonus(sd->autobonus3,ARRAYLENGTH(sd->autobonus3),bonus_script,rate,dur,atk_type,other_script,
+ sd->status.inventory[status->current_equip_item_index].equip,true)
+ ) {
+ script->add_autobonus(bonus_script);
if( other_script )
- script_add_autobonus(other_script);
+ script->add_autobonus(other_script);
}
-
+
return true;
}
@@ -7592,23 +8226,22 @@ BUILDIN(autobonus3)
/// skill <skill id>,<level>
/// skill "<skill name>",<level>,<flag>
/// skill "<skill name>",<level>
-BUILDIN(skill)
-{
+BUILDIN(skill) {
int id;
int level;
int flag = 1;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
- id = ( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
+
+ id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
level = script_getnum(st,3);
if( script_hasdata(st,4) )
flag = script_getnum(st,4);
pc->skill(sd, id, level, flag);
-
+
return true;
}
@@ -7621,23 +8254,22 @@ BUILDIN(skill)
/// addtoskill "<skill name>",<amount>
///
/// @see skill
-BUILDIN(addtoskill)
-{
+BUILDIN(addtoskill) {
int id;
int level;
int flag = 2;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
- id = ( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
+
+ id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
level = script_getnum(st,3);
if( script_hasdata(st,4) )
flag = script_getnum(st,4);
pc->skill(sd, id, level, flag);
-
+
return true;
}
@@ -7645,22 +8277,37 @@ BUILDIN(addtoskill)
///
/// guildskill <skill id>,<amount>;
/// guildskill "<skill name>",<amount>;
-BUILDIN(guildskill)
-{
- int id;
+BUILDIN(guildskill) {
+ int skill_id, id, max_points;
int level;
+
TBL_PC* sd;
- int i;
-
- sd = script_rid2sd(st);
+ struct guild *gd;
+ struct guild_skill gd_skill;
+
+ sd = script->rid2sd(st);
if( sd == NULL )
- return true;// no player attached, report source
-
- id = ( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
+ return false; // no player attached, report source
+
+ if( (gd = sd->guild) == NULL )
+ return true;
+
+ skill_id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
level = script_getnum(st,3);
- for( i=0; i < level; i++ )
- guild->skillup(sd, id);
-
+
+ id = skill_id - GD_SKILLBASE;
+ max_points = guild->skill_get_max(skill_id);
+
+ if( (gd->skill[id].lv + level) > max_points )
+ level = max_points - gd->skill[id].lv;
+
+ if( level <= 0 )
+ return true;
+
+ memcpy(&gd_skill, &(gd->skill[id]), sizeof(gd->skill[id]));
+ gd_skill.lv += level;
+
+ intif->guild_change_basicinfo( gd->guild_id, GBI_SKILLLV, &(gd_skill), sizeof(gd_skill) );
return true;
}
@@ -7668,18 +8315,17 @@ BUILDIN(guildskill)
///
/// getskilllv(<skill id>) -> <level>
/// getskilllv("<skill name>") -> <level>
-BUILDIN(getskilllv)
-{
+BUILDIN(getskilllv) {
int id;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
- id = ( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
+
+ id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
script_pushint(st, pc->checkskill(sd,id));
-
+
return true;
}
@@ -7687,20 +8333,19 @@ BUILDIN(getskilllv)
///
/// getgdskilllv(<guild id>,<skill id>) -> <level>
/// getgdskilllv(<guild id>,"<skill name>") -> <level>
-BUILDIN(getgdskilllv)
-{
+BUILDIN(getgdskilllv) {
int guild_id;
uint16 skill_id;
struct guild* g;
-
+
guild_id = script_getnum(st,2);
- skill_id = ( script_isstring(st,3) ? skill->name2id(script_getstr(st,3)) : script_getnum(st,3) );
+ skill_id = ( script_isstringtype(st,3) ? skill->name2id(script_getstr(st,3)) : script_getnum(st,3) );
g = guild->search(guild_id);
if( g == NULL )
script_pushint(st, -1);
else
script_pushint(st, guild->checkskill(g,skill_id));
-
+
return true;
}
@@ -7721,13 +8366,13 @@ BUILDIN(basicskillcheck)
BUILDIN(getgmlevel)
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
- script_pushint(st, pc->get_group_level(sd));
-
+
+ script_pushint(st, pc_get_group_level(sd));
+
return true;
}
@@ -7737,12 +8382,12 @@ BUILDIN(getgmlevel)
BUILDIN(getgroupid)
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if (sd == NULL)
return false; // no player attached, report source
script_pushint(st, pc_get_group_id(sd));
-
+
return true;
}
@@ -7751,6 +8396,18 @@ BUILDIN(getgroupid)
/// end
BUILDIN(end) {
st->state = END;
+
+ /* are we stopping inside a function? */
+ if( st->stack->defsp >= 1 && st->stack->stack_data[st->stack->defsp-1].type == C_RETINFO ) {
+ int i;
+ for(i = 0; i < st->stack->sp; i++) {
+ if( st->stack->stack_data[i].type == C_RETINFO ) {/* grab the first, aka the original */
+ struct script_retinfo *ri = st->stack->stack_data[i].u.ri;
+ st->script = ri->script;
+ break;
+ }
+ }
+ }
return true;
}
@@ -7761,17 +8418,17 @@ BUILDIN(checkoption)
{
int option;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
option = script_getnum(st,2);
if( sd->sc.option&option )
script_pushint(st, 1);
else
script_pushint(st, 0);
-
+
return true;
}
@@ -7782,17 +8439,17 @@ BUILDIN(checkoption1)
{
int opt1;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
opt1 = script_getnum(st,2);
if( sd->sc.opt1 == opt1 )
script_pushint(st, 1);
else
script_pushint(st, 0);
-
+
return true;
}
@@ -7803,17 +8460,17 @@ BUILDIN(checkoption2)
{
int opt2;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
opt2 = script_getnum(st,2);
if( sd->sc.opt2&opt2 )
script_pushint(st, 1);
else
script_pushint(st, 0);
-
+
return true;
}
@@ -7829,28 +8486,28 @@ BUILDIN(setoption)
int option;
int flag = 1;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
option = script_getnum(st,2);
if( script_hasdata(st,3) )
flag = script_getnum(st,3);
- else if( !option ){// Request to remove everything.
+ else if( !option ) {// Request to remove everything.
flag = 0;
option = OPTION_FALCON|OPTION_RIDING;
#ifndef NEW_CARTS
option |= OPTION_CART;
#endif
}
- if( flag ){// Add option
+ if( flag ) {// Add option
if( option&OPTION_WEDDING && !battle_config.wedding_modifydisplay )
option &= ~OPTION_WEDDING;// Do not show the wedding sprites
pc->setoption(sd, sd->sc.option|option);
} else// Remove option
pc->setoption(sd, sd->sc.option&~option);
-
+
return true;
}
@@ -7862,16 +8519,16 @@ BUILDIN(setoption)
BUILDIN(checkcart)
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
if( pc_iscarton(sd) )
script_pushint(st, 1);
else
script_pushint(st, 0);
-
+
return true;
}
@@ -7890,15 +8547,15 @@ BUILDIN(setcart)
{
int type = 1;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
if( script_hasdata(st,2) )
type = script_getnum(st,2);
pc->setcart(sd, type);
-
+
return true;
}
@@ -7910,16 +8567,16 @@ BUILDIN(setcart)
BUILDIN(checkfalcon)
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
if( pc_isfalcon(sd) )
script_pushint(st, 1);
else
script_pushint(st, 0);
-
+
return true;
}
@@ -7932,16 +8589,16 @@ BUILDIN(setfalcon)
{
int flag = 1;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
if( script_hasdata(st,2) )
flag = script_getnum(st,2);
-
+
pc->setfalcon(sd, flag);
-
+
return true;
}
@@ -7953,16 +8610,16 @@ BUILDIN(setfalcon)
BUILDIN(checkriding)
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
if( pc_isriding(sd) || pc_isridingwug(sd) || pc_isridingdragon(sd) )
script_pushint(st, 1);
else
script_pushint(st, 0);
-
+
return true;
}
@@ -7975,15 +8632,15 @@ BUILDIN(setriding)
{
int flag = 1;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
if( script_hasdata(st,2) )
flag = script_getnum(st,2);
pc->setriding(sd, flag);
-
+
return true;
}
@@ -7994,16 +8651,16 @@ BUILDIN(setriding)
BUILDIN(checkwug)
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
if( pc_iswug(sd) || pc_isridingwug(sd) )
script_pushint(st, 1);
else
script_pushint(st, 0);
-
+
return true;
}
@@ -8014,16 +8671,16 @@ BUILDIN(checkwug)
BUILDIN(checkmadogear)
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
if( pc_ismadogear(sd) )
script_pushint(st, 1);
else
script_pushint(st, 0);
-
+
return true;
}
@@ -8036,15 +8693,15 @@ BUILDIN(setmadogear)
{
int flag = 1;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached, report source
-
+
if( script_hasdata(st,2) )
flag = script_getnum(st,2);
pc->setmadogear(sd, flag);
-
+
return true;
}
@@ -8052,40 +8709,38 @@ BUILDIN(setmadogear)
///
/// save "<map name>",<x>,<y>
/// savepoint "<map name>",<x>,<y>
-BUILDIN(savepoint)
-{
+BUILDIN(savepoint) {
int x;
int y;
- short map;
+ short mapid;
const char* str;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
- return true;// no player attached, report source
-
- str = script_getstr(st, 2);
- x = script_getnum(st,3);
- y = script_getnum(st,4);
- map = mapindex_name2id(str);
- if( map )
- pc->setsavepoint(sd, map, x, y);
-
+ return false;// no player attached, report source
+
+ str = script_getstr(st,2);
+ x = script_getnum(st,3);
+ y = script_getnum(st,4);
+ mapid = script->mapindexname2id(st,str);
+ if( mapid )
+ pc->setsavepoint(sd, mapid, x, y);
+
return true;
}
/*==========================================
* GetTimeTick(0: System Tick, 1: Time Second Tick)
*------------------------------------------*/
-BUILDIN(gettimetick) /* Asgard Version */
-{
+BUILDIN(gettimetick) { /* Asgard Version */
int type;
- time_t timer;
+ time_t clock;
struct tm *t;
-
+
type=script_getnum(st,2);
-
- switch(type){
+
+ switch(type) {
case 2:
//type 2:(Get the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC
// from the system clock.)
@@ -8093,37 +8748,35 @@ BUILDIN(gettimetick) /* Asgard Version */
break;
case 1:
//type 1:(Second Ticks: 0-86399, 00:00:00-23:59:59)
- time(&timer);
- t=localtime(&timer);
+ time(&clock);
+ t=localtime(&clock);
script_pushint(st,((t->tm_hour)*3600+(t->tm_min)*60+t->tm_sec));
break;
case 0:
default:
//type 0:(System Ticks)
- script_pushint(st,iTimer->gettick());
+ script_pushint(st,(int)timer->gettick()); // TODO: change this to int64 when we'll support 64 bit script values
break;
}
return true;
}
-
/*==========================================
* GetTime(Type);
* 1: Sec 2: Min 3: Hour
* 4: WeekDay 5: MonthDay 6: Month
* 7: Year
*------------------------------------------*/
-BUILDIN(gettime) /* Asgard Version */
-{
+BUILDIN(gettime) { /* Asgard Version */
int type;
- time_t timer;
+ time_t clock;
struct tm *t;
-
+
type=script_getnum(st,2);
-
- time(&timer);
- t=localtime(&timer);
-
- switch(type){
+
+ time(&clock);
+ t=localtime(&clock);
+
+ switch(type) {
case 1://Sec(0~59)
script_pushint(st,t->tm_sec);
break;
@@ -8164,14 +8817,14 @@ BUILDIN(gettimestr)
const char *fmtstr;
int maxlen;
time_t now = time(NULL);
-
+
fmtstr=script_getstr(st,2);
maxlen=script_getnum(st,3);
-
+
tmpstr=(char *)aMalloc((maxlen+1)*sizeof(char));
strftime(tmpstr,maxlen,fmtstr,localtime(&now));
tmpstr[maxlen]='\0';
-
+
script_pushstr(st,tmpstr);
return true;
}
@@ -8179,28 +8832,26 @@ BUILDIN(gettimestr)
/*==========================================
* Open player storage
*------------------------------------------*/
-BUILDIN(openstorage)
-{
+BUILDIN(openstorage) {
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- storage_storageopen(sd);
+
+ storage->open(sd);
return true;
}
-BUILDIN(guildopenstorage)
-{
+BUILDIN(guildopenstorage) {
TBL_PC* sd;
int ret;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- ret = storage_guild_storageopen(sd);
+
+ ret = gstorage->open(sd);
script_pushint(st,ret);
return true;
}
@@ -8214,12 +8865,12 @@ BUILDIN(itemskill) {
int id;
int lv;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL || sd->ud.skilltimer != INVALID_TIMER )
return true;
-
- id = ( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
+
+ id = ( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
lv = script_getnum(st,3);
/* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */
#if 0
@@ -8240,11 +8891,11 @@ BUILDIN(produce)
{
int trigger;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
trigger=script_getnum(st,2);
clif->skill_produce_mix_list(sd, -1, trigger);
return true;
@@ -8256,11 +8907,11 @@ BUILDIN(cooking)
{
int trigger;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
trigger=script_getnum(st,2);
clif->cooking_list(sd, trigger, AM_PHARMACY, 1, 1);
return true;
@@ -8272,25 +8923,24 @@ BUILDIN(makepet)
{
TBL_PC* sd;
int id,pet_id;
-
+
id=script_getnum(st,2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- pet_id = search_petDB_index(id, PET_CLASS);
-
+
+ pet_id = pet->search_petDB_index(id, PET_CLASS);
+
if (pet_id < 0)
- pet_id = search_petDB_index(id, PET_EGG);
+ pet_id = pet->search_petDB_index(id, PET_EGG);
if (pet_id >= 0 && sd) {
- sd->catch_target_class = pet_db[pet_id].class_;
- intif_create_pet(
- sd->status.account_id, sd->status.char_id,
- (short)pet_db[pet_id].class_, (short)mob_db(pet_db[pet_id].class_)->lv,
- (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate,
- 100, 0, 1, pet_db[pet_id].jname);
+ sd->catch_target_class = pet->db[pet_id].class_;
+ intif->create_pet(sd->status.account_id, sd->status.char_id,
+ (short)pet->db[pet_id].class_, (short)mob->db(pet->db[pet_id].class_)->lv,
+ (short)pet->db[pet_id].EggID, 0, (short)pet->db[pet_id].intimate,
+ 100, 0, 1, pet->db[pet_id].jname);
}
-
+
return true;
}
/*==========================================
@@ -8301,23 +8951,23 @@ BUILDIN(getexp)
TBL_PC* sd;
int base=0,job=0;
double bonus;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
base=script_getnum(st,2);
job =script_getnum(st,3);
if(base<0 || job<0)
return true;
-
+
// bonus for npc-given exp
bonus = battle_config.quest_exp_rate / 100.;
base = (int) cap_value(base * bonus, 0, INT_MAX);
job = (int) cap_value(job * bonus, 0, INT_MAX);
-
- pc->gainexp(sd, NULL, base, job, true);
-
+
+ pc->gainexp(sd, &sd->bl, base, job, true);
+
return true;
}
@@ -8328,71 +8978,70 @@ BUILDIN(guildgetexp)
{
TBL_PC* sd;
int exp;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
exp = script_getnum(st,2);
if(exp < 0)
return true;
if(sd && sd->status.guild_id > 0)
guild->getexp (sd, exp);
-
+
return true;
}
/*==========================================
* Changes the guild master of a guild [Skotlex]
*------------------------------------------*/
-BUILDIN(guildchangegm)
-{
+BUILDIN(guildchangegm) {
TBL_PC *sd;
int guild_id;
const char *name;
-
+
guild_id = script_getnum(st,2);
name = script_getstr(st,3);
- sd=iMap->nick2sd(name);
-
+ sd=map->nick2sd(name);
+
if (!sd)
script_pushint(st,0);
else
script_pushint(st,guild->gm_change(guild_id, sd));
-
+
return true;
}
/*==========================================
* Spawn a monster :
- @mapn,x,y : location
- @str : monster name
- @class_ : mob_id
- @amount : nb to spawn
- @event : event to attach to mob
+ * @mapn,x,y : location
+ * @str : monster name
+ * @class_ : mob_id
+ * @amount : nb to spawn
+ * @event : event to attach to mob
*------------------------------------------*/
BUILDIN(monster)
{
- const char* mapn = script_getstr(st,2);
- int x = script_getnum(st,3);
- int y = script_getnum(st,4);
- const char* str = script_getstr(st,5);
- int class_ = script_getnum(st,6);
- int amount = script_getnum(st,7);
- const char* event = "";
- unsigned int size = SZ_SMALL;
- unsigned int ai = AI_NONE;
+ const char *mapn = script_getstr(st,2);
+ int x = script_getnum(st,3);
+ int y = script_getnum(st,4);
+ const char *str = script_getstr(st,5);
+ int class_ = script_getnum(st,6);
+ int amount = script_getnum(st,7);
+ const char *event = "";
+ unsigned int size = SZ_MEDIUM;
+ unsigned int ai = AI_NONE;
int mob_id;
-
+
struct map_session_data* sd;
int16 m;
-
+
if (script_hasdata(st, 8))
{
event = script_getstr(st, 8);
- check_event(st, event);
+ script->check_event(st, event);
}
-
+
if (script_hasdata(st, 9))
{
size = script_getnum(st, 9);
@@ -8402,7 +9051,7 @@ BUILDIN(monster)
return false;
}
}
-
+
if (script_hasdata(st, 10))
{
ai = script_getnum(st, 10);
@@ -8412,28 +9061,32 @@ BUILDIN(monster)
return false;
}
}
-
- if (class_ >= 0 && !mobdb_checkid(class_))
+
+ if (class_ >= 0 && !mob->db_checkid(class_))
{
ShowWarning("buildin_monster: Attempted to spawn non-existing monster class %d\n", class_);
return false;
}
-
- sd = iMap->id2sd(st->rid);
-
+
+ sd = map->id2sd(st->rid);
+
if (sd && strcmp(mapn, "this") == 0)
m = sd->bl.m;
else {
- m = iMap->mapname2mapid(mapn);
- if (map[m].flag.src4instance && st->instance_id >= 0) { // Try to redirect to the instance map, not the src map
+ if ( ( m = map->mapname2mapid(mapn) ) == -1 ) {
+ ShowWarning("buildin_monster: Attempted to spawn monster class %d on non-existing map '%s'\n",class_, mapn);
+ return false;
+ }
+
+ if (map->list[m].flag.src4instance && st->instance_id >= 0) { // Try to redirect to the instance map, not the src map
if ((m = instance->mapid2imapid(m, st->instance_id)) < 0) {
ShowError("buildin_monster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn);
return false;
}
}
}
-
- mob_id = mob_once_spawn(sd, m, x, y, str, class_, amount, event, size, ai);
+
+ mob_id = mob->once_spawn(sd, m, x, y, str, class_, amount, event, size, ai);
script_pushint(st, mob_id);
return true;
}
@@ -8444,60 +9097,59 @@ BUILDIN(getmobdrops)
{
int class_ = script_getnum(st,2);
int i, j = 0;
- struct mob_db *mob;
-
- if( !mobdb_checkid(class_) )
+ struct mob_db *monster;
+
+ if( !mob->db_checkid(class_) )
{
script_pushint(st, 0);
return true;
}
-
- mob = mob_db(class_);
-
+
+ monster = mob->db(class_);
+
for( i = 0; i < MAX_MOB_DROP; i++ )
{
- if( mob->dropitem[i].nameid < 1 )
+ if( monster->dropitem[i].nameid < 1 )
continue;
- if( itemdb_exists(mob->dropitem[i].nameid) == NULL )
+ if( itemdb->exists(monster->dropitem[i].nameid) == NULL )
continue;
-
- mapreg_setreg(reference_uid(add_str("$@MobDrop_item"), j), mob->dropitem[i].nameid);
- mapreg_setreg(reference_uid(add_str("$@MobDrop_rate"), j), mob->dropitem[i].p);
-
+
+ mapreg->setreg(reference_uid(script->add_str("$@MobDrop_item"), j), monster->dropitem[i].nameid);
+ mapreg->setreg(reference_uid(script->add_str("$@MobDrop_rate"), j), monster->dropitem[i].p);
+
j++;
}
-
- mapreg_setreg(add_str("$@MobDrop_count"), j);
+
+ mapreg->setreg(script->add_str("$@MobDrop_count"), j);
script_pushint(st, 1);
-
+
return true;
}
/*==========================================
* Same as monster but randomize location in x0,x1,y0,y1 area
*------------------------------------------*/
-BUILDIN(areamonster)
-{
- const char* mapn = script_getstr(st,2);
- int x0 = script_getnum(st,3);
- int y0 = script_getnum(st,4);
- int x1 = script_getnum(st,5);
- int y1 = script_getnum(st,6);
- const char* str = script_getstr(st,7);
- int class_ = script_getnum(st,8);
- int amount = script_getnum(st,9);
- const char* event = "";
- unsigned int size = SZ_SMALL;
- unsigned int ai = AI_NONE;
+BUILDIN(areamonster) {
+ const char *mapn = script_getstr(st,2);
+ int x0 = script_getnum(st,3);
+ int y0 = script_getnum(st,4);
+ int x1 = script_getnum(st,5);
+ int y1 = script_getnum(st,6);
+ const char *str = script_getstr(st,7);
+ int class_ = script_getnum(st,8);
+ int amount = script_getnum(st,9);
+ const char *event = "";
+ unsigned int size = SZ_MEDIUM;
+ unsigned int ai = AI_NONE;
int mob_id;
-
+
struct map_session_data* sd;
int16 m;
-
+
if (script_hasdata(st,10)) {
event = script_getstr(st, 10);
- check_event(st, event);
+ script->check_event(st, event);
}
-
+
if (script_hasdata(st, 11)) {
size = script_getnum(st, 11);
if (size > 3) {
@@ -8505,7 +9157,7 @@ BUILDIN(areamonster)
return false;
}
}
-
+
if (script_hasdata(st, 12)) {
ai = script_getnum(st, 12);
if (ai > 4) {
@@ -8513,64 +9165,66 @@ BUILDIN(areamonster)
return false;
}
}
-
- sd = iMap->id2sd(st->rid);
-
+
+ sd = map->id2sd(st->rid);
+
if (sd && strcmp(mapn, "this") == 0)
m = sd->bl.m;
else {
- m = iMap->mapname2mapid(mapn);
- if (map[m].flag.src4instance && st->instance_id >= 0) { // Try to redirect to the instance map, not the src map
+ if ( ( m = map->mapname2mapid(mapn) ) == -1 ) {
+ ShowWarning("buildin_areamonster: Attempted to spawn monster class %d on non-existing map '%s'\n",class_, mapn);
+ return false;
+ }
+ if (map->list[m].flag.src4instance && st->instance_id >= 0) { // Try to redirect to the instance map, not the src map
if ((m = instance->mapid2imapid(m, st->instance_id)) < 0) {
ShowError("buildin_areamonster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn);
return false;
}
}
}
-
- mob_id = mob_once_spawn_area(sd, m, x0, y0, x1, y1, str, class_, amount, event, size, ai);
+
+ mob_id = mob->once_spawn_area(sd, m, x0, y0, x1, y1, str, class_, amount, event, size, ai);
script_pushint(st, mob_id);
-
+
return true;
}
/*==========================================
* KillMonster subcheck, verify if mob to kill ain't got an even to handle, could be force kill by allflag
*------------------------------------------*/
-static int buildin_killmonster_sub_strip(struct block_list *bl,va_list ap)
+int buildin_killmonster_sub_strip(struct block_list *bl,va_list ap)
{ //same fix but with killmonster instead - stripping events from mobs.
TBL_MOB* md = (TBL_MOB*)bl;
char *event=va_arg(ap,char *);
int allflag=va_arg(ap,int);
-
+
md->state.npc_killmonster = 1;
-
- if(!allflag){
+
+ if(!allflag) {
if(strcmp(event,md->npc_event)==0)
status_kill(bl);
- }else{
+ } else {
if(!md->spawn)
status_kill(bl);
}
md->state.npc_killmonster = 0;
return 0;
}
-static int buildin_killmonster_sub(struct block_list *bl,va_list ap)
+int buildin_killmonster_sub(struct block_list *bl,va_list ap)
{
TBL_MOB* md = (TBL_MOB*)bl;
char *event=va_arg(ap,char *);
int allflag=va_arg(ap,int);
-
- if(!allflag){
+
+ if(!allflag) {
if(strcmp(event,md->npc_event)==0)
status_kill(bl);
- }else{
+ } else {
if(!md->spawn)
status_kill(bl);
}
return 0;
}
-BUILDIN(killmonster)
-{
+BUILDIN(killmonster) {
const char *mapname,*event;
int16 m,allflag=0;
mapname=script_getstr(st,2);
@@ -8578,63 +9232,62 @@ BUILDIN(killmonster)
if(strcmp(event,"All")==0)
allflag = 1;
else
- check_event(st, event);
-
- if( (m=iMap->mapname2mapid(mapname))<0 )
+ script->check_event(st, event);
+
+ if( (m=map->mapname2mapid(mapname))<0 )
return true;
-
- if( map[m].flag.src4instance && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 )
+
+ if( map->list[m].flag.src4instance && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 )
return true;
-
+
if( script_hasdata(st,4) ) {
if ( script_getnum(st,4) == 1 ) {
- iMap->foreachinmap(buildin_killmonster_sub, m, BL_MOB, event ,allflag);
+ map->foreachinmap(script->buildin_killmonster_sub, m, BL_MOB, event ,allflag);
return true;
}
}
-
- iMap->freeblock_lock();
- iMap->foreachinmap(buildin_killmonster_sub_strip, m, BL_MOB, event ,allflag);
- iMap->freeblock_unlock();
+
+ map->freeblock_lock();
+ map->foreachinmap(script->buildin_killmonster_sub_strip, m, BL_MOB, event ,allflag);
+ map->freeblock_unlock();
return true;
}
-static int buildin_killmonsterall_sub_strip(struct block_list *bl,va_list ap)
+int buildin_killmonsterall_sub_strip(struct block_list *bl,va_list ap)
{ //Strips the event from the mob if it's killed the old method.
struct mob_data *md;
-
+
md = BL_CAST(BL_MOB, bl);
if (md->npc_event[0])
md->npc_event[0] = 0;
-
+
status_kill(bl);
return 0;
}
-static int buildin_killmonsterall_sub(struct block_list *bl,va_list ap)
+int buildin_killmonsterall_sub(struct block_list *bl,va_list ap)
{
status_kill(bl);
return 0;
}
-BUILDIN(killmonsterall)
-{
+BUILDIN(killmonsterall) {
const char *mapname;
int16 m;
mapname=script_getstr(st,2);
-
- if( (m = iMap->mapname2mapid(mapname))<0 )
+
+ if( (m = map->mapname2mapid(mapname))<0 )
return true;
-
- if( map[m].flag.src4instance && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 )
+
+ if( map->list[m].flag.src4instance && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 )
return true;
-
+
if( script_hasdata(st,3) ) {
if ( script_getnum(st,3) == 1 ) {
- iMap->foreachinmap(buildin_killmonsterall_sub,m,BL_MOB);
+ map->foreachinmap(script->buildin_killmonsterall_sub,m,BL_MOB);
return true;
}
}
-
- iMap->foreachinmap(buildin_killmonsterall_sub_strip,m,BL_MOB);
+
+ map->foreachinmap(script->buildin_killmonsterall_sub_strip,m,BL_MOB);
return true;
}
@@ -8642,50 +9295,49 @@ BUILDIN(killmonsterall)
* Creates a clone of a player.
* clone map, x, y, event, char_id, master_id, mode, flag, duration
*------------------------------------------*/
-BUILDIN(clone)
-{
+BUILDIN(clone) {
TBL_PC *sd, *msd=NULL;
int char_id,master_id=0,x,y, mode = 0, flag = 0, m;
unsigned int duration = 0;
- const char *map,*event="";
-
- map=script_getstr(st,2);
+ const char *mapname, *event="";
+
+ mapname=script_getstr(st,2);
x=script_getnum(st,3);
y=script_getnum(st,4);
event=script_getstr(st,5);
char_id=script_getnum(st,6);
-
+
if( script_hasdata(st,7) )
master_id=script_getnum(st,7);
-
+
if( script_hasdata(st,8) )
mode=script_getnum(st,8);
-
+
if( script_hasdata(st,9) )
flag=script_getnum(st,9);
-
+
if( script_hasdata(st,10) )
duration=script_getnum(st,10);
-
- check_event(st, event);
-
- m = iMap->mapname2mapid(map);
+
+ script->check_event(st, event);
+
+ m = map->mapname2mapid(mapname);
if (m < 0) return true;
-
- sd = iMap->charid2sd(char_id);
-
+
+ sd = map->charid2sd(char_id);
+
if (master_id) {
- msd = iMap->charid2sd(master_id);
+ msd = map->charid2sd(master_id);
if (msd)
master_id = msd->bl.id;
else
master_id = 0;
}
if (sd) //Return ID of newly crafted clone.
- script_pushint(st,mob_clone_spawn(sd, m, x, y, event, master_id, mode, flag, 1000*duration));
+ script_pushint(st,mob->clone_spawn(sd, m, x, y, event, master_id, mode, flag, 1000*duration));
else //Failed to create clone.
script_pushint(st,0);
-
+
return true;
}
/*==========================================
@@ -8694,14 +9346,14 @@ BUILDIN(doevent)
{
const char* event = script_getstr(st,2);
struct map_session_data* sd;
-
- if( ( sd = script_rid2sd(st) ) == NULL )
+
+ if( ( sd = script->rid2sd(st) ) == NULL )
{
return true;
}
-
- check_event(st, event);
- npc_event(sd, event, 0);
+
+ script->check_event(st, event);
+ npc->event(sd, event, 0);
return true;
}
/*==========================================
@@ -8709,9 +9361,9 @@ BUILDIN(doevent)
BUILDIN(donpcevent)
{
const char* event = script_getstr(st,2);
- check_event(st, event);
- if( !npc_event_do(event) ) {
- struct npc_data * nd = iMap->id2nd(st->oid);
+ script->check_event(st, event);
+ if( !npc->event_do(event) ) {
+ struct npc_data * nd = map->id2nd(st->oid);
ShowDebug("NPCEvent '%s' not found! (source: %s)\n",event,nd?nd->name:"Unknown");
script_pushint(st, 0);
} else
@@ -8720,15 +9372,14 @@ BUILDIN(donpcevent)
}
/// for Aegis compatibility
-/// basically a specialized 'donpcevent', with the event specified as two arguments instead of one
-BUILDIN(cmdothernpc) // Added by RoVeRT
-{
- const char* npc = script_getstr(st,2);
+/// basically a specialized 'donpcevent', with the event specified as two arguments instead of one [RoVeRT]
+BUILDIN(cmdothernpc) {
+ const char* npc_name = script_getstr(st,2);
const char* command = script_getstr(st,3);
char event[EVENT_NAME_LENGTH];
- snprintf(event, sizeof(event), "%s::OnCommand%s", npc, command);
- check_event(st, event);
- npc_event_do(event);
+ snprintf(event, sizeof(event), "%s::OnCommand%s", npc_name, command);
+ script->check_event(st, event);
+ npc->event_do(event);
return true;
}
@@ -8739,13 +9390,16 @@ BUILDIN(addtimer)
int tick = script_getnum(st,2);
const char* event = script_getstr(st, 3);
TBL_PC* sd;
-
- check_event(st, event);
- sd = script_rid2sd(st);
+
+ script->check_event(st, event);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- pc->addeventtimer(sd,tick,event);
+
+ if (!pc->addeventtimer(sd,tick,event)) {
+ ShowWarning("buildin_addtimer: Event timer is full, can't add new event timer. (cid:%d timer:%s)\n",sd->status.char_id,event);
+ return false;
+ }
return true;
}
/*==========================================
@@ -8754,13 +9408,13 @@ BUILDIN(deltimer)
{
const char *event;
TBL_PC* sd;
-
+
event=script_getstr(st, 2);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- check_event(st, event);
+
+ script->check_event(st, event);
pc->deleventtimer(sd,event);
return true;
}
@@ -8771,14 +9425,14 @@ BUILDIN(addtimercount)
const char *event;
int tick;
TBL_PC* sd;
-
+
event=script_getstr(st, 2);
tick=script_getnum(st,3);
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
- check_event(st, event);
+
+ script->check_event(st, event);
pc->addeventtimercount(sd,event,tick);
return true;
}
@@ -8789,46 +9443,42 @@ BUILDIN(initnpctimer)
{
struct npc_data *nd;
int flag = 0;
-
- if( script_hasdata(st,3) )
- { //Two arguments: NPC name and attach flag.
- nd = npc_name2id(script_getstr(st, 2));
+
+ if( script_hasdata(st,3) ) {
+ //Two arguments: NPC name and attach flag.
+ nd = npc->name2id(script_getstr(st, 2));
flag = script_getnum(st,3);
- }
- else if( script_hasdata(st,2) )
- { //Check if argument is numeric (flag) or string (npc name)
+ } else if( script_hasdata(st,2) ) {
+ //Check if argument is numeric (flag) or string (npc name)
struct script_data *data;
data = script_getdata(st,2);
- script->get_val(st,data);
+ script->get_val(st,data); // dereference if it's a variable
if( data_isstring(data) ) //NPC name
- nd = npc_name2id(script->conv_str(st, data));
- else if( data_isint(data) ) //Flag
- {
- nd = (struct npc_data *)iMap->id2bl(st->oid);
+ nd = npc->name2id(script->conv_str(st, data));
+ else if( data_isint(data) ) {
+ //Flag
+ nd = (struct npc_data *)map->id2bl(st->oid);
flag = script->conv_num(st,data);
- }
- else
- {
+ } else {
ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n");
return false;
}
- }
- else
- nd = (struct npc_data *)iMap->id2bl(st->oid);
-
+ } else
+ nd = (struct npc_data *)map->id2bl(st->oid);
+
if( !nd )
return true;
if( flag ) //Attach
{
- TBL_PC* sd = script_rid2sd(st);
+ TBL_PC* sd = script->rid2sd(st);
if( sd == NULL )
return true;
nd->u.scr.rid = sd->bl.id;
}
-
+
nd->u.scr.timertick = 0;
- npc_settimerevent_tick(nd,0);
- npc_timerevent_start(nd, st->rid);
+ npc->settimerevent_tick(nd,0);
+ npc->timerevent_start(nd, st->rid);
return true;
}
/*==========================================
@@ -8837,117 +9487,104 @@ BUILDIN(startnpctimer)
{
struct npc_data *nd;
int flag = 0;
-
- if( script_hasdata(st,3) )
- { //Two arguments: NPC name and attach flag.
- nd = npc_name2id(script_getstr(st, 2));
+
+ if( script_hasdata(st,3) ) {
+ //Two arguments: NPC name and attach flag.
+ nd = npc->name2id(script_getstr(st, 2));
flag = script_getnum(st,3);
- }
- else if( script_hasdata(st,2) )
- { //Check if argument is numeric (flag) or string (npc name)
+ } else if( script_hasdata(st,2) ) {
+ //Check if argument is numeric (flag) or string (npc name)
struct script_data *data;
data = script_getdata(st,2);
- script->get_val(st,data);
+ script->get_val(st,data); // dereference if it's a variable
if( data_isstring(data) ) //NPC name
- nd = npc_name2id(script->conv_str(st, data));
- else if( data_isint(data) ) //Flag
- {
- nd = (struct npc_data *)iMap->id2bl(st->oid);
+ nd = npc->name2id(script->conv_str(st, data));
+ else if( data_isint(data) ) {
+ //Flag
+ nd = (struct npc_data *)map->id2bl(st->oid);
flag = script->conv_num(st,data);
- }
- else
- {
+ } else {
ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n");
return false;
}
- }
- else
- nd=(struct npc_data *)iMap->id2bl(st->oid);
-
+ } else
+ nd=(struct npc_data *)map->id2bl(st->oid);
+
if( !nd )
return true;
if( flag ) //Attach
{
- TBL_PC* sd = script_rid2sd(st);
+ TBL_PC* sd = script->rid2sd(st);
if( sd == NULL )
return true;
nd->u.scr.rid = sd->bl.id;
}
-
- npc_timerevent_start(nd, st->rid);
+
+ npc->timerevent_start(nd, st->rid);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(stopnpctimer)
-{
+BUILDIN(stopnpctimer) {
struct npc_data *nd;
int flag = 0;
-
- if( script_hasdata(st,3) )
- { //Two arguments: NPC name and attach flag.
- nd = npc_name2id(script_getstr(st, 2));
+
+ if( script_hasdata(st,3) ) {
+ //Two arguments: NPC name and attach flag.
+ nd = npc->name2id(script_getstr(st, 2));
flag = script_getnum(st,3);
- }
- else if( script_hasdata(st,2) )
- { //Check if argument is numeric (flag) or string (npc name)
+ } else if( script_hasdata(st,2) ) {
+ //Check if argument is numeric (flag) or string (npc name)
struct script_data *data;
data = script_getdata(st,2);
- script->get_val(st,data);
+ script->get_val(st,data); // Dereference if it's a variable
if( data_isstring(data) ) //NPC name
- nd = npc_name2id(script->conv_str(st, data));
- else if( data_isint(data) ) //Flag
- {
- nd = (struct npc_data *)iMap->id2bl(st->oid);
+ nd = npc->name2id(script->conv_str(st, data));
+ else if( data_isint(data) ) {
+ //Flag
+ nd = (struct npc_data *)map->id2bl(st->oid);
flag = script->conv_num(st,data);
- }
- else
- {
+ } else {
ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n");
return false;
}
- }
- else
- nd=(struct npc_data *)iMap->id2bl(st->oid);
-
+ } else
+ nd=(struct npc_data *)map->id2bl(st->oid);
+
if( !nd )
return true;
if( flag ) //Detach
nd->u.scr.rid = 0;
-
- npc_timerevent_stop(nd);
+
+ npc->timerevent_stop(nd);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(getnpctimer)
-{
+BUILDIN(getnpctimer) {
struct npc_data *nd;
TBL_PC *sd;
int type = script_getnum(st,2);
int val = 0;
-
+
if( script_hasdata(st,3) )
- nd = npc_name2id(script_getstr(st,3));
+ nd = npc->name2id(script_getstr(st,3));
else
- nd = (struct npc_data *)iMap->id2bl(st->oid);
-
+ nd = (struct npc_data *)map->id2bl(st->oid);
+
if( !nd || nd->bl.type != BL_NPC )
{
script_pushint(st,0);
ShowError("getnpctimer: Invalid NPC.\n");
return false;
}
-
- switch( type )
- {
- case 0: val = npc_gettimerevent_tick(nd); break;
+
+ switch( type ) {
+ case 0: val = (int)npc->gettimerevent_tick(nd); break; // FIXME: change this to int64 when we'll support 64 bit script values
case 1:
- if( nd->u.scr.rid )
- {
- sd = iMap->id2sd(nd->u.scr.rid);
- if( !sd )
- {
+ if( nd->u.scr.rid ) {
+ sd = map->id2sd(nd->u.scr.rid);
+ if( !sd ) {
ShowError("buildin_getnpctimer: Attached player not found!\n");
break;
}
@@ -8958,7 +9595,7 @@ BUILDIN(getnpctimer)
break;
case 2: val = nd->u.scr.timeramount; break;
}
-
+
script_pushint(st,val);
return true;
}
@@ -8968,21 +9605,20 @@ BUILDIN(setnpctimer)
{
int tick;
struct npc_data *nd;
-
+
tick = script_getnum(st,2);
if( script_hasdata(st,3) )
- nd = npc_name2id(script_getstr(st,3));
+ nd = npc->name2id(script_getstr(st,3));
else
- nd = (struct npc_data *)iMap->id2bl(st->oid);
-
- if( !nd || nd->bl.type != BL_NPC )
- {
+ nd = (struct npc_data *)map->id2bl(st->oid);
+
+ if( !nd || nd->bl.type != BL_NPC ) {
script_pushint(st,1);
ShowError("setnpctimer: Invalid NPC.\n");
return false;
}
-
- npc_settimerevent_tick(nd,tick);
+
+ npc->settimerevent_tick(nd,tick);
script_pushint(st,0);
return true;
}
@@ -8990,30 +9626,29 @@ BUILDIN(setnpctimer)
/*==========================================
* attaches the player rid to the timer [Celest]
*------------------------------------------*/
-BUILDIN(attachnpctimer)
-{
+BUILDIN(attachnpctimer) {
TBL_PC *sd;
- struct npc_data *nd = (struct npc_data *)iMap->id2bl(st->oid);
-
+ struct npc_data *nd = (struct npc_data *)map->id2bl(st->oid);
+
if( !nd || nd->bl.type != BL_NPC )
{
script_pushint(st,1);
ShowError("setnpctimer: Invalid NPC.\n");
return false;
}
-
+
if( script_hasdata(st,2) )
- sd = iMap->nick2sd(script_getstr(st,2));
+ sd = map->nick2sd(script_getstr(st,2));
else
- sd = script_rid2sd(st);
-
+ sd = script->rid2sd(st);
+
if( !sd )
{
script_pushint(st,1);
ShowWarning("attachnpctimer: Invalid player.\n");
return false;
}
-
+
nd->u.scr.rid = sd->bl.id;
script_pushint(st,0);
return true;
@@ -9022,22 +9657,21 @@ BUILDIN(attachnpctimer)
/*==========================================
* detaches a player rid from the timer [Celest]
*------------------------------------------*/
-BUILDIN(detachnpctimer)
-{
+BUILDIN(detachnpctimer) {
struct npc_data *nd;
-
+
if( script_hasdata(st,2) )
- nd = npc_name2id(script_getstr(st,2));
+ nd = npc->name2id(script_getstr(st,2));
else
- nd = (struct npc_data *)iMap->id2bl(st->oid);
-
+ nd = (struct npc_data *)map->id2bl(st->oid);
+
if( !nd || nd->bl.type != BL_NPC )
{
script_pushint(st,1);
ShowError("detachnpctimer: Invalid NPC.\n");
return false;
}
-
+
nd->u.scr.rid = 0;
script_pushint(st,0);
return true;
@@ -9048,9 +9682,8 @@ BUILDIN(detachnpctimer)
* it checks if there is a player attached to the current script. [Skotlex]
* If no, returns 0, if yes, returns the account_id of the attached player.
*------------------------------------------*/
-BUILDIN(playerattached)
-{
- if(st->rid == 0 || iMap->id2sd(st->rid) == NULL)
+BUILDIN(playerattached) {
+ if(st->rid == 0 || map->id2sd(st->rid) == NULL)
script_pushint(st,0);
else
script_pushint(st,st->rid);
@@ -9059,8 +9692,7 @@ BUILDIN(playerattached)
/*==========================================
*------------------------------------------*/
-BUILDIN(announce)
-{
+BUILDIN(announce) {
const char *mes = script_getstr(st,2);
int flag = script_getnum(st,3);
const char *fontColor = script_hasdata(st,4) ? script_getstr(st,4) : NULL;
@@ -9068,36 +9700,36 @@ BUILDIN(announce)
int fontSize = script_hasdata(st,6) ? script_getnum(st,6) : 12; // default fontSize
int fontAlign = script_hasdata(st,7) ? script_getnum(st,7) : 0; // default fontAlign
int fontY = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontY
-
- if (flag&0x0f) // Broadcast source or broadcast region defined
- {
+
+ if( flag&(BC_TARGET_MASK|BC_SOURCE_MASK) ) {
+ // Broadcast source or broadcast region defined
send_target target;
- struct block_list *bl = (flag&0x08) ? iMap->id2bl(st->oid) : (struct block_list *)script_rid2sd(st); // If bc_npc flag is set, use NPC as broadcast source
+ struct block_list *bl = (flag&BC_NPC) ? map->id2bl(st->oid) : (struct block_list *)script->rid2sd(st); // If bc_npc flag is set, use NPC as broadcast source
if (bl == NULL)
return true;
-
- flag &= 0x07;
- target = (flag == 1) ? ALL_SAMEMAP :
- (flag == 2) ? AREA :
- (flag == 3) ? SELF :
- ALL_CLIENT;
+
+ switch( flag&BC_TARGET_MASK ) {
+ case BC_MAP: target = ALL_SAMEMAP; break;
+ case BC_AREA: target = AREA; break;
+ case BC_SELF: target = SELF; break;
+ default: target = ALL_CLIENT; break; // BC_ALL
+ }
+
if (fontColor)
- clif->broadcast2(bl, mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, target);
+ clif->broadcast2(bl, mes, (int)strlen(mes)+1, (unsigned int)strtoul(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, target);
else
- clif->broadcast(bl, mes, (int)strlen(mes)+1, flag&0xf0, target);
- }
- else
- {
+ clif->broadcast(bl, mes, (int)strlen(mes)+1, flag&BC_COLOR_MASK, target);
+ } else {
if (fontColor)
- intif_broadcast2(mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY);
+ intif->broadcast2(mes, (int)strlen(mes)+1, (unsigned int)strtoul(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY);
else
- intif_broadcast(mes, (int)strlen(mes)+1, flag&0xf0);
+ intif->broadcast(mes, (int)strlen(mes)+1, flag&BC_COLOR_MASK);
}
return true;
}
/*==========================================
*------------------------------------------*/
-static int buildin_announce_sub(struct block_list *bl, va_list ap)
+int buildin_announce_sub(struct block_list *bl, va_list ap)
{
char *mes = va_arg(ap, char *);
int len = va_arg(ap, int);
@@ -9108,7 +9740,7 @@ static int buildin_announce_sub(struct block_list *bl, va_list ap)
short fontAlign = (short)va_arg(ap, int);
short fontY = (short)va_arg(ap, int);
if (fontColor)
- clif->broadcast2(bl, mes, len, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, SELF);
+ clif->broadcast2(bl, mes, len, (unsigned int)strtoul(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, SELF);
else
clif->broadcast(bl, mes, len, type, SELF);
return 0;
@@ -9119,41 +9751,38 @@ static int buildin_announce_sub(struct block_list *bl, va_list ap)
BUILDIN(itemeffect) {
TBL_NPC *nd;
TBL_PC *sd;
- struct script_data *data;
struct item_data *item_data;
-
- nullpo_retr( 1, ( sd = script_rid2sd( st ) ) );
- nullpo_retr( 1, ( nd = (TBL_NPC *)iMap->id2bl( sd->npc_id ) ) );
-
- data = script_getdata( st, 2 );
- script->get_val( st, data );
-
- if( data_isstring( data ) ){
- const char *name = script->conv_str( st, data );
-
- if( ( item_data = itemdb_searchname( name ) ) == NULL ){
+
+ sd = script->rid2sd(st);
+ if( sd == NULL )
+ return false;
+
+ nd = (TBL_NPC *)map->id2bl(sd->npc_id);
+ if( nd == NULL )
+ return false;
+
+ if( script_isstringtype(st, 2) ) {
+ const char *name = script_getstr(st, 2);
+
+ if( ( item_data = itemdb->search_name( name ) ) == NULL ) {
ShowError( "buildin_itemeffect: Nonexistant item %s requested.\n", name );
return false;
}
- } else if( data_isint( data ) ){
- int nameid = script->conv_num( st, data );
-
- if( ( item_data = itemdb_exists( nameid ) ) == NULL ){
+ } else {
+ int nameid = script_getnum(st, 2);
+
+ if( ( item_data = itemdb->exists( nameid ) ) == NULL ) {
ShowError("buildin_itemeffect: Nonexistant item %d requested.\n", nameid );
return false;
}
- } else {
- ShowError("buildin_itemeffect: invalid data type for argument #1 (%d).", data->type );
- return false;
}
-
- run_script( item_data->script, 0, sd->bl.id, nd->bl.id );
-
+
+ script->run( item_data->script, 0, sd->bl.id, nd->bl.id );
+
return true;
}
-BUILDIN(mapannounce)
-{
+BUILDIN(mapannounce) {
const char *mapname = script_getstr(st,2);
const char *mes = script_getstr(st,3);
int flag = script_getnum(st,4);
@@ -9163,18 +9792,17 @@ BUILDIN(mapannounce)
int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign
int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY
int16 m;
-
- if ((m = iMap->mapname2mapid(mapname)) < 0)
+
+ if ((m = map->mapname2mapid(mapname)) < 0)
return true;
-
- iMap->foreachinmap(buildin_announce_sub, m, BL_PC,
- mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY);
+
+ map->foreachinmap(script->buildin_announce_sub, m, BL_PC,
+ mes, strlen(mes)+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(areaannounce)
-{
+BUILDIN(areaannounce) {
const char *mapname = script_getstr(st,2);
int x0 = script_getnum(st,3);
int y0 = script_getnum(st,4);
@@ -9188,51 +9816,47 @@ BUILDIN(areaannounce)
int fontAlign = script_hasdata(st,12) ? script_getnum(st,12) : 0; // default fontAlign
int fontY = script_hasdata(st,13) ? script_getnum(st,13) : 0; // default fontY
int16 m;
-
- if ((m = iMap->mapname2mapid(mapname)) < 0)
+
+ if ((m = map->mapname2mapid(mapname)) < 0)
return true;
-
- iMap->foreachinarea(buildin_announce_sub, m, x0, y0, x1, y1, BL_PC,
- mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY);
+
+ map->foreachinarea(script->buildin_announce_sub, m, x0, y0, x1, y1, BL_PC,
+ mes, strlen(mes)+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(getusers)
-{
+BUILDIN(getusers) {
int flag, val = 0;
struct map_session_data* sd;
struct block_list* bl = NULL;
-
+
flag = script_getnum(st,2);
-
- switch(flag&0x07)
- {
+
+ switch(flag&0x07) {
case 0:
- if(flag&0x8)
- {// npc
- bl = iMap->id2bl(st->oid);
- }
- else if((sd = script_rid2sd(st))!=NULL)
- {// pc
+ if(flag&0x8) {
+ // npc
+ bl = map->id2bl(st->oid);
+ } else if((sd = script->rid2sd(st))!=NULL) {
+ // pc
bl = &sd->bl;
}
-
- if(bl)
- {
- val = map[bl->m].users;
+
+ if(bl) {
+ val = map->list[bl->m].users;
}
break;
case 1:
- val = iMap->getusers();
+ val = map->getusers();
break;
default:
ShowWarning("buildin_getusers: Unknown type %d.\n", flag);
script_pushint(st,0);
return false;
}
-
+
script_pushint(st,val);
return true;
}
@@ -9244,17 +9868,17 @@ BUILDIN(getusersname)
TBL_PC *sd, *pl_sd;
int /*disp_num=1,*/ group_level = 0;
struct s_mapiterator* iter;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if (!sd) return true;
-
- group_level = pc->get_group_level(sd);
+
+ group_level = pc_get_group_level(sd);
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
- if (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc->get_group_level(pl_sd) > group_level)
+ if (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > group_level)
continue; // skip hidden sessions
-
+
/* Temporary fix for bugreport:1023.
* Do not uncomment unless you want thousands of 'next' buttons.
if((disp_num++)%10==0)
@@ -9262,7 +9886,7 @@ BUILDIN(getusersname)
clif->scriptmes(sd,st->oid,pl_sd->status.name);
}
mapit->free(iter);
-
+
return true;
}
/*==========================================
@@ -9277,40 +9901,39 @@ BUILDIN(getmapguildusers)
struct guild *g = NULL;
str=script_getstr(st,2);
gid=script_getnum(st,3);
- if ((m = iMap->mapname2mapid(str)) < 0) { // map id on this server (m == -1 if not in actual map-server)
+ if ((m = map->mapname2mapid(str)) < 0) { // map id on this server (m == -1 if not in actual map-server)
script_pushint(st,-1);
return true;
}
g = guild->search(gid);
-
- if (g){
+
+ if (g) {
for(i = 0; i < g->max_member; i++)
{
if (g->member[i].sd && g->member[i].sd->bl.m == m)
c++;
}
}
-
+
script_pushint(st,c);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(getmapusers)
-{
+BUILDIN(getmapusers) {
const char *str;
int16 m;
str=script_getstr(st,2);
- if( (m=iMap->mapname2mapid(str))< 0){
+ if( (m=map->mapname2mapid(str))< 0) {
script_pushint(st,-1);
return true;
}
- script_pushint(st,map[m].users);
+ script_pushint(st,map->list[m].users);
return true;
}
/*==========================================
*------------------------------------------*/
-static int buildin_getareausers_sub(struct block_list *bl,va_list ap)
+int buildin_getareausers_sub(struct block_list *bl,va_list ap)
{
int *users=va_arg(ap,int *);
(*users)++;
@@ -9325,59 +9948,56 @@ BUILDIN(getareausers)
y0=script_getnum(st,4);
x1=script_getnum(st,5);
y1=script_getnum(st,6);
- if( (m=iMap->mapname2mapid(str))< 0){
+ if( (m=map->mapname2mapid(str))< 0) {
script_pushint(st,-1);
return true;
}
- iMap->foreachinarea(buildin_getareausers_sub,
- m,x0,y0,x1,y1,BL_PC,&users);
+ map->foreachinarea(script->buildin_getareausers_sub,
+ m,x0,y0,x1,y1,BL_PC,&users);
script_pushint(st,users);
return true;
}
/*==========================================
*------------------------------------------*/
-static int buildin_getareadropitem_sub(struct block_list *bl,va_list ap)
+int buildin_getareadropitem_sub(struct block_list *bl,va_list ap)
{
int item=va_arg(ap,int);
int *amount=va_arg(ap,int *);
struct flooritem_data *drop=(struct flooritem_data *)bl;
-
+
if(drop->item_data.nameid==item)
(*amount)+=drop->item_data.amount;
-
+
return 0;
}
-BUILDIN(getareadropitem)
-{
+BUILDIN(getareadropitem) {
const char *str;
int16 m,x0,y0,x1,y1;
int item,amount=0;
- struct script_data *data;
-
+
str=script_getstr(st,2);
x0=script_getnum(st,3);
y0=script_getnum(st,4);
x1=script_getnum(st,5);
y1=script_getnum(st,6);
-
- data=script_getdata(st,7);
- script->get_val(st,data);
- if( data_isstring(data) ){
- const char *name=script->conv_str(st,data);
- struct item_data *item_data = itemdb_searchname(name);
+
+ if( script_isstringtype(st, 7) ) {
+ const char *name = script_getstr(st, 7);
+ struct item_data *item_data = itemdb->search_name(name);
item=UNKNOWN_ITEM_ID;
if( item_data )
item=item_data->nameid;
- }else
- item=script->conv_num(st,data);
-
- if( (m=iMap->mapname2mapid(str))< 0){
+ } else {
+ item=script_getnum(st, 7);
+ }
+
+ if( (m=map->mapname2mapid(str))< 0) {
script_pushint(st,-1);
return true;
}
- iMap->foreachinarea(buildin_getareadropitem_sub,
- m,x0,y0,x1,y1,BL_ITEM,item,&amount);
+ map->foreachinarea(script->buildin_getareadropitem_sub,
+ m,x0,y0,x1,y1,BL_ITEM,item,&amount);
script_pushint(st,amount);
return true;
}
@@ -9387,7 +10007,7 @@ BUILDIN(enablenpc)
{
const char *str;
str=script_getstr(st,2);
- npc_enable(str,1);
+ npc->enable(str,1);
return true;
}
/*==========================================
@@ -9396,7 +10016,7 @@ BUILDIN(disablenpc)
{
const char *str;
str=script_getstr(st,2);
- npc_enable(str,0);
+ npc->enable(str,0);
return true;
}
@@ -9406,7 +10026,7 @@ BUILDIN(hideoffnpc)
{
const char *str;
str=script_getstr(st,2);
- npc_enable(str,2);
+ npc->enable(str,2);
return true;
}
/*==========================================
@@ -9415,91 +10035,88 @@ BUILDIN(hideonnpc)
{
const char *str;
str=script_getstr(st,2);
- npc_enable(str,4);
+ npc->enable(str,4);
return true;
}
/// Starts a status effect on the target unit or on the attached player.
///
/// sc_start <effect_id>,<duration>,<val1>{,<unit_id>};
-BUILDIN(sc_start)
-{
+BUILDIN(sc_start) {
struct block_list* bl;
enum sc_type type;
int tick;
int val1;
int val4 = 0;
-
+
type = (sc_type)script_getnum(st,2);
tick = script_getnum(st,3);
val1 = script_getnum(st,4);
if( script_hasdata(st,5) )
- bl = iMap->id2bl(script_getnum(st,5));
+ bl = map->id2bl(script_getnum(st,5));
else
- bl = iMap->id2bl(st->rid);
-
- if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0 )
- {// When there isn't a duration specified, try to get it from the skill_db
- tick = skill->get_time(status_sc2skill(type), val1);
+ bl = map->id2bl(st->rid);
+
+ if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status->sc2skill(type) != 0 ) {
+ // When there isn't a duration specified, try to get it from the skill_db
+ tick = skill->get_time(status->sc2skill(type), val1);
}
-
- if( potion_flag == 1 && potion_target )
- { //skill.c set the flags before running the script, this must be a potion-pitched effect.
- bl = iMap->id2bl(potion_target);
+
+ if( script->potion_flag == 1 && script->potion_target ) {
+ //skill.c set the flags before running the script, this must be a potion-pitched effect.
+ bl = map->id2bl(script->potion_target);
tick /= 2;// Thrown potions only last half.
val4 = 1;// Mark that this was a thrown sc_effect
}
-
+
if( bl )
- status_change_start(bl, type, 10000, val1, 0, 0, val4, tick, 2);
-
+ status->change_start(NULL, bl, type, 10000, val1, 0, 0, val4, tick, 2);
+
return true;
}
/// Starts a status effect on the target unit or on the attached player.
///
/// sc_start2 <effect_id>,<duration>,<val1>,<percent chance>{,<unit_id>};
-BUILDIN(sc_start2)
-{
+BUILDIN(sc_start2) {
struct block_list* bl;
enum sc_type type;
int tick;
int val1;
int val4 = 0;
int rate;
-
+
type = (sc_type)script_getnum(st,2);
tick = script_getnum(st,3);
val1 = script_getnum(st,4);
rate = script_getnum(st,5);
if( script_hasdata(st,6) )
- bl = iMap->id2bl(script_getnum(st,6));
+ bl = map->id2bl(script_getnum(st,6));
else
- bl = iMap->id2bl(st->rid);
-
- if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0 )
- {// When there isn't a duration specified, try to get it from the skill_db
- tick = skill->get_time(status_sc2skill(type), val1);
+ bl = map->id2bl(st->rid);
+
+ if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status->sc2skill(type) != 0 ) {
+ // When there isn't a duration specified, try to get it from the skill_db
+ tick = skill->get_time(status->sc2skill(type), val1);
}
-
- if( potion_flag == 1 && potion_target )
- { //skill.c set the flags before running the script, this must be a potion-pitched effect.
- bl = iMap->id2bl(potion_target);
+
+ if( script->potion_flag == 1 && script->potion_target ) {
+ //skill.c set the flags before running the script, this must be a potion-pitched effect.
+ bl = map->id2bl(script->potion_target);
tick /= 2;// Thrown potions only last half.
val4 = 1;// Mark that this was a thrown sc_effect
}
-
+
if( bl )
- status_change_start(bl, type, rate, val1, 0, 0, val4, tick, 2);
-
+ status->change_start(NULL, bl, type, rate, val1, 0, 0, val4, tick, 2);
+
return true;
}
/// Starts a status effect on the target unit or on the attached player.
///
/// sc_start4 <effect_id>,<duration>,<val1>,<val2>,<val3>,<val4>{,<unit_id>};
-BUILDIN(sc_start4)
-{
+BUILDIN(sc_start4) {
struct block_list* bl;
enum sc_type type;
int tick;
@@ -9507,7 +10124,7 @@ BUILDIN(sc_start4)
int val2;
int val3;
int val4;
-
+
type = (sc_type)script_getnum(st,2);
tick = script_getnum(st,3);
val1 = script_getnum(st,4);
@@ -9515,96 +10132,91 @@ BUILDIN(sc_start4)
val3 = script_getnum(st,6);
val4 = script_getnum(st,7);
if( script_hasdata(st,8) )
- bl = iMap->id2bl(script_getnum(st,8));
+ bl = map->id2bl(script_getnum(st,8));
else
- bl = iMap->id2bl(st->rid);
-
- if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0 )
- {// When there isn't a duration specified, try to get it from the skill_db
- tick = skill->get_time(status_sc2skill(type), val1);
+ bl = map->id2bl(st->rid);
+
+ if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status->sc2skill(type) != 0 ) {
+ // When there isn't a duration specified, try to get it from the skill_db
+ tick = skill->get_time(status->sc2skill(type), val1);
}
-
- if( potion_flag == 1 && potion_target )
- { //skill.c set the flags before running the script, this must be a potion-pitched effect.
- bl = iMap->id2bl(potion_target);
+
+ if( script->potion_flag == 1 && script->potion_target ) {
+ //skill.c set the flags before running the script, this must be a potion-pitched effect.
+ bl = map->id2bl(script->potion_target);
tick /= 2;// Thrown potions only last half.
}
-
+
if( bl )
- status_change_start(bl, type, 10000, val1, val2, val3, val4, tick, 2);
-
+ status->change_start(NULL, bl, type, 10000, val1, val2, val3, val4, tick, 2);
+
return true;
}
/// Ends one or all status effects on the target unit or on the attached player.
///
/// sc_end <effect_id>{,<unit_id>};
-BUILDIN(sc_end)
-{
+BUILDIN(sc_end) {
struct block_list* bl;
int type;
-
+
type = script_getnum(st, 2);
if (script_hasdata(st, 3))
- bl = iMap->id2bl(script_getnum(st, 3));
+ bl = map->id2bl(script_getnum(st, 3));
else
- bl = iMap->id2bl(st->rid);
-
- if (potion_flag == 1 && potion_target) //##TODO how does this work [FlavioJS]
- bl = iMap->id2bl(potion_target);
-
+ bl = map->id2bl(st->rid);
+
+ if (script->potion_flag == 1 && script->potion_target) //##TODO how does this work [FlavioJS]
+ bl = map->id2bl(script->potion_target);
+
if (!bl)
return true;
-
- if (type >= 0 && type < SC_MAX)
- {
- struct status_change *sc = status_get_sc(bl);
+
+ if (type >= 0 && type < SC_MAX) {
+ struct status_change *sc = status->get_sc(bl);
struct status_change_entry *sce = sc ? sc->data[type] : NULL;
-
+
if (!sce)
return true;
-
-
- switch (type)
- {
+
+ /* status that can't be individually removed (TODO sc_config option?) */
+ switch (type) {
case SC_WEIGHTOVER50:
case SC_WEIGHTOVER90:
case SC_NOCHAT:
case SC_PUSH_CART:
return true;
-
default:
break;
}
-
+
//This should help status_change_end force disabling the SC in case it has no limit.
sce->val1 = sce->val2 = sce->val3 = sce->val4 = 0;
status_change_end(bl, (sc_type)type, INVALID_TIMER);
}
else
- status_change_clear(bl, 3); // remove all effects
-
+ status->change_clear(bl, 3); // remove all effects
+
return true;
}
/*==========================================
* @FIXME atm will return reduced tick, 0 immune, 1 no tick
*------------------------------------------*/
-BUILDIN(getscrate)
-{
+BUILDIN(getscrate) {
struct block_list *bl;
int type,rate;
-
+
type=script_getnum(st,2);
rate=script_getnum(st,3);
if( script_hasdata(st,4) ) //get for the bl assigned
- bl = iMap->id2bl(script_getnum(st,4));
+ bl = map->id2bl(script_getnum(st,4));
else
- bl = iMap->id2bl(st->rid);
-
+ bl = map->id2bl(st->rid);
+
if (bl)
- rate = status_get_sc_def(bl, (sc_type)type, 10000, 10000, 0);
-
+ rate = status->get_sc_def(bl, bl, (sc_type)type, 10000, 10000, 0);
+
script_pushint(st,rate);
return true;
}
@@ -9615,47 +10227,46 @@ BUILDIN(getscrate)
BUILDIN(getstatus)
{
int id, type;
- struct map_session_data* sd = script_rid2sd(st);
-
+ struct map_session_data* sd = script->rid2sd(st);
+
if( sd == NULL )
{// no player attached
return true;
}
-
+
id = script_getnum(st, 2);
type = script_hasdata(st, 3) ? script_getnum(st, 3) : 0;
-
+
if( id <= SC_NONE || id >= SC_MAX )
{// invalid status type given
ShowWarning("script.c:getstatus: Invalid status type given (%d).\n", id);
return true;
}
-
+
if( sd->sc.count == 0 || !sd->sc.data[id] )
{// no status is active
script_pushint(st, 0);
return true;
}
-
- switch( type )
- {
- case 1: script_pushint(st, sd->sc.data[id]->val1); break;
- case 2: script_pushint(st, sd->sc.data[id]->val2); break;
- case 3: script_pushint(st, sd->sc.data[id]->val3); break;
- case 4: script_pushint(st, sd->sc.data[id]->val4); break;
+
+ switch( type ) {
+ case 1: script_pushint(st, sd->sc.data[id]->val1); break;
+ case 2: script_pushint(st, sd->sc.data[id]->val2); break;
+ case 3: script_pushint(st, sd->sc.data[id]->val3); break;
+ case 4: script_pushint(st, sd->sc.data[id]->val4); break;
case 5:
{
- struct TimerData* timer = (struct TimerData*)iTimer->get_timer(sd->sc.data[id]->timer);
-
- if( timer )
- {// return the amount of time remaining
- script_pushint(st, timer->tick - iTimer->gettick());
+ struct TimerData* td = (struct TimerData*)timer->get(sd->sc.data[id]->timer);
+
+ if( td ) {
+ // return the amount of time remaining
+ script_pushint(st, (int)(td->tick - timer->gettick())); // TODO: change this to int64 when we'll support 64 bit script values
}
}
break;
default: script_pushint(st, 1); break;
}
-
+
return true;
}
@@ -9676,13 +10287,13 @@ BUILDIN(catchpet)
{
int pet_id;
TBL_PC *sd;
-
+
pet_id= script_getnum(st,2);
- sd=script_rid2sd(st);
+ sd=script->rid2sd(st);
if( sd == NULL )
return true;
-
- pet_catch_process1(sd,pet_id);
+
+ pet->catch_process1(sd,pet_id);
return true;
}
@@ -9692,11 +10303,11 @@ BUILDIN(catchpet)
BUILDIN(homunculus_evolution)
{
TBL_PC *sd;
-
- sd=script_rid2sd(st);
+
+ sd=script->rid2sd(st);
if( sd == NULL )
return true;
-
+
if(homun_alive(sd->hd)) {
if (sd->hd->homunculus.intimacy > 91000)
homun->evolve(sd->hd);
@@ -9708,44 +10319,82 @@ BUILDIN(homunculus_evolution)
/*==========================================
* [Xantara]
+ * Checks for vaporized morph state
+ * and deletes ITEMID_STRANGE_EMBRYO.
*------------------------------------------*/
BUILDIN(homunculus_mutate) {
int homun_id;
enum homun_type m_class, m_id;
TBL_PC *sd;
-
- sd = script_rid2sd(st);
+ bool success = false;
+
+ sd = script->rid2sd(st);
if( sd == NULL || sd->hd == NULL )
return true;
-
- if(script_hasdata(st,2))
- homun_id = script_getnum(st,2);
- else
- homun_id = 6048 + (rnd() % 4);
-
- if(homun_alive(sd->hd)) {
+
+ if( sd->hd->homunculus.vaporize == HOM_ST_MORPH ) {
+ int i = pc->search_inventory(sd, ITEMID_STRANGE_EMBRYO);
+ if( script_hasdata(st,2) )
+ homun_id = script_getnum(st,2);
+ else
+ homun_id = 6048 + (rnd() % 4);
+
m_class = homun->class2type(sd->hd->homunculus.class_);
m_id = homun->class2type(homun_id);
-
- if ( m_class != -1 && m_id != -1 && m_class == HT_EVO && m_id == HT_S && sd->hd->homunculus.level >= 99 )
+
+ if( m_class == HT_EVO && m_id == HT_S &&
+ sd->hd->homunculus.level >= 99 && i != INDEX_NOT_FOUND &&
+ !pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_SCRIPT) ) {
+ sd->hd->homunculus.vaporize = HOM_ST_REST; // Remove morph state.
+ homun->call(sd); // Respawn homunculus.
homun->mutate(sd->hd, homun_id);
- else
+ success = true;
+ } else
clif->emotion(&sd->hd->bl, E_SWT);
- }
+ } else
+ clif->emotion(&sd->hd->bl, E_SWT);
+
+ script_pushint(st,success?1:0);
return true;
}
-// [Zephyrus]
-BUILDIN(homunculus_shuffle) {
+/*==========================================
+ * Puts homunculus into morph state
+ * and gives ITEMID_STRANGE_EMBRYO.
+ *------------------------------------------*/
+BUILDIN(homunculus_morphembryo) {
+ enum homun_type m_class;
+ int i = 0;
TBL_PC *sd;
-
- sd=script_rid2sd(st);
- if( sd == NULL )
+ bool success = false;
+
+ sd = script->rid2sd(st);
+ if( sd == NULL || sd->hd == NULL )
return true;
-
- if(homun_alive(sd->hd))
- homun->shuffle(sd->hd);
-
+
+ if( homun_alive(sd->hd) ) {
+ m_class = homun->class2type(sd->hd->homunculus.class_);
+
+ if ( m_class == HT_EVO && sd->hd->homunculus.level >= 99 ) {
+ struct item item_tmp;
+
+ memset(&item_tmp, 0, sizeof(item_tmp));
+ item_tmp.nameid = ITEMID_STRANGE_EMBRYO;
+ item_tmp.identify = 1;
+
+ if( (i = pc->additem(sd, &item_tmp, 1, LOG_TYPE_SCRIPT)) ) {
+ clif->additem(sd, 0, 0, i);
+ clif->emotion(&sd->hd->bl, E_SWT);
+ } else {
+ homun->vaporize(sd, HOM_ST_MORPH);
+ success = true;
+ }
+ } else
+ clif->emotion(&sd->hd->bl, E_SWT);
+ } else
+ clif->emotion(&sd->hd->bl, E_SWT);
+
+ script_pushint(st, success?1:0);
return true;
}
@@ -9756,20 +10405,28 @@ BUILDIN(homunculus_shuffle) {
* 1 = Homunculus is vaporized (rest)
* 2 = Homunculus is in morph state
*------------------------------------------*/
-BUILDIN(checkhomcall)
-{
- TBL_PC *sd = script_rid2sd(st);
- TBL_HOM *hd;
+BUILDIN(homunculus_checkcall) {
+ TBL_PC *sd = script->rid2sd(st);
- if( sd == NULL )
- return false;
-
- hd = sd->hd;
-
- if( !hd )
+ if( sd == NULL || !sd->hd )
script_pushint(st, -1);
else
- script_pushint(st, hd->homunculus.vaporize);
+ script_pushint(st, sd->hd->homunculus.vaporize);
+
+ return true;
+}
+
+
+// [Zephyrus]
+BUILDIN(homunculus_shuffle) {
+ TBL_PC *sd;
+
+ sd=script->rid2sd(st);
+ if( sd == NULL )
+ return true;
+
+ if(homun_alive(sd->hd))
+ homun->shuffle(sd->hd);
return true;
}
@@ -9782,11 +10439,9 @@ BUILDIN(eaclass)
class_ = script_getnum(st,2);
else {
TBL_PC *sd;
- sd=script_rid2sd(st);
- if (!sd) {
- script_pushint(st,-1);
+ sd=script->rid2sd(st);
+ if( !sd )
return true;
- }
class_ = sd->status.class_;
}
script_pushint(st,pc->jobid2mapid(class_));
@@ -9801,7 +10456,7 @@ BUILDIN(roclass)
sex = script_getnum(st,3);
else {
TBL_PC *sd;
- if (st->rid && (sd=script_rid2sd(st)))
+ if (st->rid && (sd=script->rid2sd(st)))
sex = sd->status.sex;
else
sex = 1; //Just use male when not found.
@@ -9816,15 +10471,15 @@ BUILDIN(roclass)
BUILDIN(birthpet)
{
TBL_PC *sd;
- sd=script_rid2sd(st);
+ sd=script->rid2sd(st);
if( sd == NULL )
return true;
-
+
if( sd->status.pet_id )
{// do not send egg list, when you already have a pet
return true;
}
-
+
clif->sendegg(sd);
return true;
}
@@ -9832,21 +10487,21 @@ BUILDIN(birthpet)
/*==========================================
* Added - AppleGirl For Advanced Classes, (Updated for Cleaner Script Purposes)
* @type
- * 1 : make like after rebirth
- * 2 : blvl,jlvl=1, skillpoint=0
- * 3 : don't reset skill, blvl=1
- * 4 : jlvl=0
+ * 1 : make like after rebirth
+ * 2 : blvl,jlvl=1, skillpoint=0
+ * 3 : don't reset skill, blvl=1
+ * 4 : jlvl=0
*------------------------------------------*/
BUILDIN(resetlvl)
{
TBL_PC *sd;
-
+
int type=script_getnum(st,2);
-
- sd=script_rid2sd(st);
+
+ sd=script->rid2sd(st);
if( sd == NULL )
return true;
-
+
pc->resetlvl(sd,type);
return true;
}
@@ -9856,7 +10511,9 @@ BUILDIN(resetlvl)
BUILDIN(resetstatus)
{
TBL_PC *sd;
- sd=script_rid2sd(st);
+ sd=script->rid2sd(st);
+ if( sd == NULL )
+ return false;
pc->resetstate(sd);
return true;
}
@@ -9867,7 +10524,9 @@ BUILDIN(resetstatus)
BUILDIN(resetskill)
{
TBL_PC *sd;
- sd=script_rid2sd(st);
+ sd=script->rid2sd(st);
+ if( sd == NULL )
+ return false;
pc->resetskill(sd,1);
return true;
}
@@ -9878,7 +10537,9 @@ BUILDIN(resetskill)
BUILDIN(skillpointcount)
{
TBL_PC *sd;
- sd=script_rid2sd(st);
+ sd=script->rid2sd(st);
+ if( sd == NULL )
+ return false;
script_pushint(st,sd->status.skill_point + pc->resetskill(sd,2));
return true;
}
@@ -9886,19 +10547,18 @@ BUILDIN(skillpointcount)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(changebase)
-{
+BUILDIN(changebase) {
TBL_PC *sd=NULL;
int vclass;
-
+
if( script_hasdata(st,3) )
- sd=iMap->id2sd(script_getnum(st,3));
+ sd=map->id2sd(script_getnum(st,3));
else
- sd=script_rid2sd(st);
-
+ sd=script->rid2sd(st);
+
if(sd == NULL)
return true;
-
+
vclass = script_getnum(st,2);
if(vclass == JOB_WEDDING)
{
@@ -9907,9 +10567,9 @@ BUILDIN(changebase)
)
return true;
}
-
+
if(sd->disguise == -1 && vclass != sd->vd.class_) {
- status_set_viewdata(&sd->bl, vclass);
+ status->set_viewdata(&sd->bl, vclass);
//Updated client view. Base, Weapon and Cloth Colors.
clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_);
clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
@@ -9917,7 +10577,7 @@ BUILDIN(changebase)
clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
clif->skillinfoblock(sd);
}
-
+
return true;
}
@@ -9928,36 +10588,39 @@ BUILDIN(changesex)
{
int i;
TBL_PC *sd = NULL;
- sd = script_rid2sd(st);
-
+ sd = script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
pc->resetskill(sd,4);
// to avoid any problem with equipment and invalid sex, equipment is unequiped.
for( i=0; i<EQI_MAX; i++ )
if( sd->equip_index[i] >= 0 ) pc->unequipitem(sd, sd->equip_index[i], 3);
- chrif_changesex(sd);
+ chrif->changesex(sd);
return true;
}
/*==========================================
* Works like 'announce' but outputs in the common chat window
*------------------------------------------*/
-BUILDIN(globalmes)
-{
- struct block_list *bl = iMap->id2bl(st->oid);
+BUILDIN(globalmes) {
+ struct block_list *bl = map->id2bl(st->oid);
struct npc_data *nd = (struct npc_data *)bl;
const char *name=NULL,*mes;
-
+
mes=script_getstr(st,2);
if(mes==NULL) return true;
-
- if(script_hasdata(st,3)){ // npc name to display
+
+ if(script_hasdata(st,3)) {
+ // npc name to display
name=script_getstr(st,3);
} else {
name=nd->name; //use current npc name
}
-
- npc_globalmessage(name,mes); // broadcast to all players connected
-
+
+ npc->globalmessage(name,mes); // broadcast to all players connected
+
return true;
}
@@ -9968,8 +10631,7 @@ BUILDIN(globalmes)
/// Creates a waiting room (chat room) for this npc.
///
/// waitingroom "<title>",<limit>{,"<event>"{,<trigger>{,<zeny>{,<minlvl>{,<maxlvl>}}}}};
-BUILDIN(waitingroom)
-{
+BUILDIN(waitingroom) {
struct npc_data* nd;
int pub = 1;
const char* title = script_getstr(st, 2);
@@ -9979,11 +10641,11 @@ BUILDIN(waitingroom)
int zeny = script_hasdata(st,6) ? script_getnum(st,6) : 0;
int minLvl = script_hasdata(st,7) ? script_getnum(st,7) : 1;
int maxLvl = script_hasdata(st,8) ? script_getnum(st,8) : MAX_LEVEL;
-
- nd = (struct npc_data *)iMap->id2bl(st->oid);
+
+ nd = (struct npc_data *)map->id2bl(st->oid);
if( nd != NULL )
- chat_createnpcchat(nd, title, limit, pub, trigger, ev, zeny, minLvl, maxLvl);
-
+ chat->create_npc_chat(nd, title, limit, pub, trigger, ev, zeny, minLvl, maxLvl);
+
return true;
}
@@ -9991,15 +10653,14 @@ BUILDIN(waitingroom)
///
/// delwaitingroom "<npc_name>";
/// delwaitingroom;
-BUILDIN(delwaitingroom)
-{
+BUILDIN(delwaitingroom) {
struct npc_data* nd;
if( script_hasdata(st,2) )
- nd = npc_name2id(script_getstr(st, 2));
+ nd = npc->name2id(script_getstr(st, 2));
else
- nd = (struct npc_data *)iMap->id2bl(st->oid);
+ nd = (struct npc_data *)map->id2bl(st->oid);
if( nd != NULL )
- chat_deletenpcchat(nd);
+ chat->delete_npc_chat(nd);
return true;
}
@@ -10007,18 +10668,17 @@ BUILDIN(delwaitingroom)
///
/// kickwaitingroomall "<npc_name>";
/// kickwaitingroomall;
-BUILDIN(waitingroomkickall)
-{
+BUILDIN(waitingroomkickall) {
struct npc_data* nd;
struct chat_data* cd;
-
+
if( script_hasdata(st,2) )
- nd = npc_name2id(script_getstr(st,2));
+ nd = npc->name2id(script_getstr(st,2));
else
- nd = (struct npc_data *)iMap->id2bl(st->oid);
-
- if( nd != NULL && (cd=(struct chat_data *)iMap->id2bl(nd->chat_id)) != NULL )
- chat_npckickall(cd);
+ nd = (struct npc_data *)map->id2bl(st->oid);
+
+ if( nd != NULL && (cd=(struct chat_data *)map->id2bl(nd->chat_id)) != NULL )
+ chat->npc_kick_all(cd);
return true;
}
@@ -10026,18 +10686,17 @@ BUILDIN(waitingroomkickall)
///
/// enablewaitingroomevent "<npc_name>";
/// enablewaitingroomevent;
-BUILDIN(enablewaitingroomevent)
-{
+BUILDIN(enablewaitingroomevent) {
struct npc_data* nd;
struct chat_data* cd;
-
+
if( script_hasdata(st,2) )
- nd = npc_name2id(script_getstr(st, 2));
+ nd = npc->name2id(script_getstr(st, 2));
else
- nd = (struct npc_data *)iMap->id2bl(st->oid);
-
- if( nd != NULL && (cd=(struct chat_data *)iMap->id2bl(nd->chat_id)) != NULL )
- chat_enableevent(cd);
+ nd = (struct npc_data *)map->id2bl(st->oid);
+
+ if( nd != NULL && (cd=(struct chat_data *)map->id2bl(nd->chat_id)) != NULL )
+ chat->enable_event(cd);
return true;
}
@@ -10045,18 +10704,17 @@ BUILDIN(enablewaitingroomevent)
///
/// disablewaitingroomevent "<npc_name>";
/// disablewaitingroomevent;
-BUILDIN(disablewaitingroomevent)
-{
+BUILDIN(disablewaitingroomevent) {
struct npc_data *nd;
struct chat_data *cd;
-
+
if( script_hasdata(st,2) )
- nd = npc_name2id(script_getstr(st, 2));
+ nd = npc->name2id(script_getstr(st, 2));
else
- nd = (struct npc_data *)iMap->id2bl(st->oid);
-
- if( nd != NULL && (cd=(struct chat_data *)iMap->id2bl(nd->chat_id)) != NULL )
- chat_disableevent(cd);
+ nd = (struct npc_data *)map->id2bl(st->oid);
+
+ if( nd != NULL && (cd=(struct chat_data *)map->id2bl(nd->chat_id)) != NULL )
+ chat->disable_event(cd);
return true;
}
@@ -10074,26 +10732,23 @@ BUILDIN(disablewaitingroomevent)
///
/// getwaitingroomstate(<type>,"<npc_name>") -> <info>
/// getwaitingroomstate(<type>) -> <info>
-BUILDIN(getwaitingroomstate)
-{
+BUILDIN(getwaitingroomstate) {
struct npc_data *nd;
struct chat_data *cd;
int type;
-
+
type = script_getnum(st,2);
if( script_hasdata(st,3) )
- nd = npc_name2id(script_getstr(st, 3));
+ nd = npc->name2id(script_getstr(st, 3));
else
- nd = (struct npc_data *)iMap->id2bl(st->oid);
-
- if( nd == NULL || (cd=(struct chat_data *)iMap->id2bl(nd->chat_id)) == NULL )
- {
+ nd = (struct npc_data *)map->id2bl(st->oid);
+
+ if( nd == NULL || (cd=(struct chat_data *)map->id2bl(nd->chat_id)) == NULL ) {
script_pushint(st, -1);
return true;
}
-
- switch(type)
- {
+
+ switch(type) {
case 0: script_pushint(st, cd->users); break;
case 1: script_pushint(st, cd->limit); break;
case 2: script_pushint(st, cd->trigger&0x7f); break;
@@ -10120,8 +10775,7 @@ BUILDIN(getwaitingroomstate)
///
/// warpwaitingpc "<map name>",<x>,<y>,<number of players>;
/// warpwaitingpc "<map name>",<x>,<y>;
-BUILDIN(warpwaitingpc)
-{
+BUILDIN(warpwaitingpc) {
int x;
int y;
int i;
@@ -10130,47 +10784,46 @@ BUILDIN(warpwaitingpc)
struct npc_data* nd;
struct chat_data* cd;
TBL_PC* sd;
-
- nd = (struct npc_data *)iMap->id2bl(st->oid);
- if( nd == NULL || (cd=(struct chat_data *)iMap->id2bl(nd->chat_id)) == NULL )
+
+ nd = (struct npc_data *)map->id2bl(st->oid);
+ if( nd == NULL || (cd=(struct chat_data *)map->id2bl(nd->chat_id)) == NULL )
return true;
-
+
map_name = script_getstr(st,2);
x = script_getnum(st,3);
y = script_getnum(st,4);
n = cd->trigger&0x7f;
-
+
if( script_hasdata(st,5) )
n = script_getnum(st,5);
-
- for( i = 0; i < n && cd->users > 0; i++ )
- {
+
+ for( i = 0; i < n && cd->users > 0; i++ ) {
sd = cd->usersd[0];
-
- if( strcmp(map_name,"SavePoint") == 0 && map[sd->bl.m].flag.noteleport )
- {// can't teleport on this map
+
+ if( strcmp(map_name,"SavePoint") == 0 && map->list[sd->bl.m].flag.noteleport ) {
+ // can't teleport on this map
break;
}
-
- if( cd->zeny )
- {// fee set
- if( (uint32)sd->status.zeny < cd->zeny )
- {// no zeny to cover set fee
+
+ if( cd->zeny ) {
+ // fee set
+ if( (uint32)sd->status.zeny < cd->zeny ) {
+ // no zeny to cover set fee
break;
}
pc->payzeny(sd, cd->zeny, LOG_TYPE_NPC, NULL);
}
-
- mapreg_setreg(reference_uid(add_str("$@warpwaitingpc"), i), sd->bl.id);
-
+
+ mapreg->setreg(reference_uid(script->add_str("$@warpwaitingpc"), i), sd->bl.id);
+
if( strcmp(map_name,"Random") == 0 )
pc->randomwarp(sd,CLR_TELEPORT);
else if( strcmp(map_name,"SavePoint") == 0 )
pc->setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
else
- pc->setpos(sd, mapindex_name2id(map_name), x, y, CLR_OUTSIGHT);
+ pc->setpos(sd, script->mapindexname2id(st,map_name), x, y, CLR_OUTSIGHT);
}
- mapreg_setreg(add_str("$@warpwaitingpcnum"), i);
+ mapreg->setreg(script->add_str("$@warpwaitingpcnum"), i);
return true;
}
@@ -10183,7 +10836,7 @@ BUILDIN(warpwaitingpc)
/// @param st Script state to detach the character from.
void script_detach_rid(struct script_state* st) {
if(st->rid) {
- script_detach_state(st, false);
+ script->detach_state(st, false);
st->rid = 0;
}
}
@@ -10191,15 +10844,14 @@ void script_detach_rid(struct script_state* st) {
/*==========================================
* Attach sd char id to script and detach current one if any
*------------------------------------------*/
-BUILDIN(attachrid)
-{
+BUILDIN(attachrid) {
int rid = script_getnum(st,2);
-
- if (iMap->id2sd(rid) != NULL) {
- script_detach_rid(st);
-
+
+ if (map->id2sd(rid) != NULL) {
+ script->detach_rid(st);
+
st->rid = rid;
- script_attach_state(st);
+ script->attach_state(st);
script_pushint(st,1);
} else
script_pushint(st,0);
@@ -10210,15 +10862,14 @@ BUILDIN(attachrid)
*------------------------------------------*/
BUILDIN(detachrid)
{
- script_detach_rid(st);
+ script->detach_rid(st);
return true;
}
/*==========================================
* Chk if account connected, (and charid from account if specified)
*------------------------------------------*/
-BUILDIN(isloggedin)
-{
- TBL_PC* sd = iMap->id2sd(script_getnum(st,2));
+BUILDIN(isloggedin) {
+ TBL_PC* sd = map->id2sd(script_getnum(st,2));
if (script_hasdata(st,3) && sd &&
sd->status.char_id != script_getnum(st,3))
sd = NULL;
@@ -10230,26 +10881,25 @@ BUILDIN(isloggedin)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(setmapflagnosave)
-{
+BUILDIN(setmapflagnosave) {
int16 m,x,y;
- unsigned short mapindex;
+ unsigned short map_index;
const char *str,*str2;
-
+
str=script_getstr(st,2);
str2=script_getstr(st,3);
x=script_getnum(st,4);
y=script_getnum(st,5);
- m = iMap->mapname2mapid(str);
- mapindex = mapindex_name2id(str2);
-
- if(m >= 0 && mapindex) {
- map[m].flag.nosave=1;
- map[m].save.map=mapindex;
- map[m].save.x=x;
- map[m].save.y=y;
+ m = map->mapname2mapid(str);
+ map_index = script->mapindexname2id(st,str2);
+
+ if(m >= 0 && map_index) {
+ map->list[m].flag.nosave=1;
+ map->list[m].save.map=map_index;
+ map->list[m].save.x=x;
+ map->list[m].save.y=y;
}
-
+
return true;
}
@@ -10257,72 +10907,74 @@ BUILDIN(getmapflag)
{
int16 m,i;
const char *str;
-
+
str=script_getstr(st,2);
i=script_getnum(st,3);
-
- m = iMap->mapname2mapid(str);
+
+ m = map->mapname2mapid(str);
if(m >= 0) {
switch(i) {
- case MF_NOMEMO: script_pushint(st,map[m].flag.nomemo); break;
- case MF_NOTELEPORT: script_pushint(st,map[m].flag.noteleport); break;
- case MF_NOSAVE: script_pushint(st,map[m].flag.nosave); break;
- case MF_NOBRANCH: script_pushint(st,map[m].flag.nobranch); break;
- case MF_NOPENALTY: script_pushint(st,map[m].flag.noexppenalty); break;
- case MF_NOZENYPENALTY: script_pushint(st,map[m].flag.nozenypenalty); break;
- case MF_PVP: script_pushint(st,map[m].flag.pvp); break;
- case MF_PVP_NOPARTY: script_pushint(st,map[m].flag.pvp_noparty); break;
- case MF_PVP_NOGUILD: script_pushint(st,map[m].flag.pvp_noguild); break;
- case MF_GVG: script_pushint(st,map[m].flag.gvg); break;
- case MF_GVG_NOPARTY: script_pushint(st,map[m].flag.gvg_noparty); break;
- case MF_NOTRADE: script_pushint(st,map[m].flag.notrade); break;
- case MF_NOSKILL: script_pushint(st,map[m].flag.noskill); break;
- case MF_NOWARP: script_pushint(st,map[m].flag.nowarp); break;
- case MF_PARTYLOCK: script_pushint(st,map[m].flag.partylock); break;
- case MF_NOICEWALL: script_pushint(st,map[m].flag.noicewall); break;
- case MF_SNOW: script_pushint(st,map[m].flag.snow); break;
- case MF_FOG: script_pushint(st,map[m].flag.fog); break;
- case MF_SAKURA: script_pushint(st,map[m].flag.sakura); break;
- case MF_LEAVES: script_pushint(st,map[m].flag.leaves); break;
- case MF_CLOUDS: script_pushint(st,map[m].flag.clouds); break;
- case MF_CLOUDS2: script_pushint(st,map[m].flag.clouds2); break;
- case MF_FIREWORKS: script_pushint(st,map[m].flag.fireworks); break;
- case MF_GVG_CASTLE: script_pushint(st,map[m].flag.gvg_castle); break;
- case MF_GVG_DUNGEON: script_pushint(st,map[m].flag.gvg_dungeon); break;
- case MF_NIGHTENABLED: script_pushint(st,map[m].flag.nightenabled); break;
- case MF_NOBASEEXP: script_pushint(st,map[m].flag.nobaseexp); break;
- case MF_NOJOBEXP: script_pushint(st,map[m].flag.nojobexp); break;
- case MF_NOMOBLOOT: script_pushint(st,map[m].flag.nomobloot); break;
- case MF_NOMVPLOOT: script_pushint(st,map[m].flag.nomvploot); break;
- case MF_NORETURN: script_pushint(st,map[m].flag.noreturn); break;
- case MF_NOWARPTO: script_pushint(st,map[m].flag.nowarpto); break;
- case MF_NIGHTMAREDROP: script_pushint(st,map[m].flag.pvp_nightmaredrop); break;
- case MF_NOCOMMAND: script_pushint(st,map[m].nocommand); break;
- case MF_NODROP: script_pushint(st,map[m].flag.nodrop); break;
- case MF_JEXP: script_pushint(st,map[m].jexp); break;
- case MF_BEXP: script_pushint(st,map[m].bexp); break;
- case MF_NOVENDING: script_pushint(st,map[m].flag.novending); break;
- case MF_LOADEVENT: script_pushint(st,map[m].flag.loadevent); break;
- case MF_NOCHAT: script_pushint(st,map[m].flag.nochat); break;
- case MF_NOEXPPENALTY: script_pushint(st,map[m].flag.noexppenalty ); break;
- case MF_GUILDLOCK: script_pushint(st,map[m].flag.guildlock); break;
- case MF_TOWN: script_pushint(st,map[m].flag.town); break;
- case MF_AUTOTRADE: script_pushint(st,map[m].flag.autotrade); break;
- case MF_ALLOWKS: script_pushint(st,map[m].flag.allowks); break;
- case MF_MONSTER_NOTELEPORT: script_pushint(st,map[m].flag.monster_noteleport); break;
- case MF_PVP_NOCALCRANK: script_pushint(st,map[m].flag.pvp_nocalcrank); break;
- case MF_BATTLEGROUND: script_pushint(st,map[m].flag.battleground); break;
- case MF_RESET: script_pushint(st,map[m].flag.reset); break;
+ case MF_NOMEMO: script_pushint(st,map->list[m].flag.nomemo); break;
+ case MF_NOTELEPORT: script_pushint(st,map->list[m].flag.noteleport); break;
+ case MF_NOSAVE: script_pushint(st,map->list[m].flag.nosave); break;
+ case MF_NOBRANCH: script_pushint(st,map->list[m].flag.nobranch); break;
+ case MF_NOPENALTY: script_pushint(st,map->list[m].flag.noexppenalty); break;
+ case MF_NOZENYPENALTY: script_pushint(st,map->list[m].flag.nozenypenalty); break;
+ case MF_PVP: script_pushint(st,map->list[m].flag.pvp); break;
+ case MF_PVP_NOPARTY: script_pushint(st,map->list[m].flag.pvp_noparty); break;
+ case MF_PVP_NOGUILD: script_pushint(st,map->list[m].flag.pvp_noguild); break;
+ case MF_GVG: script_pushint(st,map->list[m].flag.gvg); break;
+ case MF_GVG_NOPARTY: script_pushint(st,map->list[m].flag.gvg_noparty); break;
+ case MF_NOTRADE: script_pushint(st,map->list[m].flag.notrade); break;
+ case MF_NOSKILL: script_pushint(st,map->list[m].flag.noskill); break;
+ case MF_NOWARP: script_pushint(st,map->list[m].flag.nowarp); break;
+ case MF_PARTYLOCK: script_pushint(st,map->list[m].flag.partylock); break;
+ case MF_NOICEWALL: script_pushint(st,map->list[m].flag.noicewall); break;
+ case MF_SNOW: script_pushint(st,map->list[m].flag.snow); break;
+ case MF_FOG: script_pushint(st,map->list[m].flag.fog); break;
+ case MF_SAKURA: script_pushint(st,map->list[m].flag.sakura); break;
+ case MF_LEAVES: script_pushint(st,map->list[m].flag.leaves); break;
+ case MF_CLOUDS: script_pushint(st,map->list[m].flag.clouds); break;
+ case MF_CLOUDS2: script_pushint(st,map->list[m].flag.clouds2); break;
+ case MF_FIREWORKS: script_pushint(st,map->list[m].flag.fireworks); break;
+ case MF_GVG_CASTLE: script_pushint(st,map->list[m].flag.gvg_castle); break;
+ case MF_GVG_DUNGEON: script_pushint(st,map->list[m].flag.gvg_dungeon); break;
+ case MF_NIGHTENABLED: script_pushint(st,map->list[m].flag.nightenabled); break;
+ case MF_NOBASEEXP: script_pushint(st,map->list[m].flag.nobaseexp); break;
+ case MF_NOJOBEXP: script_pushint(st,map->list[m].flag.nojobexp); break;
+ case MF_NOMOBLOOT: script_pushint(st,map->list[m].flag.nomobloot); break;
+ case MF_NOMVPLOOT: script_pushint(st,map->list[m].flag.nomvploot); break;
+ case MF_NORETURN: script_pushint(st,map->list[m].flag.noreturn); break;
+ case MF_NOWARPTO: script_pushint(st,map->list[m].flag.nowarpto); break;
+ case MF_NIGHTMAREDROP: script_pushint(st,map->list[m].flag.pvp_nightmaredrop); break;
+ case MF_NOCOMMAND: script_pushint(st,map->list[m].nocommand); break;
+ case MF_NODROP: script_pushint(st,map->list[m].flag.nodrop); break;
+ case MF_JEXP: script_pushint(st,map->list[m].jexp); break;
+ case MF_BEXP: script_pushint(st,map->list[m].bexp); break;
+ case MF_NOVENDING: script_pushint(st,map->list[m].flag.novending); break;
+ case MF_LOADEVENT: script_pushint(st,map->list[m].flag.loadevent); break;
+ case MF_NOCHAT: script_pushint(st,map->list[m].flag.nochat); break;
+ case MF_NOEXPPENALTY: script_pushint(st,map->list[m].flag.noexppenalty ); break;
+ case MF_GUILDLOCK: script_pushint(st,map->list[m].flag.guildlock); break;
+ case MF_TOWN: script_pushint(st,map->list[m].flag.town); break;
+ case MF_AUTOTRADE: script_pushint(st,map->list[m].flag.autotrade); break;
+ case MF_ALLOWKS: script_pushint(st,map->list[m].flag.allowks); break;
+ case MF_MONSTER_NOTELEPORT: script_pushint(st,map->list[m].flag.monster_noteleport); break;
+ case MF_PVP_NOCALCRANK: script_pushint(st,map->list[m].flag.pvp_nocalcrank); break;
+ case MF_BATTLEGROUND: script_pushint(st,map->list[m].flag.battleground); break;
+ case MF_RESET: script_pushint(st,map->list[m].flag.reset); break;
+ case MF_NOTOMB: script_pushint(st,map->list[m].flag.notomb); break;
+ case MF_NOCASHSHOP: script_pushint(st,map->list[m].flag.nocashshop); break;
}
}
-
+
return true;
}
/* pvp timer handling */
-static int script_mapflag_pvp_sub(struct block_list *bl,va_list ap) {
+int script_mapflag_pvp_sub(struct block_list *bl,va_list ap) {
TBL_PC* sd = (TBL_PC*)bl;
if (sd->pvp_timer == INVALID_TIMER) {
- sd->pvp_timer = iTimer->add_timer(iTimer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
+ sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
sd->pvp_rank = 0;
sd->pvp_lastusers = 0;
sd->pvp_point = 5;
@@ -10333,227 +10985,229 @@ static int script_mapflag_pvp_sub(struct block_list *bl,va_list ap) {
clif->maptypeproperty2(&sd->bl,SELF);
return 0;
}
-BUILDIN(setmapflag)
-{
+BUILDIN(setmapflag) {
int16 m,i;
const char *str, *val2 = NULL;
- struct script_data* data;
int val=0;
-
+
str=script_getstr(st,2);
-
+
i = script_getnum(st, 3);
-
- if(script_hasdata(st,4)){
- data = script_getdata(st,4);
- script->get_val(st, data);
-
-
- if( data_isstring(data) )
+
+ if (script_hasdata(st,4)) {
+ if (script_isstringtype(st, 4)) {
val2 = script_getstr(st, 4);
- else
+ } else if (script_isinttype(st, 4)) {
val = script_getnum(st, 4);
-
+ } else {
+ ShowError("buildin_setmapflag: invalid data type for argument 3.\n");
+ return false;
+ }
}
- m = iMap->mapname2mapid(str);
-
+ m = map->mapname2mapid(str);
+
if(m >= 0) {
switch(i) {
- case MF_NOMEMO: map[m].flag.nomemo = 1; break;
- case MF_NOTELEPORT: map[m].flag.noteleport = 1; break;
- case MF_NOSAVE: map[m].flag.nosave = 1; break;
- case MF_NOBRANCH: map[m].flag.nobranch = 1; break;
- case MF_NOPENALTY: map[m].flag.noexppenalty = 1; map[m].flag.nozenypenalty = 1; break;
- case MF_NOZENYPENALTY: map[m].flag.nozenypenalty = 1; break;
+ case MF_NOMEMO: map->list[m].flag.nomemo = 1; break;
+ case MF_NOTELEPORT: map->list[m].flag.noteleport = 1; break;
+ case MF_NOSAVE: map->list[m].flag.nosave = 1; break;
+ case MF_NOBRANCH: map->list[m].flag.nobranch = 1; break;
+ case MF_NOPENALTY: map->list[m].flag.noexppenalty = 1; map->list[m].flag.nozenypenalty = 1; break;
+ case MF_NOZENYPENALTY: map->list[m].flag.nozenypenalty = 1; break;
case MF_PVP:
- map[m].flag.pvp = 1;
+ map->list[m].flag.pvp = 1;
if( !battle_config.pk_mode ) {
- iMap->foreachinmap(script_mapflag_pvp_sub,m,BL_PC);
+ map->foreachinmap(script->mapflag_pvp_sub,m,BL_PC);
}
break;
- case MF_PVP_NOPARTY: map[m].flag.pvp_noparty = 1; break;
- case MF_PVP_NOGUILD: map[m].flag.pvp_noguild = 1; break;
+ case MF_PVP_NOPARTY: map->list[m].flag.pvp_noparty = 1; break;
+ case MF_PVP_NOGUILD: map->list[m].flag.pvp_noguild = 1; break;
case MF_GVG: {
struct block_list bl;
- map[m].flag.gvg = 1;
+ map->list[m].flag.gvg = 1;
clif->map_property_mapall(m, MAPPROPERTY_AGITZONE);
bl.type = BL_NUL;
bl.m = m;
clif->maptypeproperty2(&bl,ALL_SAMEMAP);
}
break;
- case MF_GVG_NOPARTY: map[m].flag.gvg_noparty = 1; break;
- case MF_NOTRADE: map[m].flag.notrade = 1; break;
- case MF_NOSKILL: map[m].flag.noskill = 1; break;
- case MF_NOWARP: map[m].flag.nowarp = 1; break;
- case MF_PARTYLOCK: map[m].flag.partylock = 1; break;
- case MF_NOICEWALL: map[m].flag.noicewall = 1; break;
- case MF_SNOW: map[m].flag.snow = 1; break;
- case MF_FOG: map[m].flag.fog = 1; break;
- case MF_SAKURA: map[m].flag.sakura = 1; break;
- case MF_LEAVES: map[m].flag.leaves = 1; break;
- case MF_CLOUDS: map[m].flag.clouds = 1; break;
- case MF_CLOUDS2: map[m].flag.clouds2 = 1; break;
- case MF_FIREWORKS: map[m].flag.fireworks = 1; break;
- case MF_GVG_CASTLE: map[m].flag.gvg_castle = 1; break;
- case MF_GVG_DUNGEON: map[m].flag.gvg_dungeon = 1; break;
- case MF_NIGHTENABLED: map[m].flag.nightenabled = 1; break;
- case MF_NOBASEEXP: map[m].flag.nobaseexp = 1; break;
- case MF_NOJOBEXP: map[m].flag.nojobexp = 1; break;
- case MF_NOMOBLOOT: map[m].flag.nomobloot = 1; break;
- case MF_NOMVPLOOT: map[m].flag.nomvploot = 1; break;
- case MF_NORETURN: map[m].flag.noreturn = 1; break;
- case MF_NOWARPTO: map[m].flag.nowarpto = 1; break;
- case MF_NIGHTMAREDROP: map[m].flag.pvp_nightmaredrop = 1; break;
- case MF_ZONE: {
- char zone[6] = "zone\0";
- char empty[1] = "\0";
- char params[MAP_ZONE_MAPFLAG_LENGTH];
- memcpy(params, val2, MAP_ZONE_MAPFLAG_LENGTH);
- npc_parse_mapflag(map[m].name, empty, zone, params, empty, empty, empty);
- }
+ case MF_GVG_NOPARTY: map->list[m].flag.gvg_noparty = 1; break;
+ case MF_NOTRADE: map->list[m].flag.notrade = 1; break;
+ case MF_NOSKILL: map->list[m].flag.noskill = 1; break;
+ case MF_NOWARP: map->list[m].flag.nowarp = 1; break;
+ case MF_PARTYLOCK: map->list[m].flag.partylock = 1; break;
+ case MF_NOICEWALL: map->list[m].flag.noicewall = 1; break;
+ case MF_SNOW: map->list[m].flag.snow = 1; break;
+ case MF_FOG: map->list[m].flag.fog = 1; break;
+ case MF_SAKURA: map->list[m].flag.sakura = 1; break;
+ case MF_LEAVES: map->list[m].flag.leaves = 1; break;
+ case MF_CLOUDS: map->list[m].flag.clouds = 1; break;
+ case MF_CLOUDS2: map->list[m].flag.clouds2 = 1; break;
+ case MF_FIREWORKS: map->list[m].flag.fireworks = 1; break;
+ case MF_GVG_CASTLE: map->list[m].flag.gvg_castle = 1; break;
+ case MF_GVG_DUNGEON: map->list[m].flag.gvg_dungeon = 1; break;
+ case MF_NIGHTENABLED: map->list[m].flag.nightenabled = 1; break;
+ case MF_NOBASEEXP: map->list[m].flag.nobaseexp = 1; break;
+ case MF_NOJOBEXP: map->list[m].flag.nojobexp = 1; break;
+ case MF_NOMOBLOOT: map->list[m].flag.nomobloot = 1; break;
+ case MF_NOMVPLOOT: map->list[m].flag.nomvploot = 1; break;
+ case MF_NORETURN: map->list[m].flag.noreturn = 1; break;
+ case MF_NOWARPTO: map->list[m].flag.nowarpto = 1; break;
+ case MF_NIGHTMAREDROP: map->list[m].flag.pvp_nightmaredrop = 1; break;
+ case MF_ZONE:
+ if( val2 ) {
+ char zone[6] = "zone\0";
+ char empty[1] = "\0";
+ char params[MAP_ZONE_MAPFLAG_LENGTH];
+ memcpy(params, val2, MAP_ZONE_MAPFLAG_LENGTH);
+ npc->parse_mapflag(map->list[m].name, empty, zone, params, empty, empty, empty, NULL);
+ }
break;
- case MF_NOCOMMAND: map[m].nocommand = (val <= 0) ? 100 : val; break;
- case MF_NODROP: map[m].flag.nodrop = 1; break;
- case MF_JEXP: map[m].jexp = (val <= 0) ? 100 : val; break;
- case MF_BEXP: map[m].bexp = (val <= 0) ? 100 : val; break;
- case MF_NOVENDING: map[m].flag.novending = 1; break;
- case MF_LOADEVENT: map[m].flag.loadevent = 1; break;
- case MF_NOCHAT: map[m].flag.nochat = 1; break;
- case MF_NOEXPPENALTY: map[m].flag.noexppenalty = 1; break;
- case MF_GUILDLOCK: map[m].flag.guildlock = 1; break;
- case MF_TOWN: map[m].flag.town = 1; break;
- case MF_AUTOTRADE: map[m].flag.autotrade = 1; break;
- case MF_ALLOWKS: map[m].flag.allowks = 1; break;
- case MF_MONSTER_NOTELEPORT: map[m].flag.monster_noteleport = 1; break;
- case MF_PVP_NOCALCRANK: map[m].flag.pvp_nocalcrank = 1; break;
- case MF_BATTLEGROUND: map[m].flag.battleground = (val <= 0 || val > 2) ? 1 : val; break;
- case MF_RESET: map[m].flag.reset = 1; break;
+ case MF_NOCOMMAND: map->list[m].nocommand = (val <= 0) ? 100 : val; break;
+ case MF_NODROP: map->list[m].flag.nodrop = 1; break;
+ case MF_JEXP: map->list[m].jexp = (val <= 0) ? 100 : val; break;
+ case MF_BEXP: map->list[m].bexp = (val <= 0) ? 100 : val; break;
+ case MF_NOVENDING: map->list[m].flag.novending = 1; break;
+ case MF_LOADEVENT: map->list[m].flag.loadevent = 1; break;
+ case MF_NOCHAT: map->list[m].flag.nochat = 1; break;
+ case MF_NOEXPPENALTY: map->list[m].flag.noexppenalty = 1; break;
+ case MF_GUILDLOCK: map->list[m].flag.guildlock = 1; break;
+ case MF_TOWN: map->list[m].flag.town = 1; break;
+ case MF_AUTOTRADE: map->list[m].flag.autotrade = 1; break;
+ case MF_ALLOWKS: map->list[m].flag.allowks = 1; break;
+ case MF_MONSTER_NOTELEPORT: map->list[m].flag.monster_noteleport = 1; break;
+ case MF_PVP_NOCALCRANK: map->list[m].flag.pvp_nocalcrank = 1; break;
+ case MF_BATTLEGROUND: map->list[m].flag.battleground = (val <= 0 || val > 2) ? 1 : val; break;
+ case MF_RESET: map->list[m].flag.reset = 1; break;
+ case MF_NOTOMB: map->list[m].flag.notomb = 1; break;
+ case MF_NOCASHSHOP: map->list[m].flag.nocashshop = 1; break;
}
}
-
+
return true;
}
-BUILDIN(removemapflag)
-{
+BUILDIN(removemapflag) {
int16 m,i;
const char *str;
- int val=0;
-
+
str=script_getstr(st,2);
i=script_getnum(st,3);
- if(script_hasdata(st,4)){
- val=script_getnum(st,4);
- }
- m = iMap->mapname2mapid(str);
+
+ m = map->mapname2mapid(str);
if(m >= 0) {
switch(i) {
- case MF_NOMEMO: map[m].flag.nomemo = 0; break;
- case MF_NOTELEPORT: map[m].flag.noteleport = 0; break;
- case MF_NOSAVE: map[m].flag.nosave = 0; break;
- case MF_NOBRANCH: map[m].flag.nobranch = 0; break;
- case MF_NOPENALTY: map[m].flag.noexppenalty = 0; map[m].flag.nozenypenalty = 0; break;
- case MF_NOZENYPENALTY: map[m].flag.nozenypenalty = 0; break;
+ case MF_NOMEMO: map->list[m].flag.nomemo = 0; break;
+ case MF_NOTELEPORT: map->list[m].flag.noteleport = 0; break;
+ case MF_NOSAVE: map->list[m].flag.nosave = 0; break;
+ case MF_NOBRANCH: map->list[m].flag.nobranch = 0; break;
+ case MF_NOPENALTY: map->list[m].flag.noexppenalty = 0; map->list[m].flag.nozenypenalty = 0; break;
+ case MF_NOZENYPENALTY: map->list[m].flag.nozenypenalty = 0; break;
case MF_PVP: {
struct block_list bl;
bl.type = BL_NUL;
bl.m = m;
- map[m].flag.pvp = 0;
+ map->list[m].flag.pvp = 0;
clif->map_property_mapall(m, MAPPROPERTY_NOTHING);
clif->maptypeproperty2(&bl,ALL_SAMEMAP);
}
break;
- case MF_PVP_NOPARTY: map[m].flag.pvp_noparty = 0; break;
- case MF_PVP_NOGUILD: map[m].flag.pvp_noguild = 0; break;
+ case MF_PVP_NOPARTY: map->list[m].flag.pvp_noparty = 0; break;
+ case MF_PVP_NOGUILD: map->list[m].flag.pvp_noguild = 0; break;
case MF_GVG: {
struct block_list bl;
bl.type = BL_NUL;
bl.m = m;
- map[m].flag.gvg = 0;
+ map->list[m].flag.gvg = 0;
clif->map_property_mapall(m, MAPPROPERTY_NOTHING);
clif->maptypeproperty2(&bl,ALL_SAMEMAP);
}
break;
- case MF_GVG_NOPARTY: map[m].flag.gvg_noparty = 0; break;
- case MF_NOTRADE: map[m].flag.notrade = 0; break;
- case MF_NOSKILL: map[m].flag.noskill = 0; break;
- case MF_NOWARP: map[m].flag.nowarp = 0; break;
- case MF_PARTYLOCK: map[m].flag.partylock = 0; break;
- case MF_NOICEWALL: map[m].flag.noicewall = 0; break;
- case MF_SNOW: map[m].flag.snow = 0; break;
- case MF_FOG: map[m].flag.fog = 0; break;
- case MF_SAKURA: map[m].flag.sakura = 0; break;
- case MF_LEAVES: map[m].flag.leaves = 0; break;
- case MF_CLOUDS: map[m].flag.clouds = 0; break;
- case MF_CLOUDS2: map[m].flag.clouds2 = 0; break;
- case MF_FIREWORKS: map[m].flag.fireworks = 0; break;
- case MF_GVG_CASTLE: map[m].flag.gvg_castle = 0; break;
- case MF_GVG_DUNGEON: map[m].flag.gvg_dungeon = 0; break;
- case MF_NIGHTENABLED: map[m].flag.nightenabled = 0; break;
- case MF_NOBASEEXP: map[m].flag.nobaseexp = 0; break;
- case MF_NOJOBEXP: map[m].flag.nojobexp = 0; break;
- case MF_NOMOBLOOT: map[m].flag.nomobloot = 0; break;
- case MF_NOMVPLOOT: map[m].flag.nomvploot = 0; break;
- case MF_NORETURN: map[m].flag.noreturn = 0; break;
- case MF_NOWARPTO: map[m].flag.nowarpto = 0; break;
- case MF_NIGHTMAREDROP: map[m].flag.pvp_nightmaredrop = 0; break;
+ case MF_GVG_NOPARTY: map->list[m].flag.gvg_noparty = 0; break;
+ case MF_NOTRADE: map->list[m].flag.notrade = 0; break;
+ case MF_NOSKILL: map->list[m].flag.noskill = 0; break;
+ case MF_NOWARP: map->list[m].flag.nowarp = 0; break;
+ case MF_PARTYLOCK: map->list[m].flag.partylock = 0; break;
+ case MF_NOICEWALL: map->list[m].flag.noicewall = 0; break;
+ case MF_SNOW: map->list[m].flag.snow = 0; break;
+ case MF_FOG: map->list[m].flag.fog = 0; break;
+ case MF_SAKURA: map->list[m].flag.sakura = 0; break;
+ case MF_LEAVES: map->list[m].flag.leaves = 0; break;
+ case MF_CLOUDS: map->list[m].flag.clouds = 0; break;
+ case MF_CLOUDS2: map->list[m].flag.clouds2 = 0; break;
+ case MF_FIREWORKS: map->list[m].flag.fireworks = 0; break;
+ case MF_GVG_CASTLE: map->list[m].flag.gvg_castle = 0; break;
+ case MF_GVG_DUNGEON: map->list[m].flag.gvg_dungeon = 0; break;
+ case MF_NIGHTENABLED: map->list[m].flag.nightenabled = 0; break;
+ case MF_NOBASEEXP: map->list[m].flag.nobaseexp = 0; break;
+ case MF_NOJOBEXP: map->list[m].flag.nojobexp = 0; break;
+ case MF_NOMOBLOOT: map->list[m].flag.nomobloot = 0; break;
+ case MF_NOMVPLOOT: map->list[m].flag.nomvploot = 0; break;
+ case MF_NORETURN: map->list[m].flag.noreturn = 0; break;
+ case MF_NOWARPTO: map->list[m].flag.nowarpto = 0; break;
+ case MF_NIGHTMAREDROP: map->list[m].flag.pvp_nightmaredrop = 0; break;
case MF_ZONE:
- iMap->zone_change2(m, map[m].prev_zone);
+ map->zone_change2(m, map->list[m].prev_zone);
break;
- case MF_NOCOMMAND: map[m].nocommand = 0; break;
- case MF_NODROP: map[m].flag.nodrop = 0; break;
- case MF_JEXP: map[m].jexp = 0; break;
- case MF_BEXP: map[m].bexp = 0; break;
- case MF_NOVENDING: map[m].flag.novending = 0; break;
- case MF_LOADEVENT: map[m].flag.loadevent = 0; break;
- case MF_NOCHAT: map[m].flag.nochat = 0; break;
- case MF_NOEXPPENALTY: map[m].flag.noexppenalty = 0; break;
- case MF_GUILDLOCK: map[m].flag.guildlock = 0; break;
- case MF_TOWN: map[m].flag.town = 0; break;
- case MF_AUTOTRADE: map[m].flag.autotrade = 0; break;
- case MF_ALLOWKS: map[m].flag.allowks = 0; break;
- case MF_MONSTER_NOTELEPORT: map[m].flag.monster_noteleport = 0; break;
- case MF_PVP_NOCALCRANK: map[m].flag.pvp_nocalcrank = 0; break;
- case MF_BATTLEGROUND: map[m].flag.battleground = 0; break;
- case MF_RESET: map[m].flag.reset = 0; break;
+ case MF_NOCOMMAND: map->list[m].nocommand = 0; break;
+ case MF_NODROP: map->list[m].flag.nodrop = 0; break;
+ case MF_JEXP: map->list[m].jexp = 0; break;
+ case MF_BEXP: map->list[m].bexp = 0; break;
+ case MF_NOVENDING: map->list[m].flag.novending = 0; break;
+ case MF_LOADEVENT: map->list[m].flag.loadevent = 0; break;
+ case MF_NOCHAT: map->list[m].flag.nochat = 0; break;
+ case MF_NOEXPPENALTY: map->list[m].flag.noexppenalty = 0; break;
+ case MF_GUILDLOCK: map->list[m].flag.guildlock = 0; break;
+ case MF_TOWN: map->list[m].flag.town = 0; break;
+ case MF_AUTOTRADE: map->list[m].flag.autotrade = 0; break;
+ case MF_ALLOWKS: map->list[m].flag.allowks = 0; break;
+ case MF_MONSTER_NOTELEPORT: map->list[m].flag.monster_noteleport = 0; break;
+ case MF_PVP_NOCALCRANK: map->list[m].flag.pvp_nocalcrank = 0; break;
+ case MF_BATTLEGROUND: map->list[m].flag.battleground = 0; break;
+ case MF_RESET: map->list[m].flag.reset = 0; break;
+ case MF_NOTOMB: map->list[m].flag.notomb = 0; break;
+ case MF_NOCASHSHOP: map->list[m].flag.nocashshop = 0; break;
}
}
-
+
return true;
}
-BUILDIN(pvpon)
-{
+BUILDIN(pvpon) {
int16 m;
const char *str;
TBL_PC* sd = NULL;
struct s_mapiterator* iter;
struct block_list bl;
-
+
str = script_getstr(st,2);
- m = iMap->mapname2mapid(str);
- if( m < 0 || map[m].flag.pvp )
+ m = map->mapname2mapid(str);
+ if( m < 0 || map->list[m].flag.pvp )
return true; // nothing to do
-
- iMap->zone_change2(m, strdb_get(zone_db, MAP_ZONE_PVP_NAME));
- map[m].flag.pvp = 1;
+
+ if( !strdb_exists(map->zone_db,MAP_ZONE_PVP_NAME) ) {
+ ShowError("buildin_pvpon: zone_db missing '%s'\n",MAP_ZONE_PVP_NAME);
+ return true;
+ }
+
+ map->zone_change2(m, strdb_get(map->zone_db, MAP_ZONE_PVP_NAME));
+ map->list[m].flag.pvp = 1;
clif->map_property_mapall(m, MAPPROPERTY_FREEPVPZONE);
bl.type = BL_NUL;
bl.m = m;
clif->maptypeproperty2(&bl,ALL_SAMEMAP);
-
-
+
+
if(battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris]
return true;
-
+
iter = mapit_getallusers();
for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) )
{
if( sd->bl.m != m || sd->pvp_timer != INVALID_TIMER )
continue; // not applicable
-
- sd->pvp_timer = iTimer->add_timer(iTimer->gettick()+200,pc->calc_pvprank_timer,sd->bl.id,0);
+
+ sd->pvp_timer = timer->add(timer->gettick()+200,pc->calc_pvprank_timer,sd->bl.id,0);
sd->pvp_rank = 0;
sd->pvp_lastusers = 0;
sd->pvp_point = 5;
@@ -10561,227 +11215,218 @@ BUILDIN(pvpon)
sd->pvp_lost = 0;
}
mapit->free(iter);
-
+
return true;
}
-static int buildin_pvpoff_sub(struct block_list *bl,va_list ap)
+int buildin_pvpoff_sub(struct block_list *bl,va_list ap)
{
TBL_PC* sd = (TBL_PC*)bl;
clif->pvpset(sd, 0, 0, 2);
if (sd->pvp_timer != INVALID_TIMER) {
- iTimer->delete_timer(sd->pvp_timer, pc->calc_pvprank_timer);
+ timer->delete(sd->pvp_timer, pc->calc_pvprank_timer);
sd->pvp_timer = INVALID_TIMER;
}
return 0;
}
-BUILDIN(pvpoff)
-{
+BUILDIN(pvpoff) {
int16 m;
const char *str;
struct block_list bl;
-
+
str=script_getstr(st,2);
- m = iMap->mapname2mapid(str);
- if(m < 0 || !map[m].flag.pvp)
+ m = map->mapname2mapid(str);
+ if(m < 0 || !map->list[m].flag.pvp)
return true; //fixed Lupus
-
- iMap->zone_change2(m, map[m].prev_zone);
- map[m].flag.pvp = 0;
+
+ map->zone_change2(m, map->list[m].prev_zone);
+ map->list[m].flag.pvp = 0;
clif->map_property_mapall(m, MAPPROPERTY_NOTHING);
bl.type = BL_NUL;
bl.m = m;
clif->maptypeproperty2(&bl,ALL_SAMEMAP);
-
+
if(battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris]
return true;
-
- iMap->foreachinmap(buildin_pvpoff_sub, m, BL_PC);
+
+ map->foreachinmap(script->buildin_pvpoff_sub, m, BL_PC);
return true;
}
-BUILDIN(gvgon)
-{
+BUILDIN(gvgon) {
int16 m;
const char *str;
-
+
str=script_getstr(st,2);
- m = iMap->mapname2mapid(str);
- if(m >= 0 && !map[m].flag.gvg) {
+ m = map->mapname2mapid(str);
+ if(m >= 0 && !map->list[m].flag.gvg) {
struct block_list bl;
- iMap->zone_change2(m, strdb_get(zone_db, MAP_ZONE_GVG_NAME));
- map[m].flag.gvg = 1;
+
+ if( !strdb_exists(map->zone_db,MAP_ZONE_GVG_NAME) ) {
+ ShowError("buildin_gvgon: zone_db missing '%s'\n",MAP_ZONE_GVG_NAME);
+ return true;
+ }
+
+ map->zone_change2(m, strdb_get(map->zone_db, MAP_ZONE_GVG_NAME));
+ map->list[m].flag.gvg = 1;
clif->map_property_mapall(m, MAPPROPERTY_AGITZONE);
bl.type = BL_NUL;
bl.m = m;
clif->maptypeproperty2(&bl,ALL_SAMEMAP);
}
-
+
return true;
}
-BUILDIN(gvgoff)
-{
+BUILDIN(gvgoff) {
int16 m;
const char *str;
-
+
str=script_getstr(st,2);
- m = iMap->mapname2mapid(str);
- if(m >= 0 && map[m].flag.gvg) {
+ m = map->mapname2mapid(str);
+ if(m >= 0 && map->list[m].flag.gvg) {
struct block_list bl;
- iMap->zone_change2(m, map[m].prev_zone);
- map[m].flag.gvg = 0;
+ map->zone_change2(m, map->list[m].prev_zone);
+ map->list[m].flag.gvg = 0;
clif->map_property_mapall(m, MAPPROPERTY_NOTHING);
bl.type = BL_NUL;
bl.m = m;
clif->maptypeproperty2(&bl,ALL_SAMEMAP);
}
-
+
return true;
}
/*==========================================
- * Shows an emoticon on top of the player/npc
- * emotion emotion#, <target: 0 - NPC, 1 - PC>, <NPC/PC name>
+ * Shows an emoticon on top of the player/npc
+ * emotion emotion#, <target: 0 - NPC, 1 - PC>, <NPC/PC name>
*------------------------------------------*/
//Optional second parameter added by [Skotlex]
-BUILDIN(emotion)
-{
+BUILDIN(emotion) {
int type;
int player=0;
-
+
type=script_getnum(st,2);
if(type < 0 || type > 100)
return true;
-
+
if( script_hasdata(st,3) )
player=script_getnum(st,3);
-
+
if (player) {
TBL_PC *sd = NULL;
if( script_hasdata(st,4) )
- sd = iMap->nick2sd(script_getstr(st,4));
+ sd = map->nick2sd(script_getstr(st,4));
else
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if (sd)
clif->emotion(&sd->bl,type);
+ } else if( script_hasdata(st,4) ) {
+ TBL_NPC *nd = npc->name2id(script_getstr(st,4));
+ if(nd)
+ clif->emotion(&nd->bl,type);
} else
- if( script_hasdata(st,4) )
- {
- TBL_NPC *nd = npc_name2id(script_getstr(st,4));
- if(nd)
- clif->emotion(&nd->bl,type);
- }
- else
- clif->emotion(iMap->id2bl(st->oid),type);
+ clif->emotion(map->id2bl(st->oid),type);
return true;
}
-static int buildin_maprespawnguildid_sub_pc(struct map_session_data* sd, va_list ap)
+int buildin_maprespawnguildid_sub_pc(struct map_session_data* sd, va_list ap)
{
int16 m=va_arg(ap,int);
int g_id=va_arg(ap,int);
int flag=va_arg(ap,int);
-
+
if(!sd || sd->bl.m != m)
return 0;
if(
- (sd->status.guild_id == g_id && flag&1) || //Warp out owners
- (sd->status.guild_id != g_id && flag&2) || //Warp out outsiders
- (sd->status.guild_id == 0) // Warp out players not in guild [Valaris]
- )
+ (sd->status.guild_id == g_id && flag&1) //Warp out owners
+ || (sd->status.guild_id != g_id && flag&2) //Warp out outsiders
+ || (sd->status.guild_id == 0) // Warp out players not in guild [Valaris]
+ )
pc->setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
return 1;
}
-static int buildin_maprespawnguildid_sub_mob(struct block_list *bl,va_list ap)
+int buildin_maprespawnguildid_sub_mob(struct block_list *bl,va_list ap)
{
struct mob_data *md=(struct mob_data *)bl;
-
+
if(!md->guardian_data && md->class_ != MOBID_EMPERIUM)
status_kill(bl);
-
+
return 0;
}
-BUILDIN(maprespawnguildid)
-{
+BUILDIN(maprespawnguildid) {
const char *mapname=script_getstr(st,2);
int g_id=script_getnum(st,3);
int flag=script_getnum(st,4);
-
- int16 m=iMap->mapname2mapid(mapname);
-
+
+ int16 m=map->mapname2mapid(mapname);
+
if(m == -1)
return true;
-
+
//Catch ALL players (in case some are 'between maps' on execution time)
- iMap->map_foreachpc(buildin_maprespawnguildid_sub_pc,m,g_id,flag);
+ map->foreachpc(script->buildin_maprespawnguildid_sub_pc,m,g_id,flag);
if (flag&4) //Remove script mobs.
- iMap->foreachinmap(buildin_maprespawnguildid_sub_mob,m,BL_MOB);
+ map->foreachinmap(script->buildin_maprespawnguildid_sub_mob,m,BL_MOB);
return true;
}
-BUILDIN(agitstart)
-{
- if(iMap->agit_flag==1) return true; // Agit already Start.
- iMap->agit_flag=1;
+BUILDIN(agitstart) {
+ if(map->agit_flag==1) return true; // Agit already Start.
+ map->agit_flag=1;
guild->agit_start();
return true;
}
-BUILDIN(agitend)
-{
- if(iMap->agit_flag==0) return true; // Agit already End.
- iMap->agit_flag=0;
+BUILDIN(agitend) {
+ if(map->agit_flag==0) return true; // Agit already End.
+ map->agit_flag=0;
guild->agit_end();
return true;
}
-BUILDIN(agitstart2)
-{
- if(iMap->agit2_flag==1) return true; // Agit2 already Start.
- iMap->agit2_flag=1;
+BUILDIN(agitstart2) {
+ if(map->agit2_flag==1) return true; // Agit2 already Start.
+ map->agit2_flag=1;
guild->agit2_start();
return true;
}
-BUILDIN(agitend2)
-{
- if(iMap->agit2_flag==0) return true; // Agit2 already End.
- iMap->agit2_flag=0;
+BUILDIN(agitend2) {
+ if(map->agit2_flag==0) return true; // Agit2 already End.
+ map->agit2_flag=0;
guild->agit2_end();
return true;
}
/*==========================================
- * Returns whether woe is on or off. // choice script
+ * Returns whether woe is on or off.
*------------------------------------------*/
-BUILDIN(agitcheck)
-{
- script_pushint(st,iMap->agit_flag);
+BUILDIN(agitcheck) {
+ script_pushint(st,map->agit_flag);
return true;
}
/*==========================================
- * Returns whether woese is on or off. // choice script
+ * Returns whether woese is on or off.
*------------------------------------------*/
-BUILDIN(agitcheck2)
-{
- script_pushint(st,iMap->agit2_flag);
+BUILDIN(agitcheck2) {
+ script_pushint(st,map->agit2_flag);
return true;
}
/// Sets the guild_id of this npc.
///
/// flagemblem <guild_id>;
-BUILDIN(flagemblem)
-{
+BUILDIN(flagemblem) {
TBL_NPC* nd;
int g_id = script_getnum(st,2);
-
+
if(g_id < 0) return true;
-
- nd = (TBL_NPC*)iMap->id2nd(st->oid);
+
+ nd = (TBL_NPC*)map->id2nd(st->oid);
if( nd == NULL ) {
ShowError("script:flagemblem: npc %d not found\n", st->oid);
} else if( nd->subtype != SCRIPT ) {
@@ -10801,7 +11446,7 @@ BUILDIN(flagemblem)
BUILDIN(getcastlename)
{
- const char* mapname = mapindex_getmapname(script_getstr(st,2),NULL);
+ const char* mapname = mapindex->getmapname(script_getstr(st,2),NULL);
struct guild_castle* gc = guild->mapname2gc(mapname);
const char* name = (gc) ? gc->castle_name : "";
script_pushstrcopy(st,name);
@@ -10810,16 +11455,16 @@ BUILDIN(getcastlename)
BUILDIN(getcastledata)
{
- const char *mapname = mapindex_getmapname(script_getstr(st,2),NULL);
+ const char *mapname = mapindex->getmapname(script_getstr(st,2),NULL);
int index = script_getnum(st,3);
struct guild_castle *gc = guild->mapname2gc(mapname);
-
+
if (gc == NULL) {
script_pushint(st,0);
ShowWarning("buildin_setcastledata: guild castle for map '%s' not found\n", mapname);
return false;
}
-
+
switch (index) {
case 1:
script_pushint(st,gc->guild_id); break;
@@ -10853,21 +11498,21 @@ BUILDIN(getcastledata)
BUILDIN(setcastledata)
{
- const char *mapname = mapindex_getmapname(script_getstr(st,2),NULL);
+ const char *mapname = mapindex->getmapname(script_getstr(st,2),NULL);
int index = script_getnum(st,3);
int value = script_getnum(st,4);
struct guild_castle *gc = guild->mapname2gc(mapname);
-
+
if (gc == NULL) {
ShowWarning("buildin_setcastledata: guild castle for map '%s' not found\n", mapname);
return false;
}
-
+
if (index <= 0 || index > 9+MAX_GUARDIANS) {
ShowWarning("buildin_setcastledata: index = '%d' is out of allowed range\n", index);
return false;
}
-
+
guild->castledatasave(gc->castle_id, index, value);
return true;
}
@@ -10878,12 +11523,12 @@ BUILDIN(requestguildinfo)
{
int guild_id=script_getnum(st,2);
const char *event=NULL;
-
- if( script_hasdata(st,3) ){
+
+ if( script_hasdata(st,3) ) {
event=script_getstr(st,3);
- check_event(st, event);
+ script->check_event(st, event);
}
-
+
if(guild_id>0)
guild->npc_request_info(guild_id,event);
return true;
@@ -10896,28 +11541,32 @@ BUILDIN(getequipcardcnt)
int i=-1,j,num;
TBL_PC *sd;
int count;
-
+
num=script_getnum(st,2);
- sd=script_rid2sd(st);
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
-
+ sd=script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
+
if (i < 0 || !sd->inventory_data[i]) {
script_pushint(st,0);
return true;
}
-
+
if(itemdb_isspecial(sd->status.inventory[i].card[0]))
{
script_pushint(st,0);
return true;
}
-
+
count = 0;
for( j = 0; j < sd->inventory_data[i]->slot; j++ )
if( sd->status.inventory[i].card[j] && itemdb_type(sd->status.inventory[i].card[j]) == IT_CARD )
count++;
-
+
script_pushint(st,count);
return true;
}
@@ -10927,20 +11576,23 @@ BUILDIN(getequipcardcnt)
/// successremovecards <slot>;
BUILDIN(successremovecards) {
int i=-1,j,c,cardflag=0;
-
- TBL_PC* sd = script_rid2sd(st);
+
+ TBL_PC* sd = script->rid2sd(st);
int num = script_getnum(st,2);
-
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
-
+
+ if( sd == NULL )
+ return false;
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
+
if (i < 0 || !sd->inventory_data[i]) {
return true;
}
-
+
if(itemdb_isspecial(sd->status.inventory[i].card[0]))
return true;
-
+
for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) {
if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) {// extract this card from the item
int flag;
@@ -10949,34 +11601,37 @@ BUILDIN(successremovecards) {
cardflag = 1;
item_tmp.nameid = sd->status.inventory[i].card[c];
item_tmp.identify = 1;
-
- if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ // get back the cart in inventory
+
+ if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
+ // get back the cart in inventory
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
}
-
+
if(cardflag == 1) {//if card was remove remplace item with no card
int flag;
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
-
+
item_tmp.nameid = sd->status.inventory[i].nameid;
item_tmp.identify = 1;
item_tmp.refine = sd->status.inventory[i].refine;
item_tmp.attribute = sd->status.inventory[i].attribute;
item_tmp.expire_time = sd->status.inventory[i].expire_time;
-
+ item_tmp.bound = sd->status.inventory[i].bound;
+
for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++)
item_tmp.card[j]=sd->status.inventory[i].card[j];
-
+
pc->delitem(sd,i,1,0,3,LOG_TYPE_SCRIPT);
- if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ //chk if can be spawn in inventory otherwise put on floor
+ if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
+ //chk if can be spawn in inventory otherwise put on floor
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
-
+
clif->misceffect(&sd->bl,3);
}
return true;
@@ -10990,80 +11645,86 @@ BUILDIN(successremovecards) {
/// <type>=? : will just display the failure effect.
BUILDIN(failedremovecards) {
int i=-1,j,c,cardflag=0;
-
- TBL_PC* sd = script_rid2sd(st);
+
+ TBL_PC* sd = script->rid2sd(st);
int num = script_getnum(st,2);
int typefail = script_getnum(st,3);
-
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
-
+
+ if( sd == NULL )
+ return false;
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
+
if (i < 0 || !sd->inventory_data[i])
return true;
-
+
if(itemdb_isspecial(sd->status.inventory[i].card[0]))
return true;
-
+
for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) {
if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) {
cardflag = 1;
-
+
if(typefail == 2) {// add cards to inventory, clear
int flag;
struct item item_tmp;
-
+
memset(&item_tmp,0,sizeof(item_tmp));
-
+
item_tmp.nameid = sd->status.inventory[i].card[c];
item_tmp.identify = 1;
-
- if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){
+
+ if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
}
}
-
+
if(cardflag == 1) {
- if(typefail == 0 || typefail == 2){ // destroy the item
+ if(typefail == 0 || typefail == 2) {
+ // destroy the item
pc->delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT);
}
- if(typefail == 1){ // destroy the card
+ if(typefail == 1) {
+ // destroy the card
int flag;
struct item item_tmp;
-
+
memset(&item_tmp,0,sizeof(item_tmp));
-
+
item_tmp.nameid = sd->status.inventory[i].nameid;
item_tmp.identify = 1;
item_tmp.refine = sd->status.inventory[i].refine;
item_tmp.attribute = sd->status.inventory[i].attribute;
item_tmp.expire_time = sd->status.inventory[i].expire_time;
-
+ item_tmp.bound = sd->status.inventory[i].bound;
+
for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++)
item_tmp.card[j]=sd->status.inventory[i].card[j];
-
+
pc->delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT);
-
- if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){
+
+ if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) {
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
clif->misceffect(&sd->bl,2);
}
-
+
return true;
}
/* ================================================================
* mapwarp "<from map>","<to map>",<x>,<y>,<type>,<ID for Type>;
- * type: 0=everyone, 1=guild, 2=party; [Reddozen]
+ * type: 0=everyone, 1=guild, 2=party; [Reddozen]
* improved by [Lance]
* ================================================================*/
-BUILDIN(mapwarp) // Added by RoVeRT
-{
+// Added by RoVeRT
+BUILDIN(mapwarp) {
int x,y,m,check_val=0,check_ID=0,i=0;
struct guild *g = NULL;
struct party_data *p = NULL;
@@ -11074,24 +11735,24 @@ BUILDIN(mapwarp) // Added by RoVeRT
str=script_getstr(st,3);
x=script_getnum(st,4);
y=script_getnum(st,5);
- if(script_hasdata(st,7)){
+ if(script_hasdata(st,7)) {
check_val=script_getnum(st,6);
check_ID=script_getnum(st,7);
}
-
- if((m=iMap->mapname2mapid(mapname))< 0)
+
+ if((m=map->mapname2mapid(mapname))< 0)
return true;
-
- if(!(index=mapindex_name2id(str)))
+
+ if(!(index=script->mapindexname2id(st,str)))
return true;
-
- switch(check_val){
+
+ switch(check_val) {
case 1:
g = guild->search(check_ID);
- if (g){
+ if (g) {
for( i=0; i < g->max_member; i++)
{
- if(g->member[i].sd && g->member[i].sd->bl.m==m){
+ if(g->member[i].sd && g->member[i].sd->bl.m==m) {
pc->setpos(g->member[i].sd,index,x,y,CLR_TELEPORT);
}
}
@@ -11099,24 +11760,24 @@ BUILDIN(mapwarp) // Added by RoVeRT
break;
case 2:
p = party->search(check_ID);
- if(p){
- for(i=0;i<MAX_PARTY; i++){
- if(p->data[i].sd && p->data[i].sd->bl.m == m){
+ if(p) {
+ for(i=0;i<MAX_PARTY; i++) {
+ if(p->data[i].sd && p->data[i].sd->bl.m == m) {
pc->setpos(p->data[i].sd,index,x,y,CLR_TELEPORT);
}
}
}
break;
default:
- iMap->foreachinmap(buildin_areawarp_sub,m,BL_PC,index,x,y,0,0);
+ map->foreachinmap(script->buildin_areawarp_sub,m,BL_PC,index,x,y,0,0);
break;
}
-
+
return true;
}
-static int buildin_mobcount_sub(struct block_list *bl,va_list ap) // Added by RoVeRT
-{
+// Added by RoVeRT
+int buildin_mobcount_sub(struct block_list *bl,va_list ap) {
char *event=va_arg(ap,char *);
struct mob_data *md = ((struct mob_data *)bl);
if( md->status.hp > 0 && (!event || strcmp(event,md->npc_event) == 0) )
@@ -11124,70 +11785,67 @@ static int buildin_mobcount_sub(struct block_list *bl,va_list ap) // Added by Ro
return 0;
}
-BUILDIN(mobcount) // Added by RoVeRT
-{
+// Added by RoVeRT
+BUILDIN(mobcount) {
const char *mapname,*event;
int16 m;
mapname=script_getstr(st,2);
event=script_getstr(st,3);
-
+
if( strcmp(event, "all") == 0 )
event = NULL;
else
- check_event(st, event);
+ script->check_event(st, event);
if( strcmp(mapname, "this") == 0 ) {
- struct map_session_data *sd = script_rid2sd(st);
- if( sd )
- m = sd->bl.m;
- else {
- script_pushint(st,-1);
- return true;
- }
- } else if( (m = iMap->mapname2mapid(mapname)) < 0 ) {
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
+ m = sd->bl.m;
+ } else if( (m = map->mapname2mapid(mapname)) < 0 ) {
script_pushint(st,-1);
return true;
}
- if( map[m].flag.src4instance && map[m].instance_id == -1 && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 ) {
+ if( map->list[m].flag.src4instance && map->list[m].instance_id == -1 && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 ) {
script_pushint(st,-1);
return true;
}
- script_pushint(st,iMap->foreachinmap(buildin_mobcount_sub, m, BL_MOB, event));
-
+ script_pushint(st,map->foreachinmap(script->buildin_mobcount_sub, m, BL_MOB, event));
+
return true;
}
-BUILDIN(marriage)
-{
+BUILDIN(marriage) {
const char *partner=script_getstr(st,2);
- TBL_PC *sd=script_rid2sd(st);
- TBL_PC *p_sd=iMap->nick2sd(partner);
-
- if(sd==NULL || p_sd==NULL || pc->marriage(sd,p_sd) < 0){
+ TBL_PC *sd=script->rid2sd(st);
+ TBL_PC *p_sd=map->nick2sd(partner);
+
+ if(sd==NULL || p_sd==NULL || pc->marriage(sd,p_sd) < 0) {
script_pushint(st,0);
return true;
}
script_pushint(st,1);
return true;
}
-BUILDIN(wedding_effect)
-{
- TBL_PC *sd=script_rid2sd(st);
+BUILDIN(wedding_effect) {
+ TBL_PC *sd=script->rid2sd(st);
struct block_list *bl;
-
- if(sd==NULL) {
- bl=iMap->id2bl(st->oid);
- } else
- bl=&sd->bl;
+
+ if( sd == NULL )
+ return false; //bl=map->id2bl(st->oid);
+
+ bl=&sd->bl;
clif->wedding_effect(bl);
return true;
}
BUILDIN(divorce)
{
- TBL_PC *sd=script_rid2sd(st);
- if(sd==NULL || pc->divorce(sd) < 0){
+ TBL_PC *sd=script->rid2sd(st);
+ if(sd==NULL || pc->divorce(sd) < 0) {
script_pushint(st,0);
return true;
}
@@ -11195,89 +11853,76 @@ BUILDIN(divorce)
return true;
}
-BUILDIN(ispartneron)
-{
- TBL_PC *sd=script_rid2sd(st);
-
- if(sd==NULL || !pc->ismarried(sd) ||
- iMap->charid2sd(sd->status.partner_id) == NULL) {
+BUILDIN(ispartneron) {
+ TBL_PC *sd=script->rid2sd(st);
+
+ if (sd==NULL || !pc->ismarried(sd)
+ || map->charid2sd(sd->status.partner_id) == NULL) {
script_pushint(st,0);
return true;
}
-
+
script_pushint(st,1);
return true;
}
-BUILDIN(getpartnerid)
-{
- TBL_PC *sd=script_rid2sd(st);
- if (sd == NULL) {
- script_pushint(st,0);
- return true;
- }
-
- script_pushint(st,sd->status.partner_id);
- return true;
+BUILDIN(getpartnerid) {
+ TBL_PC *sd=script->rid2sd(st);
+ if( sd == NULL )
+ return false;
+
+ script_pushint(st,sd->status.partner_id);
+ return true;
}
-BUILDIN(getchildid)
-{
- TBL_PC *sd=script_rid2sd(st);
- if (sd == NULL) {
- script_pushint(st,0);
- return true;
- }
-
- script_pushint(st,sd->status.child);
- return true;
+BUILDIN(getchildid) {
+ TBL_PC *sd=script->rid2sd(st);
+ if( sd == NULL )
+ return false;
+
+ script_pushint(st,sd->status.child);
+ return true;
}
-BUILDIN(getmotherid)
-{
- TBL_PC *sd=script_rid2sd(st);
- if (sd == NULL) {
- script_pushint(st,0);
- return true;
- }
-
- script_pushint(st,sd->status.mother);
- return true;
+BUILDIN(getmotherid) {
+ TBL_PC *sd=script->rid2sd(st);
+ if( sd == NULL )
+ return false;
+
+ script_pushint(st,sd->status.mother);
+ return true;
}
-BUILDIN(getfatherid)
-{
- TBL_PC *sd=script_rid2sd(st);
- if (sd == NULL) {
- script_pushint(st,0);
- return true;
- }
-
- script_pushint(st,sd->status.father);
- return true;
+BUILDIN(getfatherid) {
+ TBL_PC *sd=script->rid2sd(st);
+ if( sd == NULL )
+ return false;
+
+ script_pushint(st,sd->status.father);
+ return true;
}
BUILDIN(warppartner)
{
int x,y;
- unsigned short mapindex;
+ unsigned short map_index;
const char *str;
- TBL_PC *sd=script_rid2sd(st);
+ TBL_PC *sd=script->rid2sd(st);
TBL_PC *p_sd=NULL;
-
- if(sd==NULL || !pc->ismarried(sd) ||
- (p_sd=iMap->charid2sd(sd->status.partner_id)) == NULL) {
+
+ if ( sd==NULL || !pc->ismarried(sd)
+ || (p_sd=map->charid2sd(sd->status.partner_id)) == NULL) {
script_pushint(st,0);
return true;
}
-
+
str=script_getstr(st,2);
x=script_getnum(st,3);
y=script_getnum(st,4);
-
- mapindex = mapindex_name2id(str);
- if (mapindex) {
- pc->setpos(p_sd,mapindex,x,y,CLR_OUTSIGHT);
+
+ map_index = script->mapindexname2id(st,str);
+ if (map_index) {
+ pc->setpos(p_sd,map_index,x,y,CLR_OUTSIGHT);
script_pushint(st,1);
} else
script_pushint(st,0);
@@ -11289,11 +11934,11 @@ BUILDIN(warppartner)
*------------------------------------------------*/
BUILDIN(strmobinfo)
{
-
+
int num=script_getnum(st,2);
int class_=script_getnum(st,3);
-
- if(!mobdb_checkid(class_))
+
+ if(!mob->db_checkid(class_))
{
if (num < 3) //requested a string
script_pushconststr(st,"");
@@ -11301,15 +11946,15 @@ BUILDIN(strmobinfo)
script_pushint(st,0);
return true;
}
-
+
switch (num) {
- case 1: script_pushstrcopy(st,mob_db(class_)->name); break;
- case 2: script_pushstrcopy(st,mob_db(class_)->jname); break;
- case 3: script_pushint(st,mob_db(class_)->lv); break;
- case 4: script_pushint(st,mob_db(class_)->status.max_hp); break;
- case 5: script_pushint(st,mob_db(class_)->status.max_sp); break;
- case 6: script_pushint(st,mob_db(class_)->base_exp); break;
- case 7: script_pushint(st,mob_db(class_)->job_exp); break;
+ case 1: script_pushstrcopy(st,mob->db(class_)->name); break;
+ case 2: script_pushstrcopy(st,mob->db(class_)->jname); break;
+ case 3: script_pushint(st,mob->db(class_)->lv); break;
+ case 4: script_pushint(st,mob->db(class_)->status.max_hp); break;
+ case 5: script_pushint(st,mob->db(class_)->status.max_sp); break;
+ case 6: script_pushint(st,mob->db(class_)->base_exp); break;
+ case 7: script_pushint(st,mob->db(class_)->job_exp); break;
default:
script_pushint(st,0);
break;
@@ -11321,74 +11966,70 @@ BUILDIN(strmobinfo)
* Summon guardians [Valaris]
* guardian("<map name>",<x>,<y>,"<name to show>",<mob id>{,"<event label>"}{,<guardian index>}) -> <id>
*------------------------------------------*/
-BUILDIN(guardian)
-{
- int class_=0,x=0,y=0,guardian=0;
- const char *str,*map,*evt="";
- struct script_data *data;
+BUILDIN(guardian) {
+ int class_ = 0, x = 0, y = 0, guardian = 0;
+ const char *str, *mapname, *evt="";
bool has_index = false;
-
- map =script_getstr(st,2);
- x =script_getnum(st,3);
- y =script_getnum(st,4);
- str =script_getstr(st,5);
- class_=script_getnum(st,6);
-
+
+ mapname = script_getstr(st,2);
+ x = script_getnum(st,3);
+ y = script_getnum(st,4);
+ str = script_getstr(st,5);
+ class_ = script_getnum(st,6);
+
if( script_hasdata(st,8) )
{// "<event label>",<guardian index>
evt=script_getstr(st,7);
guardian=script_getnum(st,8);
has_index = true;
- } else if( script_hasdata(st,7) ){
- data=script_getdata(st,7);
- script->get_val(st,data);
- if( data_isstring(data) )
- {// "<event label>"
+ } else if( script_hasdata(st,7) ) {
+ struct script_data *data = script_getdata(st,7);
+ script->get_val(st,data); // Dereference if it's a variable
+ if( data_isstring(data) ) {
+ // "<event label>"
evt=script_getstr(st,7);
- } else if( data_isint(data) )
- {// <guardian index>
+ } else if( data_isint(data) ) {
+ // <guardian index>
guardian=script_getnum(st,7);
has_index = true;
} else {
ShowError("script:guardian: invalid data type for argument #6 (from 1)\n");
- script_reportdata(data);
+ script->reportdata(data);
return false;
}
}
-
- check_event(st, evt);
- script_pushint(st, mob_spawn_guardian(map,x,y,str,class_,evt,guardian,has_index));
-
+
+ script->check_event(st, evt);
+ script_pushint(st, mob->spawn_guardian(mapname,x,y,str,class_,evt,guardian,has_index));
+
return true;
}
/*==========================================
* Invisible Walls [Zephyrus]
*------------------------------------------*/
-BUILDIN(setwall)
-{
- const char *map, *name;
+BUILDIN(setwall) {
+ const char *mapname, *name;
int x, y, m, size, dir;
bool shootable;
-
- map = script_getstr(st,2);
- x = script_getnum(st,3);
- y = script_getnum(st,4);
- size = script_getnum(st,5);
- dir = script_getnum(st,6);
+
+ mapname = script_getstr(st,2);
+ x = script_getnum(st,3);
+ y = script_getnum(st,4);
+ size = script_getnum(st,5);
+ dir = script_getnum(st,6);
shootable = script_getnum(st,7);
- name = script_getstr(st,8);
-
- if( (m = iMap->mapname2mapid(map)) < 0 )
+ name = script_getstr(st,8);
+
+ if( (m = map->mapname2mapid(mapname)) < 0 )
return true; // Invalid Map
-
- iMap->iwall_set(m, x, y, size, dir, shootable, name);
+
+ map->iwall_set(m, x, y, size, dir, shootable, name);
return true;
}
-BUILDIN(delwall)
-{
+BUILDIN(delwall) {
const char *name = script_getstr(st,2);
- iMap->iwall_remove(name);
-
+ map->iwall_remove(name);
+
return true;
}
@@ -11399,69 +12040,59 @@ BUILDIN(delwall)
/// 1 - maximum hp
/// 2 - current hp
///
-BUILDIN(guardianinfo)
-{
- const char* mapname = mapindex_getmapname(script_getstr(st,2),NULL);
+BUILDIN(guardianinfo) {
+ const char* mapname = mapindex->getmapname(script_getstr(st,2),NULL);
int id = script_getnum(st,3);
int type = script_getnum(st,4);
-
+
struct guild_castle* gc = guild->mapname2gc(mapname);
struct mob_data* gd;
-
- if( gc == NULL || id < 0 || id >= MAX_GUARDIANS )
- {
+
+ if( gc == NULL || id < 0 || id >= MAX_GUARDIANS ) {
script_pushint(st,-1);
return true;
}
-
+
if( type == 0 )
script_pushint(st, gc->guardian[id].visible);
+ else if( !gc->guardian[id].visible )
+ script_pushint(st,-1);
+ else if( (gd = map->id2md(gc->guardian[id].id)) == NULL )
+ script_pushint(st,-1);
+ else if( type == 1 )
+ script_pushint(st,gd->status.max_hp);
+ else if( type == 2 )
+ script_pushint(st,gd->status.hp);
else
- if( !gc->guardian[id].visible )
- script_pushint(st,-1);
- else
- if( (gd = iMap->id2md(gc->guardian[id].id)) == NULL )
- script_pushint(st,-1);
- else
- {
- if ( type == 1 ) script_pushint(st,gd->status.max_hp);
- else if( type == 2 ) script_pushint(st,gd->status.hp);
- else
- script_pushint(st,-1);
- }
-
+ script_pushint(st,-1);
+
return true;
}
/*==========================================
* Get the item name by item_id or null
*------------------------------------------*/
-BUILDIN(getitemname)
-{
+BUILDIN(getitemname) {
int item_id=0;
struct item_data *i_data;
char *item_name;
- struct script_data *data;
-
- data=script_getdata(st,2);
- script->get_val(st,data);
-
- if( data_isstring(data) ){
- const char *name=script->conv_str(st,data);
- struct item_data *item_data = itemdb_searchname(name);
+
+ if( script_isstringtype(st, 2) ) {
+ const char *name = script_getstr(st, 2);
+ struct item_data *item_data = itemdb->search_name(name);
if( item_data )
item_id=item_data->nameid;
- }else
- item_id=script->conv_num(st,data);
-
- i_data = itemdb_exists(item_id);
- if (i_data == NULL)
- {
+ } else {
+ item_id = script_getnum(st, 2);
+ }
+
+ i_data = itemdb->exists(item_id);
+ if (i_data == NULL) {
script_pushconststr(st,"null");
return true;
}
item_name=(char *)aMalloc(ITEM_NAME_LENGTH*sizeof(char));
-
+
memcpy(item_name, i_data->jname, ITEM_NAME_LENGTH);
script_pushstr(st,item_name);
return true;
@@ -11473,11 +12104,11 @@ BUILDIN(getitemslots)
{
int item_id;
struct item_data *i_data;
-
+
item_id=script_getnum(st,2);
-
- i_data = itemdb_exists(item_id);
-
+
+ i_data = itemdb->exists(item_id);
+
if (i_data)
script_pushint(st,i_data->slot);
else
@@ -11490,35 +12121,35 @@ BUILDIN(getitemslots)
/*==========================================
* Returns some values of an item [Lupus]
* Price, Weight, etc...
- getiteminfo(itemID,n), where n
- 0 value_buy;
- 1 value_sell;
- 2 type;
- 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc..
- if = 0, then monsters don't drop it at all (rare or a quest item)
- if = -1, then this item is sold in NPC shops only
- 4 sex;
- 5 equip;
- 6 weight;
- 7 atk;
- 8 def;
- 9 range;
- 10 slot;
- 11 look;
- 12 elv;
- 13 wlv;
- 14 view id
+ * getiteminfo(itemID,n), where n
+ * 0 value_buy;
+ * 1 value_sell;
+ * 2 type;
+ * 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc..
+ * if = 0, then monsters don't drop it at all (rare or a quest item)
+ * if = -1, then this item is sold in NPC shops only
+ * 4 sex;
+ * 5 equip;
+ * 6 weight;
+ * 7 atk;
+ * 8 def;
+ * 9 range;
+ * 10 slot;
+ * 11 look;
+ * 12 elv;
+ * 13 wlv;
+ * 14 view id
*------------------------------------------*/
BUILDIN(getiteminfo)
{
int item_id,n;
int *item_arr;
struct item_data *i_data;
-
- item_id = script_getnum(st,2);
- n = script_getnum(st,3);
- i_data = itemdb_exists(item_id);
-
+
+ item_id = script_getnum(st,2);
+ n = script_getnum(st,3);
+ i_data = itemdb->exists(item_id);
+
if (i_data && n>=0 && n<=14) {
item_arr = (int*)&i_data->value_buy;
script_pushint(st,item_arr[n]);
@@ -11530,24 +12161,24 @@ BUILDIN(getiteminfo)
/*==========================================
* Set some values of an item [Lupus]
* Price, Weight, etc...
- setiteminfo(itemID,n,Value), where n
- 0 value_buy;
- 1 value_sell;
- 2 type;
- 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc..
- if = 0, then monsters don't drop it at all (rare or a quest item)
- if = -1, then this item is sold in NPC shops only
- 4 sex;
- 5 equip;
- 6 weight;
- 7 atk;
- 8 def;
- 9 range;
- 10 slot;
- 11 look;
- 12 elv;
- 13 wlv;
- 14 view id
+ * setiteminfo(itemID,n,Value), where n
+ * 0 value_buy;
+ * 1 value_sell;
+ * 2 type;
+ * 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc..
+ * if = 0, then monsters don't drop it at all (rare or a quest item)
+ * if = -1, then this item is sold in NPC shops only
+ * 4 sex;
+ * 5 equip;
+ * 6 weight;
+ * 7 atk;
+ * 8 def;
+ * 9 range;
+ * 10 slot;
+ * 11 look;
+ * 12 elv;
+ * 13 wlv;
+ * 14 view id
* Returns Value or -1 if the wrong field's been set
*------------------------------------------*/
BUILDIN(setiteminfo)
@@ -11555,12 +12186,12 @@ BUILDIN(setiteminfo)
int item_id,n,value;
int *item_arr;
struct item_data *i_data;
-
- item_id = script_getnum(st,2);
- n = script_getnum(st,3);
- value = script_getnum(st,4);
- i_data = itemdb_exists(item_id);
-
+
+ item_id = script_getnum(st,2);
+ n = script_getnum(st,3);
+ value = script_getnum(st,4);
+ i_data = itemdb->exists(item_id);
+
if (i_data && n>=0 && n<=14) {
item_arr = (int*)&i_data->value_buy;
item_arr[n] = value;
@@ -11572,31 +12203,35 @@ BUILDIN(setiteminfo)
/*==========================================
* Returns value from equipped item slot n [Lupus]
- getequpcardid(num,slot)
- where
- num = eqip position slot
- slot = 0,1,2,3 (Card Slot N)
-
- This func returns CARD ID, 255,254,-255 (for card 0, if the item is produced)
- it's useful when you want to check item cards or if it's signed
- Useful for such quests as "Sign this refined item with players name" etc
- Hat[0] +4 -> Player's Hat[0] +4
+ * getequpcardid(num,slot)
+ * where
+ * num = eqip position slot
+ * slot = 0,1,2,3 (Card Slot N)
+ *
+ * This func returns CARD ID, 255,254,-255 (for card 0, if the item is produced)
+ * it's useful when you want to check item cards or if it's signed
+ * Useful for such quests as "Sign this refined item with players name" etc
+ * Hat[0] +4 -> Player's Hat[0] +4
*------------------------------------------*/
BUILDIN(getequipcardid)
{
int i=-1,num,slot;
TBL_PC *sd;
-
+
num=script_getnum(st,2);
slot=script_getnum(st,3);
- sd=script_rid2sd(st);
- if (num > 0 && num <= ARRAYLENGTH(equip))
- i=pc->checkequip(sd,equip[num-1]);
+ sd=script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
+ if (num > 0 && num <= ARRAYLENGTH(script->equip))
+ i=pc->checkequip(sd,script->equip[num-1]);
if(i >= 0 && slot>=0 && slot<4)
script_pushint(st,sd->status.inventory[i].card[slot]);
else
script_pushint(st,0);
-
+
return true;
}
@@ -11606,34 +12241,34 @@ BUILDIN(getequipcardid)
BUILDIN(petskillbonus)
{
struct pet_data *pd;
-
- TBL_PC *sd=script_rid2sd(st);
-
+
+ TBL_PC *sd=script->rid2sd(st);
+
if(sd==NULL || sd->pd==NULL)
return true;
-
+
pd=sd->pd;
if (pd->bonus)
{ //Clear previous bonus
if (pd->bonus->timer != INVALID_TIMER)
- iTimer->delete_timer(pd->bonus->timer, pet_skill_bonus_timer);
+ timer->delete(pd->bonus->timer, pet->skill_bonus_timer);
} else //init
pd->bonus = (struct pet_bonus *) aMalloc(sizeof(struct pet_bonus));
-
+
pd->bonus->type=script_getnum(st,2);
pd->bonus->val=script_getnum(st,3);
pd->bonus->duration=script_getnum(st,4);
pd->bonus->delay=script_getnum(st,5);
-
+
if (pd->state.skillbonus == 1)
- pd->state.skillbonus=0; // waiting state
-
+ pd->state.skillbonus=0; // waiting state
+
// wait for timer to start
if (battle_config.pet_equip_required && pd->pet.equip == 0)
pd->bonus->timer = INVALID_TIMER;
else
- pd->bonus->timer = iTimer->add_timer(iTimer->gettick()+pd->bonus->delay*1000, pet_skill_bonus_timer, sd->bl.id, 0);
-
+ pd->bonus->timer = timer->add(timer->gettick()+pd->bonus->delay*1000, pet->skill_bonus_timer, sd->bl.id, 0);
+
return true;
}
@@ -11644,33 +12279,33 @@ BUILDIN(petloot)
{
int max;
struct pet_data *pd;
- TBL_PC *sd=script_rid2sd(st);
-
+ TBL_PC *sd=script->rid2sd(st);
+
if(sd==NULL || sd->pd==NULL)
return true;
-
+
max=script_getnum(st,2);
-
+
if(max < 1)
- max = 1; //Let'em loot at least 1 item.
+ max = 1; //Let'em loot at least 1 item.
else if (max > MAX_PETLOOT_SIZE)
max = MAX_PETLOOT_SIZE;
-
+
pd = sd->pd;
- if (pd->loot != NULL)
- { //Release whatever was there already and reallocate memory
- pet_lootitem_drop(pd, pd->msd);
+ if (pd->loot != NULL) {
+ //Release whatever was there already and reallocate memory
+ pet->lootitem_drop(pd, pd->msd);
aFree(pd->loot->item);
}
else
pd->loot = (struct pet_loot *)aMalloc(sizeof(struct pet_loot));
-
+
pd->loot->item = (struct item *)aCalloc(max,sizeof(struct item));
-
+
pd->loot->max=max;
pd->loot->count = 0;
pd->loot->weight = 0;
-
+
return true;
}
/*==========================================
@@ -11682,52 +12317,53 @@ BUILDIN(petloot)
*------------------------------------------*/
BUILDIN(getinventorylist)
{
- TBL_PC *sd=script_rid2sd(st);
+ TBL_PC *sd=script->rid2sd(st);
char card_var[NAME_LENGTH];
-
+
int i,j=0,k;
if(!sd) return true;
- for(i=0;i<MAX_INVENTORY;i++){
- if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0){
- pc->setreg(sd,reference_uid(add_str("@inventorylist_id"), j),sd->status.inventory[i].nameid);
- pc->setreg(sd,reference_uid(add_str("@inventorylist_amount"), j),sd->status.inventory[i].amount);
- pc->setreg(sd,reference_uid(add_str("@inventorylist_equip"), j),sd->status.inventory[i].equip);
- pc->setreg(sd,reference_uid(add_str("@inventorylist_refine"), j),sd->status.inventory[i].refine);
- pc->setreg(sd,reference_uid(add_str("@inventorylist_identify"), j),sd->status.inventory[i].identify);
- pc->setreg(sd,reference_uid(add_str("@inventorylist_attribute"), j),sd->status.inventory[i].attribute);
+ for(i=0;i<MAX_INVENTORY;i++) {
+ if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0) {
+ pc->setreg(sd,reference_uid(script->add_str("@inventorylist_id"), j),sd->status.inventory[i].nameid);
+ pc->setreg(sd,reference_uid(script->add_str("@inventorylist_amount"), j),sd->status.inventory[i].amount);
+ pc->setreg(sd,reference_uid(script->add_str("@inventorylist_equip"), j),sd->status.inventory[i].equip);
+ pc->setreg(sd,reference_uid(script->add_str("@inventorylist_refine"), j),sd->status.inventory[i].refine);
+ pc->setreg(sd,reference_uid(script->add_str("@inventorylist_identify"), j),sd->status.inventory[i].identify);
+ pc->setreg(sd,reference_uid(script->add_str("@inventorylist_attribute"), j),sd->status.inventory[i].attribute);
for (k = 0; k < MAX_SLOTS; k++)
{
sprintf(card_var, "@inventorylist_card%d",k+1);
- pc->setreg(sd,reference_uid(add_str(card_var), j),sd->status.inventory[i].card[k]);
+ pc->setreg(sd,reference_uid(script->add_str(card_var), j),sd->status.inventory[i].card[k]);
}
- pc->setreg(sd,reference_uid(add_str("@inventorylist_expire"), j),sd->status.inventory[i].expire_time);
+ pc->setreg(sd,reference_uid(script->add_str("@inventorylist_expire"), j),sd->status.inventory[i].expire_time);
+ pc->setreg(sd,reference_uid(script->add_str("@inventorylist_bound"), j),sd->status.inventory[i].bound);
j++;
}
}
- pc->setreg(sd,add_str("@inventorylist_count"),j);
+ pc->setreg(sd,script->add_str("@inventorylist_count"),j);
return true;
}
BUILDIN(getskilllist)
{
- TBL_PC *sd=script_rid2sd(st);
+ TBL_PC *sd=script->rid2sd(st);
int i,j=0;
if(!sd) return true;
- for(i=0;i<MAX_SKILL;i++){
- if(sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0){
- pc->setreg(sd,reference_uid(add_str("@skilllist_id"), j),sd->status.skill[i].id);
- pc->setreg(sd,reference_uid(add_str("@skilllist_lv"), j),sd->status.skill[i].lv);
- pc->setreg(sd,reference_uid(add_str("@skilllist_flag"), j),sd->status.skill[i].flag);
+ for(i=0;i<MAX_SKILL;i++) {
+ if(sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0) {
+ pc->setreg(sd,reference_uid(script->add_str("@skilllist_id"), j),sd->status.skill[i].id);
+ pc->setreg(sd,reference_uid(script->add_str("@skilllist_lv"), j),sd->status.skill[i].lv);
+ pc->setreg(sd,reference_uid(script->add_str("@skilllist_flag"), j),sd->status.skill[i].flag);
j++;
}
}
- pc->setreg(sd,add_str("@skilllist_count"),j);
+ pc->setreg(sd,script->add_str("@skilllist_count"),j);
return true;
}
BUILDIN(clearitem)
{
- TBL_PC *sd=script_rid2sd(st);
+ TBL_PC *sd=script->rid2sd(st);
int i;
if(sd==NULL) return true;
for (i=0; i<MAX_INVENTORY; i++) {
@@ -11744,17 +12380,17 @@ BUILDIN(clearitem)
BUILDIN(disguise)
{
int id;
- TBL_PC* sd = script_rid2sd(st);
+ TBL_PC* sd = script->rid2sd(st);
if (sd == NULL) return true;
-
+
id = script_getnum(st,2);
-
- if (mobdb_checkid(id) || npcdb_checkid(id)) {
+
+ if (mob->db_checkid(id) || npcdb_checkid(id)) {
pc->disguise(sd, id);
script_pushint(st,id);
} else
script_pushint(st,0);
-
+
return true;
}
@@ -11763,9 +12399,9 @@ BUILDIN(disguise)
*------------------------------------------*/
BUILDIN(undisguise)
{
- TBL_PC* sd = script_rid2sd(st);
+ TBL_PC* sd = script->rid2sd(st);
if (sd == NULL) return true;
-
+
if (sd->disguise != -1) {
pc->disguise(sd, -1);
script_pushint(st,0);
@@ -11776,19 +12412,18 @@ BUILDIN(undisguise)
}
/*==========================================
- * Transform a bl to another _class,
+ * Transform a bl to another class,
* @type unused
*------------------------------------------*/
-BUILDIN(classchange)
-{
- int _class,type;
- struct block_list *bl=iMap->id2bl(st->oid);
-
+BUILDIN(classchange) {
+ int class_,type;
+ struct block_list *bl=map->id2bl(st->oid);
+
if(bl==NULL) return true;
-
- _class=script_getnum(st,2);
+
+ class_=script_getnum(st,2);
type=script_getnum(st,3);
- clif->class_change(bl,_class,type);
+ clif->class_change(bl,class_,type);
return true;
}
@@ -11798,14 +12433,14 @@ BUILDIN(classchange)
BUILDIN(misceffect)
{
int type;
-
+
type=script_getnum(st,2);
- if(st->oid && st->oid != fake_nd->bl.id) {
- struct block_list *bl = iMap->id2bl(st->oid);
+ if(st->oid && st->oid != npc->fake_nd->bl.id) {
+ struct block_list *bl = map->id2bl(st->oid);
if (bl)
clif->specialeffect(bl,type,AREA);
- } else{
- TBL_PC *sd=script_rid2sd(st);
+ } else {
+ TBL_PC *sd=script->rid2sd(st);
if(sd)
clif->specialeffect(&sd->bl,type,AREA);
}
@@ -11814,34 +12449,34 @@ BUILDIN(misceffect)
/*==========================================
* Play a BGM on a single client [Rikter/Yommy]
*------------------------------------------*/
-BUILDIN(playBGM)
+BUILDIN(playbgm)
{
const char* name;
struct map_session_data* sd;
-
- if( ( sd = script_rid2sd(st) ) != NULL )
+
+ if( ( sd = script->rid2sd(st) ) != NULL )
{
name = script_getstr(st,2);
-
+
clif->playBGM(sd, name);
}
-
+
return true;
}
-static int playBGM_sub(struct block_list* bl,va_list ap)
+int playbgm_sub(struct block_list* bl,va_list ap)
{
const char* name = va_arg(ap,const char*);
-
+
clif->playBGM(BL_CAST(BL_PC, bl), name);
-
+
return 0;
}
-static int playBGM_foreachpc_sub(struct map_session_data* sd, va_list args)
+int playbgm_foreachpc_sub(struct map_session_data* sd, va_list args)
{
const char* name = va_arg(args, const char*);
-
+
clif->playBGM(sd, name);
return 0;
}
@@ -11849,33 +12484,42 @@ static int playBGM_foreachpc_sub(struct map_session_data* sd, va_list args)
/*==========================================
* Play a BGM on multiple client [Rikter/Yommy]
*------------------------------------------*/
-BUILDIN(playBGMall)
-{
+BUILDIN(playbgmall) {
const char* name;
-
+
name = script_getstr(st,2);
-
- if( script_hasdata(st,7) )
- {// specified part of map
- const char* map = script_getstr(st,3);
+
+ if( script_hasdata(st,7) ) {
+ // specified part of map
+ const char *mapname = script_getstr(st,3);
int x0 = script_getnum(st,4);
int y0 = script_getnum(st,5);
int x1 = script_getnum(st,6);
int y1 = script_getnum(st,7);
-
- iMap->foreachinarea(playBGM_sub, iMap->mapname2mapid(map), x0, y0, x1, y1, BL_PC, name);
- }
- else if( script_hasdata(st,3) )
- {// entire map
- const char* map = script_getstr(st,3);
-
- iMap->foreachinmap(playBGM_sub, iMap->mapname2mapid(map), BL_PC, name);
- }
- else
- {// entire server
- iMap->map_foreachpc(&playBGM_foreachpc_sub, name);
+ int m;
+
+ if ( ( m = map->mapname2mapid(mapname) ) == -1 ) {
+ ShowWarning("playbgmall: Attempted to play song '%s' on non-existent map '%s'\n",name, mapname);
+ return true;
+ }
+
+ map->foreachinarea(script->playbgm_sub, m, x0, y0, x1, y1, BL_PC, name);
+ } else if( script_hasdata(st,3) ) {
+ // entire map
+ const char* mapname = script_getstr(st,3);
+ int m;
+
+ if ( ( m = map->mapname2mapid(mapname) ) == -1 ) {
+ ShowWarning("playbgmall: Attempted to play song '%s' on non-existent map '%s'\n",name, mapname);
+ return true;
+ }
+
+ map->foreachinmap(script->playbgm_sub, m, BL_PC, name);
+ } else {
+ // entire server
+ map->foreachpc(script->playbgm_foreachpc_sub, name);
}
-
+
return true;
}
@@ -11884,10 +12528,10 @@ BUILDIN(playBGMall)
*------------------------------------------*/
BUILDIN(soundeffect)
{
- TBL_PC* sd = script_rid2sd(st);
+ TBL_PC* sd = script->rid2sd(st);
const char* name = script_getstr(st,2);
int type = script_getnum(st,3);
-
+
if(sd)
{
clif->soundeffect(sd,&sd->bl,name,type);
@@ -11899,9 +12543,9 @@ int soundeffect_sub(struct block_list* bl,va_list ap)
{
char* name = va_arg(ap,char*);
int type = va_arg(ap,int);
-
+
clif->soundeffect((TBL_PC *)bl, bl, name, type);
-
+
return true;
}
@@ -11909,46 +12553,52 @@ int soundeffect_sub(struct block_list* bl,va_list ap)
* Play a sound effect (.wav) on multiple clients
* soundeffectall "<filepath>",<type>{,"<map name>"}{,<x0>,<y0>,<x1>,<y1>};
*------------------------------------------*/
-BUILDIN(soundeffectall)
-{
+BUILDIN(soundeffectall) {
struct block_list* bl;
const char* name;
int type;
-
- bl = (st->rid) ? &(script_rid2sd(st)->bl) : iMap->id2bl(st->oid);
+
+ bl = (st->rid) ? &(script->rid2sd(st)->bl) : map->id2bl(st->oid);
if (!bl)
return true;
-
+
name = script_getstr(st,2);
type = script_getnum(st,3);
-
- //FIXME: enumerating map squares (iMap->foreach) is slower than enumerating the list of online players (iMap->foreachpc?) [ultramage]
-
- if(!script_hasdata(st,4))
- { // area around
+
+ //FIXME: enumerating map squares (map->foreach) is slower than enumerating the list of online players (map->foreachpc?) [ultramage]
+
+ if(!script_hasdata(st,4)) { // area around
clif->soundeffectall(bl, name, type, AREA);
- }
- else
- if(!script_hasdata(st,5))
- { // entire map
- const char* map = script_getstr(st,4);
- iMap->foreachinmap(soundeffect_sub, iMap->mapname2mapid(map), BL_PC, name, type);
- }
- else
- if(script_hasdata(st,8))
- { // specified part of map
- const char* map = script_getstr(st,4);
- int x0 = script_getnum(st,5);
- int y0 = script_getnum(st,6);
- int x1 = script_getnum(st,7);
- int y1 = script_getnum(st,8);
- iMap->foreachinarea(soundeffect_sub, iMap->mapname2mapid(map), x0, y0, x1, y1, BL_PC, name, type);
+ } else {
+ if(!script_hasdata(st,5)) { // entire map
+ const char *mapname = script_getstr(st,4);
+ int m;
+
+ if ( ( m = map->mapname2mapid(mapname) ) == -1 ) {
+ ShowWarning("soundeffectall: Attempted to play song '%s' (type %d) on non-existent map '%s'\n",name,type, mapname);
+ return true;
}
- else
- {
- ShowError("buildin_soundeffectall: insufficient arguments for specific area broadcast.\n");
+
+ map->foreachinmap(script->soundeffect_sub, m, BL_PC, name, type);
+ } else if(script_hasdata(st,8)) { // specified part of map
+ const char *mapname = script_getstr(st,4);
+ int x0 = script_getnum(st,5);
+ int y0 = script_getnum(st,6);
+ int x1 = script_getnum(st,7);
+ int y1 = script_getnum(st,8);
+ int m;
+
+ if ( ( m = map->mapname2mapid(mapname) ) == -1 ) {
+ ShowWarning("soundeffectall: Attempted to play song '%s' (type %d) on non-existent map '%s'\n",name,type, mapname);
+ return true;
}
-
+
+ map->foreachinarea(script->soundeffect_sub, m, x0, y0, x1, y1, BL_PC, name, type);
+ } else {
+ ShowError("buildin_soundeffectall: insufficient arguments for specific area broadcast.\n");
+ }
+ }
+
return true;
}
/*==========================================
@@ -11957,24 +12607,24 @@ BUILDIN(soundeffectall)
BUILDIN(petrecovery)
{
struct pet_data *pd;
- TBL_PC *sd=script_rid2sd(st);
-
+ TBL_PC *sd=script->rid2sd(st);
+
if(sd==NULL || sd->pd==NULL)
return true;
-
+
pd=sd->pd;
-
+
if (pd->recovery)
{ //Halt previous bonus
if (pd->recovery->timer != INVALID_TIMER)
- iTimer->delete_timer(pd->recovery->timer, pet_recovery_timer);
+ timer->delete(pd->recovery->timer, pet->recovery_timer);
} else //Init
pd->recovery = (struct pet_recovery *)aMalloc(sizeof(struct pet_recovery));
-
+
pd->recovery->type = (sc_type)script_getnum(st,2);
pd->recovery->delay = script_getnum(st,3);
pd->recovery->timer = INVALID_TIMER;
-
+
return true;
}
@@ -11984,37 +12634,37 @@ BUILDIN(petrecovery)
BUILDIN(petheal)
{
struct pet_data *pd;
- TBL_PC *sd=script_rid2sd(st);
-
+ TBL_PC *sd=script->rid2sd(st);
+
if(sd==NULL || sd->pd==NULL)
return true;
-
+
pd=sd->pd;
if (pd->s_skill)
{ //Clear previous skill
if (pd->s_skill->timer != INVALID_TIMER)
{
if (pd->s_skill->id)
- iTimer->delete_timer(pd->s_skill->timer, pet_skill_support_timer);
+ timer->delete(pd->s_skill->timer, pet->skill_support_timer);
else
- iTimer->delete_timer(pd->s_skill->timer, pet_heal_timer);
+ timer->delete(pd->s_skill->timer, pet->heal_timer);
}
} else //init memory
pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support));
-
+
pd->s_skill->id=0; //This id identifies that it IS petheal rather than pet_skillsupport
//Use the lv as the amount to heal
pd->s_skill->lv=script_getnum(st,2);
pd->s_skill->delay=script_getnum(st,3);
pd->s_skill->hp=script_getnum(st,4);
pd->s_skill->sp=script_getnum(st,5);
-
+
//Use delay as initial offset to avoid skill/heal exploits
if (battle_config.pet_equip_required && pd->pet.equip == 0)
pd->s_skill->timer = INVALID_TIMER;
else
- pd->s_skill->timer = iTimer->add_timer(iTimer->gettick()+pd->s_skill->delay*1000,pet_heal_timer,sd->bl.id,0);
-
+ pd->s_skill->timer = timer->add(timer->gettick()+pd->s_skill->delay*1000,pet->heal_timer,sd->bl.id,0);
+
return true;
}
@@ -12023,24 +12673,23 @@ BUILDIN(petheal)
*------------------------------------------*/
/// petskillattack <skill id>,<level>,<rate>,<bonusrate>
/// petskillattack "<skill name>",<level>,<rate>,<bonusrate>
-BUILDIN(petskillattack)
-{
+BUILDIN(petskillattack) {
struct pet_data *pd;
- TBL_PC *sd=script_rid2sd(st);
-
+ TBL_PC *sd=script->rid2sd(st);
+
if(sd==NULL || sd->pd==NULL)
return true;
-
+
pd=sd->pd;
if (pd->a_skill == NULL)
pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack));
-
- pd->a_skill->id=( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
+
+ pd->a_skill->id=( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
pd->a_skill->lv=script_getnum(st,3);
pd->a_skill->div_ = 0;
pd->a_skill->rate=script_getnum(st,4);
pd->a_skill->bonusrate=script_getnum(st,5);
-
+
return true;
}
@@ -12049,24 +12698,23 @@ BUILDIN(petskillattack)
*------------------------------------------*/
/// petskillattack2 <skill id>,<level>,<div>,<rate>,<bonusrate>
/// petskillattack2 "<skill name>",<level>,<div>,<rate>,<bonusrate>
-BUILDIN(petskillattack2)
-{
+BUILDIN(petskillattack2) {
struct pet_data *pd;
- TBL_PC *sd=script_rid2sd(st);
-
+ TBL_PC *sd=script->rid2sd(st);
+
if(sd==NULL || sd->pd==NULL)
return true;
-
+
pd=sd->pd;
if (pd->a_skill == NULL)
pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack));
-
- pd->a_skill->id=( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
+
+ pd->a_skill->id=( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
pd->a_skill->lv=script_getnum(st,3);
pd->a_skill->div_ = script_getnum(st,4);
pd->a_skill->rate=script_getnum(st,5);
pd->a_skill->bonusrate=script_getnum(st,6);
-
+
return true;
}
@@ -12075,39 +12723,38 @@ BUILDIN(petskillattack2)
*------------------------------------------*/
/// petskillsupport <skill id>,<level>,<delay>,<hp>,<sp>
/// petskillsupport "<skill name>",<level>,<delay>,<hp>,<sp>
-BUILDIN(petskillsupport)
-{
+BUILDIN(petskillsupport) {
struct pet_data *pd;
- TBL_PC *sd=script_rid2sd(st);
-
+ TBL_PC *sd=script->rid2sd(st);
+
if(sd==NULL || sd->pd==NULL)
return true;
-
+
pd=sd->pd;
if (pd->s_skill)
{ //Clear previous skill
if (pd->s_skill->timer != INVALID_TIMER)
{
if (pd->s_skill->id)
- iTimer->delete_timer(pd->s_skill->timer, pet_skill_support_timer);
+ timer->delete(pd->s_skill->timer, pet->skill_support_timer);
else
- iTimer->delete_timer(pd->s_skill->timer, pet_heal_timer);
+ timer->delete(pd->s_skill->timer, pet->heal_timer);
}
} else //init memory
pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support));
-
- pd->s_skill->id=( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
+
+ pd->s_skill->id=( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
pd->s_skill->lv=script_getnum(st,3);
pd->s_skill->delay=script_getnum(st,4);
pd->s_skill->hp=script_getnum(st,5);
pd->s_skill->sp=script_getnum(st,6);
-
+
//Use delay as initial offset to avoid skill/heal exploits
if (battle_config.pet_equip_required && pd->pet.equip == 0)
pd->s_skill->timer = INVALID_TIMER;
else
- pd->s_skill->timer = iTimer->add_timer(iTimer->gettick()+pd->s_skill->delay*1000,pet_skill_support_timer,sd->bl.id,0);
-
+ pd->s_skill->timer = timer->add(timer->gettick()+pd->s_skill->delay*1000,pet->skill_support_timer,sd->bl.id,0);
+
return true;
}
@@ -12116,16 +12763,25 @@ BUILDIN(petskillsupport)
*------------------------------------------*/
/// skilleffect <skill id>,<level>
/// skilleffect "<skill name>",<level>
-BUILDIN(skilleffect)
-{
+BUILDIN(skilleffect) {
TBL_PC *sd;
-
- uint16 skill_id=( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
+
+ uint16 skill_id=( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
uint16 skill_lv=script_getnum(st,3);
- sd=script_rid2sd(st);
-
+ sd=script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
+ /* ensure we're standing because the following packet causes the client to virtually set the char to stand,
+ * which leaves the server thinking it still is sitting. */
+ if( pc_issit(sd) ) {
+ pc->setstand(sd);
+ skill->sit(sd,0);
+ clif->standing(&sd->bl);
+ }
clif->skill_nodamage(&sd->bl,&sd->bl,skill_id,skill_lv,1);
-
+
return true;
}
@@ -12134,65 +12790,64 @@ BUILDIN(skilleffect)
*------------------------------------------*/
/// npcskilleffect <skill id>,<level>,<x>,<y>
/// npcskilleffect "<skill name>",<level>,<x>,<y>
-BUILDIN(npcskilleffect)
-{
- struct block_list *bl= iMap->id2bl(st->oid);
-
- uint16 skill_id=( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
+BUILDIN(npcskilleffect) {
+ struct block_list *bl= map->id2bl(st->oid);
+
+ uint16 skill_id=( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
uint16 skill_lv=script_getnum(st,3);
int x=script_getnum(st,4);
int y=script_getnum(st,5);
-
+
if (bl)
- clif->skill_poseffect(bl,skill_id,skill_lv,x,y,iTimer->gettick());
-
+ clif->skill_poseffect(bl,skill_id,skill_lv,x,y,timer->gettick());
+
return true;
}
/*==========================================
* Special effects [Valaris]
*------------------------------------------*/
-BUILDIN(specialeffect)
-{
- struct block_list *bl=iMap->id2bl(st->oid);
+BUILDIN(specialeffect) {
+ struct block_list *bl=map->id2bl(st->oid);
int type = script_getnum(st,2);
enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA;
-
+
if(bl==NULL)
return true;
-
+
if( script_hasdata(st,4) )
{
- TBL_NPC *nd = npc_name2id(script_getstr(st,4));
+ TBL_NPC *nd = npc->name2id(script_getstr(st,4));
if(nd)
clif->specialeffect(&nd->bl, type, target);
}
else
{
if (target == SELF) {
- TBL_PC *sd=script_rid2sd(st);
+ TBL_PC *sd=script->rid2sd(st);
if (sd)
clif->specialeffect_single(bl,type,sd->fd);
} else {
clif->specialeffect(bl, type, target);
}
}
-
+
return true;
}
-BUILDIN(specialeffect2)
-{
- TBL_PC *sd=script_rid2sd(st);
+BUILDIN(specialeffect2) {
+ TBL_PC *sd;
int type = script_getnum(st,2);
enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA;
-
+
if( script_hasdata(st,4) )
- sd = iMap->nick2sd(script_getstr(st,4));
-
+ sd = map->nick2sd(script_getstr(st,4));
+ else
+ sd = script->rid2sd(st);
+
if (sd)
clif->specialeffect(&sd->bl, type, target);
-
+
return true;
}
@@ -12201,12 +12856,12 @@ BUILDIN(specialeffect2)
*------------------------------------------*/
BUILDIN(nude)
{
- TBL_PC *sd = script_rid2sd(st);
+ TBL_PC *sd = script->rid2sd(st);
int i, calcflag = 0;
-
+
if( sd == NULL )
return true;
-
+
for( i = 0 ; i < EQI_MAX; i++ ) {
if( sd->equip_index[ i ] >= 0 ) {
if( !calcflag )
@@ -12214,49 +12869,48 @@ BUILDIN(nude)
pc->unequipitem( sd , sd->equip_index[ i ] , 2);
}
}
-
+
if( calcflag )
- status_calc_pc(sd,0);
-
+ status_calc_pc(sd,SCO_NONE);
+
return true;
}
/*==========================================
* gmcommand [MouseJstr]
*------------------------------------------*/
-BUILDIN(atcommand)
-{
- TBL_PC dummy_sd;
- TBL_PC* sd;
+BUILDIN(atcommand) {
+ TBL_PC *sd, *dummy_sd = NULL;
int fd;
const char* cmd;
-
+ bool ret = true;
+
cmd = script_getstr(st,2);
-
+
if (st->rid) {
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
+ if( sd == NULL )
+ return false;
fd = sd->fd;
} else { //Use a dummy character.
- sd = &dummy_sd;
+ sd = dummy_sd = pc->get_dummy_sd();
fd = 0;
-
- memset(&dummy_sd, 0, sizeof(TBL_PC));
- if (st->oid)
- {
- struct block_list* bl = iMap->id2bl(st->oid);
- memcpy(&dummy_sd.bl, bl, sizeof(struct block_list));
+
+ if (st->oid) {
+ struct block_list* bl = map->id2bl(st->oid);
+ memcpy(&sd->bl, bl, sizeof(struct block_list));
if (bl->type == BL_NPC)
- safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
+ safestrncpy(sd->status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
}
}
-
- if (!atcommand->parse(fd, sd, cmd, 0)) {
+
+ if (!atcommand->exec(fd, sd, cmd, false)) {
ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd);
- script_reportsrc(st);
- return false;
+ script->reportsrc(st);
+ ret = false;
}
-
- return true;
+ if (dummy_sd) aFree(dummy_sd);
+ return ret;
}
/*==========================================
@@ -12264,11 +12918,11 @@ BUILDIN(atcommand)
*------------------------------------------*/
BUILDIN(dispbottom)
{
- TBL_PC *sd=script_rid2sd(st);
+ TBL_PC *sd=script->rid2sd(st);
const char *message;
message=script_getstr(st,2);
if(sd)
- clif->disp_onlyself(sd,message,(int)strlen(message));
+ clif_disp_onlyself(sd,message,(int)strlen(message));
return true;
}
@@ -12280,15 +12934,15 @@ BUILDIN(recovery)
{
TBL_PC* sd;
struct s_mapiterator* iter;
-
+
iter = mapit_getallusers();
for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) )
{
if(pc_isdead(sd))
- status_revive(&sd->bl, 100, 100);
+ status->revive(&sd->bl, 100, 100);
else
status_percent_heal(&sd->bl, 100, 100);
- clif->message(sd->fd,msg_txt(680));
+ clif->message(sd->fd,msg_txt(880)); // "You have been recovered!"
}
mapit->free(iter);
return true;
@@ -12300,10 +12954,10 @@ BUILDIN(recovery)
*------------------------------------------*/
BUILDIN(getpetinfo)
{
- TBL_PC *sd=script_rid2sd(st);
+ TBL_PC *sd=script->rid2sd(st);
TBL_PET *pd;
int type=script_getnum(st,2);
-
+
if(!sd || !sd->pd) {
if (type == 2)
script_pushconststr(st,"null");
@@ -12312,7 +12966,7 @@ BUILDIN(getpetinfo)
return true;
}
pd = sd->pd;
- switch(type){
+ switch(type) {
case 0: script_pushint(st,pd->pet.pet_id); break;
case 1: script_pushint(st,pd->pet.class_); break;
case 2: script_pushstrcopy(st,pd->pet.name); break;
@@ -12334,28 +12988,25 @@ BUILDIN(getpetinfo)
*------------------------------------------*/
BUILDIN(gethominfo)
{
- TBL_PC *sd=script_rid2sd(st);
- TBL_HOM *hd;
- int type=script_getnum(st,2);
-
- hd = sd?sd->hd:NULL;
- if(!homun_alive(hd))
- {
+ TBL_PC *sd=script->rid2sd(st);
+ int type = script_getnum(st,2);
+
+ if(!sd || !sd->hd) {
if (type == 2)
script_pushconststr(st,"null");
else
script_pushint(st,0);
return true;
}
-
- switch(type){
- case 0: script_pushint(st,hd->homunculus.hom_id); break;
- case 1: script_pushint(st,hd->homunculus.class_); break;
- case 2: script_pushstrcopy(st,hd->homunculus.name); break;
- case 3: script_pushint(st,hd->homunculus.intimacy); break;
- case 4: script_pushint(st,hd->homunculus.hunger); break;
- case 5: script_pushint(st,hd->homunculus.rename_flag); break;
- case 6: script_pushint(st,hd->homunculus.level); break;
+
+ switch(type) {
+ case 0: script_pushint(st,sd->hd->homunculus.hom_id); break;
+ case 1: script_pushint(st,sd->hd->homunculus.class_); break;
+ case 2: script_pushstrcopy(st,sd->hd->homunculus.name); break;
+ case 3: script_pushint(st,sd->hd->homunculus.intimacy); break;
+ case 4: script_pushint(st,sd->hd->homunculus.hunger); break;
+ case 5: script_pushint(st,sd->hd->homunculus.rename_flag); break;
+ case 6: script_pushint(st,sd->hd->homunculus.level); break;
default:
script_pushint(st,0);
break;
@@ -12365,36 +13016,28 @@ BUILDIN(gethominfo)
/// Retrieves information about character's mercenary
/// getmercinfo <type>[,<char id>];
-BUILDIN(getmercinfo)
-{
+BUILDIN(getmercinfo) {
int type, char_id;
struct map_session_data* sd;
struct mercenary_data* md;
-
+
type = script_getnum(st,2);
-
- if( script_hasdata(st,3) )
- {
+
+ if( script_hasdata(st,3) ) {
char_id = script_getnum(st,3);
-
- if( ( sd = iMap->charid2sd(char_id) ) == NULL )
- {
+
+ if( ( sd = map->charid2sd(char_id) ) == NULL ) {
ShowError("buildin_getmercinfo: No such character (char_id=%d).\n", char_id);
script_pushnil(st);
return false;
}
- }
- else
- {
- if( ( sd = script_rid2sd(st) ) == NULL )
- {
- script_pushnil(st);
+ } else {
+ if( ( sd = script->rid2sd(st) ) == NULL )
return true;
- }
}
-
+
md = ( sd->status.mer_id && sd->md ) ? sd->md : NULL;
-
+
switch( type )
{
case 0: script_pushint(st,md ? md->mercenary.mercenary_id : 0); break;
@@ -12405,46 +13048,48 @@ BUILDIN(getmercinfo)
else
script_pushconststr(st,"");
break;
- case 3: script_pushint(st,md ? mercenary_get_faith(md) : 0); break;
- case 4: script_pushint(st,md ? mercenary_get_calls(md) : 0); break;
+ case 3: script_pushint(st,md ? mercenary->get_faith(md) : 0); break;
+ case 4: script_pushint(st,md ? mercenary->get_calls(md) : 0); break;
case 5: script_pushint(st,md ? md->mercenary.kill_count : 0); break;
- case 6: script_pushint(st,md ? mercenary_get_lifetime(md) : 0); break;
+ case 6: script_pushint(st,md ? mercenary->get_lifetime(md) : 0); break;
case 7: script_pushint(st,md ? md->db->lv : 0); break;
default:
ShowError("buildin_getmercinfo: Invalid type %d (char_id=%d).\n", type, sd->status.char_id);
script_pushnil(st);
return false;
}
-
+
return true;
}
/*==========================================
* Shows wether your inventory(and equips) contain
- selected card or not.
- checkequipedcard(4001);
+ * selected card or not.
+ * checkequipedcard(4001);
*------------------------------------------*/
BUILDIN(checkequipedcard)
{
- TBL_PC *sd=script_rid2sd(st);
-
- if(sd){
- int n,i,c=0;
- c=script_getnum(st,2);
-
- for(i=0;i<MAX_INVENTORY;i++){
- if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount && sd->inventory_data[i]){
- if (itemdb_isspecial(sd->status.inventory[i].card[0]))
- continue;
- for(n=0;n<sd->inventory_data[i]->slot;n++){
- if(sd->status.inventory[i].card[n]==c){
- script_pushint(st,1);
- return true;
- }
+ int n,i,c=0;
+ TBL_PC *sd=script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
+ c = script_getnum(st,2);
+
+ for( i=0; i<MAX_INVENTORY; i++) {
+ if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount && sd->inventory_data[i]) {
+ if (itemdb_isspecial(sd->status.inventory[i].card[0]))
+ continue;
+ for(n=0;n<sd->inventory_data[i]->slot;n++) {
+ if(sd->status.inventory[i].card[n]==c) {
+ script_pushint(st,1);
+ return true;
}
}
}
}
+
script_pushint(st,0);
return true;
}
@@ -12455,12 +13100,12 @@ BUILDIN(jump_zero)
sel=script_getnum(st,2);
if(!sel) {
int pos;
- if( !data_islabel(script_getdata(st,3)) ){
+ if( !data_islabel(script_getdata(st,3)) ) {
ShowError("script: jump_zero: not label !\n");
st->state=END;
return false;
}
-
+
pos=script_getnum(st,3);
st->pos=pos;
st->state=GOTO;
@@ -12473,51 +13118,49 @@ BUILDIN(jump_zero)
*------------------------------------------*/
BUILDIN(movenpc) {
TBL_NPC *nd = NULL;
- const char *npc;
+ const char *npc_name;
int x,y;
-
- npc = script_getstr(st,2);
+
+ npc_name = script_getstr(st,2);
x = script_getnum(st,3);
y = script_getnum(st,4);
-
- if ((nd = npc_name2id(npc)) == NULL)
+
+ if ((nd = npc->name2id(npc_name)) == NULL)
return -1;
-
+
if (script_hasdata(st,5))
nd->dir = script_getnum(st,5) % 8;
- npc_movenpc(nd, x, y);
+ npc->movenpc(nd, x, y);
return true;
}
/*==========================================
* message [MouseJstr]
*------------------------------------------*/
-BUILDIN(message)
-{
+BUILDIN(message) {
const char *msg,*player;
TBL_PC *pl_sd = NULL;
-
+
player = script_getstr(st,2);
msg = script_getstr(st,3);
-
- if((pl_sd=iMap->nick2sd((char *) player)) == NULL)
+
+ if((pl_sd=map->nick2sd((char *) player)) == NULL)
return true;
clif->message(pl_sd->fd, msg);
-
+
return true;
}
/*==========================================
* npctalk (sends message to surrounding area)
*------------------------------------------*/
-BUILDIN(npctalk)
-{
+BUILDIN(npctalk) {
const char* str;
char name[NAME_LENGTH], message[256];
-
- struct npc_data* nd = (struct npc_data *)iMap->id2bl(st->oid);
+
+ struct npc_data* nd = (struct npc_data *)map->id2bl(st->oid);
str = script_getstr(st,2);
-
+
if(nd)
{
safestrncpy(name, nd->name, sizeof(name));
@@ -12525,65 +13168,55 @@ BUILDIN(npctalk)
safesnprintf(message, sizeof(message), "%s : %s", name, str);
clif->disp_overhead(&nd->bl, message);
}
-
+
return true;
}
// change npc walkspeed [Valaris]
-BUILDIN(npcspeed)
-{
+BUILDIN(npcspeed) {
struct npc_data* nd;
int speed;
-
+
speed = script_getnum(st,2);
- nd =(struct npc_data *)iMap->id2bl(st->oid);
-
+ nd = (struct npc_data *)map->id2bl(st->oid);
+
if( nd ) {
- if( nd->ud == &npc_base_ud ) {
- nd->ud = NULL;
- CREATE(nd->ud, struct unit_data, 1);
- unit_dataset(&nd->bl);
- }
+ unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit
nd->speed = speed;
nd->ud->state.speed_changed = 1;
}
-
+
return true;
}
// make an npc walk to a position [Valaris]
BUILDIN(npcwalkto) {
- struct npc_data *nd=(struct npc_data *)iMap->id2bl(st->oid);
+ struct npc_data *nd=(struct npc_data *)map->id2bl(st->oid);
int x=0,y=0;
-
+
x=script_getnum(st,2);
y=script_getnum(st,3);
-
- if(nd) {
- if( nd->ud == &npc_base_ud ) {
- nd->ud = NULL;
- CREATE(nd->ud, struct unit_data, 1);
- unit_dataset(&nd->bl);
- }
-
+
+ if( nd ) {
+ unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit
if (!nd->status.hp) {
- status_calc_npc(nd, true);
+ status_calc_npc(nd, SCO_FIRST);
} else {
- status_calc_npc(nd, false);
+ status_calc_npc(nd, SCO_NONE);
}
- unit_walktoxy(&nd->bl,x,y,0);
+ unit->walktoxy(&nd->bl,x,y,0);
}
-
+
return true;
}
// stop an npc's movement [Valaris]
-BUILDIN(npcstop)
-{
- struct npc_data *nd=(struct npc_data *)iMap->id2bl(st->oid);
-
- if(nd) {
- unit_stop_walking(&nd->bl,1|4);
+BUILDIN(npcstop) {
+ struct npc_data *nd = (struct npc_data *)map->id2bl(st->oid);
+
+ if( nd ) {
+ unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit
+ unit->stop_walking(&nd->bl,1|4);
}
-
+
return true;
}
@@ -12595,23 +13228,25 @@ BUILDIN(getlook)
{
int type,val;
TBL_PC *sd;
- sd=script_rid2sd(st);
-
+ sd=script->rid2sd(st);
+ if( sd == NULL )
+ return false;
+
type=script_getnum(st,2);
- val=-1;
+ val = -1;
switch(type) {
- case LOOK_HAIR: val=sd->status.hair; break; //1
- case LOOK_WEAPON: val=sd->status.weapon; break; //2
- case LOOK_HEAD_BOTTOM: val=sd->status.head_bottom; break; //3
- case LOOK_HEAD_TOP: val=sd->status.head_top; break; //4
- case LOOK_HEAD_MID: val=sd->status.head_mid; break; //5
- case LOOK_HAIR_COLOR: val=sd->status.hair_color; break; //6
- case LOOK_CLOTHES_COLOR:val=sd->status.clothes_color; break; //7
- case LOOK_SHIELD: val=sd->status.shield; break; //8
- case LOOK_SHOES: break; //9
- case LOOK_ROBE: val=sd->status.robe; break; //12
+ case LOOK_HAIR: val = sd->status.hair; break; //1
+ case LOOK_WEAPON: val = sd->status.weapon; break; //2
+ case LOOK_HEAD_BOTTOM: val = sd->status.head_bottom; break; //3
+ case LOOK_HEAD_TOP: val = sd->status.head_top; break; //4
+ case LOOK_HEAD_MID: val = sd->status.head_mid; break; //5
+ case LOOK_HAIR_COLOR: val = sd->status.hair_color; break; //6
+ case LOOK_CLOTHES_COLOR: val = sd->status.clothes_color; break; //7
+ case LOOK_SHIELD: val = sd->status.shield; break; //8
+ case LOOK_SHOES: break; //9
+ case LOOK_ROBE: val = sd->status.robe; break; //12
}
-
+
script_pushint(st,val);
return true;
}
@@ -12623,15 +13258,13 @@ BUILDIN(getsavepoint)
{
TBL_PC* sd;
int type;
-
- sd = script_rid2sd(st);
- if (sd == NULL) {
- script_pushint(st,0);
- return true;
- }
-
+
+ sd = script->rid2sd(st);
+ if( sd == NULL )
+ return false;
+
type = script_getnum(st,2);
-
+
switch(type) {
case 0: script_pushstrcopy(st,mapindex_id2name(sd->status.save_point.map)); break;
case 1: script_pushint(st,sd->status.save_point.x); break;
@@ -12669,88 +13302,106 @@ BUILDIN(getmapxy)
{
struct block_list *bl = NULL;
TBL_PC *sd=NULL;
-
- int num;
+
+ int64 num;
const char *name;
char prefix;
-
+
int x,y,type;
char mapname[MAP_NAME_LENGTH];
-
- if( !data_isreference(script_getdata(st,2)) ){
+
+ if( !data_isreference(script_getdata(st,2)) ) {
ShowWarning("script: buildin_getmapxy: not mapname variable\n");
script_pushint(st,-1);
return false;
}
- if( !data_isreference(script_getdata(st,3)) ){
+ if( !data_isreference(script_getdata(st,3)) ) {
ShowWarning("script: buildin_getmapxy: not mapx variable\n");
script_pushint(st,-1);
return false;
}
- if( !data_isreference(script_getdata(st,4)) ){
+ if( !data_isreference(script_getdata(st,4)) ) {
ShowWarning("script: buildin_getmapxy: not mapy variable\n");
script_pushint(st,-1);
return false;
}
+ if( !is_string_variable(reference_getname(script_getdata(st, 2))) ) {
+ ShowWarning("script: buildin_getmapxy: %s is not a string variable\n",reference_getname(script_getdata(st, 2)));
+ script_pushint(st,-1);
+ return false;
+ }
+
+ if( is_string_variable(reference_getname(script_getdata(st, 3))) ) {
+ ShowWarning("script: buildin_getmapxy: %s is a string variable, should be int\n",reference_getname(script_getdata(st, 3)));
+ script_pushint(st,-1);
+ return false;
+ }
+
+ if( is_string_variable(reference_getname(script_getdata(st, 4))) ) {
+ ShowWarning("script: buildin_getmapxy: %s is a string variable, should be int\n",reference_getname(script_getdata(st, 4)));
+ script_pushint(st,-1);
+ return false;
+ }
+
// Possible needly check function parameters on C_STR,C_INT,C_INT
type=script_getnum(st,5);
-
- switch (type){
- case 0: //Get Character Position
+
+ switch (type) {
+ case 0: //Get Character Position
if( script_hasdata(st,6) )
- sd=iMap->nick2sd(script_getstr(st,6));
+ sd=map->nick2sd(script_getstr(st,6));
else
- sd=script_rid2sd(st);
-
+ sd=script->rid2sd(st);
+
if (sd)
bl = &sd->bl;
break;
- case 1: //Get NPC Position
+ case 1: //Get NPC Position
if( script_hasdata(st,6) )
{
struct npc_data *nd;
- nd=npc_name2id(script_getstr(st,6));
+ nd=npc->name2id(script_getstr(st,6));
if (nd)
bl = &nd->bl;
} else //In case the origin is not an npc?
- bl=iMap->id2bl(st->oid);
+ bl=map->id2bl(st->oid);
break;
- case 2: //Get Pet Position
+ case 2: //Get Pet Position
if(script_hasdata(st,6))
- sd=iMap->nick2sd(script_getstr(st,6));
+ sd=map->nick2sd(script_getstr(st,6));
else
- sd=script_rid2sd(st);
-
+ sd=script->rid2sd(st);
+
if (sd && sd->pd)
bl = &sd->pd->bl;
break;
- case 3: //Get Mob Position
+ case 3: //Get Mob Position
break; //Not supported?
- case 4: //Get Homun Position
+ case 4: //Get Homun Position
if(script_hasdata(st,6))
- sd=iMap->nick2sd(script_getstr(st,6));
+ sd=map->nick2sd(script_getstr(st,6));
else
- sd=script_rid2sd(st);
-
+ sd=script->rid2sd(st);
+
if (sd && sd->hd)
bl = &sd->hd->bl;
break;
case 5: //Get Mercenary Position
if(script_hasdata(st,6))
- sd=iMap->nick2sd(script_getstr(st,6));
+ sd=map->nick2sd(script_getstr(st,6));
else
- sd=script_rid2sd(st);
-
+ sd=script->rid2sd(st);
+
if (sd && sd->md)
bl = &sd->md->bl;
break;
case 6: //Get Elemental Position
if(script_hasdata(st,6))
- sd=iMap->nick2sd(script_getstr(st,6));
+ sd=map->nick2sd(script_getstr(st,6));
else
- sd=script_rid2sd(st);
-
+ sd=script->rid2sd(st);
+
if (sd && sd->ed)
bl = &sd->ed->bl;
break;
@@ -12763,44 +13414,44 @@ BUILDIN(getmapxy)
script_pushint(st,-1);
return true;
}
-
+
x= bl->x;
y= bl->y;
- safestrncpy(mapname, map[bl->m].name, MAP_NAME_LENGTH);
-
+ safestrncpy(mapname, map->list[bl->m].name, MAP_NAME_LENGTH);
+
//Set MapName$
num=st->stack->stack_data[st->start+2].u.num;
- name=get_str(num&0x00ffffff);
+ name=script->get_str(script_getvarid(num));
prefix=*name;
if(not_server_variable(prefix))
- sd=script_rid2sd(st);
+ sd=script->rid2sd(st);
else
sd=NULL;
- set_reg(st,sd,num,name,(void*)mapname,script_getref(st,2));
-
+ script->set_reg(st,sd,num,name,(void*)mapname,script_getref(st,2));
+
//Set MapX
num=st->stack->stack_data[st->start+3].u.num;
- name=get_str(num&0x00ffffff);
+ name=script->get_str(script_getvarid(num));
prefix=*name;
-
+
if(not_server_variable(prefix))
- sd=script_rid2sd(st);
+ sd=script->rid2sd(st);
else
sd=NULL;
- set_reg(st,sd,num,name,(void*)__64BPTRSIZE(x),script_getref(st,3));
-
+ script->set_reg(st,sd,num,name,(void*)h64BPTRSIZE(x),script_getref(st,3));
+
//Set MapY
num=st->stack->stack_data[st->start+4].u.num;
- name=get_str(num&0x00ffffff);
+ name=script->get_str(script_getvarid(num));
prefix=*name;
-
+
if(not_server_variable(prefix))
- sd=script_rid2sd(st);
+ sd=script->rid2sd(st);
else
sd=NULL;
- set_reg(st,sd,num,name,(void*)__64BPTRSIZE(y),script_getref(st,4));
-
+ script->set_reg(st,sd,num,name,(void*)h64BPTRSIZE(y),script_getref(st,4));
+
//Return Success value
script_pushint(st,0);
return true;
@@ -12813,11 +13464,11 @@ BUILDIN(logmes)
{
const char *str;
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return false;
-
+
str = script_getstr(st,2);
logs->npc(sd,str);
return true;
@@ -12825,36 +13476,36 @@ BUILDIN(logmes)
BUILDIN(summon)
{
- int _class, timeout=0;
+ int class_, timeout=0;
const char *str,*event="";
TBL_PC *sd;
struct mob_data *md;
- int tick = iTimer->gettick();
-
- sd=script_rid2sd(st);
+ int64 tick = timer->gettick();
+
+ sd=script->rid2sd(st);
if (!sd) return true;
-
- str =script_getstr(st,2);
- _class=script_getnum(st,3);
+
+ str = script_getstr(st,2);
+ class_ = script_getnum(st,3);
if( script_hasdata(st,4) )
timeout=script_getnum(st,4);
- if( script_hasdata(st,5) ){
+ if( script_hasdata(st,5) ) {
event=script_getstr(st,5);
- check_event(st, event);
+ script->check_event(st, event);
}
-
+
clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick);
-
- md = mob_once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, _class, event, SZ_SMALL, AI_NONE);
+
+ md = mob->once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, class_, event, SZ_MEDIUM, AI_NONE);
if (md) {
md->master_id=sd->bl.id;
md->special_state.ai = AI_ATTACK;
if( md->deletetimer != INVALID_TIMER )
- iTimer->delete_timer(md->deletetimer, mob_timer_delete);
- md->deletetimer = iTimer->add_timer(tick+(timeout>0?timeout*1000:60000),mob_timer_delete,md->bl.id,0);
- mob_spawn (md); //Now it is ready for spawning.
+ timer->delete(md->deletetimer, mob->timer_delete);
+ md->deletetimer = timer->add(tick+(timeout>0?timeout*1000:60000),mob->timer_delete,md->bl.id,0);
+ mob->spawn (md); //Now it is ready for spawning.
clif->specialeffect(&md->bl,344,AREA);
- sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000);
+ sc_start4(NULL, &md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000);
}
return true;
}
@@ -12862,15 +13513,13 @@ BUILDIN(summon)
/*==========================================
* Checks whether it is daytime/nighttime
*------------------------------------------*/
-BUILDIN(isnight)
-{
- script_pushint(st,(iMap->night_flag == 1));
+BUILDIN(isnight) {
+ script_pushint(st,(map->night_flag == 1));
return true;
}
-BUILDIN(isday)
-{
- script_pushint(st,(iMap->night_flag == 0));
+BUILDIN(isday) {
+ script_pushint(st,(map->night_flag == 0));
return true;
}
@@ -12883,18 +13532,16 @@ BUILDIN(isequippedcnt)
TBL_PC *sd;
int i, j, k, id = 1;
int ret = 0;
-
- sd = script_rid2sd(st);
- if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing...
- script_pushint(st,0);
- return true;
- }
-
+
+ sd = script->rid2sd(st);
+ if( sd == NULL )
+ return false;
+
for (i=0; id!=0; i++) {
- FETCH (i+2, id) else id = 0;
+ script_fetch(st,i+2, id);
if (id <= 0)
continue;
-
+
for (j=0; j<EQI_MAX; j++) {
int index;
index = sd->equip_index[j];
@@ -12902,10 +13549,10 @@ BUILDIN(isequippedcnt)
if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue;
if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue;
if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue;
-
+
if(!sd->inventory_data[index])
continue;
-
+
if (itemdb_type(id) != IT_CARD) { //No card. Count amount in inventory.
if (sd->inventory_data[index]->nameid == id)
ret+= sd->status.inventory[index].amount;
@@ -12919,7 +13566,7 @@ BUILDIN(isequippedcnt)
}
}
}
-
+
script_pushint(st,ret);
return true;
}
@@ -12938,18 +13585,16 @@ BUILDIN(isequipped)
int ret = -1;
//Original hash to reverse it when full check fails.
unsigned int setitem_hash = 0, setitem_hash2 = 0;
-
- sd = script_rid2sd(st);
-
- if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing...
- script_pushint(st,0);
- return true;
- }
-
+
+ sd = script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
setitem_hash = sd->bonus.setitem_hash;
setitem_hash2 = sd->bonus.setitem_hash2;
for (i=0; id!=0; i++) {
- FETCH (i+2, id) else id = 0;
+ script_fetch(st,i+2, id);
if (id <= 0)
continue;
flag = 0;
@@ -12959,10 +13604,10 @@ BUILDIN(isequipped)
if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue;
if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue;
if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue;
-
+
if(!sd->inventory_data[index])
continue;
-
+
if (itemdb_type(id) != IT_CARD) {
if (sd->inventory_data[index]->nameid != id)
continue;
@@ -12972,18 +13617,18 @@ BUILDIN(isequipped)
if (sd->inventory_data[index]->slot == 0 ||
itemdb_isspecial(sd->status.inventory[index].card[0]))
continue;
-
- for (k = 0; k < sd->inventory_data[index]->slot; k++)
- { //New hash system which should support up to 4 slots on any equipment. [Skotlex]
+
+ for (k = 0; k < sd->inventory_data[index]->slot; k++) {
+ //New hash system which should support up to 4 slots on any equipment. [Skotlex]
unsigned int hash = 0;
if (sd->status.inventory[index].card[k] != id)
continue;
-
+
hash = 1<<((j<5?j:j-5)*4 + k);
// check if card is already used by another set
if ( ( j < 5 ? sd->bonus.setitem_hash : sd->bonus.setitem_hash2 ) & hash)
continue;
-
+
// We have found a match
flag = 1;
// Set hash so this card cannot be used by another
@@ -13014,26 +13659,28 @@ BUILDIN(isequipped)
* Check how many given inserted cards in the CURRENT
* weapon - used for 2/15's cards patch [Lupus]
*------------------------------------------------*/
-BUILDIN(cardscnt)
-{
+BUILDIN(cardscnt) {
TBL_PC *sd;
int i, k, id = 1;
int ret = 0;
int index;
-
- sd = script_rid2sd(st);
-
+
+ sd = script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
for (i=0; id!=0; i++) {
- FETCH (i+2, id) else id = 0;
+ script_fetch(st,i+2, id);
if (id <= 0)
continue;
-
- index = current_equip_item_index; //we get CURRENT WEAPON inventory index from status.c [Lupus]
+
+ index = status->current_equip_item_index; //we get CURRENT WEAPON inventory index from status.c [Lupus]
if(index < 0) continue;
-
+
if(!sd->inventory_data[index])
continue;
-
+
if(itemdb_type(id) != IT_CARD) {
if (sd->inventory_data[index]->nameid == id)
ret+= sd->status.inventory[index].amount;
@@ -13047,7 +13694,7 @@ BUILDIN(cardscnt)
}
}
script_pushint(st,ret);
- // script_pushint(st,current_equip_item_index);
+ // script_pushint(st,status->current_equip_item_index);
return true;
}
@@ -13055,27 +13702,26 @@ BUILDIN(cardscnt)
* Returns the refined number of the current item, or an
* item with inventory index specified
*-------------------------------------------------------*/
-BUILDIN(getrefine)
-{
+BUILDIN(getrefine) {
TBL_PC *sd;
- if ((sd = script_rid2sd(st))!= NULL)
- script_pushint(st,sd->status.inventory[current_equip_item_index].refine);
- else
- script_pushint(st,0);
+
+ sd = script->rid2sd(st);
+ if( sd == NULL )
+ return false;
+
+ script_pushint(st,sd->status.inventory[status->current_equip_item_index].refine);
return true;
}
/*=======================================================
* Day/Night controls
*-------------------------------------------------------*/
-BUILDIN(night)
-{
- if (iMap->night_flag != 1) pc->map_night_timer(pc->night_timer_tid, 0, 0, 1);
+BUILDIN(night) {
+ if (map->night_flag != 1) pc->map_night_timer(pc->night_timer_tid, 0, 0, 1);
return true;
}
-BUILDIN(day)
-{
- if (iMap->night_flag != 0) pc->map_day_timer(pc->day_timer_tid, 0, 0, 1);
+BUILDIN(day) {
+ if (map->night_flag != 0) pc->map_day_timer(pc->day_timer_tid, 0, 0, 1);
return true;
}
@@ -13087,12 +13733,12 @@ BUILDIN(unequip)
int i;
size_t num;
TBL_PC *sd;
-
+
num = script_getnum(st,2);
- sd = script_rid2sd(st);
- if( sd != NULL && num >= 1 && num <= ARRAYLENGTH(equip) )
+ sd = script->rid2sd(st);
+ if( sd != NULL && num >= 1 && num <= ARRAYLENGTH(script->equip) )
{
- i = pc->checkequip(sd,equip[num-1]);
+ i = pc->checkequip(sd,script->equip[num-1]);
if (i >= 0)
pc->unequipitem(sd,i,1|2);
}
@@ -13104,19 +13750,21 @@ BUILDIN(equip)
int nameid=0,i;
TBL_PC *sd;
struct item_data *item_data;
-
- sd = script_rid2sd(st);
-
+
+ sd = script->rid2sd(st);
+ if( sd == NULL )
+ return false;
+
nameid=script_getnum(st,2);
- if((item_data = itemdb_exists(nameid)) == NULL)
+ if((item_data = itemdb->exists(nameid)) == NULL)
{
ShowError("wrong item ID : equipitem(%i)\n",nameid);
return false;
}
- ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == nameid );
+ ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == nameid && sd->status.inventory[i].equip == 0 );
if( i < MAX_INVENTORY )
pc->equipitem(sd,i,item_data->equip);
-
+
return true;
}
@@ -13126,19 +13774,19 @@ BUILDIN(autoequip)
struct item_data *item_data;
nameid=script_getnum(st,2);
flag=script_getnum(st,3);
-
- if( ( item_data = itemdb_exists(nameid) ) == NULL )
+
+ if( ( item_data = itemdb->exists(nameid) ) == NULL )
{
ShowError("buildin_autoequip: Invalid item '%d'.\n", nameid);
return false;
}
-
- if( !itemdb_isequip2(item_data) )
+
+ if( !itemdb->isequip2(item_data) )
{
ShowError("buildin_autoequip: Item '%d' cannot be equipped.\n", nameid);
return false;
}
-
+
item_data->flag.autoequip = flag>0?1:0;
return true;
}
@@ -13146,15 +13794,15 @@ BUILDIN(autoequip)
BUILDIN(setbattleflag)
{
const char *flag, *value;
-
+
flag = script_getstr(st,2);
value = script_getstr(st,3); // HACK: Retrieve number as string (auto-converted) for battle_set_value
-
+
if (battle->config_set_value(flag, value) == 0)
ShowWarning("buildin_setbattleflag: unknown battle_config flag '%s'\n",flag);
else
ShowInfo("buildin_setbattleflag: battle_config flag '%s' is now set to '%s'.\n",flag,value);
-
+
return true;
}
@@ -13171,10 +13819,10 @@ BUILDIN(getbattleflag)
//-------------------------------------------------------
BUILDIN(getstrlen)
{
-
+
const char *str = script_getstr(st,2);
int len = (str) ? (int)strlen(str) : 0;
-
+
script_pushint(st,len);
return true;
}
@@ -13186,9 +13834,9 @@ BUILDIN(charisalpha)
{
const char *str=script_getstr(st,2);
int pos=script_getnum(st,3);
-
+
int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISALPHA( str[pos] ) != 0 : 0;
-
+
script_pushint(st,val);
return true;
}
@@ -13200,9 +13848,9 @@ BUILDIN(charisupper)
{
const char *str = script_getstr(st,2);
int pos = script_getnum(st,3);
-
+
int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISUPPER( str[pos] ) : 0;
-
+
script_pushint(st,val);
return true;
}
@@ -13214,9 +13862,9 @@ BUILDIN(charislower)
{
const char *str = script_getstr(st,2);
int pos = script_getnum(st,3);
-
+
int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISLOWER( str[pos] ) : 0;
-
+
script_pushint(st,val);
return true;
}
@@ -13227,7 +13875,7 @@ BUILDIN(charislower)
BUILDIN(charat) {
const char *str = script_getstr(st,2);
int pos = script_getnum(st,3);
-
+
if( pos >= 0 && (unsigned int)pos < strlen(str) ) {
char output[2];
output[0] = str[pos];
@@ -13247,10 +13895,10 @@ BUILDIN(setchar)
const char *c = script_getstr(st,3);
int index = script_getnum(st,4);
char *output = aStrdup(str);
-
+
if(index >= 0 && index < strlen(output))
output[index] = *c;
-
+
script_pushstr(st, output);
return true;
}
@@ -13265,19 +13913,19 @@ BUILDIN(insertchar)
int index = script_getnum(st,4);
char *output;
size_t len = strlen(str);
-
+
if(index < 0)
index = 0;
else if(index > len)
- index = len;
-
+ index = (int)len;
+
output = (char*)aMalloc(len + 2);
-
+
memcpy(output, str, index);
output[index] = c[0];
memcpy(&output[index+1], &str[index], len - index);
output[len+1] = '\0';
-
+
script_pushstr(st, output);
return true;
}
@@ -13291,19 +13939,19 @@ BUILDIN(delchar)
int index = script_getnum(st,3);
char *output;
size_t len = strlen(str);
-
+
if(index < 0 || index > len) {
//return original
output = aStrdup(str);
script_pushstr(st, output);
return true;
}
-
+
output = (char*)aMalloc(len);
-
+
memcpy(output, str, index);
memcpy(&output[index], &str[index+1], len - index);
-
+
script_pushstr(st, output);
return true;
}
@@ -13316,12 +13964,12 @@ BUILDIN(strtoupper)
const char *str = script_getstr(st,2);
char *output = aStrdup(str);
char *cursor = output;
-
+
while (*cursor != '\0') {
*cursor = TOUPPER(*cursor);
cursor++;
}
-
+
script_pushstr(st, output);
return true;
}
@@ -13334,12 +13982,12 @@ BUILDIN(strtolower)
const char *str = script_getstr(st,2);
char *output = aStrdup(str);
char *cursor = output;
-
+
while (*cursor != '\0') {
*cursor = TOLOWER(*cursor);
cursor++;
}
-
+
script_pushstr(st, output);
return true;
}
@@ -13353,18 +14001,18 @@ BUILDIN(substr)
char *output;
int start = script_getnum(st,3);
int end = script_getnum(st,4);
-
+
int len = 0;
-
+
if(start >= 0 && end < strlen(str) && start <= end) {
len = end - start + 1;
output = (char*)aMalloc(len + 1);
memcpy(output, &str[start], len);
} else
output = (char*)aMalloc(1);
-
+
output[len] = '\0';
-
+
script_pushstr(st, output);
return true;
}
@@ -13382,54 +14030,46 @@ BUILDIN(explode)
size_t len = strlen(str);
int i = 0, j = 0;
int start;
-
-
+
+
char *temp;
const char* name;
-
+
TBL_PC* sd = NULL;
-
+
temp = (char*)aMalloc(len + 1);
-
+
if( !data_isreference(data) )
{
ShowError("script:explode: not a variable\n");
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;// not a variable
}
-
+
id = reference_getid(data);
start = reference_getindex(data);
name = reference_getname(data);
-
- if( not_array_variable(*name) )
- {
- ShowError("script:explode: illegal scope\n");
- script_reportdata(data);
- st->state = END;
- return false;// not supported
- }
-
+
if( !is_string_variable(name) )
{
ShowError("script:explode: not string array\n");
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;// data type mismatch
}
-
+
if( not_server_variable(*name) )
{
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached
}
-
+
while(str[i] != '\0') {
if(str[i] == delimiter && start < SCRIPT_MAX_ARRAYSIZE-1) { //break at delimiter but ignore after reaching last array index
temp[j] = '\0';
- set_reg(st, sd, reference_uid(id, start++), name, (void*)temp, reference_getref(data));
+ script->set_reg(st, sd, reference_uid(id, start++), name, (void*)temp, reference_getref(data));
j = 0;
++i;
} else {
@@ -13438,8 +14078,8 @@ BUILDIN(explode)
}
//set last string
temp[j] = '\0';
- set_reg(st, sd, reference_uid(id, start), name, (void*)temp, reference_getref(data));
-
+ script->set_reg(st, sd, reference_uid(id, start), name, (void*)temp, reference_getref(data));
+
aFree(temp);
return true;
}
@@ -13452,63 +14092,55 @@ BUILDIN(implode)
{
struct script_data* data = script_getdata(st, 2);
const char *glue = NULL, *name, *temp;
- int32 glue_len = 0, array_size, id;
- size_t len = 0;
- int i, k = 0;
-
+ uint32 array_size, id;
+ size_t len = 0, glue_len = 0, k = 0;
+ int i;
+
TBL_PC* sd = NULL;
-
+
char *output;
-
+
if( !data_isreference(data) )
{
ShowError("script:implode: not a variable\n");
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;// not a variable
}
-
+
id = reference_getid(data);
name = reference_getname(data);
-
- if( not_array_variable(*name) )
- {
- ShowError("script:implode: illegal scope\n");
- script_reportdata(data);
- st->state = END;
- return false;// not supported
- }
-
+
if( !is_string_variable(name) )
{
ShowError("script:implode: not string array\n");
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;// data type mismatch
}
-
+
if( not_server_variable(*name) )
{
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached
}
-
+
//count chars
- array_size = getarraysize(st, id, reference_getindex(data), is_string_variable(name), reference_getref(data)) - 1;
-
- if(array_size == -1) //empty array check (AmsTaff)
- {
- ShowWarning("script:implode: array length = 0\n");
- output = (char*)aMalloc(sizeof(char)*5);
- sprintf(output,"%s","NULL");
+ array_size = script->array_highest_key(st,sd,name,reference_getref(data)) - 1;
+
+ if(array_size == -1) {
+ //empty array check (AmsTaff)
+ ShowWarning("script:implode: array length = 0\n");
+ output = (char*)aMalloc(sizeof(char)*5);
+ sprintf(output,"%s","NULL");
} else {
for(i = 0; i <= array_size; ++i) {
temp = (char*) script->get_val2(st, reference_uid(id, i), reference_getref(data));
len += strlen(temp);
script_removetop(st, -1, 0);
}
-
+
//allocate mem
if( script_hasdata(st,3) ) {
glue = script_getstr(st,3);
@@ -13516,7 +14148,7 @@ BUILDIN(implode)
len += glue_len * (array_size);
}
output = (char*)aMalloc(len + 1);
-
+
//build output
for(i = 0; i < array_size; ++i) {
temp = (char*) script->get_val2(st, reference_uid(id, i), reference_getref(data));
@@ -13534,10 +14166,10 @@ BUILDIN(implode)
memcpy(&output[k], temp, len);
k += len;
script_removetop(st, -1, 0);
-
+
output[k] = '\0';
}
-
+
script_pushstr(st, output);
return true;
}
@@ -13547,232 +14179,242 @@ BUILDIN(implode)
// Implements C sprintf, except format %n. The resulting string is
// returned, instead of being saved in variable by reference.
//-------------------------------------------------------
-BUILDIN(sprintf)
-{
- unsigned int len, argc = 0, arg = 0, buf2_len = 0;
- const char* format;
- char* p;
- char* q;
- char* buf = NULL;
- char* buf2 = NULL;
- struct script_data* data;
- StringBuf final_buf;
-
- // Fetch init data
- format = script_getstr(st, 2);
- argc = script_lastdata(st)-2;
- len = strlen(format);
-
- // Skip parsing, where no parsing is required.
- if(len==0){
- script_pushconststr(st,"");
- return true;
- }
-
- // Pessimistic alloc
- CREATE(buf, char, len+1);
-
- // Need not be parsed, just solve stuff like %%.
- if(argc==0){
+BUILDIN(sprintf) {
+ unsigned int argc = 0, arg = 0;
+ const char* format;
+ char* p;
+ char* q;
+ char* buf = NULL;
+ char* buf2 = NULL;
+ struct script_data* data;
+ size_t len, buf2_len = 0;
+ StringBuf final_buf;
+
+ // Fetch init data
+ format = script_getstr(st, 2);
+ argc = script_lastdata(st)-2;
+ len = strlen(format);
+
+ // Skip parsing, where no parsing is required.
+ if(len==0) {
+ script_pushconststr(st,"");
+ return true;
+ }
+
+ // Pessimistic alloc
+ CREATE(buf, char, len+1);
+
+ // Need not be parsed, just solve stuff like %%.
+ if(argc==0) {
memcpy(buf,format,len+1);
- script_pushstrcopy(st, buf);
- aFree(buf);
- return true;
- }
-
- safestrncpy(buf, format, len+1);
-
- // Issue sprintf for each parameter
- StrBuf->Init(&final_buf);
- q = buf;
- while((p = strchr(q, '%'))!=NULL){
- if(p!=q){
- len = p-q+1;
- if(buf2_len<len){
- RECREATE(buf2, char, len);
- buf2_len = len;
- }
- safestrncpy(buf2, q, len);
- StrBuf->AppendStr(&final_buf, buf2);
- q = p;
- }
- p = q+1;
- if(*p=='%'){ // %%
- StrBuf->AppendStr(&final_buf, "%");
- q+=2;
- continue;
- }
- if(*p=='n'){ // %n
- ShowWarning("buildin_sprintf: Format %%n not supported! Skipping...\n");
- script_reportsrc(st);
- q+=2;
- continue;
- }
- if(arg>=argc){
- ShowError("buildin_sprintf: Not enough arguments passed!\n");
- if(buf) aFree(buf);
- if(buf2) aFree(buf2);
- StrBuf->Destroy(&final_buf);
- script_pushconststr(st,"");
- return false;
- }
- if((p = strchr(q+1, '%'))==NULL){
- p = strchr(q, 0); // EOS
- }
- len = p-q+1;
- if(buf2_len<len){
- RECREATE(buf2, char, len);
- buf2_len = len;
- }
- safestrncpy(buf2, q, len);
- q = p;
-
- // Note: This assumes the passed value being the correct
- // type to the current format specifier. If not, the server
- // probably crashes or returns anything else, than expected,
- // but it would behave in normal code the same way so it's
- // the scripter's responsibility.
- data = script_getdata(st, arg+3);
- if(data_isstring(data)){ // String
- StrBuf->Printf(&final_buf, buf2, script_getstr(st, arg+3));
- }else if(data_isint(data)){ // Number
- StrBuf->Printf(&final_buf, buf2, script_getnum(st, arg+3));
- }else if(data_isreference(data)){ // Variable
- char* name = reference_getname(data);
- if(name[strlen(name)-1]=='$'){ // var Str
- StrBuf->Printf(&final_buf, buf2, script_getstr(st, arg+3));
- }else{ // var Int
- StrBuf->Printf(&final_buf, buf2, script_getnum(st, arg+3));
- }
- }else{ // Unsupported type
- ShowError("buildin_sprintf: Unknown argument type!\n");
- if(buf) aFree(buf);
- if(buf2) aFree(buf2);
- StrBuf->Destroy(&final_buf);
- script_pushconststr(st,"");
- return false;
- }
- arg++;
- }
-
- // Append anything left
- if(*q){
- StrBuf->AppendStr(&final_buf, q);
- }
-
- // Passed more, than needed
- if(arg<argc){
- ShowWarning("buildin_sprintf: Unused arguments passed.\n");
- script_reportsrc(st);
- }
-
- script_pushstrcopy(st, StrBuf->Value(&final_buf));
-
- if(buf) aFree(buf);
- if(buf2) aFree(buf2);
- StrBuf->Destroy(&final_buf);
-
- return true;
+ script_pushstrcopy(st, buf);
+ aFree(buf);
+ return true;
+ }
+
+ safestrncpy(buf, format, len+1);
+
+ // Issue sprintf for each parameter
+ StrBuf->Init(&final_buf);
+ q = buf;
+ while((p = strchr(q, '%'))!=NULL) {
+ if(p!=q) {
+ len = p-q+1;
+ if(buf2_len<len) {
+ RECREATE(buf2, char, len);
+ buf2_len = len;
+ }
+ safestrncpy(buf2, q, len);
+ StrBuf->AppendStr(&final_buf, buf2);
+ q = p;
+ }
+ p = q+1;
+ if(*p=='%') { // %%
+ StrBuf->AppendStr(&final_buf, "%");
+ q+=2;
+ continue;
+ }
+ if(*p=='n') { // %n
+ ShowWarning("buildin_sprintf: Format %%n not supported! Skipping...\n");
+ script->reportsrc(st);
+ q+=2;
+ continue;
+ }
+ if(arg>=argc) {
+ ShowError("buildin_sprintf: Not enough arguments passed!\n");
+ if(buf) aFree(buf);
+ if(buf2) aFree(buf2);
+ StrBuf->Destroy(&final_buf);
+ script_pushconststr(st,"");
+ return false;
+ }
+ if((p = strchr(q+1, '%'))==NULL) {
+ p = strchr(q, 0); // EOS
+ }
+ len = p-q+1;
+ if(buf2_len<len) {
+ RECREATE(buf2, char, len);
+ buf2_len = len;
+ }
+ safestrncpy(buf2, q, len);
+ q = p;
+
+ // Note: This assumes the passed value being the correct
+ // type to the current format specifier. If not, the server
+ // probably crashes or returns anything else, than expected,
+ // but it would behave in normal code the same way so it's
+ // the scripter's responsibility.
+ data = script_getdata(st, arg+3);
+ if(data_isstring(data)) { // String
+ StrBuf->Printf(&final_buf, buf2, script_getstr(st, arg+3));
+ } else if(data_isint(data)) { // Number
+ StrBuf->Printf(&final_buf, buf2, script_getnum(st, arg+3));
+ } else if(data_isreference(data)) { // Variable
+ char* name = reference_getname(data);
+ if(name[strlen(name)-1]=='$') { // var Str
+ StrBuf->Printf(&final_buf, buf2, script_getstr(st, arg+3));
+ } else { // var Int
+ StrBuf->Printf(&final_buf, buf2, script_getnum(st, arg+3));
+ }
+ } else { // Unsupported type
+ ShowError("buildin_sprintf: Unknown argument type!\n");
+ if(buf) aFree(buf);
+ if(buf2) aFree(buf2);
+ StrBuf->Destroy(&final_buf);
+ script_pushconststr(st,"");
+ return false;
+ }
+ arg++;
+ }
+
+ // Append anything left
+ if(*q) {
+ StrBuf->AppendStr(&final_buf, q);
+ }
+
+ // Passed more, than needed
+ if(arg<argc) {
+ ShowWarning("buildin_sprintf: Unused arguments passed.\n");
+ script->reportsrc(st);
+ }
+
+ script_pushstrcopy(st, StrBuf->Value(&final_buf));
+
+ if(buf) aFree(buf);
+ if(buf2) aFree(buf2);
+ StrBuf->Destroy(&final_buf);
+
+ return true;
}
//=======================================================
// sscanf(<str>, <format>, ...);
// Implements C sscanf.
//-------------------------------------------------------
-BUILDIN(sscanf){
- unsigned int argc, arg = 0, len;
- struct script_data* data;
- struct map_session_data* sd = NULL;
- const char* str;
- const char* format;
- const char* p;
- const char* q;
- char* buf = NULL;
- char* buf_p;
- char* ref_str = NULL;
- int ref_int;
-
- // Get data
- str = script_getstr(st, 2);
- format = script_getstr(st, 3);
- argc = script_lastdata(st)-3;
-
- len = strlen(format);
- CREATE(buf, char, len*2+1);
-
- // Issue sscanf for each parameter
- *buf = 0;
- q = format;
- while((p = strchr(q, '%'))){
- if(p!=q){
- strncat(buf, q, (size_t)(p-q));
- q = p;
- }
- p = q+1;
- if(*p=='*' || *p=='%'){ // Skip
- strncat(buf, q, 2);
- q+=2;
- continue;
- }
- if(arg>=argc){
- ShowError("buildin_sscanf: Not enough arguments passed!\n");
- script_pushint(st, -1);
- if(buf) aFree(buf);
- if(ref_str) aFree(ref_str);
- return false;
- }
- if((p = strchr(q+1, '%'))==NULL){
- p = strchr(q, 0); // EOS
- }
- len = p-q;
- strncat(buf, q, len);
- q = p;
-
- // Validate output
- data = script_getdata(st, arg+4);
- if(!data_isreference(data) || !reference_tovariable(data)){
- ShowError("buildin_sscanf: Target argument is not a variable!\n");
- script_pushint(st, -1);
- if(buf) aFree(buf);
- if(ref_str) aFree(ref_str);
- return false;
- }
- buf_p = reference_getname(data);
- if(not_server_variable(*buf_p) && (sd = script_rid2sd(st))==NULL){
- script_pushint(st, -1);
- if(buf) aFree(buf);
- if(ref_str) aFree(ref_str);
- return true;
- }
-
- // Save value if any
- if(buf_p[strlen(buf_p)-1]=='$'){ // String
- if(ref_str==NULL){
- CREATE(ref_str, char, strlen(str)+1);
- }
- if(sscanf(str, buf, ref_str)==0){
- break;
- }
- set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, (void *)(ref_str), reference_getref(data));
- } else { // Number
- if(sscanf(str, buf, &ref_int)==0){
- break;
- }
- set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, (void *)__64BPTRSIZE(ref_int), reference_getref(data));
- }
- arg++;
-
- // Disable used format (%... -> %*...)
- buf_p = strchr(buf, 0);
- memmove(buf_p-len+2, buf_p-len+1, len);
- *(buf_p-len+1) = '*';
- }
-
- script_pushint(st, arg);
- if(buf) aFree(buf);
- if(ref_str) aFree(ref_str);
-
- return true;
+BUILDIN(sscanf) {
+ unsigned int argc, arg = 0;
+ struct script_data* data;
+ struct map_session_data* sd = NULL;
+ const char* str;
+ const char* format;
+ const char* p;
+ const char* q;
+ char* buf = NULL;
+ char* buf_p;
+ char* ref_str = NULL;
+ int ref_int;
+ size_t len;
+
+ // Get data
+ str = script_getstr(st, 2);
+ format = script_getstr(st, 3);
+ argc = script_lastdata(st)-3;
+
+ len = strlen(format);
+
+ if (len != 0 && strlen(str) == 0) {
+ // If the source string is empty but the format string is not, we return -1
+ // according to the C specs. (if the format string is also empty, we shall
+ // continue and return 0: 0 conversions took place out of the 0 attempted.)
+ script_pushint(st, -1);
+ return true;
+ }
+
+ CREATE(buf, char, len*2+1);
+
+ // Issue sscanf for each parameter
+ *buf = 0;
+ q = format;
+ while((p = strchr(q, '%'))) {
+ if(p!=q) {
+ strncat(buf, q, (size_t)(p-q));
+ q = p;
+ }
+ p = q+1;
+ if(*p=='*' || *p=='%') { // Skip
+ strncat(buf, q, 2);
+ q+=2;
+ continue;
+ }
+ if(arg>=argc) {
+ ShowError("buildin_sscanf: Not enough arguments passed!\n");
+ script_pushint(st, -1);
+ if(buf) aFree(buf);
+ if(ref_str) aFree(ref_str);
+ return false;
+ }
+ if((p = strchr(q+1, '%'))==NULL) {
+ p = strchr(q, 0); // EOS
+ }
+ len = p-q;
+ strncat(buf, q, len);
+ q = p;
+
+ // Validate output
+ data = script_getdata(st, arg+4);
+ if(!data_isreference(data) || !reference_tovariable(data)) {
+ ShowError("buildin_sscanf: Target argument is not a variable!\n");
+ script_pushint(st, -1);
+ if(buf) aFree(buf);
+ if(ref_str) aFree(ref_str);
+ return false;
+ }
+ buf_p = reference_getname(data);
+ if(not_server_variable(*buf_p) && (sd = script->rid2sd(st))==NULL) {
+ script_pushint(st, -1);
+ if(buf) aFree(buf);
+ if(ref_str) aFree(ref_str);
+ return true;
+ }
+
+ // Save value if any
+ if(buf_p[strlen(buf_p)-1]=='$') { // String
+ if(ref_str==NULL) {
+ CREATE(ref_str, char, strlen(str)+1);
+ }
+ if(sscanf(str, buf, ref_str)==0) {
+ break;
+ }
+ script->set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, (void *)(ref_str), reference_getref(data));
+ } else { // Number
+ if(sscanf(str, buf, &ref_int)==0) {
+ break;
+ }
+ script->set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, (void *)h64BPTRSIZE(ref_int), reference_getref(data));
+ }
+ arg++;
+
+ // Disable used format (%... -> %*...)
+ buf_p = strchr(buf, 0);
+ memmove(buf_p-len+2, buf_p-len+1, len);
+ *(buf_p-len+1) = '*';
+ }
+
+ script_pushint(st, arg);
+ if(buf) aFree(buf);
+ if(ref_str) aFree(ref_str);
+
+ return true;
}
//=======================================================
@@ -13787,17 +14429,17 @@ BUILDIN(strpos) {
const char *needle = script_getstr(st,3);
int i;
size_t len;
-
+
if( script_hasdata(st,4) )
i = script_getnum(st,4);
else
i = 0;
-
+
if (needle[0] == '\0') {
script_pushint(st, -1);
return true;
}
-
+
len = strlen(haystack);
for ( ; i < len; ++i ) {
if ( haystack[i] == *needle ) {
@@ -13835,48 +14477,47 @@ BUILDIN(replacestr)
size_t findlen = strlen(find);
struct StringBuf output;
bool usecase = true;
-
+
int count = 0;
int numFinds = 0;
int i = 0, f = 0;
-
+
if(findlen == 0) {
ShowError("script:replacestr: Invalid search length.\n");
st->state = END;
return false;
}
-
+
if(script_hasdata(st, 5)) {
- if( !script_isstring(st,5) )
+ if( script_isinttype(st,5) ) {
usecase = script_getnum(st, 5) != 0;
- else {
- ShowError("script:replacestr: Invalid usecase value. Expected int got string\n");
+ } else {
+ ShowError("script:replacestr: Invalid usecase value. Expected int.\n");
st->state = END;
return false;
}
}
-
+
if(script_hasdata(st, 6)) {
- count = script_getnum(st, 6);
- if(count == 0) {
- ShowError("script:replacestr: Invalid count value. Expected int got string\n");
+ if (!script_isinttype(st, 5) || (count = script_getnum(st, 6) == 0)) {
+ ShowError("script:replacestr: Invalid count value. Expected int.\n");
st->state = END;
return false;
}
}
-
+
StrBuf->Init(&output);
-
+
for(; i < inputlen; i++) {
- if(count && count == numFinds) { //found enough, stop looking
- break;
+ if(count && count == numFinds) {
+ break; //found enough, stop looking
}
-
+
for(f = 0; f <= findlen; f++) {
if(f == findlen) { //complete match
numFinds++;
StrBuf->AppendStr(&output, replace);
-
+
i += findlen - 1;
break;
} else {
@@ -13894,11 +14535,11 @@ BUILDIN(replacestr)
}
}
}
-
+
//append excess after enough found
if(i < inputlen)
StrBuf->AppendStr(&output, &(input[i]));
-
+
script_pushstrcopy(st, StrBuf->Value(&output));
StrBuf->Destroy(&output);
return true;
@@ -13917,26 +14558,26 @@ BUILDIN(countstr)
size_t inputlen = strlen(input);
size_t findlen = strlen(find);
bool usecase = true;
-
+
int numFinds = 0;
int i = 0, f = 0;
-
+
if(findlen == 0) {
ShowError("script:countstr: Invalid search length.\n");
st->state = END;
return false;
}
-
+
if(script_hasdata(st, 4)) {
- if( !script_isstring(st,4) )
+ if( script_isinttype(st,4) )
usecase = script_getnum(st, 4) != 0;
else {
- ShowError("script:countstr: Invalid usecase value. Expected int got string\n");
+ ShowError("script:countstr: Invalid usecase value. Expected int.\n");
st->state = END;
return false;
}
}
-
+
for(; i < inputlen; i++) {
for(f = 0; f <= findlen; f++) {
if(f == findlen) { //complete match
@@ -13968,70 +14609,80 @@ BUILDIN(countstr)
/// setnpcdisplay("<npc name>", "<new display name>", <new class id>) -> <int>
/// setnpcdisplay("<npc name>", "<new display name>") -> <int>
/// setnpcdisplay("<npc name>", <new class id>) -> <int>
-BUILDIN(setnpcdisplay)
-{
+BUILDIN(setnpcdisplay) {
const char* name;
const char* newname = NULL;
int class_ = -1, size = -1;
- struct script_data* data;
struct npc_data* nd;
-
+
name = script_getstr(st,2);
- data = script_getdata(st,3);
-
+
if( script_hasdata(st,4) )
class_ = script_getnum(st,4);
if( script_hasdata(st,5) )
size = script_getnum(st,5);
-
- script->get_val(st, data);
- if( data_isstring(data) )
- newname = script->conv_str(st,data);
- else if( data_isint(data) )
- class_ = script->conv_num(st,data);
+
+ if( script_isstringtype(st, 3) )
+ newname = script_getstr(st, 3);
else
- {
- ShowError("script:setnpcdisplay: expected string or number\n");
- script_reportdata(data);
- return false;
- }
-
- nd = npc_name2id(name);
+ class_ = script_getnum(st, 3);
+
+ nd = npc->name2id(name);
if( nd == NULL )
{// not found
script_pushint(st,1);
return true;
}
-
+
// update npc
if( newname )
- npc_setdisplayname(nd, newname);
-
+ npc->setdisplayname(nd, newname);
+
if( size != -1 && size != (int)nd->size )
nd->size = size;
else
size = -1;
-
+
if( class_ != -1 && nd->class_ != class_ )
- npc_setclass(nd, class_);
+ npc->setclass(nd, class_);
else if( size != -1 )
{ // Required to update the visual size
clif->clearunit_area(&nd->bl, CLR_OUTSIGHT);
clif->spawn(&nd->bl);
}
-
+
script_pushint(st,0);
return true;
}
-BUILDIN(atoi)
-{
+BUILDIN(atoi) {
const char *value;
value = script_getstr(st,2);
script_pushint(st,atoi(value));
return true;
}
+BUILDIN(axtoi) {
+ const char *hex = script_getstr(st,2);
+ long value = strtol(hex, NULL, 16);
+#if LONG_MAX > INT_MAX || LONG_MIN < INT_MIN
+ value = cap_value(value, INT_MIN, INT_MAX);
+#endif
+ script_pushint(st, (int)value);
+ return true;
+}
+
+BUILDIN(strtol) {
+ const char *string = script_getstr(st, 2);
+ int base = script_getnum(st, 3);
+ long value = strtol(string, NULL, base);
+#if LONG_MAX > INT_MAX || LONG_MIN < INT_MIN
+ value = cap_value(value, INT_MIN, INT_MAX);
+#endif
+ script_pushint(st, (int)value);
+ return true;
+}
+
// case-insensitive substring search [lordalfa]
BUILDIN(compare)
{
@@ -14066,12 +14717,12 @@ BUILDIN(pow)
BUILDIN(distance)
{
int x0, y0, x1, y1;
-
+
x0 = script_getnum(st,2);
y0 = script_getnum(st,3);
x1 = script_getnum(st,4);
y1 = script_getnum(st,5);
-
+
script_pushint(st,distance_xy(x0,y0,x1,y1));
return true;
}
@@ -14082,7 +14733,7 @@ BUILDIN(md5)
{
const char *tmpstr;
char *md5str;
-
+
tmpstr = script_getstr(st,2);
md5str = (char *)aMalloc((32+1)*sizeof(char));
MD5_String(tmpstr, md5str);
@@ -14099,26 +14750,26 @@ BUILDIN(setd)
const char *buffer;
int elem;
buffer = script_getstr(st, 2);
-
+
if(sscanf(buffer, "%99[^[][%d]", varname, &elem) < 2)
elem = 0;
-
+
if( not_server_variable(*varname) )
{
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
{
ShowError("script:setd: no player attached for player variable '%s'\n", buffer);
return true;
}
}
-
+
if( is_string_variable(varname) ) {
- setd_sub(st, sd, varname, elem, (void *)script_getstr(st, 3), NULL);
+ script->setd_sub(st, sd, varname, elem, (void *)script_getstr(st, 3), NULL);
} else {
- setd_sub(st, sd, varname, elem, (void *)__64BPTRSIZE(script_getnum(st, 3)), NULL);
+ script->setd_sub(st, sd, varname, elem, (void *)h64BPTRSIZE(script_getnum(st, 3)), NULL);
}
-
+
return true;
}
@@ -14129,97 +14780,92 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle)
const char* query;
struct script_data* data;
const char* name;
- int max_rows = SCRIPT_MAX_ARRAYSIZE; // maximum number of rows
+ unsigned int max_rows = SCRIPT_MAX_ARRAYSIZE; // maximum number of rows
int num_vars;
int num_cols;
-
+
// check target variables
for( i = 3; script_hasdata(st,i); ++i ) {
data = script_getdata(st, i);
if( data_isreference(data) ) { // it's a variable
name = reference_getname(data);
if( not_server_variable(*name) && sd == NULL ) { // requires a player
- sd = script_rid2sd(st);
- if( sd == NULL ) { // no player attached
- script_reportdata(data);
- st->state = END;
+ sd = script->rid2sd(st);
+ if( sd == NULL )// no player attached
return false;
- }
}
- if( not_array_variable(*name) )
- max_rows = 1;// not an array, limit to one row
} else {
ShowError("script:query_sql: not a variable\n");
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;
}
}
num_vars = i - 3;
-
+
// Execute the query
query = script_getstr(st,2);
-
+
if( SQL_ERROR == SQL->QueryStr(handle, query) ) {
Sql_ShowDebug(handle);
- script_pushint(st, 0);
+ st->state = END;
return false;
}
-
+
if( SQL->NumRows(handle) == 0 ) { // No data received
SQL->FreeResult(handle);
script_pushint(st, 0);
return true;
}
-
+
// Count the number of columns to store
num_cols = SQL->NumColumns(handle);
if( num_vars < num_cols ) {
ShowWarning("script:query_sql: Too many columns, discarding last %u columns.\n", (unsigned int)(num_cols-num_vars));
- script_reportsrc(st);
+ script->reportsrc(st);
} else if( num_vars > num_cols ) {
ShowWarning("script:query_sql: Too many variables (%u extra).\n", (unsigned int)(num_vars-num_cols));
- script_reportsrc(st);
+ script->reportsrc(st);
}
-
+
// Store data
for( i = 0; i < max_rows && SQL_SUCCESS == SQL->NextRow(handle); ++i ) {
for( j = 0; j < num_vars; ++j ) {
char* str = NULL;
-
+
if( j < num_cols )
SQL->GetData(handle, j, &str, NULL);
-
+
data = script_getdata(st, j+3);
name = reference_getname(data);
if( is_string_variable(name) )
- setd_sub(st, sd, name, i, (void *)(str?str:""), reference_getref(data));
+ script->setd_sub(st, sd, name, i, (void *)(str?str:""), reference_getref(data));
else
- setd_sub(st, sd, name, i, (void *)__64BPTRSIZE((str?atoi(str):0)), reference_getref(data));
+ script->setd_sub(st, sd, name, i, (void *)h64BPTRSIZE((str?atoi(str):0)), reference_getref(data));
}
}
if( i == max_rows && max_rows < SQL->NumRows(handle) ) {
ShowWarning("script:query_sql: Only %d/%u rows have been stored.\n", max_rows, (unsigned int)SQL->NumRows(handle));
- script_reportsrc(st);
+ script->reportsrc(st);
}
-
+
// Free data
SQL->FreeResult(handle);
script_pushint(st, i);
-
+
return true;
}
BUILDIN(query_sql) {
- return buildin_query_sql_sub(st, mmysql_handle);
+ return script->buildin_query_sql_sub(st, map->mysql_handle);
}
BUILDIN(query_logsql) {
- if( !logs->config.sql_logs ) {// logmysql_handle == NULL
+ if( !logs->config.sql_logs ) {// logs->mysql_handle == NULL
ShowWarning("buildin_query_logsql: SQL logs are disabled, query '%s' will not be executed.\n", script_getstr(st,2));
script_pushint(st,-1);
return false;
}
- return buildin_query_sql_sub(st, logmysql_handle);
+ return script->buildin_query_sql_sub(st, logs->mysql_handle);
}
//Allows escaping of a given string.
@@ -14228,29 +14874,28 @@ BUILDIN(escape_sql)
const char *str;
char *esc_str;
size_t len;
-
+
str = script_getstr(st,2);
len = strlen(str);
esc_str = (char*)aMalloc(len*2+1);
- SQL->EscapeStringLen(mmysql_handle, esc_str, str, len);
+ SQL->EscapeStringLen(map->mysql_handle, esc_str, str, len);
script_pushstr(st, esc_str);
return true;
}
-BUILDIN(getd)
-{
+BUILDIN(getd) {
char varname[100];
const char *buffer;
int elem;
-
+
buffer = script_getstr(st, 2);
-
- if(sscanf(buffer, "%[^[][%d]", varname, &elem) < 2)
+
+ if (sscanf(buffer, "%99[^[][%d]", varname, &elem) < 2)
elem = 0;
-
+
// Push the 'pointer' so it's more flexible [Lance]
- script->push_val(st->stack, C_NAME, reference_uid(add_str(varname), elem),NULL);
-
+ script->push_val(st->stack, C_NAME, reference_uid(script->add_str(varname), elem),NULL);
+
return true;
}
@@ -14261,8 +14906,8 @@ BUILDIN(petstat)
TBL_PC *sd = NULL;
struct pet_data *pd;
int flag = script_getnum(st,2);
- sd = script_rid2sd(st);
- if(!sd || !sd->status.pet_id || !sd->pd){
+ sd = script->rid2sd(st);
+ if(!sd || !sd->status.pet_id || !sd->pd) {
if(flag == 2)
script_pushconststr(st, "");
else
@@ -14270,7 +14915,7 @@ BUILDIN(petstat)
return true;
}
pd = sd->pd;
- switch(flag){
+ switch(flag) {
case 1: script_pushint(st,(int)pd->pet.class_); break;
case 2: script_pushstrcopy(st, pd->pet.name); break;
case 3: script_pushint(st,(int)pd->pet.level); break;
@@ -14289,37 +14934,35 @@ BUILDIN(callshop)
struct npc_data *nd;
const char *shopname;
int flag = 0;
- sd = script_rid2sd(st);
- if (!sd) {
- script_pushint(st,0);
- return true;
- }
+ sd = script->rid2sd(st);
+ if( sd == NULL )
+ return false;
shopname = script_getstr(st, 2);
if( script_hasdata(st,3) )
flag = script_getnum(st,3);
- nd = npc_name2id(shopname);
+ nd = npc->name2id(shopname);
if( !nd || nd->bl.type != BL_NPC || (nd->subtype != SHOP && nd->subtype != CASHSHOP) )
{
ShowError("buildin_callshop: Shop [%s] not found (or NPC is not shop type)\n", shopname);
script_pushint(st,0);
return false;
}
-
+
if( nd->subtype == SHOP )
{
// flag the user as using a valid script call for opening the shop (for floating NPCs)
sd->state.callshop = 1;
-
+
switch( flag )
{
- case 1: npc_buysellsel(sd,nd->bl.id,0); break; //Buy window
- case 2: npc_buysellsel(sd,nd->bl.id,1); break; //Sell window
+ case 1: npc->buysellsel(sd,nd->bl.id,0); break; //Buy window
+ case 2: npc->buysellsel(sd,nd->bl.id,1); break; //Sell window
default: clif->npcbuysell(sd,nd->bl.id); break; //Show menu
}
}
else
clif->cashshop_show(sd, nd);
-
+
sd->npc_shopid = nd->bl.id;
script_pushint(st,1);
return true;
@@ -14328,19 +14971,19 @@ BUILDIN(callshop)
BUILDIN(npcshopitem)
{
const char* npcname = script_getstr(st, 2);
- struct npc_data* nd = npc_name2id(npcname);
+ struct npc_data* nd = npc->name2id(npcname);
int n, i;
int amount;
-
- if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) )
- { //Not found.
+
+ if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) {
+ //Not found.
script_pushint(st,0);
return true;
}
-
+
// get the count of new entries
amount = (script_lastdata(st)-2)/2;
-
+
// generate new shop item list
RECREATE(nd->u.shop.shop_item, struct npc_item_list, amount);
for( n = 0, i = 3; n < amount; n++, i+=2 )
@@ -14349,7 +14992,7 @@ BUILDIN(npcshopitem)
nd->u.shop.shop_item[n].value = script_getnum(st,i+1);
}
nd->u.shop.count = n;
-
+
script_pushint(st,1);
return true;
}
@@ -14357,19 +15000,19 @@ BUILDIN(npcshopitem)
BUILDIN(npcshopadditem)
{
const char* npcname = script_getstr(st,2);
- struct npc_data* nd = npc_name2id(npcname);
+ struct npc_data* nd = npc->name2id(npcname);
int n, i;
int amount;
-
- if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) )
- { //Not found.
+
+ if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) {
+ //Not found.
script_pushint(st,0);
return true;
}
-
+
// get the count of new entries
amount = (script_lastdata(st)-2)/2;
-
+
// append new items to existing shop item list
RECREATE(nd->u.shop.shop_item, struct npc_item_list, nd->u.shop.count+amount);
for( n = nd->u.shop.count, i = 3; n < nd->u.shop.count+amount; n++, i+=2 )
@@ -14378,7 +15021,7 @@ BUILDIN(npcshopadditem)
nd->u.shop.shop_item[n].value = script_getnum(st,i+1);
}
nd->u.shop.count = n;
-
+
script_pushint(st,1);
return true;
}
@@ -14386,26 +15029,26 @@ BUILDIN(npcshopadditem)
BUILDIN(npcshopdelitem)
{
const char* npcname = script_getstr(st,2);
- struct npc_data* nd = npc_name2id(npcname);
+ struct npc_data* nd = npc->name2id(npcname);
unsigned int nameid;
int n, i;
int amount;
int size;
-
- if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) )
- { //Not found.
+
+ if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) {
+ //Not found.
script_pushint(st,0);
return true;
}
-
+
amount = script_lastdata(st)-2;
size = nd->u.shop.count;
-
+
// remove specified items from the shop item list
for( i = 3; i < 3 + amount; i++ )
{
nameid = script_getnum(st,i);
-
+
ARR_FIND( 0, size, n, nd->u.shop.shop_item[n].nameid == nameid );
if( n < size )
{
@@ -14413,35 +15056,34 @@ BUILDIN(npcshopdelitem)
size--;
}
}
-
+
RECREATE(nd->u.shop.shop_item, struct npc_item_list, size);
nd->u.shop.count = size;
-
+
script_pushint(st,1);
return true;
}
//Sets a script to attach to a shop npc.
-BUILDIN(npcshopattach)
-{
+BUILDIN(npcshopattach) {
const char* npcname = script_getstr(st,2);
- struct npc_data* nd = npc_name2id(npcname);
+ struct npc_data* nd = npc->name2id(npcname);
int flag = 1;
-
+
if( script_hasdata(st,3) )
flag = script_getnum(st,3);
-
- if( !nd || nd->subtype != SHOP )
- { //Not found.
+
+ if( !nd || nd->subtype != SHOP ) {
+ //Not found.
script_pushint(st,0);
return true;
}
-
+
if (flag)
- nd->master_nd = ((struct npc_data *)iMap->id2bl(st->oid));
+ nd->master_nd = ((struct npc_data *)map->id2bl(st->oid));
else
nd->master_nd = NULL;
-
+
script_pushint(st,1);
return true;
}
@@ -14449,11 +15091,11 @@ BUILDIN(npcshopattach)
/*==========================================
* Returns some values of an item [Lupus]
* Price, Weight, etc...
- setitemscript(itemID,"{new item bonus script}",[n]);
- Where n:
- 0 - script
- 1 - Equip script
- 2 - Unequip script
+ * setitemscript(itemID,"{new item bonus script}",[n]);
+ * Where n:
+ * 0 - script
+ * 1 - Equip script
+ * 2 - Unequip script
*------------------------------------------*/
BUILDIN(setitemscript)
{
@@ -14461,13 +15103,13 @@ BUILDIN(setitemscript)
const char *new_bonus_script;
struct item_data *i_data;
struct script_code **dstscript;
-
- item_id = script_getnum(st,2);
+
+ item_id = script_getnum(st,2);
new_bonus_script = script_getstr(st,3);
if( script_hasdata(st,4) )
n=script_getnum(st,4);
- i_data = itemdb_exists(item_id);
-
+ i_data = itemdb->exists(item_id);
+
if (!i_data || new_bonus_script==NULL || ( new_bonus_script[0] && new_bonus_script[0]!='{' )) {
script_pushint(st,0);
return true;
@@ -14484,52 +15126,132 @@ BUILDIN(setitemscript)
break;
}
if(*dstscript)
- script_free_code(*dstscript);
-
- *dstscript = new_bonus_script[0] ? parse_script(new_bonus_script, "script_setitemscript", 0, 0) : NULL;
+ script->free_code(*dstscript);
+
+ *dstscript = new_bonus_script[0] ? script->parse(new_bonus_script, "script_setitemscript", 0, 0, NULL) : NULL;
script_pushint(st,1);
return true;
}
-/* Work In Progress [Lupus]
- BUILDIN(addmonsterdrop)
- {
- int class_,item_id,chance;
- class_=script_getnum(st,2);
- item_id=script_getnum(st,3);
- chance=script_getnum(st,4);
- if(class_>1000 && item_id>500 && chance>0) {
- script_pushint(st,1);
- } else {
- script_pushint(st,0);
- }
- }
-
- BUILDIN(delmonsterdrop)
- {
- int class_,item_id;
- class_=script_getnum(st,2);
- item_id=script_getnum(st,3);
- if(class_>1000 && item_id>500) {
- script_pushint(st,1);
- } else {
- script_pushint(st,0);
- }
- }
- */
+/*=======================================================
+ * Temporarily add or update a mob drop
+ * Original Idea By: [Lupus], [Akinari]
+ *
+ * addmonsterdrop <mob_id or name>,<item_id>,<rate>;
+ *
+ * If given an item the mob already drops, the rate
+ * is updated to the new rate. Rate must be in the range [1:10000]
+ * Returns 1 if succeeded (added/updated a mob drop)
+ *-------------------------------------------------------*/
+BUILDIN(addmonsterdrop) {
+ struct mob_db *monster;
+ int item_id, rate, i, c = MAX_MOB_DROP;
+
+ if( script_isstringtype(st,2) )
+ monster = mob->db(mob->db_searchname(script_getstr(st,2)));
+ else
+ monster = mob->db(script_getnum(st,2));
+
+ if( monster == mob->dummy ) {
+ if( script_isstringtype(st,2) ) {
+ ShowError("buildin_addmonsterdrop: invalid mob name: '%s'.\n", script_getstr(st,2));
+ } else {
+ ShowError("buildin_addmonsterdrop: invalid mob id: '%d'.\n", script_getnum(st,2));
+ }
+ return false;
+ }
+
+ item_id = script_getnum(st,3);
+ if( !itemdb->exists(item_id) ) {
+ ShowError("buildin_addmonsterdrop: Invalid item ID: '%d'.\n", item_id);
+ return false;
+ }
+
+ rate = script_getnum(st,4);
+ if( rate < 1 || rate > 10000 ) {
+ ShowWarning("buildin_addmonsterdrop: Invalid drop rate '%d'. Capping to the [1:10000] range.\n", rate);
+ rate = cap_value(rate,1,10000);
+ }
+
+ for( i = 0; i < MAX_MOB_DROP; i++ ) {
+ if( monster->dropitem[i].nameid == item_id ) // Item ID found
+ break;
+ if( c == MAX_MOB_DROP && monster->dropitem[i].nameid < 1 ) // First empty slot
+ c = i;
+ }
+ if( i < MAX_MOB_DROP ) // If the item ID was found, prefer it
+ c = i;
+
+ if( c < MAX_MOB_DROP ) {
+ // Fill in the slot with the item and rate
+ monster->dropitem[c].nameid = item_id;
+ monster->dropitem[c].p = rate;
+ script_pushint(st,1);
+ } else {
+ //No place to put the new drop
+ script_pushint(st,0);
+ }
+
+ return true;
+}
+
+/*=======================================================
+ * Temporarily remove a mob drop
+ * Original Idea By: [Lupus], [Akinari]
+ *
+ * delmonsterdrop <mob_id or name>,<item_id>;
+ *
+ * Returns 1 if succeeded (deleted a mob drop)
+ *-------------------------------------------------------*/
+BUILDIN(delmonsterdrop) {
+ struct mob_db *monster;
+ int item_id, i;
+
+ if( script_isstringtype(st, 2) )
+ monster = mob->db(mob->db_searchname(script_getstr(st, 2)));
+ else
+ monster = mob->db(script_getnum(st, 2));
+
+ if( monster == mob->dummy ) {
+ if( script_isstringtype(st, 2) ) {
+ ShowError("buildin_delmonsterdrop: invalid mob name: '%s'.\n", script_getstr(st,2));
+ } else {
+ ShowError("buildin_delmonsterdrop: invalid mob id: '%d'.\n", script_getnum(st,2));
+ }
+ return false;
+ }
+
+ item_id = script_getnum(st,3);
+ if( !itemdb->exists(item_id) ) {
+ ShowError("buildin_delmonsterdrop: Invalid item ID: '%d'.\n", item_id);
+ return false;
+ }
+
+ for( i = 0; i < MAX_MOB_DROP; i++ ) {
+ if( monster->dropitem[i].nameid == item_id ) {
+ monster->dropitem[i].nameid = 0;
+ monster->dropitem[i].p = 0;
+ script_pushint(st,1);
+ return true;
+ }
+ }
+ // No drop on that monster
+ script_pushint(st,0);
+ return true;
+}
/*==========================================
* Returns some values of a monster [Lupus]
* Name, Level, race, size, etc...
- getmonsterinfo(monsterID,queryIndex);
+ * getmonsterinfo(monsterID,queryIndex);
*------------------------------------------*/
BUILDIN(getmonsterinfo)
{
- struct mob_db *mob;
+ struct mob_db *monster;
int mob_id;
-
- mob_id = script_getnum(st,2);
- if (!mobdb_checkid(mob_id)) {
+
+ mob_id = script_getnum(st,2);
+ if (!mob->db_checkid(mob_id)) {
ShowError("buildin_getmonsterinfo: Wrong Monster ID: %i\n", mob_id);
if ( !script_getnum(st,3) ) //requested a string
script_pushconststr(st,"null");
@@ -14537,31 +15259,31 @@ BUILDIN(getmonsterinfo)
script_pushint(st,-1);
return -1;
}
- mob = mob_db(mob_id);
+ monster = mob->db(mob_id);
switch ( script_getnum(st,3) ) {
- case 0: script_pushstrcopy(st,mob->jname); break;
- case 1: script_pushint(st,mob->lv); break;
- case 2: script_pushint(st,mob->status.max_hp); break;
- case 3: script_pushint(st,mob->base_exp); break;
- case 4: script_pushint(st,mob->job_exp); break;
- case 5: script_pushint(st,mob->status.rhw.atk); break;
- case 6: script_pushint(st,mob->status.rhw.atk2); break;
- case 7: script_pushint(st,mob->status.def); break;
- case 8: script_pushint(st,mob->status.mdef); break;
- case 9: script_pushint(st,mob->status.str); break;
- case 10: script_pushint(st,mob->status.agi); break;
- case 11: script_pushint(st,mob->status.vit); break;
- case 12: script_pushint(st,mob->status.int_); break;
- case 13: script_pushint(st,mob->status.dex); break;
- case 14: script_pushint(st,mob->status.luk); break;
- case 15: script_pushint(st,mob->status.rhw.range); break;
- case 16: script_pushint(st,mob->range2); break;
- case 17: script_pushint(st,mob->range3); break;
- case 18: script_pushint(st,mob->status.size); break;
- case 19: script_pushint(st,mob->status.race); break;
- case 20: script_pushint(st,mob->status.def_ele); break;
- case 21: script_pushint(st,mob->status.mode); break;
- case 22: script_pushint(st,mob->mexp); break;
+ case 0: script_pushstrcopy(st,monster->jname); break;
+ case 1: script_pushint(st,monster->lv); break;
+ case 2: script_pushint(st,monster->status.max_hp); break;
+ case 3: script_pushint(st,monster->base_exp); break;
+ case 4: script_pushint(st,monster->job_exp); break;
+ case 5: script_pushint(st,monster->status.rhw.atk); break;
+ case 6: script_pushint(st,monster->status.rhw.atk2); break;
+ case 7: script_pushint(st,monster->status.def); break;
+ case 8: script_pushint(st,monster->status.mdef); break;
+ case 9: script_pushint(st,monster->status.str); break;
+ case 10: script_pushint(st,monster->status.agi); break;
+ case 11: script_pushint(st,monster->status.vit); break;
+ case 12: script_pushint(st,monster->status.int_); break;
+ case 13: script_pushint(st,monster->status.dex); break;
+ case 14: script_pushint(st,monster->status.luk); break;
+ case 15: script_pushint(st,monster->status.rhw.range); break;
+ case 16: script_pushint(st,monster->range2); break;
+ case 17: script_pushint(st,monster->range3); break;
+ case 18: script_pushint(st,monster->status.size); break;
+ case 19: script_pushint(st,monster->status.race); break;
+ case 20: script_pushint(st,monster->status.def_ele); break;
+ case 21: script_pushint(st,monster->status.mode); break;
+ case 22: script_pushint(st,monster->mexp); break;
default: script_pushint(st,-1); //wrong Index
}
return true;
@@ -14570,52 +15292,51 @@ BUILDIN(getmonsterinfo)
BUILDIN(checkvending) // check vending [Nab4]
{
TBL_PC *sd = NULL;
-
+
if(script_hasdata(st,2))
- sd = iMap->nick2sd(script_getstr(st,2));
+ sd = map->nick2sd(script_getstr(st,2));
else
- sd = script_rid2sd(st);
-
+ sd = script->rid2sd(st);
+
if(sd)
script_pushint(st, sd->state.autotrade ? 2 : sd->state.vending);
else
script_pushint(st,0);
-
+
return true;
}
-BUILDIN(checkchatting) // check chatting [Marka]
-{
+// check chatting [Marka]
+BUILDIN(checkchatting) {
TBL_PC *sd = NULL;
-
+
if(script_hasdata(st,2))
- sd = iMap->nick2sd(script_getstr(st,2));
+ sd = map->nick2sd(script_getstr(st,2));
else
- sd = script_rid2sd(st);
-
+ sd = script->rid2sd(st);
+
if(sd)
script_pushint(st,(sd->chatID != 0));
else
script_pushint(st,0);
-
+
return true;
}
-BUILDIN(checkidle)
-{
+BUILDIN(checkidle) {
TBL_PC *sd = NULL;
-
+
if (script_hasdata(st, 2))
- sd = iMap->nick2sd(script_getstr(st, 2));
+ sd = map->nick2sd(script_getstr(st, 2));
else
- sd = script_rid2sd(st);
-
+ sd = script->rid2sd(st);
+
if (sd)
- script_pushint(st, DIFF_TICK(last_tick, sd->idletime));
+ script_pushint(st, DIFF_TICK32(sockt->last_tick, sd->idletime)); // TODO: change this to int64 when we'll support 64 bit script values
else
script_pushint(st, 0);
-
+
return true;
}
@@ -14625,117 +15346,67 @@ BUILDIN(searchitem)
const char *itemname = script_getstr(st,3);
struct item_data *items[MAX_SEARCH];
int count;
-
+
char* name;
int32 start;
int32 id;
int32 i;
TBL_PC* sd = NULL;
-
- if ((items[0] = itemdb_exists(atoi(itemname))))
+
+ if ((items[0] = itemdb->exists(atoi(itemname))))
count = 1;
else {
- count = itemdb_searchname_array(items, ARRAYLENGTH(items), itemname);
+ count = itemdb->search_name_array(items, ARRAYLENGTH(items), itemname, 0);
if (count > MAX_SEARCH) count = MAX_SEARCH;
}
-
+
if (!count) {
script_pushint(st, 0);
return true;
}
-
+
if( !data_isreference(data) )
{
ShowError("script:searchitem: not a variable\n");
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;// not a variable
}
-
+
id = reference_getid(data);
start = reference_getindex(data);
name = reference_getname(data);
- if( not_array_variable(*name) )
- {
- ShowError("script:searchitem: illegal scope\n");
- script_reportdata(data);
- st->state = END;
- return false;// not supported
- }
-
+
if( not_server_variable(*name) )
{
- sd = script_rid2sd(st);
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;// no player attached
}
-
+
if( is_string_variable(name) )
{// string array
ShowError("script:searchitem: not an integer array reference\n");
- script_reportdata(data);
+ script->reportdata(data);
st->state = END;
return false;// not supported
}
-
+
for( i = 0; i < count; ++start, ++i )
{// Set array
- void* v = (void*)__64BPTRSIZE((int)items[i]->nameid);
- set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data));
+ void* v = (void*)h64BPTRSIZE((int)items[i]->nameid);
+ script->set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data));
}
-
- script_pushint(st, count);
- return true;
-}
-int axtoi(const char *hexStg)
-{
- int n = 0; // position in string
- int16 m = 0; // position in digit[] to shift
- int count; // loop index
- int intValue = 0; // integer value of hex string
- int digit[11]; // hold values to convert
- while (n < 10) {
- if (hexStg[n]=='\0')
- break;
- if (hexStg[n] > 0x29 && hexStg[n] < 0x40 ) //if 0 to 9
- digit[n] = hexStg[n] & 0x0f; //convert to int
- else if (hexStg[n] >='a' && hexStg[n] <= 'f') //if a to f
- digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int
- else if (hexStg[n] >='A' && hexStg[n] <= 'F') //if A to F
- digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int
- else break;
- n++;
- }
- count = n;
- m = n - 1;
- n = 0;
- while(n < count) {
- // digit[n] is value of hex digit at position n
- // (m << 2) is the number of positions to shift
- // OR the bits into return value
- intValue = intValue | (digit[n] << (m << 2));
- m--; // adjust the position to set
- n++; // next digit to process
- }
- return (intValue);
-}
-
-// [Lance] Hex string to integer converter
-BUILDIN(axtoi)
-{
- const char *hex = script_getstr(st,2);
- script_pushint(st,axtoi(hex));
+ script_pushint(st, count);
return true;
}
// [zBuffer] List of player cont commands --->
-BUILDIN(rid2name)
-{
+BUILDIN(rid2name) {
struct block_list *bl = NULL;
int rid = script_getnum(st,2);
- if((bl = iMap->id2bl(rid)))
- {
+ if((bl = map->id2bl(rid))) {
switch(bl->type) {
case BL_MOB: script_pushstrcopy(st,((TBL_MOB*)bl)->name); break;
case BL_PC: script_pushstrcopy(st,((TBL_PC*)bl)->status.name); break;
@@ -14755,93 +15426,91 @@ BUILDIN(rid2name)
return true;
}
-BUILDIN(pcblockmove)
-{
+BUILDIN(pcblockmove) {
int id, flag;
TBL_PC *sd = NULL;
-
+
id = script_getnum(st,2);
flag = script_getnum(st,3);
-
+
if(id)
- sd = iMap->id2sd(id);
+ sd = map->id2sd(id);
else
- sd = script_rid2sd(st);
-
+ sd = script->rid2sd(st);
+
if(sd)
sd->state.blockedmove = flag > 0;
-
+
return true;
}
-BUILDIN(pcfollow)
-{
+BUILDIN(pcfollow) {
int id, targetid;
TBL_PC *sd = NULL;
-
-
+
+
id = script_getnum(st,2);
targetid = script_getnum(st,3);
-
+
if(id)
- sd = iMap->id2sd(id);
+ sd = map->id2sd(id);
else
- sd = script_rid2sd(st);
-
+ sd = script->rid2sd(st);
+
if(sd)
pc->follow(sd, targetid);
-
- return true;
+
+ return true;
}
BUILDIN(pcstopfollow)
{
int id;
TBL_PC *sd = NULL;
-
-
+
+
id = script_getnum(st,2);
-
+
if(id)
- sd = iMap->id2sd(id);
+ sd = map->id2sd(id);
else
- sd = script_rid2sd(st);
-
+ sd = script->rid2sd(st);
+
if(sd)
pc->stop_following(sd);
-
+
return true;
}
// <--- [zBuffer] List of player cont commands
// [zBuffer] List of mob control commands --->
//## TODO always return if the request/whatever was successfull [FlavioJS]
-/// Makes the unit walk to target position or map
+/// Makes the unit walk to target position or target id
/// Returns if it was successfull
///
/// unitwalk(<unit_id>,<x>,<y>) -> <bool>
-/// unitwalk(<unit_id>,<map_id>) -> <bool>
-BUILDIN(unitwalk)
-{
+/// unitwalk(<unit_id>,<target_id>) -> <bool>
+BUILDIN(unitwalk) {
struct block_list* bl;
-
- bl = iMap->id2bl(script_getnum(st,2));
- if( bl == NULL )
- {
+
+ bl = map->id2bl(script_getnum(st,2));
+ if( bl == NULL ) {
script_pushint(st, 0);
+ return true;
}
- else if( script_hasdata(st,4) )
- {
+
+ if( bl->type == BL_NPC ) {
+ unit->bl2ud2(bl); // ensure the ((TBL_NPC*)bl)->ud is safe to edit
+ }
+ if( script_hasdata(st,4) ) {
int x = script_getnum(st,3);
int y = script_getnum(st,4);
- script_pushint(st, unit_walktoxy(bl,x,y,0));// We'll use harder calculations.
- }
- else
- {
- int map_id = script_getnum(st,3);
- script_pushint(st, unit_walktobl(bl,iMap->id2bl(map_id),65025,1));
+ script_pushint(st, unit->walktoxy(bl,x,y,0));// We'll use harder calculations.
+ } else {
+ int target_id = script_getnum(st,3);
+ script_pushint(st, unit->walktobl(bl,map->id2bl(target_id),1,1));
}
-
+
return true;
}
@@ -14850,10 +15519,10 @@ BUILDIN(unitwalk)
/// unitkill <unit_id>;
BUILDIN(unitkill)
{
- struct block_list* bl = iMap->id2bl(script_getnum(st,2));
+ struct block_list* bl = map->id2bl(script_getnum(st,2));
if( bl != NULL )
status_kill(bl);
-
+
return true;
}
@@ -14861,35 +15530,36 @@ BUILDIN(unitkill)
/// Returns if it was successfull
///
/// unitwarp(<unit_id>,"<map name>",<x>,<y>) -> <bool>
-BUILDIN(unitwarp)
-{
+BUILDIN(unitwarp) {
int unit_id;
- int map;
+ int mapid;
short x;
short y;
struct block_list* bl;
const char *mapname;
-
+
unit_id = script_getnum(st,2);
mapname = script_getstr(st, 3);
x = (short)script_getnum(st,4);
y = (short)script_getnum(st,5);
-
+
if (!unit_id) //Warp the script's runner
- bl = iMap->id2bl(st->rid);
+ bl = map->id2bl(st->rid);
else
- bl = iMap->id2bl(unit_id);
-
+ bl = map->id2bl(unit_id);
+
if( strcmp(mapname,"this") == 0 )
- map = bl?bl->m:-1;
- else
- map = iMap->mapname2mapid(mapname);
-
- if( map >= 0 && bl != NULL )
- script_pushint(st, unit_warp(bl,map,x,y,CLR_OUTSIGHT));
+ mapid = bl?bl->m:-1;
else
+ mapid = map->mapname2mapid(mapname);
+
+ if( mapid >= 0 && bl != NULL ) {
+ unit->bl2ud2(bl); // ensure ((TBL_NPC*)bl)->ud is safe to edit
+ script_pushint(st, unit->warp(bl,mapid,x,y,CLR_OUTSIGHT));
+ } else {
script_pushint(st, 0);
-
+ }
+
return true;
}
@@ -14900,44 +15570,39 @@ BUILDIN(unitwarp)
///
/// unitattack(<unit_id>,"<target name>"{,<action type>}) -> <bool>
/// unitattack(<unit_id>,<target_id>{,<action type>}) -> <bool>
-BUILDIN(unitattack)
-{
+BUILDIN(unitattack) {
struct block_list* unit_bl;
struct block_list* target_bl = NULL;
- struct script_data* data;
int actiontype = 0;
-
+
// get unit
- unit_bl = iMap->id2bl(script_getnum(st,2));
+ unit_bl = map->id2bl(script_getnum(st,2));
if( unit_bl == NULL ) {
script_pushint(st, 0);
return true;
}
-
- data = script_getdata(st, 3);
- script->get_val(st, data);
- if( data_isstring(data) )
- {
- TBL_PC* sd = iMap->nick2sd(script->conv_str(st, data));
+
+ if( script_isstringtype(st, 3) ) {
+ TBL_PC* sd = map->nick2sd(script_getstr(st, 3));
if( sd != NULL )
target_bl = &sd->bl;
} else
- target_bl = iMap->id2bl(script->conv_num(st, data));
+ target_bl = map->id2bl(script_getnum(st, 3));
// request the attack
if( target_bl == NULL )
{
script_pushint(st, 0);
return true;
}
-
+
// get actiontype
if( script_hasdata(st,4) )
actiontype = script_getnum(st,4);
-
+
switch( unit_bl->type )
{
case BL_PC:
- clif->pActionRequest_sub(((TBL_PC *)unit_bl), actiontype > 0 ? 0x07 : 0x00, target_bl->id, iTimer->gettick());
+ clif->pActionRequest_sub(((TBL_PC *)unit_bl), actiontype > 0 ? 0x07 : 0x00, target_bl->id, timer->gettick());
script_pushint(st, 1);
return true;
case BL_MOB:
@@ -14951,56 +15616,53 @@ BUILDIN(unitattack)
script_pushint(st, 0);
return false;
}
- script_pushint(st, unit_walktobl(unit_bl, target_bl, 65025, 2));
+ script_pushint(st, unit->walktobl(unit_bl, target_bl, 65025, 2));
return true;
}
/// Makes the unit stop attacking and moving
///
/// unitstop <unit_id>;
-BUILDIN(unitstop)
-{
+BUILDIN(unitstop) {
int unit_id;
struct block_list* bl;
-
+
unit_id = script_getnum(st,2);
-
- bl = iMap->id2bl(unit_id);
- if( bl != NULL )
- {
- unit_stop_attack(bl);
- unit_stop_walking(bl,4);
+
+ bl = map->id2bl(unit_id);
+ if( bl != NULL ) {
+ unit->bl2ud2(bl); // ensure ((TBL_NPC*)bl)->ud is safe to edit
+ unit->stop_attack(bl);
+ unit->stop_walking(bl,4);
if( bl->type == BL_MOB )
((TBL_MOB*)bl)->target_id = 0;
}
-
+
return true;
}
/// Makes the unit say the message
///
/// unittalk <unit_id>,"<message>";
-BUILDIN(unittalk)
-{
+BUILDIN(unittalk) {
int unit_id;
const char* message;
struct block_list* bl;
-
+
unit_id = script_getnum(st,2);
message = script_getstr(st, 3);
-
- bl = iMap->id2bl(unit_id);
- if( bl != NULL )
- {
+
+ bl = map->id2bl(unit_id);
+ if( bl != NULL ) {
struct StringBuf sbuf;
StrBuf->Init(&sbuf);
- StrBuf->Printf(&sbuf, "%s : %s", status_get_name(bl), message);
+ StrBuf->Printf(&sbuf, "%s : %s", status->get_name(bl), message);
clif->disp_overhead(bl, StrBuf->Value(&sbuf));
if( bl->type == BL_PC )
clif->message(((TBL_PC*)bl)->fd, StrBuf->Value(&sbuf));
StrBuf->Destroy(&sbuf);
}
-
+
return true;
}
@@ -15009,18 +15671,17 @@ BUILDIN(unittalk)
/// unitemote <unit_id>,<emotion>;
///
/// @see e_* in const.txt
-BUILDIN(unitemote)
-{
+BUILDIN(unitemote) {
int unit_id;
int emotion;
struct block_list* bl;
-
+
unit_id = script_getnum(st,2);
emotion = script_getnum(st,3);
- bl = iMap->id2bl(unit_id);
+ bl = map->id2bl(unit_id);
if( bl != NULL )
clif->emotion(bl, emotion);
-
+
return true;
}
@@ -15028,23 +15689,31 @@ BUILDIN(unitemote)
///
/// unitskilluseid <unit_id>,<skill_id>,<skill_lv>{,<target_id>};
/// unitskilluseid <unit_id>,"<skill name>",<skill_lv>{,<target_id>};
-BUILDIN(unitskilluseid)
-{
+BUILDIN(unitskilluseid) {
int unit_id;
uint16 skill_id;
uint16 skill_lv;
int target_id;
struct block_list* bl;
-
+
unit_id = script_getnum(st,2);
- skill_id = ( script_isstring(st,3) ? skill->name2id(script_getstr(st,3)) : script_getnum(st,3) );
+ skill_id = ( script_isstringtype(st, 3) ? skill->name2id(script_getstr(st, 3)) : script_getnum(st, 3) );
skill_lv = script_getnum(st,4);
target_id = ( script_hasdata(st,5) ? script_getnum(st,5) : unit_id );
-
- bl = iMap->id2bl(unit_id);
- if( bl != NULL )
- unit_skilluse_id(bl, target_id, skill_id, skill_lv);
-
+
+ bl = map->id2bl(unit_id);
+
+ if( bl != NULL ) {
+ if( bl->type == BL_NPC ) {
+ if (!((TBL_NPC*)bl)->status.hp) {
+ status_calc_npc(((TBL_NPC*)bl), SCO_FIRST);
+ } else {
+ status_calc_npc(((TBL_NPC*)bl), SCO_NONE);
+ }
+ }
+ unit->skilluse_id(bl, target_id, skill_id, skill_lv);
+ }
+
return true;
}
@@ -15052,25 +15721,33 @@ BUILDIN(unitskilluseid)
///
/// unitskillusepos <unit_id>,<skill_id>,<skill_lv>,<target_x>,<target_y>;
/// unitskillusepos <unit_id>,"<skill name>",<skill_lv>,<target_x>,<target_y>;
-BUILDIN(unitskillusepos)
-{
+BUILDIN(unitskillusepos) {
int unit_id;
uint16 skill_id;
uint16 skill_lv;
int skill_x;
int skill_y;
struct block_list* bl;
-
+
unit_id = script_getnum(st,2);
- skill_id = ( script_isstring(st,3) ? skill->name2id(script_getstr(st,3)) : script_getnum(st,3) );
+ skill_id = ( script_isstringtype(st, 3) ? skill->name2id(script_getstr(st, 3)) : script_getnum(st, 3) );
skill_lv = script_getnum(st,4);
skill_x = script_getnum(st,5);
skill_y = script_getnum(st,6);
-
- bl = iMap->id2bl(unit_id);
- if( bl != NULL )
- unit_skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv);
-
+
+ bl = map->id2bl(unit_id);
+
+ if( bl != NULL ) {
+ if( bl->type == BL_NPC ) {
+ if (!((TBL_NPC*)bl)->status.hp) {
+ status_calc_npc(((TBL_NPC*)bl), SCO_FIRST);
+ } else {
+ status_calc_npc(((TBL_NPC*)bl), SCO_NONE);
+ }
+ }
+ unit->skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv);
+ }
+
return true;
}
@@ -15082,12 +15759,12 @@ BUILDIN(unitskillusepos)
BUILDIN(sleep)
{
int ticks;
-
+
ticks = script_getnum(st,2);
-
+
// detach the player
- script_detach_rid(st);
-
+ script->detach_rid(st);
+
if( ticks <= 0 )
{// do nothing
}
@@ -15108,26 +15785,23 @@ BUILDIN(sleep)
/// Returns if a player is still attached
///
/// sleep2(<mili secconds>) -> <bool>
-BUILDIN(sleep2)
-{
+BUILDIN(sleep2) {
int ticks;
-
+
ticks = script_getnum(st,2);
-
- if( ticks <= 0 )
- {// do nothing
- script_pushint(st, (iMap->id2sd(st->rid)!=NULL));
- }
- else if( !st->sleep.tick )
- {// sleep for the target amount of time
+
+ if( ticks <= 0 ) {
+ // do nothing
+ script_pushint(st, (map->id2sd(st->rid)!=NULL));
+ } else if( !st->sleep.tick ) {
+ // sleep for the target amount of time
st->state = RERUNLINE;
st->sleep.tick = ticks;
- }
- else
- {// sleep time is over
+ } else {
+ // sleep time is over
st->state = RUN;
st->sleep.tick = 0;
- script_pushint(st, (iMap->id2sd(st->rid)!=NULL));
+ script_pushint(st, (map->id2sd(st->rid)!=NULL));
}
return true;
}
@@ -15139,18 +15813,18 @@ BUILDIN(awake) {
DBIterator *iter;
struct script_state *tst;
struct npc_data* nd;
-
- if( ( nd = npc_name2id(script_getstr(st, 2)) ) == NULL ) {
+
+ if( ( nd = npc->name2id(script_getstr(st, 2)) ) == NULL ) {
ShowError("awake: NPC \"%s\" not found\n", script_getstr(st, 2));
return false;
}
-
+
iter = db_iterator(script->st_db);
-
+
for( tst = dbi_first(iter); dbi_exists(iter); tst = dbi_next(iter) ) {
if( tst->oid == nd->bl.id ) {
- TBL_PC* sd = iMap->id2sd(tst->rid);
-
+ TBL_PC* sd = map->id2sd(tst->rid);
+
if( tst->sleep.timer == INVALID_TIMER ) {// already awake ???
continue;
}
@@ -15159,17 +15833,17 @@ BUILDIN(awake) {
tst->state = END;
tst->rid = 0;
}
-
- iTimer->delete_timer(tst->sleep.timer, run_script_timer);
+
+ timer->delete(tst->sleep.timer, script->run_timer);
tst->sleep.timer = INVALID_TIMER;
if(tst->state != RERUNLINE)
tst->sleep.tick = 0;
- run_script_main(tst);
+ script->run_main(tst);
}
}
-
+
dbi_destroy(iter);
-
+
return true;
}
@@ -15182,28 +15856,28 @@ BUILDIN(getvariableofnpc)
struct script_data* data;
const char* name;
struct npc_data* nd;
-
+
data = script_getdata(st,2);
if( !data_isreference(data) )
{// Not a reference (aka varaible name)
ShowError("script:getvariableofnpc: not a variable\n");
- script_reportdata(data);
+ script->reportdata(data);
script_pushnil(st);
st->state = END;
return false;
}
-
+
name = reference_getname(data);
if( *name != '.' || name[1] == '@' )
{// not a npc variable
ShowError("script:getvariableofnpc: invalid scope (not npc variable)\n");
- script_reportdata(data);
+ script->reportdata(data);
script_pushnil(st);
st->state = END;
return false;
}
-
- nd = npc_name2id(script_getstr(st,3));
+
+ nd = npc->name2id(script_getstr(st,3));
if( nd == NULL || nd->subtype != SCRIPT || nd->u.scr.script == NULL )
{// NPC not found or has no script
ShowError("script:getvariableofnpc: can't find npc %s\n", script_getstr(st,3));
@@ -15211,8 +15885,11 @@ BUILDIN(getvariableofnpc)
st->state = END;
return false;
}
+
+ if( !nd->u.scr.script->local.vars )
+ nd->u.scr.script->local.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
- script->push_val(st->stack, C_NAME, reference_getuid(data), &nd->u.scr.script->script_vars );
+ script->push_val(st->stack, C_NAME, reference_getuid(data), &nd->u.scr.script->local);
return true;
}
@@ -15222,65 +15899,64 @@ BUILDIN(getvariableofnpc)
/// warpportal <source x>,<source y>,"<target map>",<target x>,<target y>;
///
/// @author blackhole89
-BUILDIN(warpportal)
-{
+BUILDIN(warpportal) {
int spx;
int spy;
- unsigned short mapindex;
+ unsigned short map_index;
int tpx;
int tpy;
struct skill_unit_group* group;
struct block_list* bl;
-
- bl = iMap->id2bl(st->oid);
+
+ bl = map->id2bl(st->oid);
if( bl == NULL )
{
ShowError("script:warpportal: npc is needed\n");
return false;
}
-
+
spx = script_getnum(st,2);
spy = script_getnum(st,3);
- mapindex = mapindex_name2id(script_getstr(st, 4));
+ map_index = script->mapindexname2id(st,script_getstr(st, 4));
tpx = script_getnum(st,5);
tpy = script_getnum(st,6);
-
- if( mapindex == 0 )
+
+ if( map_index == 0 )
return true;// map not found
-
+
group = skill->unitsetting(bl, AL_WARP, 4, spx, spy, 0);
if( group == NULL )
return true;// failed
group->val1 = (group->val1<<16)|(short)0;
group->val2 = (tpx<<16) | tpy;
- group->val3 = mapindex;
-
+ group->val3 = map_index;
+
return true;
}
BUILDIN(openmail)
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
mail->openmail(sd);
-
+
return true;
}
BUILDIN(openauction)
{
TBL_PC* sd;
-
- sd = script_rid2sd(st);
+
+ sd = script->rid2sd(st);
if( sd == NULL )
return true;
-
+
clif->auction_openwindow(sd);
-
+
return true;
}
@@ -15289,15 +15965,19 @@ BUILDIN(openauction)
/// checkcell("<map name>",<x>,<y>,<type>) -> <bool>
///
/// @see cell_chk* constants in const.txt for the types
-BUILDIN(checkcell)
-{
- int16 m = iMap->mapname2mapid(script_getstr(st,2));
+BUILDIN(checkcell) {
+ int16 m = map->mapname2mapid(script_getstr(st,2));
int16 x = script_getnum(st,3);
int16 y = script_getnum(st,4);
cell_chk type = (cell_chk)script_getnum(st,5);
-
- script_pushint(st, iMap->getcell(m, x, y, type));
-
+
+ if ( m == -1 ) {
+ ShowWarning("checkcell: Attempted to run on unexsitent map '%s', type %d, x/y %d,%d\n",script_getstr(st,2),type,x,y);
+ return true;
+ }
+
+ script_pushint(st, map->getcell(m, x, y, type));
+
return true;
}
@@ -15306,25 +15986,29 @@ BUILDIN(checkcell)
/// setcell "<map name>",<x1>,<y1>,<x2>,<y2>,<type>,<flag>;
///
/// @see cell_* constants in const.txt for the types
-BUILDIN(setcell)
-{
- int16 m = iMap->mapname2mapid(script_getstr(st,2));
+BUILDIN(setcell) {
+ int16 m = map->mapname2mapid(script_getstr(st,2));
int16 x1 = script_getnum(st,3);
int16 y1 = script_getnum(st,4);
int16 x2 = script_getnum(st,5);
int16 y2 = script_getnum(st,6);
cell_t type = (cell_t)script_getnum(st,7);
bool flag = (bool)script_getnum(st,8);
-
+
int x,y;
-
+
+ if ( m == -1 ) {
+ ShowWarning("setcell: Attempted to run on unexistent map '%s', type %d, x1/y1 - %d,%d | x2/y2 - %d,%d\n",script_getstr(st, 2),type,x1,y1,x2,y2);
+ return true;
+ }
+
if( x1 > x2 ) swap(x1,x2);
if( y1 > y2 ) swap(y1,y2);
-
+
for( y = y1; y <= y2; ++y )
for( x = x1; x <= x2; ++x )
- map[m].setcell(m, x, y, type, flag);
-
+ map->list[m].setcell(m, x, y, type, flag);
+
return true;
}
@@ -15335,62 +16019,58 @@ BUILDIN(mercenary_create)
{
struct map_session_data *sd;
int class_, contract_time;
-
- if( (sd = script_rid2sd(st)) == NULL || sd->md || sd->status.mer_id != 0 )
+
+ if( (sd = script->rid2sd(st)) == NULL || sd->md || sd->status.mer_id != 0 )
return true;
-
+
class_ = script_getnum(st,2);
-
- if( !merc_class(class_) )
+
+ if( !mercenary->class(class_) )
return true;
-
+
contract_time = script_getnum(st,3);
- merc_create(sd, class_, contract_time);
+ mercenary->create(sd, class_, contract_time);
return true;
}
-BUILDIN(mercenary_heal)
-{
- struct map_session_data *sd = script_rid2sd(st);
+BUILDIN(mercenary_heal) {
+ struct map_session_data *sd = script->rid2sd(st);
int hp, sp;
-
+
if( sd == NULL || sd->md == NULL )
return true;
hp = script_getnum(st,2);
sp = script_getnum(st,3);
-
- status_heal(&sd->md->bl, hp, sp, 0);
+
+ status->heal(&sd->md->bl, hp, sp, 0);
return true;
}
-BUILDIN(mercenary_sc_start)
-{
- struct map_session_data *sd = script_rid2sd(st);
+BUILDIN(mercenary_sc_start) {
+ struct map_session_data *sd = script->rid2sd(st);
enum sc_type type;
int tick, val1;
-
+
if( sd == NULL || sd->md == NULL )
return true;
-
+
type = (sc_type)script_getnum(st,2);
tick = script_getnum(st,3);
val1 = script_getnum(st,4);
-
- status_change_start(&sd->md->bl, type, 10000, val1, 0, 0, 0, tick, 2);
+
+ status->change_start(NULL, &sd->md->bl, type, 10000, val1, 0, 0, 0, tick, 2);
return true;
}
-BUILDIN(mercenary_get_calls)
-{
- struct map_session_data *sd = script_rid2sd(st);
- int guild;
-
+BUILDIN(mercenary_get_calls) {
+ struct map_session_data *sd = script->rid2sd(st);
+ int guild_id;
+
if( sd == NULL )
return true;
-
- guild = script_getnum(st,2);
- switch( guild )
- {
+
+ guild_id = script_getnum(st,2);
+ switch( guild_id ) {
case ARCH_MERC_GUILD:
script_pushint(st,sd->status.arch_calls);
break;
@@ -15404,23 +16084,21 @@ BUILDIN(mercenary_get_calls)
script_pushint(st,0);
break;
}
-
+
return true;
}
-BUILDIN(mercenary_set_calls)
-{
- struct map_session_data *sd = script_rid2sd(st);
- int guild, value, *calls;
-
+BUILDIN(mercenary_set_calls) {
+ struct map_session_data *sd = script->rid2sd(st);
+ int guild_id, value, *calls;
+
if( sd == NULL )
return true;
-
- guild = script_getnum(st,2);
+
+ guild_id = script_getnum(st,2);
value = script_getnum(st,3);
-
- switch( guild )
- {
+
+ switch( guild_id ) {
case ARCH_MERC_GUILD:
calls = &sd->status.arch_calls;
break;
@@ -15433,24 +16111,22 @@ BUILDIN(mercenary_set_calls)
default:
return true; // Invalid Guild
}
-
+
*calls += value;
*calls = cap_value(*calls, 0, INT_MAX);
-
+
return true;
}
-BUILDIN(mercenary_get_faith)
-{
- struct map_session_data *sd = script_rid2sd(st);
- int guild;
-
+BUILDIN(mercenary_get_faith) {
+ struct map_session_data *sd = script->rid2sd(st);
+ int guild_id;
+
if( sd == NULL )
return true;
-
- guild = script_getnum(st,2);
- switch( guild )
- {
+
+ guild_id = script_getnum(st,2);
+ switch( guild_id ) {
case ARCH_MERC_GUILD:
script_pushint(st,sd->status.arch_faith);
break;
@@ -15464,23 +16140,21 @@ BUILDIN(mercenary_get_faith)
script_pushint(st,0);
break;
}
-
+
return true;
}
-BUILDIN(mercenary_set_faith)
-{
- struct map_session_data *sd = script_rid2sd(st);
- int guild, value, *calls;
-
+BUILDIN(mercenary_set_faith) {
+ struct map_session_data *sd = script->rid2sd(st);
+ int guild_id, value, *calls;
+
if( sd == NULL )
return true;
-
- guild = script_getnum(st,2);
+
+ guild_id = script_getnum(st,2);
value = script_getnum(st,3);
-
- switch( guild )
- {
+
+ switch( guild_id ) {
case ARCH_MERC_GUILD:
calls = &sd->status.arch_faith;
break;
@@ -15493,12 +16167,12 @@ BUILDIN(mercenary_set_faith)
default:
return true; // Invalid Guild
}
-
+
*calls += value;
*calls = cap_value(*calls, 0, INT_MAX);
- if( mercenary_get_guild(sd->md) == guild )
+ if( mercenary->get_guild(sd->md) == guild_id )
clif->mercenary_updatestatus(sd,SP_MERCFAITH);
-
+
return true;
}
@@ -15509,337 +16183,419 @@ BUILDIN(readbook)
{
struct map_session_data *sd;
int book_id, page;
-
- if( (sd = script_rid2sd(st)) == NULL )
+
+ if( (sd = script->rid2sd(st)) == NULL )
return true;
-
+
book_id = script_getnum(st,2);
page = script_getnum(st,3);
-
+
clif->readbook(sd->fd, book_id, page);
return true;
}
-/******************
- Questlog script commands
- *******************/
+/****************************
+ * Questlog script commands *
+ ****************************/
-BUILDIN(setquest)
+BUILDIN(questinfo)
{
- struct map_session_data *sd = script_rid2sd(st);
- nullpo_ret(sd);
-
- quest_add(sd, script_getnum(st, 2));
+ struct npc_data *nd = map->id2nd(st->oid);
+ int quest_id, icon, job, color = 0;
+ struct questinfo qi;
+
+ if( nd == NULL || nd->bl.m == -1 )
+ return true;
+
+ quest_id = script_getnum(st, 2);
+ icon = script_getnum(st, 3);
+
+ #if PACKETVER >= 20120410
+ if(icon < 0 || (icon > 8 && icon != 9999) || icon == 7)
+ icon = 9999; // Default to nothing if icon id is invalid.
+ #else
+ if(icon < 0 || icon > 7)
+ icon = 0;
+ else
+ icon = icon + 1;
+ #endif
+
+ qi.quest_id = quest_id;
+ qi.icon = (unsigned char)icon;
+ qi.nd = nd;
+
+ if( script_hasdata(st, 4) ) {
+ color = script_getnum(st, 4);
+ if( color < 0 || color > 3 ) {
+ ShowWarning("buildin_questinfo: invalid color '%d', changing to 0\n",color);
+ script->reportfunc(st);
+ color = 0;
+ }
+ qi.color = (unsigned char)color;
+ }
+
+ qi.hasJob = false;
+
+ if(script_hasdata(st, 5)) {
+ job = script_getnum(st, 5);
+
+ if (!pcdb_checkid(job))
+ ShowError("buildin_questinfo: Nonexistant Job Class.\n");
+ else {
+ qi.hasJob = true;
+ qi.job = (unsigned short)job;
+ }
+ }
+
+ map->add_questinfo(nd->bl.m,&qi);
+
return true;
}
-BUILDIN(erasequest)
-{
- struct map_session_data *sd = script_rid2sd(st);
- nullpo_ret(sd);
-
- quest_delete(sd, script_getnum(st, 2));
+BUILDIN(setquest) {
+ struct map_session_data *sd = script->rid2sd(st);
+ unsigned short i;
+ int quest_id;
+
+ if( sd == NULL )
+ return false;
+
+ quest_id = script_getnum(st, 2);
+
+ quest->add(sd, quest_id);
+
+ // If questinfo is set, remove quest bubble once quest is set.
+ for(i = 0; i < map->list[sd->bl.m].qi_count; i++) {
+ struct questinfo *qi = &map->list[sd->bl.m].qi_data[i];
+ if( qi->quest_id == quest_id ) {
+#if PACKETVER >= 20120410
+ clif->quest_show_event(sd, &qi->nd->bl, 9999, 0);
+#else
+ clif->quest_show_event(sd, &qi->nd->bl, 0, 0);
+#endif
+ }
+ }
+
return true;
}
-BUILDIN(completequest)
-{
- struct map_session_data *sd = script_rid2sd(st);
- nullpo_ret(sd);
-
- quest_update_status(sd, script_getnum(st, 2), Q_COMPLETE);
+BUILDIN(erasequest) {
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
+ quest->delete(sd, script_getnum(st, 2));
return true;
}
-BUILDIN(changequest)
-{
- struct map_session_data *sd = script_rid2sd(st);
- nullpo_ret(sd);
-
- quest_change(sd, script_getnum(st, 2),script_getnum(st, 3));
+BUILDIN(completequest) {
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
+ quest->update_status(sd, script_getnum(st, 2), Q_COMPLETE);
return true;
}
-BUILDIN(checkquest)
-{
- struct map_session_data *sd = script_rid2sd(st);
- quest_check_type type = HAVEQUEST;
-
- nullpo_ret(sd);
-
+BUILDIN(changequest) {
+ struct map_session_data *sd = script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
+ quest->change(sd, script_getnum(st, 2),script_getnum(st, 3));
+ return true;
+}
+
+BUILDIN(checkquest) {
+ struct map_session_data *sd = script->rid2sd(st);
+ enum quest_check_type type = HAVEQUEST;
+
+ if( sd == NULL )
+ return false;
+
if( script_hasdata(st, 3) )
- type = (quest_check_type)script_getnum(st, 3);
-
- script_pushint(st, quest_check(sd, script_getnum(st, 2), type));
-
+ type = (enum quest_check_type)script_getnum(st, 3);
+
+ script_pushint(st, quest->check(sd, script_getnum(st, 2), type));
+
return true;
}
-BUILDIN(showevent)
-{
- TBL_PC *sd = script_rid2sd(st);
- struct npc_data *nd = iMap->id2nd(st->oid);
- int state, color;
-
+BUILDIN(showevent) {
+ TBL_PC *sd = script->rid2sd(st);
+ struct npc_data *nd = map->id2nd(st->oid);
+ int icon, color = 0;
+
if( sd == NULL || nd == NULL )
return true;
- state = script_getnum(st, 2);
- color = script_getnum(st, 3);
-
- if( color < 0 || color > 3 )
- color = 0; // set default color
-
- clif->quest_show_event(sd, &nd->bl, state, color);
+
+ icon = script_getnum(st, 2);
+ if( script_hasdata(st, 3) ) {
+ color = script_getnum(st, 3);
+ if( color < 0 || color > 3 ) {
+ ShowWarning("buildin_showevent: invalid color '%d', changing to 0\n",color);
+ script->reportfunc(st);
+ color = 0;
+ }
+ }
+
+ #if PACKETVER >= 20120410
+ if(icon < 0 || (icon > 8 && icon != 9999) || icon == 7)
+ icon = 9999; // Default to nothing if icon id is invalid.
+ #else
+ if(icon < 0 || icon > 7)
+ icon = 0;
+ else
+ icon = icon + 1;
+ #endif
+
+ clif->quest_show_event(sd, &nd->bl, icon, color);
return true;
}
/*==========================================
* BattleGround System
*------------------------------------------*/
-BUILDIN(waitingroom2bg)
-{
+BUILDIN(waitingroom2bg) {
struct npc_data *nd;
struct chat_data *cd;
const char *map_name, *ev = "", *dev = "";
- int x, y, i, mapindex = 0, bg_id, n;
+ int x, y, i, map_index = 0, bg_id, n;
struct map_session_data *sd;
-
+
if( script_hasdata(st,7) )
- nd = npc_name2id(script_getstr(st,7));
+ nd = npc->name2id(script_getstr(st,7));
else
- nd = (struct npc_data *)iMap->id2bl(st->oid);
-
- if( nd == NULL || (cd = (struct chat_data *)iMap->id2bl(nd->chat_id)) == NULL )
- {
+ nd = (struct npc_data *)map->id2bl(st->oid);
+
+ if( nd == NULL || (cd = (struct chat_data *)map->id2bl(nd->chat_id)) == NULL ) {
script_pushint(st,0);
return true;
}
-
+
map_name = script_getstr(st,2);
if( strcmp(map_name,"-") != 0 )
{
- mapindex = mapindex_name2id(map_name);
- if( mapindex == 0 )
+ map_index = script->mapindexname2id(st,map_name);
+ if( map_index == 0 )
{ // Invalid Map
script_pushint(st,0);
return true;
}
}
-
+
x = script_getnum(st,3);
y = script_getnum(st,4);
ev = script_getstr(st,5); // Logout Event
dev = script_getstr(st,6); // Die Event
-
- if( (bg_id = bg_create(mapindex, x, y, ev, dev)) == 0 )
+
+ if( (bg_id = bg->create(map_index, x, y, ev, dev)) == 0 )
{ // Creation failed
script_pushint(st,0);
return true;
}
-
+
n = cd->users;
for( i = 0; i < n && i < MAX_BG_MEMBERS; i++ )
{
- if( (sd = cd->usersd[i]) != NULL && bg_team_join(bg_id, sd) )
- mapreg_setreg(reference_uid(add_str("$@arenamembers"), i), sd->bl.id);
+ if( (sd = cd->usersd[i]) != NULL && bg->team_join(bg_id, sd) )
+ mapreg->setreg(reference_uid(script->add_str("$@arenamembers"), i), sd->bl.id);
else
- mapreg_setreg(reference_uid(add_str("$@arenamembers"), i), 0);
+ mapreg->setreg(reference_uid(script->add_str("$@arenamembers"), i), 0);
}
-
- mapreg_setreg(add_str("$@arenamembersnum"), i);
+
+ mapreg->setreg(script->add_str("$@arenamembersnum"), i);
script_pushint(st,bg_id);
return true;
}
-BUILDIN(waitingroom2bg_single)
-{
+BUILDIN(waitingroom2bg_single) {
const char* map_name;
struct npc_data *nd;
struct chat_data *cd;
struct map_session_data *sd;
- int x, y, mapindex, bg_id;
-
+ int x, y, map_index, bg_id;
+
bg_id = script_getnum(st,2);
map_name = script_getstr(st,3);
- if( (mapindex = mapindex_name2id(map_name)) == 0 )
+ if( (map_index = script->mapindexname2id(st,map_name)) == 0 )
return true; // Invalid Map
-
+
x = script_getnum(st,4);
y = script_getnum(st,5);
- nd = npc_name2id(script_getstr(st,6));
-
- if( nd == NULL || (cd = (struct chat_data *)iMap->id2bl(nd->chat_id)) == NULL || cd->users <= 0 )
+ nd = npc->name2id(script_getstr(st,6));
+
+ if( nd == NULL || (cd = (struct chat_data *)map->id2bl(nd->chat_id)) == NULL || cd->users <= 0 )
return true;
-
+
if( (sd = cd->usersd[0]) == NULL )
return true;
-
- if( bg_team_join(bg_id, sd) )
+
+ if( bg->team_join(bg_id, sd) )
{
- pc->setpos(sd, mapindex, x, y, CLR_TELEPORT);
+ pc->setpos(sd, map_index, x, y, CLR_TELEPORT);
script_pushint(st,1);
}
else
script_pushint(st,0);
-
+
return true;
}
BUILDIN(bg_team_setxy)
{
- struct battleground_data *bg;
+ struct battleground_data *bgd;
int bg_id;
-
+
bg_id = script_getnum(st,2);
- if( (bg = bg_team_search(bg_id)) == NULL )
+ if( (bgd = bg->team_search(bg_id)) == NULL )
return true;
-
- bg->x = script_getnum(st,3);
- bg->y = script_getnum(st,4);
+
+ bgd->x = script_getnum(st,3);
+ bgd->y = script_getnum(st,4);
return true;
}
BUILDIN(bg_warp)
{
- int x, y, mapindex, bg_id;
+ int x, y, map_index, bg_id;
const char* map_name;
-
+
bg_id = script_getnum(st,2);
map_name = script_getstr(st,3);
- if( (mapindex = mapindex_name2id(map_name)) == 0 )
+ if( (map_index = script->mapindexname2id(st,map_name)) == 0 )
return true; // Invalid Map
x = script_getnum(st,4);
y = script_getnum(st,5);
- bg_team_warp(bg_id, mapindex, x, y);
+ bg->team_warp(bg_id, map_index, x, y);
return true;
}
BUILDIN(bg_monster)
{
int class_ = 0, x = 0, y = 0, bg_id = 0;
- const char *str,*map, *evt="";
-
- bg_id = script_getnum(st,2);
- map = script_getstr(st,3);
- x = script_getnum(st,4);
- y = script_getnum(st,5);
- str = script_getstr(st,6);
- class_ = script_getnum(st,7);
+ const char *str, *mapname, *evt="";
+
+ bg_id = script_getnum(st,2);
+ mapname = script_getstr(st,3);
+ x = script_getnum(st,4);
+ y = script_getnum(st,5);
+ str = script_getstr(st,6);
+ class_ = script_getnum(st,7);
if( script_hasdata(st,8) ) evt = script_getstr(st,8);
- check_event(st, evt);
- script_pushint(st, mob_spawn_bg(map,x,y,str,class_,evt,bg_id));
+ script->check_event(st, evt);
+ script_pushint(st, mob->spawn_bg(mapname,x,y,str,class_,evt,bg_id));
return true;
}
-BUILDIN(bg_monster_set_team)
-{
+BUILDIN(bg_monster_set_team) {
struct mob_data *md;
struct block_list *mbl;
int id = script_getnum(st,2),
bg_id = script_getnum(st,3);
-
- if( (mbl = iMap->id2bl(id)) == NULL || mbl->type != BL_MOB )
+
+ if( (mbl = map->id2bl(id)) == NULL || mbl->type != BL_MOB )
return true;
md = (TBL_MOB *)mbl;
md->bg_id = bg_id;
-
+
mob_stop_attack(md);
mob_stop_walking(md, 0);
md->target_id = md->attacked_id = 0;
clif->charnameack(0, &md->bl);
-
+
return true;
}
BUILDIN(bg_leave)
{
- struct map_session_data *sd = script_rid2sd(st);
+ struct map_session_data *sd = script->rid2sd(st);
if( sd == NULL || !sd->bg_id )
return true;
-
- bg_team_leave(sd,0);
+
+ bg->team_leave(sd,BGTL_LEFT);
return true;
}
BUILDIN(bg_destroy)
{
int bg_id = script_getnum(st,2);
- bg_team_delete(bg_id);
+ bg->team_delete(bg_id);
return true;
}
-BUILDIN(bg_getareausers)
-{
+BUILDIN(bg_getareausers) {
const char *str;
int16 m, x0, y0, x1, y1;
int bg_id;
int i = 0, c = 0;
- struct battleground_data *bg = NULL;
+ struct battleground_data *bgd = NULL;
struct map_session_data *sd;
-
+
bg_id = script_getnum(st,2);
str = script_getstr(st,3);
-
- if( (bg = bg_team_search(bg_id)) == NULL || (m = iMap->mapname2mapid(str)) < 0 )
- {
+
+ if( (bgd = bg->team_search(bg_id)) == NULL || (m = map->mapname2mapid(str)) < 0 ) {
script_pushint(st,0);
return true;
}
-
+
x0 = script_getnum(st,4);
y0 = script_getnum(st,5);
x1 = script_getnum(st,6);
y1 = script_getnum(st,7);
-
+
for( i = 0; i < MAX_BG_MEMBERS; i++ )
{
- if( (sd = bg->members[i].sd) == NULL )
+ if( (sd = bgd->members[i].sd) == NULL )
continue;
if( sd->bl.m != m || sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1 )
continue;
c++;
}
-
+
script_pushint(st,c);
return true;
}
-BUILDIN(bg_updatescore)
-{
+BUILDIN(bg_updatescore) {
const char *str;
int16 m;
-
+
str = script_getstr(st,2);
- if( (m = iMap->mapname2mapid(str)) < 0 )
+ if( (m = map->mapname2mapid(str)) < 0 )
return true;
-
- map[m].bgscore_lion = script_getnum(st,3);
- map[m].bgscore_eagle = script_getnum(st,4);
-
+
+ map->list[m].bgscore_lion = script_getnum(st,3);
+ map->list[m].bgscore_eagle = script_getnum(st,4);
+
clif->bg_updatescore(m);
return true;
}
BUILDIN(bg_get_data)
{
- struct battleground_data *bg;
+ struct battleground_data *bgd;
int bg_id = script_getnum(st,2),
type = script_getnum(st,3);
-
- if( (bg = bg_team_search(bg_id)) == NULL )
+
+ if( (bgd = bg->team_search(bg_id)) == NULL )
{
script_pushint(st,0);
return true;
}
-
+
switch( type )
{
- case 0: script_pushint(st, bg->count); break;
+ case 0: script_pushint(st, bgd->count); break;
default:
ShowError("script:bg_get_data: unknown data identifier %d\n", type);
break;
}
-
+
return true;
}
@@ -15851,7 +16607,7 @@ BUILDIN(instance_create) {
const char *name;
int owner_id, res;
int type = IOT_PARTY;
-
+
name = script_getstr(st, 2);
owner_id = script_getnum(st, 3);
if( script_hasdata(st,4) ) {
@@ -15861,9 +16617,9 @@ BUILDIN(instance_create) {
return true;
}
}
-
+
res = instance->create(owner_id, name, (enum instance_owner_type) type);
- if( res == -4 ) { // Already exists
+ if( res == -4 ) { // Already exists
script_pushint(st, -1);
return true;
} else if( res < 0 ) {
@@ -15878,25 +16634,25 @@ BUILDIN(instance_create) {
script_pushint(st, -2);
return true;
}
-
+
script_pushint(st, res);
return true;
}
BUILDIN(instance_destroy) {
int instance_id = -1;
-
+
if( script_hasdata(st, 2) )
instance_id = script_getnum(st, 2);
else if( st->instance_id >= 0 )
instance_id = st->instance_id;
else return true;
-
+
if( !instance->valid(instance_id) ) {
ShowError("buildin_instance_destroy: Trying to destroy invalid instance %d.\n", instance_id);
return true;
}
-
+
instance->destroy(instance_id);
return true;
}
@@ -15906,22 +16662,22 @@ BUILDIN(instance_attachmap) {
int16 m;
int instance_id = -1;
bool usebasename = false;
-
+
name = script_getstr(st,2);
instance_id = script_getnum(st,3);
if( script_hasdata(st,4) && script_getnum(st,4) > 0 )
usebasename = true;
-
+
if( script_hasdata(st, 5) )
map_name = script_getstr(st, 5);
-
+
if( (m = instance->add_map(name, instance_id, usebasename, map_name)) < 0 ) { // [Saithis]
ShowError("buildin_instance_attachmap: instance creation failed (%s): %d\n", name, m);
script_pushconststr(st, "");
return true;
}
- script_pushconststr(st, map[m].name);
-
+ script_pushconststr(st, map->list[m].name);
+
return true;
}
@@ -15929,30 +16685,30 @@ BUILDIN(instance_detachmap) {
const char *str;
int16 m;
int instance_id = -1;
-
+
str = script_getstr(st, 2);
if( script_hasdata(st, 3) )
instance_id = script_getnum(st, 3);
else if( st->instance_id >= 0 )
instance_id = st->instance_id;
else return true;
-
- if( (m = iMap->mapname2mapid(str)) < 0 || (m = instance->map2imap(m,instance_id)) < 0 ) {
+
+ if( (m = map->mapname2mapid(str)) < 0 || (m = instance->map2imap(m,instance_id)) < 0 ) {
ShowError("buildin_instance_detachmap: Trying to detach invalid map %s\n", str);
return true;
}
-
+
instance->del_map(m);
return true;
}
BUILDIN(instance_attach) {
int instance_id = -1;
-
+
instance_id = script_getnum(st, 2);
if( !instance->valid(instance_id) )
return true;
-
+
st->instance_id = instance_id;
return true;
}
@@ -15966,35 +16722,35 @@ BUILDIN(instance_set_timeout)
{
int progress_timeout, idle_timeout;
int instance_id = -1;
-
+
progress_timeout = script_getnum(st, 2);
idle_timeout = script_getnum(st, 3);
-
+
if( script_hasdata(st, 4) )
instance_id = script_getnum(st, 4);
else if( st->instance_id >= 0 )
instance_id = st->instance_id;
else return true;
-
+
if( instance_id >= 0 )
instance->set_timeout(instance_id, progress_timeout, idle_timeout);
-
+
return true;
}
BUILDIN(instance_init) {
int instance_id = script_getnum(st, 2);
-
+
if( !instance->valid(instance_id) ) {
ShowError("instance_init: invalid instance id %d.\n",instance_id);
return true;
}
-
- if( instances[instance_id].state != INSTANCE_IDLE ) {
+
+ if( instance->list[instance_id].state != INSTANCE_IDLE ) {
ShowError("instance_init: instance already initialized.\n");
return true;
}
-
+
instance->start(instance_id);
return true;
}
@@ -16008,23 +16764,23 @@ BUILDIN(instance_announce) {
int fontSize = script_hasdata(st,7) ? script_getnum(st,7) : 12; // default fontSize
int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign
int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY
-
+
int i;
-
+
if( instance_id == -1 ) {
if( st->instance_id >= 0 )
instance_id = st->instance_id;
else
return true;
}
-
+
if( !instance->valid(instance_id) )
return true;
-
- for( i = 0; i < instances[instance_id].num_map; i++ )
- iMap->foreachinmap(buildin_announce_sub, instances[instance_id].map[i], BL_PC,
- mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY);
-
+
+ for( i = 0; i < instance->list[instance_id].num_map; i++ )
+ map->foreachinmap(script->buildin_announce_sub, instance->list[instance_id].map[i], BL_PC,
+ mes, strlen(mes)+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
+
return true;
}
@@ -16032,91 +16788,107 @@ BUILDIN(instance_npcname) {
const char *str;
int instance_id = -1;
struct npc_data *nd;
-
+
str = script_getstr(st, 2);
if( script_hasdata(st, 3) )
instance_id = script_getnum(st, 3);
else if( st->instance_id >= 0 )
instance_id = st->instance_id;
-
- if( instance_id >= 0 && (nd = npc_name2id(str)) != NULL ) {
+
+ if( instance_id >= 0 && (nd = npc->name2id(str)) != NULL ) {
static char npcname[NAME_LENGTH];
snprintf(npcname, sizeof(npcname), "dup_%d_%d", instance_id, nd->bl.id);
- script_pushconststr(st,npcname);
+ script_pushconststr(st,npcname);
} else {
ShowError("script:instance_npcname: invalid instance NPC (instance_id: %d, NPC name: \"%s\".)\n", instance_id, str);
st->state = END;
return false;
}
-
+
return true;
}
BUILDIN(has_instance) {
struct map_session_data *sd;
- const char *str;
+ const char *str;
int16 m;
int instance_id = -1;
+ bool type = strcmp(script->getfuncname(st),"has_instance2") == 0 ? true : false;
- str = script_getstr(st, 2);
-
- if( (m = iMap->mapname2mapid(str)) < 0 ) {
- script_pushconststr(st, "");
+ str = script_getstr(st, 2);
+
+ if( (m = map->mapname2mapid(str)) < 0 ) {
+ if( type )
+ script_pushint(st, -1);
+ else
+ script_pushconststr(st, "");
return true;
}
-
+
if( script_hasdata(st, 3) )
instance_id = script_getnum(st, 3);
else if( st->instance_id >= 0 )
instance_id = st->instance_id;
- else if( (sd = script_rid2sd(st)) != NULL ) {
+ else if( (sd = script->rid2sd(st)) != NULL ) {
struct party_data *p;
int i = 0, j = 0;
if( sd->instances ) {
for( i = 0; i < sd->instances; i++ ) {
- ARR_FIND(0, instances[sd->instance[i]].num_map, j, map[instances[sd->instance[i]].map[j]].instance_src_map == m);
- if( j != instances[sd->instance[i]].num_map )
- break;
+ if( sd->instance[i] >= 0 ) {
+ ARR_FIND(0, instance->list[sd->instance[i]].num_map, j, map->list[instance->list[sd->instance[i]].map[j]].instance_src_map == m);
+ if( j != instance->list[sd->instance[i]].num_map )
+ break;
+ }
}
if( i != sd->instances )
instance_id = sd->instance[i];
}
if( instance_id == -1 && sd->status.party_id && (p = party->search(sd->status.party_id)) && p->instances ) {
for( i = 0; i < p->instances; i++ ) {
- ARR_FIND(0, instances[p->instance[i]].num_map, j, map[instances[p->instance[i]].map[j]].instance_src_map == m);
- if( j != instances[p->instance[i]].num_map )
- break;
+ if( p->instance[i] >= 0 ) {
+ ARR_FIND(0, instance->list[p->instance[i]].num_map, j, map->list[instance->list[p->instance[i]].map[j]].instance_src_map == m);
+ if( j != instance->list[p->instance[i]].num_map )
+ break;
+ }
}
if( i != p->instances )
instance_id = p->instance[i];
}
if( instance_id == -1 && sd->guild && sd->guild->instances ) {
for( i = 0; i < sd->guild->instances; i++ ) {
- ARR_FIND(0, instances[sd->guild->instance[i]].num_map, j, map[instances[sd->guild->instance[i]].map[j]].instance_src_map == m);
- if( j != instances[sd->guild->instance[i]].num_map )
- break;
+ if( sd->guild->instance[i] >= 0 ) {
+ ARR_FIND(0, instance->list[sd->guild->instance[i]].num_map, j, map->list[instance->list[sd->guild->instance[i]].map[j]].instance_src_map == m);
+ if( j != instance->list[sd->guild->instance[i]].num_map )
+ break;
+ }
}
if( i != sd->guild->instances )
instance_id = sd->guild->instance[i];
}
}
-
+
if( !instance->valid(instance_id) || (m = instance->map2imap(m, instance_id)) < 0 ) {
- script_pushconststr(st, "");
+ if( type )
+ script_pushint(st, -1);
+ else
+ script_pushconststr(st, "");
return true;
}
-
- script_pushconststr(st, map[m].name);
+
+ if( type )
+ script_pushint(st, instance_id);
+ else
+ script_pushconststr(st, map->list[m].name);
return true;
}
-static int buildin_instance_warpall_sub(struct block_list *bl,va_list ap) {
+int buildin_instance_warpall_sub(struct block_list *bl,va_list ap) {
struct map_session_data *sd = ((TBL_PC*)bl);
- int mapindex = va_arg(ap,int);
+ int map_index = va_arg(ap,int);
int x = va_arg(ap,int);
int y = va_arg(ap,int);
-
- pc->setpos(sd,mapindex,x,y,CLR_TELEPORT);
-
+
+ pc->setpos(sd,map_index,x,y,CLR_TELEPORT);
+
return 0;
}
BUILDIN(instance_warpall) {
@@ -16124,25 +16896,25 @@ BUILDIN(instance_warpall) {
int instance_id = -1;
const char *mapn;
int x, y;
- int mapindex;
-
+ int map_index;
+
mapn = script_getstr(st,2);
x = script_getnum(st,3);
y = script_getnum(st,4);
-
+
if( script_hasdata(st,5) )
instance_id = script_getnum(st,5);
else if( st->instance_id >= 0 )
instance_id = st->instance_id;
else
return true;
-
- if( (m = iMap->mapname2mapid(mapn)) < 0 || (map[m].flag.src4instance && (m = instance->mapid2imapid(m, instance_id)) < 0) )
+
+ if( (m = map->mapname2mapid(mapn)) < 0 || (map->list[m].flag.src4instance && (m = instance->mapid2imapid(m, instance_id)) < 0) )
return true;
-
- mapindex = map_id2index(m);
-
- iMap->foreachininstance(buildin_instance_warpall_sub, instance_id, BL_PC,mapindex,x,y);
+
+ map_index = map_id2index(m);
+
+ map->foreachininstance(script->buildin_instance_warpall_sub, instance_id, BL_PC,map_index,x,y);
return true;
}
@@ -16161,46 +16933,46 @@ BUILDIN(instance_check_party) {
struct map_session_data *pl_sd;
int amount, min, max, i, party_id, c = 0;
struct party_data *p = NULL;
-
+
amount = script_hasdata(st,3) ? script_getnum(st,3) : 1; // Amount of needed Partymembers for the Instance.
min = script_hasdata(st,4) ? script_getnum(st,4) : 1; // Minimum Level needed to join the Instance.
max = script_hasdata(st,5) ? script_getnum(st,5) : MAX_LEVEL; // Maxium Level allowed to join the Instance.
-
- if( min < 1 || min > MAX_LEVEL){
+
+ if( min < 1 || min > MAX_LEVEL) {
ShowError("instance_check_party: Invalid min level, %d\n", min);
return true;
- } else if( max < 1 || max > MAX_LEVEL){
+ } else if( max < 1 || max > MAX_LEVEL) {
ShowError("instance_check_party: Invalid max level, %d\n", max);
return true;
}
-
+
if( script_hasdata(st,2) )
party_id = script_getnum(st,2);
else return true;
-
- if( !(p = party->search(party_id)) ){
+
+ if( !(p = party->search(party_id)) ) {
script_pushint(st, 0); // Returns false if party does not exist.
return true;
}
-
+
for( i = 0; i < MAX_PARTY; i++ )
if( (pl_sd = p->data[i].sd) )
- if(iMap->id2bl(pl_sd->bl.id)){
- if(pl_sd->status.base_level < min){
+ if(map->id2bl(pl_sd->bl.id)) {
+ if(pl_sd->status.base_level < min) {
script_pushint(st, 0);
return true;
- }else if(pl_sd->status.base_level > max){
+ } else if(pl_sd->status.base_level > max) {
script_pushint(st, 0);
return true;
}
c++;
}
-
- if(c < amount){
+
+ if(c < amount) {
script_pushint(st, 0); // Not enough Members in the Party to join Instance.
- }else
+ } else
script_pushint(st, 1);
-
+
return true;
}
@@ -16209,113 +16981,112 @@ BUILDIN(instance_check_party) {
*------------------------------------------*/
BUILDIN(setfont)
{
- struct map_session_data *sd = script_rid2sd(st);
+ struct map_session_data *sd = script->rid2sd(st);
int font = script_getnum(st,2);
if( sd == NULL )
return true;
-
- if( sd->user_font != font )
- sd->user_font = font;
+
+ if( sd->status.font != font )
+ sd->status.font = font;
else
- sd->user_font = 0;
-
+ sd->status.font = 0;
+
clif->font(sd);
return true;
}
-static int buildin_mobuseskill_sub(struct block_list *bl,va_list ap)
+int buildin_mobuseskill_sub(struct block_list *bl,va_list ap)
{
- TBL_MOB* md = (TBL_MOB*)bl;
+ TBL_MOB* md = (TBL_MOB*)bl;
struct block_list *tbl;
- int mobid = va_arg(ap,int);
- uint16 skill_id = va_arg(ap,int);
- uint16 skill_lv = va_arg(ap,int);
- int casttime = va_arg(ap,int);
- int cancel = va_arg(ap,int);
- int emotion = va_arg(ap,int);
- int target = va_arg(ap,int);
-
+ int mobid = va_arg(ap,int);
+ uint16 skill_id = va_arg(ap,int);
+ uint16 skill_lv = va_arg(ap,int);
+ int casttime = va_arg(ap,int);
+ int cancel = va_arg(ap,int);
+ int emotion = va_arg(ap,int);
+ int target = va_arg(ap,int);
+
if( md->class_ != mobid )
return 0;
-
+
// 0:self, 1:target, 2:master, default:random
switch( target )
{
- case 0: tbl = iMap->id2bl(md->bl.id); break;
- case 1: tbl = iMap->id2bl(md->target_id); break;
- case 2: tbl = iMap->id2bl(md->master_id); break;
- default:tbl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md),skill->get_range2(&md->bl, skill_id, skill_lv)); break;
+ case 0: tbl = map->id2bl(md->bl.id); break;
+ case 1: tbl = map->id2bl(md->target_id); break;
+ case 2: tbl = map->id2bl(md->master_id); break;
+ default: tbl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md),skill->get_range2(&md->bl, skill_id, skill_lv)); break;
}
-
+
if( !tbl )
return 0;
-
+
if( md->ud.skilltimer != INVALID_TIMER ) // Cancel the casting skill.
- unit_skillcastcancel(bl,0);
-
+ unit->skillcastcancel(bl,0);
+
if( skill->get_casttype(skill_id) == CAST_GROUND )
- unit_skilluse_pos2(&md->bl, tbl->x, tbl->y, skill_id, skill_lv, casttime, cancel);
+ unit->skilluse_pos2(&md->bl, tbl->x, tbl->y, skill_id, skill_lv, casttime, cancel);
else
- unit_skilluse_id2(&md->bl, tbl->id, skill_id, skill_lv, casttime, cancel);
-
+ unit->skilluse_id2(&md->bl, tbl->id, skill_id, skill_lv, casttime, cancel);
+
clif->emotion(&md->bl, emotion);
-
+
return 0;
}
/*==========================================
* areamobuseskill "Map Name",<x>,<y>,<range>,<Mob ID>,"Skill Name"/<Skill ID>,<Skill Lv>,<Cast Time>,<Cancelable>,<Emotion>,<Target Type>;
*------------------------------------------*/
-BUILDIN(areamobuseskill)
-{
+BUILDIN(areamobuseskill) {
struct block_list center;
int16 m;
int range,mobid,skill_id,skill_lv,casttime,emotion,target,cancel;
-
- if( (m = iMap->mapname2mapid(script_getstr(st,2))) < 0 ) {
+
+ if( (m = map->mapname2mapid(script_getstr(st,2))) < 0 ) {
ShowError("areamobuseskill: invalid map name.\n");
return true;
}
-
- if( map[m].flag.src4instance && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 )
+
+ if( map->list[m].flag.src4instance && st->instance_id >= 0 && (m = instance->mapid2imapid(m, st->instance_id)) < 0 )
return true;
-
+
center.m = m;
center.x = script_getnum(st,3);
center.y = script_getnum(st,4);
range = script_getnum(st,5);
mobid = script_getnum(st,6);
- skill_id = ( script_isstring(st,7) ? skill->name2id(script_getstr(st,7)) : script_getnum(st,7) );
+ skill_id = ( script_isstringtype(st, 7) ? skill->name2id(script_getstr(st, 7)) : script_getnum(st, 7) );
skill_lv = script_getnum(st,8);
casttime = script_getnum(st,9);
cancel = script_getnum(st,10);
emotion = script_getnum(st,11);
target = script_getnum(st,12);
-
- iMap->foreachinrange(buildin_mobuseskill_sub, &center, range, BL_MOB, mobid, skill_id, skill_lv, casttime, cancel, emotion, target);
+
+ map->foreachinrange(script->buildin_mobuseskill_sub, &center, range, BL_MOB, mobid, skill_id, skill_lv, casttime, cancel, emotion, target);
return true;
}
BUILDIN(progressbar)
{
- struct map_session_data * sd = script_rid2sd(st);
+ struct map_session_data * sd = script->rid2sd(st);
const char * color;
unsigned int second;
-
+
if( !st || !sd )
return true;
-
+
st->state = STOP;
-
+
color = script_getstr(st,2);
second = script_getnum(st,3);
-
+
sd->progressbar.npc_id = st->oid;
- sd->progressbar.timeout = iTimer->gettick() + second*1000;
+ sd->progressbar.timeout = timer->gettick() + second*1000;
sd->state.workinprogress = 3;
-
- clif->progressbar(sd, strtol(color, (char **)NULL, 0), second);
- return true;
+
+ clif->progressbar(sd, (unsigned int)strtoul(color, (char **)NULL, 0), second);
+ return true;
}
BUILDIN(pushpc)
@@ -16323,23 +17094,23 @@ BUILDIN(pushpc)
uint8 dir;
int cells, dx, dy;
struct map_session_data* sd;
-
- if((sd = script_rid2sd(st))==NULL)
+
+ if((sd = script->rid2sd(st))==NULL)
{
return true;
}
-
+
dir = script_getnum(st,2);
cells = script_getnum(st,3);
-
+
if(dir>7)
{
ShowWarning("buildin_pushpc: Invalid direction %d specified.\n", dir);
- script_reportsrc(st);
-
+ script->reportsrc(st);
+
dir%= 8; // trim spin-over
}
-
+
if(!cells)
{// zero distance
return true;
@@ -16349,11 +17120,11 @@ BUILDIN(pushpc)
dir = (dir+4)%8; // turn around
cells = -cells;
}
-
+
dx = dirx[dir];
dy = diry[dir];
-
- unit_blown(&sd->bl, dx, dy, cells, 0);
+
+ unit->blown(&sd->bl, dx, dy, cells, 0);
return true;
}
@@ -16363,11 +17134,11 @@ BUILDIN(pushpc)
BUILDIN(buyingstore)
{
struct map_session_data* sd;
-
- if( ( sd = script_rid2sd(st) ) == NULL ) {
+
+ if( ( sd = script->rid2sd(st) ) == NULL ) {
return true;
}
-
+
buyingstore->setup(sd, script_getnum(st,2));
return true;
}
@@ -16380,27 +17151,27 @@ BUILDIN(searchstores)
unsigned short effect;
unsigned int uses;
struct map_session_data* sd;
-
- if( ( sd = script_rid2sd(st) ) == NULL )
+
+ if( ( sd = script->rid2sd(st) ) == NULL )
{
return true;
}
-
+
uses = script_getnum(st,2);
effect = script_getnum(st,3);
-
+
if( !uses )
{
ShowError("buildin_searchstores: Amount of uses cannot be zero.\n");
return false;
}
-
+
if( effect > 1 )
{
ShowError("buildin_searchstores: Invalid effect id %hu, specified.\n", effect);
return false;
}
-
+
searchstore->open(sd, uses, effect);
return true;
}
@@ -16411,25 +17182,25 @@ BUILDIN(showdigit)
unsigned int type = 0;
int value;
struct map_session_data* sd;
-
- if( ( sd = script_rid2sd(st) ) == NULL )
+
+ if( ( sd = script->rid2sd(st) ) == NULL )
{
return true;
}
-
+
value = script_getnum(st,2);
-
+
if( script_hasdata(st,3) )
{
type = script_getnum(st,3);
-
+
if( type > 3 )
{
ShowError("buildin_showdigit: Invalid type %u.\n", type);
return false;
}
}
-
+
clif->showdigit(sd, (unsigned char)type, value);
return true;
}
@@ -16438,7 +17209,7 @@ BUILDIN(showdigit)
**/
BUILDIN(makerune) {
TBL_PC* sd;
- if( (sd = script_rid2sd(st)) == NULL )
+ if( (sd = script->rid2sd(st)) == NULL )
return true;
clif->skill_produce_mix_list(sd,RK_RUNEMASTERY,24);
sd->itemid = script_getnum(st,2);
@@ -16449,7 +17220,7 @@ BUILDIN(makerune) {
**/
BUILDIN(checkdragon) {
TBL_PC* sd;
- if( (sd = script_rid2sd(st)) == NULL )
+ if( (sd = script->rid2sd(st)) == NULL )
return true;
if( pc_isridingdragon(sd) )
script_pushint(st,1);
@@ -16470,8 +17241,8 @@ BUILDIN(checkdragon) {
BUILDIN(setdragon) {
TBL_PC* sd;
int color = script_hasdata(st,2) ? script_getnum(st,2) : 0;
-
- if( (sd = script_rid2sd(st)) == NULL )
+
+ if( (sd = script->rid2sd(st)) == NULL )
return true;
if( !pc->checkskill(sd,RK_DRAGONTRAINING) || (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT )
script_pushint(st,0);//Doesn't have the skill or it's not a Rune Knight
@@ -16482,10 +17253,10 @@ BUILDIN(setdragon) {
unsigned int option = OPTION_DRAGON1;
if( color ) {
option = ( color == 1 ? OPTION_DRAGON1 :
- color == 2 ? OPTION_DRAGON2 :
- color == 3 ? OPTION_DRAGON3 :
- color == 4 ? OPTION_DRAGON4 :
- color == 5 ? OPTION_DRAGON5 : 0);
+ color == 2 ? OPTION_DRAGON2 :
+ color == 3 ? OPTION_DRAGON3 :
+ color == 4 ? OPTION_DRAGON4 :
+ color == 5 ? OPTION_DRAGON5 : 0);
if( !option ) {
ShowWarning("script_setdragon: Unknown Color %d used; changing to green (1)\n",color);
option = OPTION_DRAGON1;
@@ -16502,7 +17273,7 @@ BUILDIN(setdragon) {
**/
BUILDIN(ismounting) {
TBL_PC* sd;
- if( (sd = script_rid2sd(st)) == NULL )
+ if( (sd = script->rid2sd(st)) == NULL )
return true;
if( sd->sc.data[SC_ALL_RIDING] )
script_pushint(st,1);
@@ -16519,16 +17290,16 @@ BUILDIN(ismounting) {
**/
BUILDIN(setmounting) {
TBL_PC* sd;
- if( (sd = script_rid2sd(st)) == NULL )
+ if( (sd = script->rid2sd(st)) == NULL )
return true;
- if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) ){
+ if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) ) {
clif->msgtable(sd->fd, 0X78b);
script_pushint(st,0);//can't mount with one of these
- }else {
+ } else {
if( sd->sc.data[SC_ALL_RIDING] )
status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER);
else
- sc_start(&sd->bl, SC_ALL_RIDING, 100, 0, -1);
+ sc_start(NULL,&sd->bl, SC_ALL_RIDING, 100, 0, -1);
script_pushint(st,1);//in both cases, return 1.
}
return true;
@@ -16539,60 +17310,56 @@ BUILDIN(setmounting) {
**/
BUILDIN(getargcount) {
struct script_retinfo* ri;
-
+
if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp - 1].type != C_RETINFO ) {
ShowError("script:getargcount: used out of function or callsub label!\n");
st->state = END;
return false;
}
ri = st->stack->stack_data[st->stack->defsp - 1].u.ri;
-
+
script_pushint(st, ri->nargs);
-
+
return true;
}
/**
* getcharip(<account ID>/<character ID>/<character name>)
**/
-BUILDIN(getcharip)
-{
+BUILDIN(getcharip) {
struct map_session_data* sd = NULL;
-
+
/* check if a character name is specified */
- if( script_hasdata(st, 2) )
- {
- if (script_isstring(st, 2))
- sd = iMap->nick2sd(script_getstr(st, 2));
- else if (script_isint(st, 2) || script_getnum(st, 2))
- {
- int id;
- id = script_getnum(st, 2);
- sd = (iMap->id2sd(id) ? iMap->id2sd(id) : iMap->charid2sd(id));
+ if( script_hasdata(st, 2) ) {
+ if (script_isstringtype(st, 2)) {
+ sd = map->nick2sd(script_getstr(st, 2));
+ } else {
+ int id = script_getnum(st, 2);
+ sd = (map->id2sd(id) ? map->id2sd(id) : map->charid2sd(id));
}
+ } else {
+ sd = script->rid2sd(st);
}
- else
- sd = script_rid2sd(st);
-
+
/* check for sd and IP */
if (!sd || !session[sd->fd]->client_addr)
{
script_pushconststr(st, "");
return true;
}
-
+
/* return the client ip_addr converted for output */
if (sd && sd->fd && session[sd->fd])
{
/* initiliaze */
const char *ip_addr = NULL;
uint32 ip;
-
+
/* set ip, ip_addr and convert to ip and push str */
ip = session[sd->fd]->client_addr;
ip_addr = ip2str(ip, NULL);
script_pushstrcopy(st, ip_addr);
}
-
+
return true;
}
/**
@@ -16600,39 +17367,84 @@ BUILDIN(getcharip)
**/
BUILDIN(is_function) {
const char* str = script_getstr(st,2);
-
- if( strdb_exists(userfunc_db, str) )
+
+ if( strdb_exists(script->userfunc_db, str) )
script_pushint(st,1);
else
script_pushint(st,0);
-
- return true;
-}
-/**
- * get_revision() -> retrieves the current svn revision (if available)
- **/
-BUILDIN(get_revision) {
- const char *svn = get_svn_revision();
-
- if ( svn[0] != HERC_UNKNOWN_VER )
- script_pushint(st,atoi(svn));
- else
- script_pushint(st,-1);//unknown
-
+
return true;
}
/**
* freeloop(<toggle>) -> toggles this script instance's looping-check ability
**/
BUILDIN(freeloop) {
-
+
if( script_getnum(st,2) )
st->freeloop = 1;
else
st->freeloop = 0;
-
+
script_pushint(st, st->freeloop);
-
+
+ return true;
+}
+
+BUILDIN(sit) {
+ struct map_session_data *sd = NULL;
+
+ if( script_hasdata(st, 2) )
+ sd = map->nick2sd(script_getstr(st, 2));
+ else
+ sd = script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
+ if (!pc_issit(sd))
+ {
+ pc_setsit(sd);
+ skill->sit(sd,1);
+ clif->sitting(&sd->bl);
+ }
+ return true;
+}
+
+BUILDIN(stand) {
+ struct map_session_data *sd = NULL;
+
+ if( script_hasdata(st, 2) )
+ sd = map->nick2sd(script_getstr(st, 2));
+ else
+ sd = script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
+ if (pc_issit(sd))
+ {
+ pc->setstand(sd);
+ skill->sit(sd,0);
+ clif->standing(&sd->bl);
+ }
+ return true;
+}
+
+BUILDIN(issit) {
+ struct map_session_data *sd = NULL;
+
+ if( script_hasdata(st, 2) )
+ sd = map->nick2sd(script_getstr(st, 2));
+ else
+ sd = script->rid2sd(st);
+
+ if( sd == NULL )
+ return false;
+
+ if (pc_issit(sd))
+ script_pushint(st, 1);
+ else
+ script_pushint(st, 0);
return true;
}
@@ -16645,21 +17457,21 @@ BUILDIN(bindatcmd) {
int i, group_lv = 0, group_lv_char = 99;
bool log = false;
bool create = false;
-
+
atcmd = script_getstr(st,2);
eventName = script_getstr(st,3);
-
+
if( *atcmd == atcommand->at_symbol || *atcmd == atcommand->char_symbol )
atcmd++;
-
+
if( script_hasdata(st,4) ) group_lv = script_getnum(st,4);
if( script_hasdata(st,5) ) group_lv_char = script_getnum(st,5);
if( script_hasdata(st,6) ) log = script_getnum(st,6) ? true : false;
-
+
if( atcommand->binding_count == 0 ) {
CREATE(atcommand->binding,struct atcmd_binding_data*,1);
-
+
create = true;
} else {
ARR_FIND(0, atcommand->binding_count, i, strcmp(atcommand->binding[i]->command,atcmd) == 0);
@@ -16671,39 +17483,39 @@ BUILDIN(bindatcmd) {
} else
create = true;
}
-
+
if( create ) {
i = atcommand->binding_count;
-
+
if( atcommand->binding_count++ != 0 )
RECREATE(atcommand->binding,struct atcmd_binding_data*,atcommand->binding_count);
-
+
CREATE(atcommand->binding[i],struct atcmd_binding_data,1);
-
+
safestrncpy(atcommand->binding[i]->command, atcmd, 50);
safestrncpy(atcommand->binding[i]->npc_event, eventName, 50);
atcommand->binding[i]->group_lv = group_lv;
atcommand->binding[i]->group_lv_char = group_lv_char;
atcommand->binding[i]->log = log;
}
-
+
return true;
}
BUILDIN(unbindatcmd) {
const char* atcmd;
int i = 0;
-
+
atcmd = script_getstr(st, 2);
-
+
if( *atcmd == atcommand->at_symbol || *atcmd == atcommand->char_symbol )
atcmd++;
-
+
if( atcommand->binding_count == 0 ) {
script_pushint(st, 0);
return true;
}
-
+
ARR_FIND(0, atcommand->binding_count, i, strcmp(atcommand->binding[i]->command, atcmd) == 0);
if( i < atcommand->binding_count ) {
int cursor = 0;
@@ -16713,70 +17525,67 @@ BUILDIN(unbindatcmd) {
for( i = 0, cursor = 0; i < atcommand->binding_count; i++ ) {
if( atcommand->binding[i] == NULL )
continue;
-
+
if( cursor != i ) {
memmove(&atcommand->binding[cursor], &atcommand->binding[i], sizeof(struct atcmd_binding_data*));
}
-
+
cursor++;
}
-
+
if( (atcommand->binding_count = cursor) == 0 )
aFree(atcommand->binding);
-
+
script_pushint(st, 1);
} else
script_pushint(st, 0);/* not found */
-
+
return true;
}
-BUILDIN(useatcmd)
-{
- TBL_PC dummy_sd;
- TBL_PC* sd;
+BUILDIN(useatcmd) {
+ TBL_PC *sd, *dummy_sd = NULL;
int fd;
const char* cmd;
-
+
cmd = script_getstr(st,2);
-
- if( st->rid )
- {
- sd = script_rid2sd(st);
+
+ if( st->rid ) {
+ sd = script->rid2sd(st);
+ if( sd == NULL )
+ return false;
fd = sd->fd;
- }
- else
- { // Use a dummy character.
- sd = &dummy_sd;
+ } else {
+ // Use a dummy character.
+ sd = dummy_sd = pc->get_dummy_sd();
fd = 0;
-
- memset(&dummy_sd, 0, sizeof(TBL_PC));
- if( st->oid )
- {
- struct block_list* bl = iMap->id2bl(st->oid);
- memcpy(&dummy_sd.bl, bl, sizeof(struct block_list));
+
+ if( st->oid ) {
+ struct block_list* bl = map->id2bl(st->oid);
+ memcpy(&sd->bl, bl, sizeof(struct block_list));
if( bl->type == BL_NPC )
- safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
+ safestrncpy(sd->status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
}
}
-
+
// compatibility with previous implementation (deprecated!)
if( cmd[0] != atcommand->at_symbol ) {
cmd += strlen(sd->status.name);
while( *cmd != atcommand->at_symbol && *cmd != 0 )
cmd++;
}
-
- atcommand->parse(fd, sd, cmd, 1);
+
+ atcommand->exec(fd, sd, cmd, true);
+ if (dummy_sd) aFree(dummy_sd);
return true;
}
BUILDIN(checkre)
{
int num;
-
+
num=script_getnum(st,2);
- switch(num){
+ switch(num) {
case 0:
#ifdef RENEWAL
script_pushint(st, 1);
@@ -16833,112 +17642,112 @@ BUILDIN(checkre)
return true;
}
-/* getrandgroupitem <group_id>,<quantity> */
+/* getrandgroupitem <container_item_id>,<quantity> */
BUILDIN(getrandgroupitem) {
- TBL_PC* sd;
- int i, get_count = 0, flag, nameid, group = script_getnum(st, 2), qty = script_getnum(st,3);
- struct item item_tmp;
-
- if( !( sd = script_rid2sd(st) ) )
- return true;
-
- if( qty <= 0 ) {
- ShowError("getrandgroupitem: qty is <= 0!\n");
- return false;
- }
-
- if(group < 1 || group >= MAX_ITEMGROUP) {
- ShowError("getrandgroupitem: Invalid group id %d\n", group);
- return false;
- }
- if (!itemgroup_db[group].qty) {
- ShowError("getrandgroupitem: group id %d is empty!\n", group);
- return false;
- }
-
- nameid = itemdb_searchrandomid(group);
- memset(&item_tmp,0,sizeof(item_tmp));
-
- item_tmp.nameid = nameid;
- item_tmp.identify = itemdb_isidentified(nameid);
-
- //Check if it's stackable.
- if (!itemdb_isstackable(nameid))
- get_count = 1;
- else
- get_count = qty;
-
- for (i = 0; i < qty; i += get_count) {
- // if not pet egg
- if (!pet_create_egg(sd, nameid)) {
- if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) {
- clif->additem(sd, 0, 0, flag);
- if( pc->candrop(sd,&item_tmp) )
- iMap->addflooritem(&item_tmp,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ struct item_data *data = NULL;
+ struct map_session_data *sd = NULL;
+ int nameid = script_getnum(st, 2);
+ int count = script_getnum(st, 3);
+
+ if( !(data = itemdb->exists(nameid)) ) {
+ ShowWarning("buildin_getrandgroupitem: unknown item id %d\n",nameid);
+ script_pushint(st, 1);
+ } else if ( count <= 0 ) {
+ ShowError("buildin_getrandgroupitem: qty is <= 0!\n");
+ script_pushint(st, 1);
+ } else if ( !data->group ) {
+ ShowWarning("buildin_getrandgroupitem: item '%s' (%d) isn't a group!\n",data->name,nameid);
+ script_pushint(st, 1);
+ } else if( !( sd = script->rid2sd(st) ) ) {
+ ShowWarning("buildin_getrandgroupitem: no player attached!! (item %s (%d))\n",data->name,nameid);
+ script_pushint(st, 1);
+ } else {
+ int i, get_count, flag;
+ struct item it;
+
+ memset(&it,0,sizeof(it));
+
+ nameid = itemdb->group_item(data->group);
+
+ it.nameid = nameid;
+ it.identify = itemdb->isidentified(nameid);
+
+ if (!itemdb->isstackable(nameid))
+ get_count = 1;
+ else
+ get_count = count;
+
+ for (i = 0; i < count; i += get_count) {
+ // if not pet egg
+ if (!pet->create_egg(sd, nameid)) {
+ if ((flag = pc->additem(sd, &it, get_count, LOG_TYPE_SCRIPT))) {
+ clif->additem(sd, 0, 0, flag);
+ if( pc->candrop(sd,&it) )
+ map->addflooritem(&it,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ }
}
}
+
+ script_pushint(st, 0);
}
-
+
return true;
}
/* cleanmap <map_name>;
* cleanarea <map_name>, <x0>, <y0>, <x1>, <y1>; */
-static int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap)
-{
+int script_cleanfloor_sub(struct block_list *bl, va_list ap) {
nullpo_ret(bl);
- iMap->clearflooritem(bl);
-
+ map->clearflooritem(bl);
+
return 0;
}
-BUILDIN(cleanmap)
-{
- const char *map;
- int16 m = -1;
- int16 x0 = 0, y0 = 0, x1 = 0, y1 = 0;
-
- map = script_getstr(st, 2);
- m = iMap->mapname2mapid(map);
- if (!m)
- return false;
-
+BUILDIN(cleanmap) {
+ const char *mapname;
+ int16 m = -1;
+ int16 x0 = 0, y0 = 0, x1 = 0, y1 = 0;
+
+ mapname = script_getstr(st, 2);
+ m = map->mapname2mapid(mapname);
+ if ( m == -1 )
+ return false;
+
if ((script_lastdata(st) - 2) < 4) {
- iMap->foreachinmap(atcommand_cleanfloor_sub, m, BL_ITEM);
+ map->foreachinmap(script->cleanfloor_sub, m, BL_ITEM);
} else {
x0 = script_getnum(st, 3);
y0 = script_getnum(st, 4);
x1 = script_getnum(st, 5);
y1 = script_getnum(st, 6);
if (x0 > 0 && y0 > 0 && x1 > 0 && y1 > 0) {
- iMap->foreachinarea(atcommand_cleanfloor_sub, m, x0, y0, x1, y1, BL_ITEM);
+ map->foreachinarea(script->cleanfloor_sub, m, x0, y0, x1, y1, BL_ITEM);
} else {
ShowError("cleanarea: invalid coordinate defined!\n");
return false;
}
}
-
+
return true;
}
/* Cast a skill on the attached player.
* npcskill <skill id>, <skill lvl>, <stat point>, <NPC level>;
* npcskill "<skill name>", <skill lvl>, <stat point>, <NPC level>; */
-BUILDIN(npcskill)
-{
+BUILDIN(npcskill) {
uint16 skill_id;
unsigned short skill_level;
unsigned int stat_point;
unsigned int npc_level;
struct npc_data *nd;
struct map_session_data *sd;
-
- skill_id = script_isstring(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2);
- skill_level = script_getnum(st, 3);
- stat_point = script_getnum(st, 4);
- npc_level = script_getnum(st, 5);
- sd = script_rid2sd(st);
- nd = (struct npc_data *)iMap->id2bl(sd->npc_id);
-
+
+ skill_id = script_isstringtype(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2);
+ skill_level = script_getnum(st, 3);
+ stat_point = script_getnum(st, 4);
+ npc_level = script_getnum(st, 5);
+ sd = script->rid2sd(st);
+ nd = (struct npc_data *)map->id2bl(sd->npc_id);
+
if (stat_point > battle_config.max_third_parameter) {
ShowError("npcskill: stat point exceeded maximum of %d.\n",battle_config.max_third_parameter );
return false;
@@ -16947,112 +17756,190 @@ BUILDIN(npcskill)
ShowError("npcskill: level exceeded maximum of %d.\n", MAX_LEVEL);
return false;
}
- if (sd == NULL || nd == NULL) { //ain't possible, but I don't trust people.
+ if (sd == NULL || nd == NULL) {
return false;
}
-
+
nd->level = npc_level;
nd->stat_point = stat_point;
-
+
if (!nd->status.hp) {
- status_calc_npc(nd, true);
+ status_calc_npc(nd, SCO_FIRST);
} else {
- status_calc_npc(nd, false);
+ status_calc_npc(nd, SCO_NONE);
}
-
+
if (skill->get_inf(skill_id)&INF_GROUND_SKILL) {
- unit_skilluse_pos(&nd->bl, sd->bl.x, sd->bl.y, skill_id, skill_level);
+ unit->skilluse_pos(&nd->bl, sd->bl.x, sd->bl.y, skill_id, skill_level);
} else {
- unit_skilluse_id(&nd->bl, sd->bl.id, skill_id, skill_level);
+ unit->skilluse_id(&nd->bl, sd->bl.id, skill_id, skill_level);
+ }
+
+ return true;
+}
+
+/* Turns a player into a monster and grants SC attribute effect. [malufett/Hercules]
+ * montransform <monster name/id>, <duration>, <sc type>, <val1>, <val2>, <val3>, <val4>; */
+BUILDIN(montransform) {
+ int tick;
+ enum sc_type type;
+ struct block_list* bl;
+ char msg[CHAT_SIZE_MAX];
+ int mob_id, val1, val2, val3, val4;
+
+ if( (bl = map->id2bl(st->rid)) == NULL )
+ return true;
+
+ if( script_isstringtype(st, 2) ) {
+ mob_id = mob->db_searchname(script_getstr(st, 2));
+ } else {
+ mob_id = mob->db_checkid(script_getnum(st, 2));
+ }
+
+ if( mob_id == 0 ) {
+ if( script_isstringtype(st, 2) )
+ ShowWarning("buildin_montransform: Attempted to use non-existing monster '%s'.\n", script_getstr(st, 2));
+ else
+ ShowWarning("buildin_montransform: Attempted to use non-existing monster of ID '%d'.\n", script_getnum(st, 2));
+ return false;
+ }
+
+ tick = script_getnum(st, 3);
+ type = (sc_type)script_getnum(st, 4);
+ val1 = val2 = val3 = val4 = 0;
+
+ if( !(type > SC_NONE && type < SC_MAX) ) {
+ ShowWarning("buildin_montransform: Unsupported status change id %d\n", type);
+ return false;
+ }
+
+ if (script_hasdata(st, 5))
+ val1 = script_getnum(st, 5);
+
+ if (script_hasdata(st, 6))
+ val2 = script_getnum(st, 6);
+
+ if (script_hasdata(st, 7))
+ val3 = script_getnum(st, 7);
+
+ if (script_hasdata(st, 8))
+ val4 = script_getnum(st, 8);
+
+ if( tick != 0 ) {
+ struct map_session_data *sd = map->id2sd(bl->id);
+ struct mob_db *monster = mob->db(mob_id);
+
+ if( !sd )
+ return true;
+
+ if( battle_config.mon_trans_disable_in_gvg && map_flag_gvg2(sd->bl.m) ) {
+ clif->message(sd->fd, msg_txt(1488)); // Transforming into monster is not allowed in Guild Wars.
+ return true;
+ }
+
+ if( sd->disguise != -1 ) {
+ clif->message(sd->fd, msg_txt(1486)); // Cannot transform into monster while in disguise.
+ return true;
+ }
+
+ sprintf(msg, msg_txt(1485), monster->name); // Traaaansformation-!! %s form!!
+ clif->ShowScript(&sd->bl, msg);
+ status_change_end(bl, SC_MONSTER_TRANSFORM, INVALID_TIMER); // Clear previous
+ sc_start2(NULL, bl, SC_MONSTER_TRANSFORM, 100, mob_id, type, tick);
+ sc_start4(NULL, bl, type, 100, val1, val2, val3, val4, tick);
}
-
return true;
}
+
struct hQueue *script_hqueue_get(int idx) {
- if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 )
+ if( idx < 0 || idx >= script->hqs || script->hq[idx].size == -1 )
return NULL;
return &script->hq[idx];
}
-/* set .@id,queue(); */
-/* creates queue, returns created queue id */
-BUILDIN(queue) {
+int script_hqueue_create(void) {
int idx = script->hqs;
int i;
-
+
for(i = 0; i < script->hqs; i++) {
- if( script->hq[i].items == -1 ) {
+ if( script->hq[i].size == -1 ) {
break;
}
}
-
+
if( i == script->hqs ) {
RECREATE(script->hq, struct hQueue, ++script->hqs);
script->hq[ idx ].item = NULL;
} else
idx = i;
-
+
script->hq[ idx ].id = idx;
+ script->hq[ idx ].size = 0;
script->hq[ idx ].items = 0;
script->hq[ idx ].onDeath[0] = '\0';
script->hq[ idx ].onLogOut[0] = '\0';
script->hq[ idx ].onMapChange[0] = '\0';
-
- script_pushint(st,idx);
+ return idx;
+}
+/* set .@id,queue(); */
+/* creates queue, returns created queue id */
+BUILDIN(queue) {
+ script_pushint(st,script->queue_create());
return true;
}
/* set .@length,queuesize(.@queue_id); */
/* returns queue length */
BUILDIN(queuesize) {
int idx = script_getnum(st, 2);
-
- if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 ) {
+
+ if( idx < 0 || idx >= script->hqs || script->hq[idx].size == -1 ) {
ShowWarning("buildin_queuesize: unknown queue id %d\n",idx);
script_pushint(st, 0);
- } else
- script_pushint(st, script->hq[ idx ].items );
-
+ } else {
+ script_pushint(st, script->hq[ idx ].items);
+ }
+
return true;
}
bool script_hqueue_add(int idx, int var) {
- if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 ) {
+ if( idx < 0 || idx >= script->hqs || script->hq[idx].size == -1 ) {
ShowWarning("script_hqueue_add: unknown queue id %d\n",idx);
return true;
} else {
struct map_session_data *sd;
int i;
-
- for(i = 0; i < script->hq[idx].items; i++) {
+
+ for(i = 0; i < script->hq[idx].size; i++) {
if( script->hq[idx].item[i] == var ) {
return true;
}
}
-
- if( i == script->hq[idx].items ) {
-
- for(i = 0; i < script->hq[idx].items; i++) {
+
+ if( i == script->hq[idx].size ) {
+
+ for(i = 0; i < script->hq[idx].size; i++) {
if( script->hq[idx].item[i] == 0 ) {
break;
}
}
-
- if( i == script->hq[idx].items )
- RECREATE(script->hq[idx].item, int, ++script->hq[idx].items);
-
+
+ if( i == script->hq[idx].size )
+ RECREATE(script->hq[idx].item, int, ++script->hq[idx].size);
+
script->hq[idx].item[i] = var;
-
- if( var >= START_ACCOUNT_NUM && (sd = iMap->id2sd(var)) ) {
+ script->hq[idx].items++;
+ if( var >= START_ACCOUNT_NUM && (sd = map->id2sd(var)) ) {
for(i = 0; i < sd->queues_count; i++) {
if( sd->queues[i] == -1 ) {
break;
}
}
-
+
if( i == sd->queues_count )
RECREATE(sd->queues, int, ++sd->queues_count);
-
+
sd->queues[i] = idx;
}
-
+
}
}
return false;
@@ -17062,39 +17949,41 @@ bool script_hqueue_add(int idx, int var) {
BUILDIN(queueadd) {
int idx = script_getnum(st, 2);
int var = script_getnum(st, 3);
-
+
script_pushint(st,script->queue_add(idx,var)?1:0);
-
+
return true;
}
bool script_hqueue_remove(int idx, int var) {
- if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 ) {
+ if( idx < 0 || idx >= script->hqs || script->hq[idx].size == -1 ) {
ShowWarning("script_hqueue_remove: unknown queue id %d (used with var %d)\n",idx,var);
return true;
} else {
int i;
-
- for(i = 0; i < script->hq[idx].items; i++) {
+
+ for(i = 0; i < script->hq[idx].size; i++) {
if( script->hq[idx].item[i] == var ) {
- return true;
+ break;
}
}
-
- if( i != script->hq[idx].items ) {
+
+ if( i != script->hq[idx].size ) {
struct map_session_data *sd;
- script->hq[idx].item[i] = 0;
-
- if( var >= START_ACCOUNT_NUM && (sd = iMap->id2sd(var)) ) {
+
+ script->hq[idx].item[i] = -1;
+ script->hq[idx].items--;
+
+ if( var >= START_ACCOUNT_NUM && (sd = map->id2sd(var)) ) {
for(i = 0; i < sd->queues_count; i++) {
- if( sd->queues[i] == var ) {
+ if( sd->queues[i] == idx ) {
break;
}
}
-
+
if( i != sd->queues_count )
sd->queues[i] = -1;
}
-
+
}
}
return false;
@@ -17106,7 +17995,7 @@ BUILDIN(queueremove) {
int var = script_getnum(st, 3);
script_pushint(st, script->queue_remove(idx,var)?1:0);
-
+
return true;
}
@@ -17117,8 +18006,8 @@ BUILDIN(queueremove) {
BUILDIN(queueopt) {
int idx = script_getnum(st, 2);
int var = script_getnum(st, 3);
-
- if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 ) {
+
+ if( idx < 0 || idx >= script->hqs || script->hq[idx].size == -1 ) {
ShowWarning("buildin_queueopt: unknown queue id %d\n",idx);
script_pushint(st, 1);
} else if( var <= HQO_NONE || var >= HQO_MAX ) {
@@ -17150,32 +18039,34 @@ BUILDIN(queueopt) {
break;
}
}
-
+
return true;
}
bool script_hqueue_del(int idx) {
- if( idx < 0 || idx >= script->hqs || script->hq[idx].items == -1 ) {
+ if( idx < 0 || idx >= script->hqs || script->hq[idx].size == -1 ) {
ShowWarning("script_queue_del: unknown queue id %d\n",idx);
return true;
} else {
struct map_session_data *sd;
int i;
-
- for(i = 0; i < script->hq[idx].items; i++) {
- if( script->hq[idx].item[i] >= START_ACCOUNT_NUM && (sd = iMap->id2sd(script->hq[idx].item[i])) ) {
+
+ for(i = 0; i < script->hq[idx].size; i++) {
+ if( script->hq[idx].item[i] >= START_ACCOUNT_NUM && (sd = map->id2sd(script->hq[idx].item[i])) ) {
int j;
for(j = 0; j < sd->queues_count; j++) {
if( sd->queues[j] == script->hq[idx].item[i] ) {
break;
}
}
-
+
if( j != sd->queues_count )
sd->queues[j] = -1;
}
+ script->hq[idx].item[i] = 0;
}
-
- script->hq[idx].items = -1;
+
+ script->hq[idx].size = -1;
+ script->hq[idx].items = 0;
}
return false;
}
@@ -17183,12 +18074,39 @@ bool script_hqueue_del(int idx) {
/* deletes queue of id .@queue_id, returns 1 if id not found, 0 otherwise */
BUILDIN(queuedel) {
int idx = script_getnum(st, 2);
-
+
script_pushint(st,script->queue_del(idx)?1:0);
-
+
return true;
}
+void script_hqueue_clear(int idx) {
+ if( idx < 0 || idx >= script->hqs || script->hq[idx].size == -1 ) {
+ ShowWarning("script_hqueue_clear: unknown queue id %d\n",idx);
+ return;
+ } else {
+ struct map_session_data *sd;
+ int i, j;
+
+ for(i = 0; i < script->hq[idx].size; i++) {
+ if( script->hq[idx].item[i] > 0 ) {
+
+ if( script->hq[idx].item[i] >= START_ACCOUNT_NUM && (sd = map->id2sd(script->hq[idx].item[i])) ) {
+ for(j = 0; j < sd->queues_count; j++) {
+ if( sd->queues[j] == idx ) {
+ break;
+ }
+ }
+ if( j != sd->queues_count )
+ sd->queues[j] = -1;
+ }
+ script->hq[idx].item[i] = 0;
+ }
+ }
+ script->hq[idx].items = 0;
+ }
+ return;
+}
/* set .@id, queueiterator(.@queue_id); */
/* creates a new queue iterator, returns its id */
BUILDIN(queueiterator) {
@@ -17196,30 +18114,37 @@ BUILDIN(queueiterator) {
struct hQueue *queue = NULL;
int idx = script->hqis;
int i;
-
- if( qid < 0 || qid >= script->hqs || script->hq[idx].items == -1 || !(queue = script->queue(qid)) ) {
+
+ if( qid < 0 || qid >= script->hqs || script->hq[qid].size == -1 || !(queue = script->queue(qid)) ) {
ShowWarning("queueiterator: invalid queue id %d\n",qid);
return true;
}
-
+
+ /* what if queue->size is 0? (iterating a empty queue?) */
+ if( queue->size <= 0 ) {
+ ShowWarning("queueiterator: attempting to iterate on on empty queue id %d!\n",qid);
+ return true;
+ }
+
for(i = 0; i < script->hqis; i++) {
if( script->hqi[i].items == -1 ) {
break;
}
}
-
- if( i == script->hqis )
+
+ if( i == script->hqis ) {
RECREATE(script->hqi, struct hQueueIterator, ++script->hqis);
- else
+ script->hqi[ idx ].item = NULL;
+ } else
idx = i;
-
- RECREATE(script->hqi[ idx ].item, int, queue->items);
-
- memcpy(&script->hqi[idx].item, &queue->item, sizeof(int)*queue->items);
-
- script->hqi[ idx ].items = queue->items;
+
+ RECREATE(script->hqi[ idx ].item, int, queue->size);
+
+ memcpy(script->hqi[idx].item, queue->item, sizeof(int)*queue->size);
+
+ script->hqi[ idx ].items = queue->size;
script->hqi[ idx ].pos = 0;
-
+
script_pushint(st,idx);
return true;
}
@@ -17227,11 +18152,11 @@ BUILDIN(queueiterator) {
/* returns next/first member in the iterator, 0 if none */
BUILDIN(qiget) {
int idx = script_getnum(st, 2);
-
+
if( idx < 0 || idx >= script->hqis ) {
ShowWarning("buildin_qiget: unknown queue iterator id %d\n",idx);
script_pushint(st, 0);
- } else if ( script->hqi[idx].pos == script->hqi[idx].items ) {
+ } else if ( script->hqi[idx].pos -1 == script->hqi[idx].items ) {
script_pushint(st, 0);
} else {
struct hQueueIterator *it = &script->hqi[idx];
@@ -17244,22 +18169,22 @@ BUILDIN(qiget) {
/* returns 1:0 if there is a next member in the iterator */
BUILDIN(qicheck) {
int idx = script_getnum(st, 2);
-
+
if( idx < 0 || idx >= script->hqis ) {
ShowWarning("buildin_qicheck: unknown queue iterator id %d\n",idx);
script_pushint(st, 0);
- } else if ( script->hqi[idx].pos == script->hqi[idx].items ) {
+ } else if ( script->hqi[idx].pos -1 == script->hqi[idx].items ) {
script_pushint(st, 0);
} else {
script_pushint(st, 1);
}
-
+
return true;
}
/* Queue Iterator Check */
BUILDIN(qiclear) {
int idx = script_getnum(st, 2);
-
+
if( idx < 0 || idx >= script->hqis ) {
ShowWarning("buildin_qiclear: unknown queue iterator id %d\n",idx);
script_pushint(st, 1);
@@ -17267,57 +18192,589 @@ BUILDIN(qiclear) {
script->hqi[idx].items = -1;
script_pushint(st, 0);
}
-
+
+ return true;
+}
+/**
+ * packageitem({<optional container_item_id>})
+ * when no item id is provided it tries to assume it comes from the current item id being processed (if any)
+ **/
+BUILDIN(packageitem) {
+ struct item_data *data = NULL;
+ struct map_session_data *sd = NULL;
+ int nameid;
+
+ if( script_hasdata(st, 2) )
+ nameid = script_getnum(st, 2);
+ else if ( script->current_item_id )
+ nameid = script->current_item_id;
+ else {
+ ShowWarning("buildin_packageitem: no item id provided and no item attached\n");
+ script_pushint(st, 1);
+ return true;
+ }
+
+ if( !(data = itemdb->exists(nameid)) ) {
+ ShowWarning("buildin_packageitem: unknown item id %d\n",nameid);
+ script_pushint(st, 1);
+ } else if ( !data->package ) {
+ ShowWarning("buildin_packageitem: item '%s' (%d) isn't a package!\n",data->name,nameid);
+ script_pushint(st, 1);
+ } else if( !( sd = script->rid2sd(st) ) ) {
+ ShowWarning("buildin_packageitem: no player attached!! (item %s (%d))\n",data->name,nameid);
+ script_pushint(st, 1);
+ } else {
+ itemdb->package_item(sd,data->package);
+ script_pushint(st, 0);
+ }
+
+ return true;
+}
+/* New Battlegrounds Stuff */
+/* bg_team_create(map_name,respawn_x,respawn_y) */
+/* returns created team id or -1 when fails */
+BUILDIN(bg_create_team) {
+ const char *map_name, *ev = "", *dev = "";//ev and dev will be dropped.
+ int x, y, map_index = 0, bg_id;
+
+ map_name = script_getstr(st,2);
+ if( strcmp(map_name,"-") != 0 ) {
+ map_index = script->mapindexname2id(st,map_name);
+ if( map_index == 0 ) { // Invalid Map
+ script_pushint(st,0);
+ return true;
+ }
+ }
+
+ x = script_getnum(st,3);
+ y = script_getnum(st,4);
+
+ if( (bg_id = bg->create(map_index, x, y, ev, dev)) == 0 ) { // Creation failed
+ script_pushint(st,-1);
+ } else
+ script_pushint(st,bg_id);
+
+ return true;
+
+}
+/* bg_join_team(team_id{,optional account id}) */
+/* when account id is not present it tries to autodetect from the attached player (if any) */
+/* returns 0 when successful, 1 otherwise */
+BUILDIN(bg_join_team) {
+ struct map_session_data *sd;
+ int team_id = script_getnum(st, 2);
+
+ if( script_hasdata(st, 3) )
+ sd = map->id2sd(script_getnum(st, 3));
+ else
+ sd = script->rid2sd(st);
+
+ if( !sd )
+ script_pushint(st, 1);
+ else
+ script_pushint(st,bg->team_join(team_id, sd)?0:1);
+
+ return true;
+}
+/*==============[Mhalicot]==================
+ * countbound {<type>};
+ * Creates an array of bounded item IDs
+ * Returns amount of items found
+ * Type:
+ * 1 - Account Bound
+ * 2 - Guild Bound
+ * 3 - Party Bound
+ * 4 - Character Bound
+ *------------------------------------------*/
+BUILDIN(countbound)
+{
+ int i, type, j=0, k=0;
+ TBL_PC *sd;
+
+ if( (sd = script->rid2sd(st)) == NULL )
+ return false;
+
+ type = script_hasdata(st,2)?script_getnum(st,2):0;
+
+ for(i=0;i<MAX_INVENTORY;i++) {
+ if(sd->status.inventory[i].nameid > 0 && (
+ (!type && sd->status.inventory[i].bound > 0) ||
+ (type && sd->status.inventory[i].bound == type)
+ )) {
+ pc->setreg(sd,reference_uid(script->add_str("@bound_items"), k),sd->status.inventory[i].nameid);
+ k++;
+ j += sd->status.inventory[i].amount;
+ }
+ }
+
+ script_pushint(st,j);
+ return 0;
+}
+
+/* bg_match_over( arena_name {, optional canceled } ) */
+/* returns 0 when successful, 1 otherwise */
+BUILDIN(bg_match_over) {
+ bool canceled = script_hasdata(st,3) ? true : false;
+ struct bg_arena *arena = bg->name2arena((char*)script_getstr(st, 2));
+
+ if( arena ) {
+ bg->match_over(arena,canceled);
+ script_pushint(st, 0);
+ } else
+ script_pushint(st, 1);
+
+ return true;
+}
+
+BUILDIN(instance_mapname) {
+ const char *map_name;
+ int m;
+ short instance_id = -1;
+
+ map_name = script_getstr(st,2);
+
+ if( script_hasdata(st,3) )
+ instance_id = script_getnum(st,3);
+ else
+ instance_id = st->instance_id;
+
+ // Check that instance mapname is a valid map
+ if( instance_id == -1 || (m = instance->mapname2imap(map_name,instance_id)) == -1 )
+ script_pushconststr(st, "");
+ else
+ script_pushconststr(st, map->list[m].name);
+
+ return true;
+}
+/* modify an instances' reload-spawn point */
+/* instance_set_respawn <map_name>,<x>,<y>{,<instance_id>} */
+/* returns 1 when successful, 0 otherwise. */
+BUILDIN(instance_set_respawn) {
+ const char *map_name;
+ short instance_id = -1;
+ short mid;
+ short x,y;
+
+ map_name = script_getstr(st,2);
+ x = script_getnum(st, 3);
+ y = script_getnum(st, 4);
+
+ if( script_hasdata(st, 5) )
+ instance_id = script_getnum(st, 5);
+ else
+ instance_id = st->instance_id;
+
+ if( instance_id == -1 || !instance->valid(instance_id) )
+ script_pushint(st, 0);
+ else if( (mid = map->mapname2mapid(map_name)) == -1 ) {
+ ShowError("buildin_instance_set_respawn: unknown map '%s'\n",map_name);
+ script_pushint(st, 0);
+ } else {
+ int i;
+
+ for(i = 0; i < instance->list[instance_id].num_map; i++) {
+ if( map->list[instance->list[instance_id].map[i]].m == mid ) {
+ instance->list[instance_id].respawn.map = map_id2index(mid);
+ instance->list[instance_id].respawn.x = x;
+ instance->list[instance_id].respawn.y = y;
+ break;
+ }
+ }
+
+ if( i != instance->list[instance_id].num_map )
+ script_pushint(st, 1);
+ else {
+ ShowError("buildin_instance_set_respawn: map '%s' not part of instance '%s'\n",map_name,instance->list[instance_id].name);
+ script_pushint(st, 0);
+ }
+ }
+
+
+ return true;
+}
+/**
+ * @call openshop({NPC Name});
+ *
+ * @return 1 on success, 0 otherwise.
+ **/
+BUILDIN(openshop) {
+ struct npc_data *nd;
+ struct map_session_data *sd;
+ const char *name = NULL;
+
+ if( script_hasdata(st, 2) ) {
+ name = script_getstr(st, 2);
+ if( !(nd = npc->name2id(name)) || nd->subtype != SCRIPT ) {
+ ShowWarning("buildin_openshop(\"%s\"): trying to run without a proper NPC!\n",name);
+ return false;
+ }
+ } else if( !(nd = map->id2nd(st->oid)) ) {
+ ShowWarning("buildin_openshop: trying to run without a proper NPC!\n");
+ return false;
+ }
+ if( !( sd = script->rid2sd(st) ) ) {
+ ShowWarning("buildin_openshop: trying to run without a player attached!\n");
+ return false;
+ } else if ( !nd->u.scr.shop || !nd->u.scr.shop->items ) {
+ ShowWarning("buildin_openshop: trying to open without any items!\n");
+ return false;
+ }
+
+ if( !npc->trader_open(sd,nd) )
+ script_pushint(st, 0);
+ else
+ script_pushint(st, 1);
+
+ return true;
+}
+/**
+ * @call sellitem <Item_ID>,{,price{,qty}};
+ *
+ * adds <Item_ID> (or modifies if present) to shop
+ * if price not provided (or -1) uses the item's value_sell
+ **/
+BUILDIN(sellitem) {
+ struct npc_data *nd;
+ struct item_data *it;
+ int i = 0, id = script_getnum(st,2);
+ int value = 0;
+ int qty = 0;
+
+ if( !(nd = map->id2nd(st->oid)) ) {
+ ShowWarning("buildin_sellitem: trying to run without a proper NPC!\n");
+ return false;
+ } else if ( !(it = itemdb->exists(id)) ) {
+ ShowWarning("buildin_sellitem: unknown item id '%d'!\n",id);
+ return false;
+ }
+
+ value = script_hasdata(st,3) ? script_getnum(st, 3) : it->value_buy;
+ if( value == -1 )
+ value = it->value_buy;
+
+ if( !nd->u.scr.shop )
+ npc->trader_update(nd->src_id?nd->src_id:nd->bl.id);
+ else {/* no need to run this if its empty */
+ for( i = 0; i < nd->u.scr.shop->items; i++ ) {
+ if( nd->u.scr.shop->item[i].nameid == id )
+ break;
+ }
+ }
+
+ if( nd->u.scr.shop->type == NST_MARKET ) {
+ if( !script_hasdata(st,4) || ( qty = script_getnum(st, 4) ) <= 0 ) {
+ ShowError("buildin_sellitem: invalid 'qty' for market-type shop!\n");
+ return false;
+ }
+ }
+
+ if( ( nd->u.scr.shop->type == NST_ZENY || nd->u.scr.shop->type == NST_MARKET ) && value*0.75 < it->value_sell*1.24 ) {
+ ShowWarning("buildin_sellitem: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) in NPC %s (%s)\n",
+ it->name, id, value, (int)(value*0.75), it->value_sell, (int)(it->value_sell*1.24), nd->exname, nd->path);
+ }
+
+ if( i != nd->u.scr.shop->items ) {
+ nd->u.scr.shop->item[i].value = value;
+ nd->u.scr.shop->item[i].qty = qty;
+ if( nd->u.scr.shop->type == NST_MARKET ) /* has been manually updated, make it reflect on sql */
+ npc->market_tosql(nd,i);
+ } else {
+ for( i = 0; i < nd->u.scr.shop->items; i++ ) {
+ if( nd->u.scr.shop->item[i].nameid == 0 )
+ break;
+ }
+
+ if( i == nd->u.scr.shop->items ) {
+ if( nd->u.scr.shop->items == USHRT_MAX ) {
+ ShowWarning("buildin_sellitem: Can't add %s (%s/%s), shop list is full!\n", it->name, nd->exname, nd->path);
+ return false;
+ }
+ i = nd->u.scr.shop->items;
+ RECREATE(nd->u.scr.shop->item, struct npc_item_list, ++nd->u.scr.shop->items);
+ }
+
+ nd->u.scr.shop->item[i].nameid = it->nameid;
+ nd->u.scr.shop->item[i].value = value;
+ nd->u.scr.shop->item[i].qty = qty;
+ }
+
+ return true;
+}
+/**
+ * @call stopselling <Item_ID>;
+ *
+ * removes <Item_ID> from the current npc shop
+ *
+ * @return 1 on success, 0 otherwise
+ **/
+BUILDIN(stopselling) {
+ struct npc_data *nd;
+ int i, id = script_getnum(st,2);
+
+ if( !(nd = map->id2nd(st->oid)) || !nd->u.scr.shop ) {
+ ShowWarning("buildin_stopselling: trying to run without a proper NPC!\n");
+ return false;
+ }
+
+ for( i = 0; i < nd->u.scr.shop->items; i++ ) {
+ if( nd->u.scr.shop->item[i].nameid == id )
+ break;
+ }
+
+ if( i != nd->u.scr.shop->items ) {
+ int cursor;
+
+ if( nd->u.scr.shop->type == NST_MARKET )
+ npc->market_delfromsql(nd,i);
+
+ nd->u.scr.shop->item[i].nameid = 0;
+ nd->u.scr.shop->item[i].value = 0;
+ nd->u.scr.shop->item[i].qty = 0;
+
+ for( i = 0, cursor = 0; i < nd->u.scr.shop->items; i++ ) {
+ if( nd->u.scr.shop->item[i].nameid == 0 )
+ continue;
+
+ if( cursor != i ) {
+ nd->u.scr.shop->item[cursor].nameid = nd->u.scr.shop->item[i].nameid;
+ nd->u.scr.shop->item[cursor].value = nd->u.scr.shop->item[i].value;
+ nd->u.scr.shop->item[cursor].qty = nd->u.scr.shop->item[i].qty;
+ }
+
+ cursor++;
+ }
+
+ script_pushint(st, 1);
+ } else
+ script_pushint(st, 0);
+
+ return true;
+}
+/**
+ * @call setcurrency <Val1>{,<Val2>};
+ *
+ * updates currently-attached player shop currency
+ **/
+/* setcurrency(<Val1>,{<Val2>}) */
+BUILDIN(setcurrency) {
+ int val1 = script_getnum(st,2),
+ val2 = script_hasdata(st, 3) ? script_getnum(st,3) : 0;
+ struct npc_data *nd;
+
+ if( !(nd = map->id2nd(st->oid)) ) {
+ ShowWarning("buildin_setcurrency: trying to run without a proper NPC!\n");
+ return false;
+ }
+
+ npc->trader_funds[0] = val1;
+ npc->trader_funds[1] = val2;
+
+ return true;
+}
+/**
+ * @call tradertype(<type>);
+ *
+ * defaults to 0, so no need to call when you're doing zeny
+ * check enum npc_shop_types for list
+ * cleans shop list on use
+ **/
+BUILDIN(tradertype) {
+ int type = script_getnum(st, 2);
+ struct npc_data *nd;
+
+ if( !(nd = map->id2nd(st->oid)) ) {
+ ShowWarning("buildin_tradertype: trying to run without a proper NPC!\n");
+ return false;
+ } else if ( type < 0 || type > NST_MAX ) {
+ ShowWarning("buildin_tradertype: invalid type param %d!\n",type);
+ return false;
+ }
+
+ if( !nd->u.scr.shop )
+ npc->trader_update(nd->src_id?nd->src_id:nd->bl.id);
+ else {/* clear list */
+ int i;
+ for( i = 0; i < nd->u.scr.shop->items; i++ ) {
+ nd->u.scr.shop->item[i].nameid = 0;
+ nd->u.scr.shop->item[i].value = 0;
+ nd->u.scr.shop->item[i].qty = 0;
+ }
+ npc->market_delfromsql(nd,USHRT_MAX);
+ }
+
+#if PACKETVER < 20131223
+ if( type == NST_MARKET ) {
+ ShowWarning("buildin_tradertype: NST_MARKET is only available with PACKETVER 20131223 or newer!\n");
+ script->reportsrc(st);
+ }
+#endif
+
+ nd->u.scr.shop->type = type;
+
+ return true;
+}
+/**
+ * @call purchaseok();
+ *
+ * signs the transaction can proceed
+ **/
+BUILDIN(purchaseok) {
+ struct npc_data *nd;
+
+ if( !(nd = map->id2nd(st->oid)) || !nd->u.scr.shop ) {
+ ShowWarning("buildin_purchaseok: trying to run without a proper NPC!\n");
+ return false;
+ }
+
+ npc->trader_ok = true;
+
+ return true;
+}
+/**
+ * @call shopcount(<Item_ID>);
+ *
+ * @return number of available items in the script's attached shop
+ **/
+BUILDIN(shopcount) {
+ struct npc_data *nd;
+ int id = script_getnum(st, 2);
+ unsigned short i;
+
+ if( !(nd = map->id2nd(st->oid)) ) {
+ ShowWarning("buildin_shopcount(%d): trying to run without a proper NPC!\n",id);
+ return false;
+ } else if ( !nd->u.scr.shop || !nd->u.scr.shop->items ) {
+ ShowWarning("buildin_shopcount(%d): trying to use without any items!\n",id);
+ return false;
+ } else if ( nd->u.scr.shop->type != NST_MARKET ) {
+ ShowWarning("buildin_shopcount(%d): trying to use on a non-NST_MARKET shop!\n",id);
+ return false;
+ }
+
+ /* lookup */
+ for(i = 0; i < nd->u.scr.shop->items; i++) {
+ if( nd->u.scr.shop->item[i].nameid == id ) {
+ script_pushint(st, nd->u.scr.shop->item[i].qty);
+ break;
+ }
+ }
+
+ /* didn't find it */
+ if( i == nd->u.scr.shop->items )
+ script_pushint(st, 0);
+
return true;
}
// declarations that were supposed to be exported from npc_chat.c
#ifdef PCRE_SUPPORT
- BUILDIN(defpattern);
- BUILDIN(activatepset);
- BUILDIN(deactivatepset);
- BUILDIN(deletepset);
+BUILDIN(defpattern);
+BUILDIN(activatepset);
+BUILDIN(deactivatepset);
+BUILDIN(deletepset);
+
+BUILDIN(pcre_match) {
+ const char *input = script_getstr(st, 2);
+ const char *regex = script_getstr(st, 3);
+
+ script->op_2str(st, C_RE_EQ, input, regex);
+ return true;
+}
#endif
-bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st)) {
- int n = add_str(name), i = 0;
-
- if( script->str_data[n].type == C_FUNC ) {
- script->str_data[n].func = func;
- i = script->str_data[n].val;
- if( args ) {
- int slen = strlen(args);
- if( script->buildin[i] ) {
- aFree(script->buildin[i]);
- }
- CREATE(script->buildin[i], char, slen + 1);
- safestrncpy(script->buildin[i], args, slen + 1);
- } else {
- if( script->buildin[i] )
- aFree(script->buildin[i]);
- script->buildin[i] = NULL;
+/**
+ * Adds a built-in script function.
+ *
+ * @param buildin Script function data
+ * @param force Whether to override an existing function with the same name
+ * (i.e. a plugin overriding a built-in function)
+ * @return Whether the function was successfully added.
+ */
+bool script_add_builtin(const struct script_function *buildin, bool override) {
+ int n = 0, offset = 0;
+ size_t slen;
+ if( !buildin ) {
+ return false;
+ }
+ if( buildin->arg ) {
+ // arg must follow the pattern: (v|s|i|r|l)*\?*\*?
+ // 'v' - value (either string or int or reference)
+ // 's' - string
+ // 'i' - int
+ // 'r' - reference (of a variable)
+ // 'l' - label
+ // '?' - one optional parameter
+ // '*' - unknown number of optional parameters
+ char *p = buildin->arg;
+ while( *p == 'v' || *p == 's' || *p == 'i' || *p == 'r' || *p == 'l' ) ++p;
+ while( *p == '?' ) ++p;
+ if( *p == '*' ) ++p;
+ if( *p != 0 ) {
+ ShowWarning("add_builtin: ignoring function \"%s\" with invalid arg \"%s\".\n", buildin->name, buildin->arg);
+ return false;
}
+ }
+ if( !buildin->name || *script->skip_word(buildin->name) != 0 ) {
+ ShowWarning("add_builtin: ignoring function with invalid name \"%s\" (must be a word).\n", buildin->name);
+ return false;
+ }
+ if ( !buildin->func ) {
+ ShowWarning("add_builtin: ignoring function \"%s\" with invalid source function.\n", buildin->name);
+ return false;
+ }
+ slen = buildin->arg ? strlen(buildin->arg) : 0;
+ n = script->add_str(buildin->name);
+ if( !override && script->str_data[n].func && script->str_data[n].func != buildin->func ) {
+ return false; /* something replaced it, skip. */
+ }
+
+ if( override && script->str_data[n].type == C_FUNC ) {
+ // Overriding
+ offset = script->str_data[n].val;
+ if( script->buildin[offset] )
+ aFree(script->buildin[offset]);
+ script->buildin[offset] = NULL;
} else {
- i = script->buildin_count;
+ // Adding new function
+ if( strcmp(buildin->name, "setr") == 0 ) script->buildin_set_ref = n;
+ else if( strcmp(buildin->name, "callsub") == 0 ) script->buildin_callsub_ref = n;
+ else if( strcmp(buildin->name, "callfunc") == 0 ) script->buildin_callfunc_ref = n;
+ else if( strcmp(buildin->name, "getelementofarray") == 0 ) script->buildin_getelementofarray_ref = n;
+
+ offset = script->buildin_count;
+
script->str_data[n].type = C_FUNC;
- script->str_data[n].val = i;
- script->str_data[n].func = func;
-
+ script->str_data[n].val = offset;
+
+ // Note: This is a no-op if script->buildin is already large enough
+ // (it'll only have effect when a plugin adds a new command)
RECREATE(script->buildin, char *, ++script->buildin_count);
-
- /* we only store the arguments, its the only thing used out of this */
- if( args != NULL ) {
- int slen = strlen(args);
- CREATE(script->buildin[i], char, slen + 1);
- safestrncpy(script->buildin[i], args, slen + 1);
- } else
- script->buildin[i] = NULL;
}
-
+
+ script->str_data[n].func = buildin->func;
+
+ /* we only store the arguments, its the only thing used out of this */
+ if( slen ) {
+ CREATE(script->buildin[offset], char, slen + 1);
+ safestrncpy(script->buildin[offset], buildin->arg, slen + 1);
+ } else {
+ script->buildin[offset] = NULL;
+ }
+
return true;
}
+bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st)) {
+ struct script_function buildin;
+ buildin.name = name;
+ buildin.arg = args;
+ buildin.func = func;
+ return script->add_builtin(&buildin, true);
+}
+
+#define BUILDIN_DEF(x,args) { buildin_ ## x , #x , args }
+#define BUILDIN_DEF2(x,x2,args) { buildin_ ## x , x2 , args }
void script_parse_builtin(void) {
struct script_function BUILDIN[] = {
// NPC interaction
@@ -17344,7 +18801,8 @@ void script_parse_builtin(void) {
BUILDIN_DEF(warpguild,"siii"), // [Fredzilla]
BUILDIN_DEF(setlook,"ii"),
BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it
- BUILDIN_DEF(set,"rv"),
+ BUILDIN_DEF2(setr,"set","rv"),
+ BUILDIN_DEF(setr,"rv?"), // Not meant to be used directly, required for var++/var--
BUILDIN_DEF(setarray,"rv*"),
BUILDIN_DEF(cleararray,"rvi"),
BUILDIN_DEF(copyarray,"rri"),
@@ -17393,9 +18851,9 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getequiprefinerycnt,"i"),
BUILDIN_DEF(getequipweaponlv,"i"),
BUILDIN_DEF(getequippercentrefinery,"i"),
- BUILDIN_DEF(successrefitem,"i"),
+ BUILDIN_DEF(successrefitem,"i?"),
BUILDIN_DEF(failedrefitem,"i"),
- BUILDIN_DEF(downrefitem,"i"),
+ BUILDIN_DEF(downrefitem,"i?"),
BUILDIN_DEF(statusup,"i"),
BUILDIN_DEF(statusup2,"ii"),
BUILDIN_DEF(bonus,"iv"),
@@ -17474,7 +18932,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(sc_end,"i?"),
BUILDIN_DEF(getstatus, "i?"),
BUILDIN_DEF(getscrate,"ii?"),
- BUILDIN_DEF(debugmes,"s"),
+ BUILDIN_DEF(debugmes,"v"),
BUILDIN_DEF2(catchpet,"pet","i"),
BUILDIN_DEF2(birthpet,"bpet",""),
BUILDIN_DEF(resetlvl,"i"),
@@ -17488,8 +18946,8 @@ void script_parse_builtin(void) {
BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"),
BUILDIN_DEF(enablewaitingroomevent,"?"),
BUILDIN_DEF(disablewaitingroomevent,"?"),
- BUILDIN_DEF2(enablewaitingroomevent,"enablearena",""), // Added by RoVeRT
- BUILDIN_DEF2(disablewaitingroomevent,"disablearena",""), // Added by RoVeRT
+ BUILDIN_DEF2(enablewaitingroomevent,"enablearena",""), // Added by RoVeRT
+ BUILDIN_DEF2(disablewaitingroomevent,"disablearena",""), // Added by RoVeRT
BUILDIN_DEF(getwaitingroomstate,"i?"),
BUILDIN_DEF(warpwaitingpc,"sii?"),
BUILDIN_DEF(attachrid,"i"),
@@ -17498,17 +18956,17 @@ void script_parse_builtin(void) {
BUILDIN_DEF(setmapflagnosave,"ssii"),
BUILDIN_DEF(getmapflag,"si"),
BUILDIN_DEF(setmapflag,"si?"),
- BUILDIN_DEF(removemapflag,"si?"),
+ BUILDIN_DEF(removemapflag,"si"),
BUILDIN_DEF(pvpon,"s"),
BUILDIN_DEF(pvpoff,"s"),
BUILDIN_DEF(gvgon,"s"),
BUILDIN_DEF(gvgoff,"s"),
BUILDIN_DEF(emotion,"i??"),
BUILDIN_DEF(maprespawnguildid,"sii"),
- BUILDIN_DEF(agitstart,""), // <Agit>
+ BUILDIN_DEF(agitstart,""), // <Agit>
BUILDIN_DEF(agitend,""),
BUILDIN_DEF(agitcheck,""), // <Agitcheck>
- BUILDIN_DEF(flagemblem,"i"), // Flag Emblem
+ BUILDIN_DEF(flagemblem,"i"), // Flag Emblem
BUILDIN_DEF(getcastlename,"s"),
BUILDIN_DEF(getcastledata,"si"),
BUILDIN_DEF(setcastledata,"sii"),
@@ -17534,13 +18992,13 @@ void script_parse_builtin(void) {
BUILDIN_DEF(clearitem,""),
BUILDIN_DEF(classchange,"ii"),
BUILDIN_DEF(misceffect,"i"),
- BUILDIN_DEF(playBGM,"s"),
- BUILDIN_DEF(playBGMall,"s?????"),
+ BUILDIN_DEF(playbgm,"s"),
+ BUILDIN_DEF(playbgmall,"s?????"),
BUILDIN_DEF(soundeffect,"si"),
- BUILDIN_DEF(soundeffectall,"si?????"), // SoundEffectAll [Codemaster]
- BUILDIN_DEF(strmobinfo,"ii"), // display mob data [Valaris]
- BUILDIN_DEF(guardian,"siisi??"), // summon guardians
- BUILDIN_DEF(guardianinfo,"sii"), // display guardian data [Valaris]
+ BUILDIN_DEF(soundeffectall,"si?????"), // SoundEffectAll [Codemaster]
+ BUILDIN_DEF(strmobinfo,"ii"), // display mob data [Valaris]
+ BUILDIN_DEF(guardian,"siisi??"), // summon guardians
+ BUILDIN_DEF(guardianinfo,"sii"), // display guardian data [Valaris]
BUILDIN_DEF(petskillbonus,"iiii"), // [Valaris]
BUILDIN_DEF(petrecovery,"ii"), // [Valaris]
BUILDIN_DEF(petloot,"i"), // [Valaris]
@@ -17553,7 +19011,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(specialeffect,"i??"), // npc skill effect [Valaris]
BUILDIN_DEF(specialeffect2,"i??"), // skill effect on players[Valaris]
BUILDIN_DEF(nude,""), // nude command [Valaris]
- BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT
+ BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT
BUILDIN_DEF(atcommand,"s"), // [MouseJstr]
BUILDIN_DEF2(atcommand,"charcommand","s"), // [MouseJstr]
BUILDIN_DEF(movenpc,"sii?"), // [MouseJstr]
@@ -17565,7 +19023,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(npcspeed,"i"), // [Valaris]
BUILDIN_DEF(npcwalkto,"ii"), // [Valaris]
BUILDIN_DEF(npcstop,""), // [Valaris]
- BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus]
+ BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus]
BUILDIN_DEF(checkoption1,"i"),
BUILDIN_DEF(checkoption2,"i"),
BUILDIN_DEF(guildgetexp,"i"),
@@ -17585,6 +19043,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(activatepset,"i"), // Activate a pattern set [MouseJstr]
BUILDIN_DEF(deactivatepset,"i"), // Deactive a pattern set [MouseJstr]
BUILDIN_DEF(deletepset,"i"), // Delete a pattern set [MouseJstr]
+ BUILDIN_DEF(pcre_match,"ss"),
#endif
BUILDIN_DEF(dispbottom,"s"), //added from jA [Lupus]
BUILDIN_DEF(getusersname,""),
@@ -17643,11 +19102,14 @@ void script_parse_builtin(void) {
BUILDIN_DEF(disguise,"i"), //disguise player. Lupus
BUILDIN_DEF(undisguise,""), //undisguise player. Lupus
BUILDIN_DEF(getmonsterinfo,"ii"), //Lupus
+ BUILDIN_DEF(addmonsterdrop,"vii"),
+ BUILDIN_DEF(delmonsterdrop,"vi"),
BUILDIN_DEF(axtoi,"s"),
BUILDIN_DEF(query_sql,"s*"),
BUILDIN_DEF(query_logsql,"s*"),
BUILDIN_DEF(escape_sql,"v"),
BUILDIN_DEF(atoi,"s"),
+ BUILDIN_DEF(strtol,"si"),
// [zBuffer] List of player cont commands --->
BUILDIN_DEF(rid2name,"i"),
BUILDIN_DEF(pcfollow,"ii"),
@@ -17670,12 +19132,13 @@ void script_parse_builtin(void) {
BUILDIN_DEF(awake,"s"),
BUILDIN_DEF(getvariableofnpc,"rs"),
BUILDIN_DEF(warpportal,"iisii"),
- BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn]
+ BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn]
BUILDIN_DEF2(homunculus_mutate,"hommutate","?"),
- BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus]
- BUILDIN_DEF(checkhomcall,""),
- BUILDIN_DEF(eaclass,"?"), //[Skotlex]
- BUILDIN_DEF(roclass,"i?"), //[Skotlex]
+ BUILDIN_DEF2(homunculus_morphembryo,"morphembryo",""),
+ BUILDIN_DEF2(homunculus_checkcall,"checkhomcall",""),
+ BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus]
+ BUILDIN_DEF(eaclass,"?"), //[Skotlex]
+ BUILDIN_DEF(roclass,"i?"), //[Skotlex]
BUILDIN_DEF(checkvending,"?"),
BUILDIN_DEF(checkchatting,"?"),
BUILDIN_DEF(checkidle,"?"),
@@ -17718,7 +19181,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(bg_get_data,"ii"),
BUILDIN_DEF(bg_getareausers,"isiiii"),
BUILDIN_DEF(bg_updatescore,"sii"),
-
+
// Instancing
BUILDIN_DEF(instance_create,"si?"),
BUILDIN_DEF(instance_destroy,"?"),
@@ -17733,6 +19196,10 @@ void script_parse_builtin(void) {
BUILDIN_DEF(has_instance,"s?"),
BUILDIN_DEF(instance_warpall,"sii?"),
BUILDIN_DEF(instance_check_party,"i???"),
+ BUILDIN_DEF(instance_mapname,"s?"),
+ BUILDIN_DEF(instance_set_respawn,"sii?"),
+ BUILDIN_DEF2(has_instance,"has_instance2","s"),
+
/**
* 3rd-related
**/
@@ -17748,13 +19215,13 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getargcount,""),
BUILDIN_DEF(getcharip,"?"),
BUILDIN_DEF(is_function,"s"),
- BUILDIN_DEF(get_revision,""),
BUILDIN_DEF(freeloop,"i"),
BUILDIN_DEF(getrandgroupitem,"ii"),
BUILDIN_DEF(cleanmap,"s"),
BUILDIN_DEF2(cleanmap,"cleanarea","siiii"),
BUILDIN_DEF(npcskill,"viii"),
BUILDIN_DEF(itemeffect,"v"),
+ BUILDIN_DEF2(itemeffect,"consumeitem","v"), /* alias of itemeffect */
BUILDIN_DEF(delequip,"i"),
/**
* @commands (script based)
@@ -17762,15 +19229,23 @@ void script_parse_builtin(void) {
BUILDIN_DEF(bindatcmd, "ss???"),
BUILDIN_DEF(unbindatcmd, "s"),
BUILDIN_DEF(useatcmd, "s"),
-
+
+ /**
+ * Item bound [Xantara] [Akinari] [Mhalicot/Hercules]
+ **/
+ BUILDIN_DEF2(getitem,"getitembound","vii?"),
+ BUILDIN_DEF2(getitem2,"getitembound2","viiiiiiiii?"),
+ BUILDIN_DEF(countbound, "?"),
+
//Quest Log System [Inkfish]
+ BUILDIN_DEF(questinfo, "ii??"),
BUILDIN_DEF(setquest, "i"),
BUILDIN_DEF(erasequest, "i"),
BUILDIN_DEF(completequest, "i"),
BUILDIN_DEF(checkquest, "i?"),
BUILDIN_DEF(changequest, "ii"),
- BUILDIN_DEF(showevent, "ii"),
-
+ BUILDIN_DEF(showevent, "i?"),
+
/**
* hQueue [Ind/Hercules]
**/
@@ -17784,87 +19259,231 @@ void script_parse_builtin(void) {
BUILDIN_DEF(qicheck,"i"),
BUILDIN_DEF(qiget,"i"),
BUILDIN_DEF(qiclear,"i"),
+
+ BUILDIN_DEF(packageitem,"?"),
+
+ BUILDIN_DEF(sit, "?"),
+ BUILDIN_DEF(stand, "?"),
+ BUILDIN_DEF(issit, "?"),
+
+ BUILDIN_DEF(montransform, "vii????"), // Monster Transform [malufett/Hercules]
+
+ /* New BG Commands [Hercules] */
+ BUILDIN_DEF(bg_create_team,"sii"),
+ BUILDIN_DEF(bg_join_team,"i?"),
+ BUILDIN_DEF(bg_match_over,"s?"),
+
+ /* New Shop Support */
+ BUILDIN_DEF(openshop,"?"),
+ BUILDIN_DEF(sellitem,"i??"),
+ BUILDIN_DEF(stopselling,"i"),
+ BUILDIN_DEF(setcurrency,"i?"),
+ BUILDIN_DEF(tradertype,"i"),
+ BUILDIN_DEF(purchaseok,""),
+ BUILDIN_DEF(shopcount, "i"),
};
- int i,n, len = ARRAYLENGTH(BUILDIN), start = script->buildin_count;
- char* p;
- RECREATE(script->buildin, char *, start + len);
+ int i, len = ARRAYLENGTH(BUILDIN);
+ RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up
+ memset(script->buildin + script->buildin_count, '\0', sizeof(char *) * len);
for( i = 0; i < len; i++ ) {
- // arg must follow the pattern: (v|s|i|r|l)*\?*\*?
- // 'v' - value (either string or int or reference)
- // 's' - string
- // 'i' - int
- // 'r' - reference (of a variable)
- // 'l' - label
- // '?' - one optional parameter
- // '*' - unknown number of optional parameters
- p = BUILDIN[i].arg;
- while( *p == 'v' || *p == 's' || *p == 'i' || *p == 'r' || *p == 'l' ) ++p;
- while( *p == '?' ) ++p;
- if( *p == '*' ) ++p;
- if( *p != 0 ){
- ShowWarning("script_parse_builtin: ignoring function \"%s\" with invalid arg \"%s\".\n", BUILDIN[i].name, BUILDIN[i].arg);
- } else if( *skip_word(BUILDIN[i].name) != 0 ){
- ShowWarning("script_parse_builtin: ignoring function with invalid name \"%s\" (must be a word).\n", BUILDIN[i].name);
- } else {
- int slen = strlen(BUILDIN[i].arg), offset = start + i;
- n = add_str(BUILDIN[i].name);
-
- if (!strcmp(BUILDIN[i].name, "set")) buildin_set_ref = n;
- else if (!strcmp(BUILDIN[i].name, "callsub")) buildin_callsub_ref = n;
- else if (!strcmp(BUILDIN[i].name, "callfunc")) buildin_callfunc_ref = n;
- else if (!strcmp(BUILDIN[i].name, "getelementofarray") ) buildin_getelementofarray_ref = n;
-
- if( script->str_data[n].func && script->str_data[n].func != BUILDIN[i].func )
- continue;/* something replaced it, skip. */
-
- script->str_data[n].type = C_FUNC;
- script->str_data[n].val = offset;
- script->str_data[n].func = BUILDIN[i].func;
-
- /* we only store the arguments, its the only thing used out of this */
- if( slen ) {
- CREATE(script->buildin[offset], char, slen + 1);
- safestrncpy(script->buildin[offset], BUILDIN[i].arg, slen + 1);
- } else
- script->buildin[offset] = NULL;
-
- script->buildin_count++;
+ script->add_builtin(&BUILDIN[i], false);
+ }
+}
+#undef BUILDIN_DEF
+#undef BUILDIN_DEF2
- }
+void script_label_add(int key, int pos) {
+ int idx = script->label_count;
+
+ if( script->labels_size == script->label_count ) {
+ script->labels_size += 1024;
+ RECREATE(script->labels, struct script_label_entry, script->labels_size);
}
+
+ script->labels[idx].key = key;
+ script->labels[idx].pos = pos;
+ script->label_count++;
}
+/**
+ * Sets source-end constants for scripts to play with
+ **/
+void script_hardcoded_constants(void) {
+
+ /* server defines */
+ script->set_constant("PACKETVER",PACKETVER,false);
+ script->set_constant("MAX_LEVEL",MAX_LEVEL,false);
+ script->set_constant("MAX_STORAGE",MAX_STORAGE,false);
+ script->set_constant("MAX_GUILD_STORAGE",MAX_GUILD_STORAGE,false);
+ script->set_constant("MAX_CART",MAX_INVENTORY,false);
+ script->set_constant("MAX_INVENTORY",MAX_INVENTORY,false);
+ script->set_constant("MAX_ZENY",MAX_ZENY,false);
+ script->set_constant("MAX_BG_MEMBERS",MAX_BG_MEMBERS,false);
+ script->set_constant("MAX_CHAT_USERS",MAX_CHAT_USERS,false);
+
+ /* status options */
+ script->set_constant("Option_Nothing",OPTION_NOTHING,false);
+ script->set_constant("Option_Sight",OPTION_SIGHT,false);
+ script->set_constant("Option_Hide",OPTION_HIDE,false);
+ script->set_constant("Option_Cloak",OPTION_CLOAK,false);
+ script->set_constant("Option_Falcon",OPTION_FALCON,false);
+ script->set_constant("Option_Riding",OPTION_RIDING,false);
+ script->set_constant("Option_Invisible",OPTION_INVISIBLE,false);
+ script->set_constant("Option_Orcish",OPTION_ORCISH,false);
+ script->set_constant("Option_Wedding",OPTION_WEDDING,false);
+ script->set_constant("Option_Chasewalk",OPTION_CHASEWALK,false);
+ script->set_constant("Option_Flying",OPTION_FLYING,false);
+ script->set_constant("Option_Xmas",OPTION_XMAS,false);
+ script->set_constant("Option_Transform",OPTION_TRANSFORM,false);
+ script->set_constant("Option_Summer",OPTION_SUMMER,false);
+ script->set_constant("Option_Dragon1",OPTION_DRAGON1,false);
+ script->set_constant("Option_Wug",OPTION_WUG,false);
+ script->set_constant("Option_Wugrider",OPTION_WUGRIDER,false);
+ script->set_constant("Option_Madogear",OPTION_MADOGEAR,false);
+ script->set_constant("Option_Dragon2",OPTION_DRAGON2,false);
+ script->set_constant("Option_Dragon3",OPTION_DRAGON3,false);
+ script->set_constant("Option_Dragon4",OPTION_DRAGON4,false);
+ script->set_constant("Option_Dragon5",OPTION_DRAGON5,false);
+ script->set_constant("Option_Hanbok",OPTION_HANBOK,false);
+ script->set_constant("Option_Oktoberfest",OPTION_OKTOBERFEST,false);
+
+ /* status option compounds */
+ script->set_constant("Option_Dragon",OPTION_DRAGON,false);
+ script->set_constant("Option_Costume",OPTION_COSTUME,false);
+
+ /* send_target */
+ script->set_constant("ALL_CLIENT",ALL_CLIENT,false);
+ script->set_constant("ALL_SAMEMAP",ALL_SAMEMAP,false);
+ script->set_constant("AREA",AREA,false);
+ script->set_constant("AREA_WOS",AREA_WOS,false);
+ script->set_constant("AREA_WOC",AREA_WOC,false);
+ script->set_constant("AREA_WOSC",AREA_WOSC,false);
+ script->set_constant("AREA_CHAT_WOC",AREA_CHAT_WOC,false);
+ script->set_constant("CHAT",CHAT,false);
+ script->set_constant("CHAT_WOS",CHAT_WOS,false);
+ script->set_constant("PARTY",PARTY,false);
+ script->set_constant("PARTY_WOS",PARTY_WOS,false);
+ script->set_constant("PARTY_SAMEMAP",PARTY_SAMEMAP,false);
+ script->set_constant("PARTY_SAMEMAP_WOS",PARTY_SAMEMAP_WOS,false);
+ script->set_constant("PARTY_AREA",PARTY_AREA,false);
+ script->set_constant("PARTY_AREA_WOS",PARTY_AREA_WOS,false);
+ script->set_constant("GUILD",GUILD,false);
+ script->set_constant("GUILD_WOS",GUILD_WOS,false);
+ script->set_constant("GUILD_SAMEMAP",GUILD_SAMEMAP,false);
+ script->set_constant("GUILD_SAMEMAP_WOS",GUILD_SAMEMAP_WOS,false);
+ script->set_constant("GUILD_AREA",GUILD_AREA,false);
+ script->set_constant("GUILD_AREA_WOS",GUILD_AREA_WOS,false);
+ script->set_constant("GUILD_NOBG",GUILD_NOBG,false);
+ script->set_constant("DUEL",DUEL,false);
+ script->set_constant("DUEL_WOS",DUEL_WOS,false);
+ script->set_constant("SELF",SELF,false);
+ script->set_constant("BG",BG,false);
+ script->set_constant("BG_WOS",BG_WOS,false);
+ script->set_constant("BG_SAMEMAP",BG_SAMEMAP,false);
+ script->set_constant("BG_SAMEMAP_WOS",BG_SAMEMAP_WOS,false);
+ script->set_constant("BG_AREA",BG_AREA,false);
+ script->set_constant("BG_AREA_WOS",BG_AREA_WOS,false);
+ script->set_constant("BG_QUEUE",BG_QUEUE,false);
+}
+
+/**
+ * a mapindex_name2id wrapper meant to help with invalid name handling
+ **/
+unsigned short script_mapindexname2id (struct script_state *st, const char* name) {
+ unsigned short index;
+
+ if( !(index=mapindex->name2id(name)) ) {
+ script->reportsrc(st);
+ return 0;
+ }
+ return index;
+}
+
+
void script_defaults(void) {
+ // aegis->athena slot position conversion table
+ unsigned int equip[SCRIPT_EQUIP_TABLE_SIZE] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_GARMENT,EQP_SHADOW_ARMOR, EQP_SHADOW_WEAPON, EQP_SHADOW_SHIELD, EQP_SHADOW_SHOES, EQP_SHADOW_ACC_R, EQP_SHADOW_ACC_L};
+
script = &script_s;
-
+
script->st_db = NULL;
script->active_scripts = 0;
script->next_id = 0;
script->st_ers = NULL;
script->stack_ers = NULL;
+ script->array_ers = NULL;
script->hq = NULL;
script->hqi = NULL;
script->hqs = script->hqis = 0;
- memset(&script->hqe, 0, sizeof(script->hqe));
-
- script->buildin_count = 0;
+
script->buildin = NULL;
-
+ script->buildin_count = 0;
+
script->str_data = NULL;
script->str_data_size = 0;
script->str_num = LABEL_START;
script->str_buf = NULL;
script->str_size = 0;
script->str_pos = 0;
-
+ memset(script->str_hash, 0, sizeof(script->str_hash));
+
script->word_buf = NULL;
script->word_size = 0;
-
+
+ script->current_item_id = 0;
+
+ script->labels = NULL;
+ script->label_count = 0;
+ script->labels_size = 0;
+
+ script->buf = NULL;
+ script->pos = 0, script->size = 0;
+
+ script->parse_options = 0;
+ script->buildin_set_ref = 0;
+ script->buildin_callsub_ref = 0;
+ script->buildin_callfunc_ref = 0;
+ script->buildin_getelementofarray_ref = 0;
+
+ memset(script->error_jump,0,sizeof(script->error_jump));
+ script->error_msg = NULL;
+ script->error_pos = NULL;
+ script->error_report = 0;
+ script->parser_current_src = NULL;
+ script->parser_current_file = NULL;
+ script->parser_current_line = 0;
+
+ memset(&script->syntax,0,sizeof(script->syntax));
+
+ script->parse_syntax_for_flag = 0;
+
+ memcpy(script->equip, &equip, sizeof(script->equip));
+
+ memset(&script->config, 0, sizeof(script->config));
+
+ script->autobonus_db = NULL;
+ script->userfunc_db = NULL;
+
+ script->potion_flag = script->potion_hp = script->potion_per_hp =
+ script->potion_sp = script->potion_per_sp = script->potion_target = 0;
+
+ script->generic_ui_array = NULL;
+ script->generic_ui_array_size = 0;
+ /* */
script->init = do_init_script;
script->final = do_final_script;
-
+ script->reload = script_reload;
+
+ /* parse */
+ script->parse = parse_script;
+ script->add_builtin = script_add_builtin;
script->parse_builtin = script_parse_builtin;
+ script->skip_space = script_skip_space;
+ script->error = script_error;
+ script->warning = script_warning;
+ script->parse_subexpr = script_parse_subexpr;
+
script->addScript = script_hp_add;
script->conv_num = conv_num;
script->conv_str = conv_str;
@@ -17876,9 +19495,165 @@ void script_defaults(void) {
script->push_str = push_str;
script->push_copy = push_copy;
script->pop_stack = pop_stack;
-
+ script->set_constant = script_set_constant;
+ script->set_constant2 = script_set_constant2;
+ script->get_constant = script_get_constant;
+ script->label_add = script_label_add;
+ script->run = run_script;
+ script->run_main = run_script_main;
+ script->run_timer = run_script_timer;
+ script->set_var = set_var;
+ script->stop_instances = script_stop_instances;
+ script->free_code = script_free_code;
+ script->free_vars = script_free_vars;
+ script->alloc_state = script_alloc_state;
+ script->free_state = script_free_state;
+ script->add_pending_ref = script_add_pending_ref;
+ script->run_autobonus = script_run_autobonus;
+ script->cleararray_pc = script_cleararray_pc;
+ script->setarray_pc = script_setarray_pc;
+ script->config_read = script_config_read;
+ script->add_str = script_add_str;
+ script->get_str = script_get_str;
+ script->search_str = script_search_str;
+ script->setd_sub = setd_sub;
+ script->attach_state = script_attach_state;
+
script->queue = script_hqueue_get;
script->queue_add = script_hqueue_add;
script->queue_del = script_hqueue_del;
script->queue_remove = script_hqueue_remove;
+ script->queue_create = script_hqueue_create;
+ script->queue_clear = script_hqueue_clear;
+
+ script->parse_curly_close = parse_curly_close;
+ script->parse_syntax_close = parse_syntax_close;
+ script->parse_syntax_close_sub = parse_syntax_close_sub;
+ script->parse_syntax = parse_syntax;
+ script->get_com = get_com;
+ script->get_num = get_num;
+ script->op2name = script_op2name;
+ script->reportsrc = script_reportsrc;
+ script->reportdata = script_reportdata;
+ script->reportfunc = script_reportfunc;
+ script->disp_warning_message = disp_warning_message;
+ script->check_event = check_event;
+ script->calc_hash = calc_hash;
+ script->addb = add_scriptb;
+ script->addc = add_scriptc;
+ script->addi = add_scripti;
+ script->addl = add_scriptl;
+ script->set_label = set_label;
+ script->skip_word = skip_word;
+ script->add_word = add_word;
+ script->parse_callfunc = parse_callfunc;
+ script->parse_nextline = parse_nextline;
+ script->parse_variable = parse_variable;
+ script->parse_simpleexpr = parse_simpleexpr;
+ script->parse_expr = parse_expr;
+ script->parse_line = parse_line;
+ script->read_constdb = read_constdb;
+ script->print_line = script_print_line;
+ script->errorwarning_sub = script_errorwarning_sub;
+ script->set_reg = set_reg;
+ script->stack_expand = stack_expand;
+ script->push_retinfo = push_retinfo;
+ script->op_3 = op_3;
+ script->op_2str = op_2str;
+ script->op_2num = op_2num;
+ script->op_2 = op_2;
+ script->op_1 = op_1;
+ script->check_buildin_argtype = script_check_buildin_argtype;
+ script->detach_state = script_detach_state;
+ script->db_free_code_sub = db_script_free_code_sub;
+ script->add_autobonus = script_add_autobonus;
+ script->menu_countoptions = menu_countoptions;
+ script->buildin_areawarp_sub = buildin_areawarp_sub;
+ script->buildin_areapercentheal_sub = buildin_areapercentheal_sub;
+ script->buildin_delitem_delete = buildin_delitem_delete;
+ script->buildin_delitem_search = buildin_delitem_search;
+ script->buildin_killmonster_sub_strip = buildin_killmonster_sub_strip;
+ script->buildin_killmonster_sub = buildin_killmonster_sub;
+ script->buildin_killmonsterall_sub_strip = buildin_killmonsterall_sub_strip;
+ script->buildin_killmonsterall_sub = buildin_killmonsterall_sub;
+ script->buildin_announce_sub = buildin_announce_sub;
+ script->buildin_getareausers_sub = buildin_getareausers_sub;
+ script->buildin_getareadropitem_sub = buildin_getareadropitem_sub;
+ script->mapflag_pvp_sub = script_mapflag_pvp_sub;
+ script->buildin_pvpoff_sub = buildin_pvpoff_sub;
+ script->buildin_maprespawnguildid_sub_pc = buildin_maprespawnguildid_sub_pc;
+ script->buildin_maprespawnguildid_sub_mob = buildin_maprespawnguildid_sub_mob;
+ script->buildin_mobcount_sub = buildin_mobcount_sub;
+ script->playbgm_sub = playbgm_sub;
+ script->playbgm_foreachpc_sub = playbgm_foreachpc_sub;
+ script->soundeffect_sub = soundeffect_sub;
+ script->buildin_query_sql_sub = buildin_query_sql_sub;
+ script->buildin_instance_warpall_sub = buildin_instance_warpall_sub;
+ script->buildin_mobuseskill_sub = buildin_mobuseskill_sub;
+ script->cleanfloor_sub = script_cleanfloor_sub;
+ script->run_func = run_func;
+ script->getfuncname = script_getfuncname;
+
+ /* script_config base */
+ script->config.warn_func_mismatch_argtypes = 1;
+ script->config.warn_func_mismatch_paramnum = 1;
+ script->config.check_cmdcount = 65535;
+ script->config.check_gotocount = 2048;
+ script->config.input_min_value = 0;
+ script->config.input_max_value = INT_MAX;
+ script->config.die_event_name = "OnPCDieEvent";
+ script->config.kill_pc_event_name = "OnPCKillEvent";
+ script->config.kill_mob_event_name = "OnNPCKillEvent";
+ script->config.login_event_name = "OnPCLoginEvent";
+ script->config.logout_event_name = "OnPCLogoutEvent";
+ script->config.loadmap_event_name = "OnPCLoadMapEvent";
+ script->config.baselvup_event_name = "OnPCBaseLvUpEvent";
+ script->config.joblvup_event_name = "OnPCJobLvUpEvent";
+ script->config.ontouch_name = "OnTouch_";//ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves)
+ script->config.ontouch2_name = "OnTouch";//ontouch2_name (run whenever a char walks into the OnTouch area)
+
+ // for ENABLE_CASE_CHECK
+ script->calc_hash_ci = calc_hash_ci;
+ script->local_casecheck.add_str = script_local_casecheck_add_str;
+ script->local_casecheck.clear = script_local_casecheck_clear;
+ script->local_casecheck.str_data = NULL;
+ script->local_casecheck.str_data_size = 0;
+ script->local_casecheck.str_num = 1;
+ script->local_casecheck.str_buf = NULL;
+ script->local_casecheck.str_size = 0;
+ script->local_casecheck.str_pos = 0;
+ memset(script->local_casecheck.str_hash, 0, sizeof(script->local_casecheck.str_hash));
+ script->global_casecheck.add_str = script_global_casecheck_add_str;
+ script->global_casecheck.clear = script_global_casecheck_clear;
+ script->global_casecheck.str_data = NULL;
+ script->global_casecheck.str_data_size = 0;
+ script->global_casecheck.str_num = 1;
+ script->global_casecheck.str_buf = NULL;
+ script->global_casecheck.str_size = 0;
+ script->global_casecheck.str_pos = 0;
+ memset(script->global_casecheck.str_hash, 0, sizeof(script->global_casecheck.str_hash));
+ // end ENABLE_CASE_CHECK
+
+ /**
+ * Array Handling
+ **/
+ script->array_src = script_array_src;
+ script->array_update = script_array_update;
+ script->array_add_member = script_array_add_member;
+ script->array_remove_member = script_array_remove_member;
+ script->array_delete = script_array_delete;
+ script->array_size = script_array_size;
+ script->array_free_db = script_free_array_db;
+ script->array_highest_key = script_array_highest_key;
+ script->array_ensure_zero = script_array_ensure_zero;
+ /* */
+ script->reg_destroy_single = script_reg_destroy_single;
+ script->reg_destroy = script_reg_destroy;
+ /* */
+ script->generic_ui_array_expand = script_generic_ui_array_expand;
+ script->array_cpy_list = script_array_cpy_list;
+ /* */
+ script->hardcoded_constants = script_hardcoded_constants;
+ script->mapindexname2id = script_mapindexname2id;
+
}
diff --git a/src/map/script.h b/src/map/script.h
index 3cfcd9de4..48abf1487 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -1,41 +1,177 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _SCRIPT_H_
-#define _SCRIPT_H_
+#ifndef MAP_SCRIPT_H
+#define MAP_SCRIPT_H
+
+#include <errno.h>
+#include <setjmp.h>
#include "map.h" //EVENT_NAME_LENGTH
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/mmo.h" // struct item
+#include "../common/sql.h" // Sql
+#include "../common/strlib.h" //StringBuf
+
+/**
+ * Declarations
+ **/
+struct eri;
+
+/**
+ * Defines
+ **/
+// TODO: Remove temporary code
+#define ENABLE_CASE_CHECK
+#define get_script_source(source) ((source) ? (source) : "Unknown (Possibly source or variables stored in database")
+#define DeprecationWarning(func, bad, good, file, line) ShowError("%s: use of deprecated keyword '%s' (use '%s' instead) in file '%s', line '%d'.\n", (func), (bad), (good), get_script_source(file), (line));
+#define DeprecationWarning2(func, bad, good, where) ShowError("%s: detected possible use of wrong case in a script. Found '%s', probably meant to be '%s' (in '%s').\n", (func), (bad), (good), get_script_source(where));
+#define disp_deprecation_message(func, good, p) disp_warning_message(func": use of deprecated keyword (use '"good"' instead).", (p));
#define NUM_WHISPER_VAR 10
-struct map_session_data;
-struct eri;
+/// Maximum amount of elements in script arrays
+#define SCRIPT_MAX_ARRAYSIZE (UINT_MAX - 1)
-extern int potion_flag; //For use on Alchemist improved potions/Potion Pitcher. [Skotlex]
-extern int potion_hp, potion_per_hp, potion_sp, potion_per_sp;
-extern int potion_target;
+#define SCRIPT_BLOCK_SIZE 512
-extern struct Script_Config {
- unsigned warn_func_mismatch_argtypes : 1;
- unsigned warn_func_mismatch_paramnum : 1;
- int check_cmdcount;
- int check_gotocount;
- int input_min_value;
- int input_max_value;
+// Using a prime number for SCRIPT_HASH_SIZE should give better distributions
+#define SCRIPT_HASH_SIZE 1021
- const char *die_event_name;
- const char *kill_pc_event_name;
- const char *kill_mob_event_name;
- const char *login_event_name;
- const char *logout_event_name;
- const char *loadmap_event_name;
- const char *baselvup_event_name;
- const char *joblvup_event_name;
+// Specifies which string hashing method to use
+//#define SCRIPT_HASH_DJB2
+//#define SCRIPT_HASH_SDBM
+#define SCRIPT_HASH_ELF
- const char* ontouch_name;
- const char* ontouch2_name;
-} script_config;
+#define SCRIPT_EQUIP_TABLE_SIZE 20
+
+//#define SCRIPT_DEBUG_DISP
+//#define SCRIPT_DEBUG_DISASM
+//#define SCRIPT_DEBUG_HASH
+//#define SCRIPT_DEBUG_DUMP_STACK
+
+///////////////////////////////////////////////////////////////////////////////
+//## TODO possible enhancements: [FlavioJS]
+// - 'callfunc' supporting labels in the current npc "::LabelName"
+// - 'callfunc' supporting labels in other npcs "NpcName::LabelName"
+// - 'function FuncName;' function declarations reverting to global functions
+// if local label isn't found
+// - join callfunc and callsub's functionality
+// - remove dynamic allocation in add_word()
+// - remove GETVALUE / SETVALUE
+// - clean up the set_reg / set_val / setd_sub mess
+// - detect invalid label references at parse-time
+
+//
+// struct script_state* st;
+//
+
+/// Returns the script_data at the target index
+#define script_getdata(st,i) ( &((st)->stack->stack_data[(st)->start + (i)]) )
+/// Returns if the stack contains data at the target index
+#define script_hasdata(st,i) ( (st)->end > (st)->start + (i) )
+/// Returns the index of the last data in the stack
+#define script_lastdata(st) ( (st)->end - (st)->start - 1 )
+/// Pushes an int into the stack
+#define script_pushint(st,val) (script->push_val((st)->stack, C_INT, (val),NULL))
+/// Pushes a string into the stack (script engine frees it automatically)
+#define script_pushstr(st,val) (script->push_str((st)->stack, C_STR, (val)))
+/// Pushes a copy of a string into the stack
+#define script_pushstrcopy(st,val) (script->push_str((st)->stack, C_STR, aStrdup(val)))
+/// Pushes a constant string into the stack (must never change or be freed)
+#define script_pushconststr(st,val) (script->push_str((st)->stack, C_CONSTSTR, (val)))
+/// Pushes a nil into the stack
+#define script_pushnil(st) (script->push_val((st)->stack, C_NOP, 0,NULL))
+/// Pushes a copy of the data in the target index
+#define script_pushcopy(st,i) (script->push_copy((st)->stack, (st)->start + (i)))
+
+#define script_isstring(st,i) data_isstring(script_getdata((st),(i)))
+#define script_isint(st,i) data_isint(script_getdata((st),(i)))
+#define script_isstringtype(st,i) data_isstring(script->get_val((st), script_getdata((st),(i))))
+#define script_isinttype(st,i) data_isint(script->get_val((st), script_getdata((st),(i))))
+
+#define script_getnum(st,val) (script->conv_num((st), script_getdata((st),(val))))
+#define script_getstr(st,val) (script->conv_str((st), script_getdata((st),(val))))
+#define script_getref(st,val) ( script_getdata((st),(val))->ref )
+
+// Note: "top" functions/defines use indexes relative to the top of the stack
+// -1 is the index of the data at the top
+
+/// Returns the script_data at the target index relative to the top of the stack
+#define script_getdatatop(st,i) ( &((st)->stack->stack_data[(st)->stack->sp + (i)]) )
+/// Pushes a copy of the data in the target index relative to the top of the stack
+#define script_pushcopytop(st,i) script->push_copy((st)->stack, (st)->stack->sp + (i))
+/// Removes the range of values [start,end[ relative to the top of the stack
+#define script_removetop(st,start,end) ( script->pop_stack((st), ((st)->stack->sp + (start)), (st)->stack->sp + (end)) )
+
+//
+// struct script_data* data;
+//
+
+/// Returns if the script data is a string
+#define data_isstring(data) ( (data)->type == C_STR || (data)->type == C_CONSTSTR )
+/// Returns if the script data is an int
+#define data_isint(data) ( (data)->type == C_INT )
+/// Returns if the script data is a reference
+#define data_isreference(data) ( (data)->type == C_NAME )
+/// Returns if the script data is a label
+#define data_islabel(data) ( (data)->type == C_POS )
+/// Returns if the script data is an internal script function label
+#define data_isfunclabel(data) ( (data)->type == C_USERFUNC_POS )
+/// Returns if this is a reference to a constant
+#define reference_toconstant(data) ( script->str_data[reference_getid(data)].type == C_INT )
+/// Returns if this a reference to a param
+#define reference_toparam(data) ( script->str_data[reference_getid(data)].type == C_PARAM )
+/// Returns if this a reference to a variable
+//##TODO confirm it's C_NAME [FlavioJS]
+#define reference_tovariable(data) ( script->str_data[reference_getid(data)].type == C_NAME )
+/// Returns the unique id of the reference (id and index)
+#define reference_getuid(data) ( (data)->u.num )
+/// Returns the id of the reference
+#define reference_getid(data) ( (int32)(int64)(reference_getuid(data) & 0xFFFFFFFF) )
+/// Returns the array index of the reference
+#define reference_getindex(data) ( (uint32)(int64)((reference_getuid(data) >> 32) & 0xFFFFFFFF) )
+/// Returns the name of the reference
+#define reference_getname(data) ( script->str_buf + script->str_data[reference_getid(data)].str )
+/// Returns the linked list of uid-value pairs of the reference (can be NULL)
+#define reference_getref(data) ( (data)->ref )
+/// Returns the value of the constant
+#define reference_getconstant(data) ( script->str_data[reference_getid(data)].val )
+/// Returns the type of param
+#define reference_getparamtype(data) ( script->str_data[reference_getid(data)].val )
+
+/// Composes the uid of a reference from the id and the index
+#define reference_uid(id,idx) ( (int64) ((uint64)(id) & 0xFFFFFFFF) | ((uint64)(idx) << 32) )
+
+/// Checks whether two references point to the same variable (or array)
+#define is_same_reference(data1, data2) \
+ ( reference_getid(data1) == reference_getid(data2) \
+ && ( (data1->ref == data2->ref && data1->ref == NULL) \
+ || (data1->ref != NULL && data2->ref != NULL && data1->ref->vars == data2->ref->vars \
+ ) ) )
+
+#define script_getvarid(var) ( (int32)(int64)(var & 0xFFFFFFFF) )
+#define script_getvaridx(var) ( (uint32)(int64)((var >> 32) & 0xFFFFFFFF) )
+
+#define not_server_variable(prefix) ( (prefix) != '$' && (prefix) != '.' && (prefix) != '\'')
+#define is_string_variable(name) ( (name)[strlen(name) - 1] == '$' )
+
+#define BUILDIN(x) bool buildin_ ## x (struct script_state* st)
+
+#define script_fetch(st, n, t) do { \
+ if( script_hasdata((st),(n)) ) \
+ (t)=script_getnum((st),(n)); \
+ else \
+ (t) = 0; \
+} while(0)
+
+
+/**
+ * Enumerations
+ **/
typedef enum c_op {
C_NOP, // end of script/no value (nil)
C_POS,
@@ -51,7 +187,7 @@ typedef enum c_op {
C_USERFUNC, // internal script function
C_USERFUNC_POS, // internal script function label
C_REF, // the next call to c_op2 should push back a ref to the left operand
-
+
// operators
C_OP3, // a ? b : c
C_LOR, // a || b
@@ -75,57 +211,189 @@ typedef enum c_op {
C_NOT, // ~ a
C_R_SHIFT, // a >> b
C_L_SHIFT, // a << b
- C_ADD_PP, // ++a
- C_SUB_PP, // --a
+ C_ADD_POST, // a++
+ C_SUB_POST, // a--
+ C_ADD_PRE, // ++a
+ C_SUB_PRE, // --a
+#ifdef PCRE_SUPPORT
+ C_RE_EQ, // ~=
+ C_RE_NE, // ~!
+#endif // PCRE_SUPPORT
} c_op;
+enum hQueueOpt {
+ HQO_NONE,
+ HQO_onLogOut,
+ HQO_OnDeath,
+ HQO_OnMapChange,
+ HQO_MAX,
+};
+
+enum e_script_state { RUN,STOP,END,RERUNLINE,GOTO,RETFUNC,CLOSE };
+
+enum script_parse_options {
+ SCRIPT_USE_LABEL_DB = 0x1,// records labels in scriptlabel_db
+ SCRIPT_IGNORE_EXTERNAL_BRACKETS = 0x2,// ignores the check for {} brackets around the script
+ SCRIPT_RETURN_EMPTY_SCRIPT = 0x4// returns the script object instead of NULL for empty scripts
+};
+
+enum { LABEL_NEXTLINE=1,LABEL_START };
+
+// for advanced scripting support ( nested if, switch, while, for, do-while, function, etc )
+// [Eoe / jA 1080, 1081, 1094, 1164]
+enum curly_type {
+ TYPE_NULL = 0,
+ TYPE_IF,
+ TYPE_SWITCH,
+ TYPE_WHILE,
+ TYPE_FOR,
+ TYPE_DO,
+ TYPE_USERFUNC,
+ TYPE_ARGLIST // function argument list
+};
+
+enum e_arglist {
+ ARGLIST_UNDEFINED = 0,
+ ARGLIST_NO_PAREN = 1,
+ ARGLIST_PAREN = 2,
+};
+
+/*==========================================
+ * (Only those needed) local declaration prototype
+ * - those could be used server-wide so that the scans are done once during processing and never again,
+ * - doing so would also improve map zone processing and storage [Ind]
+ *------------------------------------------*/
+
+enum {
+ MF_NOMEMO, //0
+ MF_NOTELEPORT,
+ MF_NOSAVE,
+ MF_NOBRANCH,
+ MF_NOPENALTY,
+ MF_NOZENYPENALTY,
+ MF_PVP,
+ MF_PVP_NOPARTY,
+ MF_PVP_NOGUILD,
+ MF_GVG,
+ MF_GVG_NOPARTY, //10
+ MF_NOTRADE,
+ MF_NOSKILL,
+ MF_NOWARP,
+ MF_PARTYLOCK,
+ MF_NOICEWALL,
+ MF_SNOW,
+ MF_FOG,
+ MF_SAKURA,
+ MF_LEAVES,
+ /* 21 - 22 free */
+ MF_CLOUDS = 23,
+ MF_CLOUDS2,
+ MF_FIREWORKS,
+ MF_GVG_CASTLE,
+ MF_GVG_DUNGEON,
+ MF_NIGHTENABLED,
+ MF_NOBASEEXP,
+ MF_NOJOBEXP, //30
+ MF_NOMOBLOOT,
+ MF_NOMVPLOOT,
+ MF_NORETURN,
+ MF_NOWARPTO,
+ MF_NIGHTMAREDROP,
+ MF_ZONE,
+ MF_NOCOMMAND,
+ MF_NODROP,
+ MF_JEXP,
+ MF_BEXP, //40
+ MF_NOVENDING,
+ MF_LOADEVENT,
+ MF_NOCHAT,
+ MF_NOEXPPENALTY,
+ MF_GUILDLOCK,
+ MF_TOWN,
+ MF_AUTOTRADE,
+ MF_ALLOWKS,
+ MF_MONSTER_NOTELEPORT,
+ MF_PVP_NOCALCRANK, //50
+ MF_BATTLEGROUND,
+ MF_RESET,
+ MF_NOTOMB,
+ MF_NOCASHSHOP
+};
+
+/**
+ * Structures
+ **/
+
+struct Script_Config {
+ unsigned warn_func_mismatch_argtypes : 1;
+ unsigned warn_func_mismatch_paramnum : 1;
+ int check_cmdcount;
+ int check_gotocount;
+ int input_min_value;
+ int input_max_value;
+
+ const char *die_event_name;
+ const char *kill_pc_event_name;
+ const char *kill_mob_event_name;
+ const char *login_event_name;
+ const char *logout_event_name;
+ const char *loadmap_event_name;
+ const char *baselvup_event_name;
+ const char *joblvup_event_name;
+
+ const char* ontouch_name;
+ const char* ontouch2_name;
+};
+
+/**
+ * Generic reg database abstraction to be used with various types of regs/script variables.
+ */
+struct reg_db {
+ struct DBMap *vars;
+ struct DBMap *arrays;
+};
+
struct script_retinfo {
- struct DBMap* var_function;// scope variables
- struct script_code* script;// script code
- int pos;// script location
- int nargs;// argument count
- int defsp;// default stack pointer
+ struct reg_db scope; ///< scope variables
+ struct script_code* script; ///< script code
+ int pos; ///< script location
+ int nargs; ///< argument count
+ int defsp; ///< default stack pointer
};
struct script_data {
enum c_op type;
union script_data_val {
- int num;
+ int64 num;
char *str;
struct script_retinfo* ri;
} u;
- struct DBMap** ref;
+ struct reg_db *ref;
};
// Moved defsp from script_state to script_stack since
// it must be saved when script state is RERUNLINE. [Eoe / jA 1094]
struct script_code {
int script_size;
- unsigned char* script_buf;
- struct DBMap* script_vars;
+ unsigned char *script_buf;
+ struct reg_db local; ///< Local (npc) vars
+ unsigned short instances;
};
struct script_stack {
- int sp;// number of entries in the stack
- int sp_max;// capacity of the stack
+ int sp; ///< number of entries in the stack
+ int sp_max; ///< capacity of the stack
int defsp;
- struct script_data *stack_data;// stack
- struct DBMap* var_function;// scope variables
-};
-
-enum hQueueOpt {
- HQO_NONE,
- HQO_onLogOut,
- HQO_OnDeath,
- HQO_OnMapChange,
- HQO_MAX,
+ struct script_data *stack_data; ///< stack
+ struct reg_db scope; ///< scope variables
};
/* [Ind/Hercules] */
struct hQueue {
int id;
int *item;
- int items;
+ int items;/* how many actual items are in the array */
+ int size;/* size of the *item array, not the current amount of items in it since it can have empty slots */
/* events */
char onLogOut[EVENT_NAME_LENGTH];
char onDeath[EVENT_NAME_LENGTH];
@@ -138,18 +406,15 @@ struct hQueueIterator {
int pos;
};
-//
-// Script state
-//
-enum e_script_state { RUN,STOP,END,RERUNLINE,GOTO,RETFUNC,CLOSE };
-
struct script_state {
struct script_stack* stack;
+ struct reg_db **pending_refs; ///< References to .vars returned by sub-functions, pending deletion.
+ int pending_ref_count; ///< Amount of pending_refs currently stored.
int start,end;
int pos;
enum e_script_state state;
int rid,oid;
- struct script_code *script, *scriptroot;
+ struct script_code *script;
struct sleep_data {
int tick,timer,charid;
} sleep;
@@ -164,58 +429,6 @@ struct script_state {
unsigned int id;
};
-struct script_reg {
- int index;
- int data;
-};
-
-struct script_regstr {
- int index;
- char* data;
-};
-
-enum script_parse_options {
- SCRIPT_USE_LABEL_DB = 0x1,// records labels in scriptlabel_db
- SCRIPT_IGNORE_EXTERNAL_BRACKETS = 0x2,// ignores the check for {} brackets around the script
- SCRIPT_RETURN_EMPTY_SCRIPT = 0x4// returns the script object instead of NULL for empty scripts
-};
-
-const char* skip_space(const char* p);
-void script_error(const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos);
-
-struct script_code* parse_script(const char* src,const char* file,int line,int options);
-void run_script_sub(struct script_code *rootscript,int pos,int rid,int oid, char* file, int lineno);
-void run_script(struct script_code*,int,int,int);
-
-int set_var(struct map_session_data *sd, char *name, void *val);
-int run_script_timer(int tid, unsigned int tick, int id, intptr_t data);
-void run_script_main(struct script_state *st);
-
-void script_stop_instances(int id);
-struct linkdb_node* script_erase_sleepdb(struct linkdb_node *n);
-void script_free_code(struct script_code* code);
-void script_free_vars(struct DBMap *storage);
-struct script_state* script_alloc_state(struct script_code* rootscript, int pos, int rid, int oid);
-void script_free_state(struct script_state* st);
-
-struct DBMap* script_get_label_db(void);
-struct DBMap* script_get_userfunc_db(void);
-void script_run_autobonus(const char *autobonus,int id, int pos);
-
-bool script_get_constant(const char* name, int* value);
-void script_set_constant(const char* name, int value, bool isparameter);
-
-void script_cleararray_pc(struct map_session_data* sd, const char* varname, void* value);
-void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8 idx, void* value, int* refcache);
-
-int script_config_read(char *cfgName);
-int add_str(const char* p);
-const char* get_str(int id);
-int script_reload(void);
-
-// @commands (script based)
-void setd_sub(struct script_state *st, struct map_session_data *sd, const char *varname, int elem, void *value, struct DBMap **ref);
-
struct script_function {
bool (*func)(struct script_state *st);
char *name;
@@ -234,106 +447,44 @@ struct str_data_struct {
int next;
};
-///////////////////////////////////////////////////////////////////////////////
-//## TODO possible enhancements: [FlavioJS]
-// - 'callfunc' supporting labels in the current npc "::LabelName"
-// - 'callfunc' supporting labels in other npcs "NpcName::LabelName"
-// - 'function FuncName;' function declarations reverting to global functions
-// if local label isn't found
-// - join callfunc and callsub's functionality
-// - remove dynamic allocation in add_word()
-// - remove GETVALUE / SETVALUE
-// - clean up the set_reg / set_val / setd_sub mess
-// - detect invalid label references at parse-time
-
-//
-// struct script_state* st;
-//
-
-/// Returns the script_data at the target index
-#define script_getdata(st,i) ( &((st)->stack->stack_data[(st)->start + (i)]) )
-/// Returns if the stack contains data at the target index
-#define script_hasdata(st,i) ( (st)->end > (st)->start + (i) )
-/// Returns the index of the last data in the stack
-#define script_lastdata(st) ( (st)->end - (st)->start - 1 )
-/// Pushes an int into the stack
-#define script_pushint(st,val) script->push_val((st)->stack, C_INT, (val),NULL)
-/// Pushes a string into the stack (script engine frees it automatically)
-#define script_pushstr(st,val) script->push_str((st)->stack, C_STR, (val))
-/// Pushes a copy of a string into the stack
-#define script_pushstrcopy(st,val) script->push_str((st)->stack, C_STR, aStrdup(val))
-/// Pushes a constant string into the stack (must never change or be freed)
-#define script_pushconststr(st,val) script->push_str((st)->stack, C_CONSTSTR, (val))
-/// Pushes a nil into the stack
-#define script_pushnil(st) script->push_val((st)->stack, C_NOP, 0,NULL)
-/// Pushes a copy of the data in the target index
-#define script_pushcopy(st,i) script->push_copy((st)->stack, (st)->start + (i))
-
-#define script_isstring(st,i) data_isstring(script_getdata(st,i))
-#define script_isint(st,i) data_isint(script_getdata(st,i))
-
-#define script_getnum(st,val) script->conv_num(st, script_getdata(st,val))
-#define script_getstr(st,val) script->conv_str(st, script_getdata(st,val))
-#define script_getref(st,val) ( script_getdata(st,val)->ref )
-
-// Note: "top" functions/defines use indexes relative to the top of the stack
-// -1 is the index of the data at the top
-
-/// Returns the script_data at the target index relative to the top of the stack
-#define script_getdatatop(st,i) ( &((st)->stack->stack_data[(st)->stack->sp + (i)]) )
-/// Pushes a copy of the data in the target index relative to the top of the stack
-#define script_pushcopytop(st,i) script->push_copy((st)->stack, (st)->stack->sp + (i))
-/// Removes the range of values [start,end[ relative to the top of the stack
-#define script_removetop(st,start,end) ( script->pop_stack((st), ((st)->stack->sp + (start)), (st)->stack->sp + (end)) )
-
-//
-// struct script_data* data;
-//
-
-/// Returns if the script data is a string
-#define data_isstring(data) ( (data)->type == C_STR || (data)->type == C_CONSTSTR )
-/// Returns if the script data is an int
-#define data_isint(data) ( (data)->type == C_INT )
-/// Returns if the script data is a reference
-#define data_isreference(data) ( (data)->type == C_NAME )
-/// Returns if the script data is a label
-#define data_islabel(data) ( (data)->type == C_POS )
-/// Returns if the script data is an internal script function label
-#define data_isfunclabel(data) ( (data)->type == C_USERFUNC_POS )
-
-/// Returns if this is a reference to a constant
-#define reference_toconstant(data) ( script->str_data[reference_getid(data)].type == C_INT )
-/// Returns if this a reference to a param
-#define reference_toparam(data) ( script->str_data[reference_getid(data)].type == C_PARAM )
-/// Returns if this a reference to a variable
-//##TODO confirm it's C_NAME [FlavioJS]
-#define reference_tovariable(data) ( script->str_data[reference_getid(data)].type == C_NAME )
-/// Returns the unique id of the reference (id and index)
-#define reference_getuid(data) ( (data)->u.num )
-/// Returns the id of the reference
-#define reference_getid(data) ( (int32)(reference_getuid(data) & 0x00ffffff) )
-/// Returns the array index of the reference
-#define reference_getindex(data) ( (int32)(((uint32)(reference_getuid(data) & 0xff000000)) >> 24) )
-/// Returns the name of the reference
-#define reference_getname(data) ( script->str_buf + script->str_data[reference_getid(data)].str )
-/// Returns the linked list of uid-value pairs of the reference (can be NULL)
-#define reference_getref(data) ( (data)->ref )
-/// Returns the value of the constant
-#define reference_getconstant(data) ( script->str_data[reference_getid(data)].val )
-/// Returns the type of param
-#define reference_getparamtype(data) ( script->str_data[reference_getid(data)].val )
+struct script_label_entry {
+ int key,pos;
+};
-/// Composes the uid of a reference from the id and the index
-#define reference_uid(id,idx) ( (int32)((((uint32)(id)) & 0x00ffffff) | (((uint32)(idx)) << 24)) )
+struct script_syntax_data {
+ struct {
+ enum curly_type type;
+ int index;
+ int count;
+ int flag;
+ struct linkdb_node *case_label;
+ } curly[256]; // Information right parenthesis
+ int curly_count; // The number of right brackets
+ int index; // Number of the syntax used in the script
+};
-#define not_server_variable(prefix) ( (prefix) != '$' && (prefix) != '.' && (prefix) != '\'')
-#define not_array_variable(prefix) ( (prefix) != '$' && (prefix) != '@' && (prefix) != '.' && (prefix) != '\'' )
-#define is_string_variable(name) ( (name)[strlen(name) - 1] == '$' )
+struct casecheck_data {
+ struct str_data_struct *str_data;
+ int str_data_size; // size of the data
+ int str_num; // next id to be assigned
+ // str_buf holds the strings themselves
+ char *str_buf;
+ int str_size; // size of the buffer
+ int str_pos; // next position to be assigned
+ int str_hash[SCRIPT_HASH_SIZE];
+ const char *(*add_str) (const char* p);
+ void (*clear) (void);
+};
-#define BUILDIN(x) bool buildin_ ## x (struct script_state* st)
-#define BUILDIN_A(x) buildin_ ## x
+struct script_array {
+ unsigned int id;/* the first 32b of the 64b uid, aka the id */
+ unsigned int size;/* how many members */
+ unsigned int *members;/* member list */
+};
-/* script.c interface (incomplete) */
+/**
+ * Interface
+ **/
struct script_interface {
/* */
DBMap *st_db;
@@ -345,46 +496,223 @@ struct script_interface {
struct hQueue *hq;
struct hQueueIterator *hqi;
int hqs, hqis;
- int hqe[HQO_MAX];
/* */
char **buildin;
unsigned int buildin_count;
+ /**
+ * used to generate quick script_array entries
+ **/
+ struct eri *array_ers;
/* */
struct str_data_struct *str_data;
int str_data_size; // size of the data
int str_num; // next id to be assigned
// str_buf holds the strings themselves
char *str_buf;
- int str_size; // size of the buffer
+ size_t str_size; // size of the buffer
int str_pos; // next position to be assigned
- //
+ int str_hash[SCRIPT_HASH_SIZE];
+ /* */
char *word_buf;
- int word_size;
+ size_t word_size;
/* */
- void (*init) (void);
- void (*final) (void);
+ unsigned short current_item_id;
+ /* */
+ struct script_label_entry *labels;
+ int label_count;
+ int labels_size;
+ /* */
+ struct Script_Config config;
+ /* */
+ /// temporary buffer for passing around compiled bytecode
+ /// @see add_scriptb, set_label, parse_script
+ unsigned char* buf;
+ int pos, size;
+ /* */
+ struct script_syntax_data syntax;
+ /* */
+ int parse_options;
+ // important buildin function references for usage in scripts
+ int buildin_set_ref;
+ int buildin_callsub_ref;
+ int buildin_callfunc_ref;
+ int buildin_getelementofarray_ref;
+ /* */
+ jmp_buf error_jump;
+ char* error_msg;
+ const char* error_pos;
+ int error_report; // if the error should produce output
+ // Used by disp_warning_message
+ const char* parser_current_src;
+ const char* parser_current_file;
+ int parser_current_line;
+ int parse_syntax_for_flag;
+ // aegis->athena slot position conversion table
+ unsigned int equip[SCRIPT_EQUIP_TABLE_SIZE];
+ /* */
+ /* Caches compiled autoscript item code. */
+ /* Note: This is not cleared when reloading itemdb. */
+ DBMap* autobonus_db; // char* script -> char* bytecode
+ DBMap* userfunc_db; // const char* func_name -> struct script_code*
+ /* */
+ int potion_flag; //For use on Alchemist improved potions/Potion Pitcher. [Skotlex]
+ int potion_hp, potion_per_hp, potion_sp, potion_per_sp;
+ int potion_target;
+ /* */
+ unsigned int *generic_ui_array;
+ unsigned int generic_ui_array_size;
/* */
+ void (*init) (bool minimal);
+ void (*final) (void);
+ int (*reload) (void);
+ /* parse */
+ struct script_code* (*parse) (const char* src,const char* file,int line,int options, int *retval);
+ bool (*add_builtin) (const struct script_function *buildin, bool override);
void (*parse_builtin) (void);
+ const char* (*parse_subexpr) (const char* p,int limit);
+ const char* (*skip_space) (const char* p);
+ void (*error) (const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos);
+ void (*warning) (const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos);
+ /* */
bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st));
int (*conv_num) (struct script_state *st,struct script_data *data);
const char* (*conv_str) (struct script_state *st,struct script_data *data);
TBL_PC *(*rid2sd) (struct script_state *st);
void (*detach_rid) (struct script_state* st);
- struct script_data* (*push_val)(struct script_stack* stack, enum c_op type, int val, struct DBMap** ref);
- void (*get_val) (struct script_state* st, struct script_data* data);
- void* (*get_val2) (struct script_state* st, int uid, struct DBMap** ref);
+ struct script_data* (*push_val)(struct script_stack* stack, enum c_op type, int64 val, struct reg_db *ref);
+ struct script_data *(*get_val) (struct script_state* st, struct script_data* data);
+ void* (*get_val2) (struct script_state* st, int64 uid, struct reg_db *ref);
struct script_data* (*push_str) (struct script_stack* stack, enum c_op type, char* str);
struct script_data* (*push_copy) (struct script_stack* stack, int pos);
void (*pop_stack) (struct script_state* st, int start, int end);
+ void (*set_constant) (const char* name, int value, bool isparameter);
+ void (*set_constant2) (const char *name, int value, bool isparameter);
+ bool (*get_constant) (const char* name, int* value);
+ void (*label_add)(int key, int pos);
+ void (*run) (struct script_code *rootscript,int pos,int rid,int oid);
+ void (*run_main) (struct script_state *st);
+ int (*run_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*set_var) (struct map_session_data *sd, char *name, void *val);
+ void (*stop_instances) (struct script_code *code);
+ void (*free_code) (struct script_code* code);
+ void (*free_vars) (struct DBMap *var_storage);
+ struct script_state* (*alloc_state) (struct script_code* rootscript, int pos, int rid, int oid);
+ void (*free_state) (struct script_state* st);
+ void (*add_pending_ref) (struct script_state *st, struct reg_db *ref);
+ void (*run_autobonus) (const char *autobonus,int id, int pos);
+ void (*cleararray_pc) (struct map_session_data* sd, const char* varname, void* value);
+ void (*setarray_pc) (struct map_session_data* sd, const char* varname, uint32 idx, void* value, int* refcache);
+ int (*config_read) (char *cfgName);
+ int (*add_str) (const char* p);
+ const char* (*get_str) (int id);
+ int (*search_str) (const char* p);
+ void (*setd_sub) (struct script_state *st, struct map_session_data *sd, const char *varname, int elem, void *value, struct reg_db *ref);
+ void (*attach_state) (struct script_state* st);
/* */
struct hQueue *(*queue) (int idx);
bool (*queue_add) (int idx, int var);
bool (*queue_del) (int idx);
bool (*queue_remove) (int idx, int var);
-} script_s;
+ int (*queue_create) (void);
+ void (*queue_clear) (int idx);
+ /* */
+ const char * (*parse_curly_close) (const char *p);
+ const char * (*parse_syntax_close) (const char *p);
+ const char * (*parse_syntax_close_sub) (const char *p, int *flag);
+ const char * (*parse_syntax) (const char *p);
+ c_op (*get_com) (unsigned char *scriptbuf, int *pos);
+ int (*get_num) (unsigned char *scriptbuf, int *pos);
+ const char* (*op2name) (int op);
+ void (*reportsrc) (struct script_state *st);
+ void (*reportdata) (struct script_data *data);
+ void (*reportfunc) (struct script_state *st);
+ void (*disp_warning_message) (const char *mes, const char *pos);
+ void (*check_event) (struct script_state *st, const char *evt);
+ unsigned int (*calc_hash) (const char *p);
+ void (*addb) (int a);
+ void (*addc) (int a);
+ void (*addi) (int a);
+ void (*addl) (int l);
+ void (*set_label) (int l, int pos, const char *script_pos);
+ const char* (*skip_word) (const char *p);
+ int (*add_word) (const char *p);
+ const char* (*parse_callfunc) (const char *p, int require_paren, int is_custom);
+ void (*parse_nextline) (bool first, const char *p);
+ const char* (*parse_variable) (const char *p);
+ const char* (*parse_simpleexpr) (const char *p);
+ const char* (*parse_expr) (const char *p);
+ const char* (*parse_line) (const char *p);
+ void (*read_constdb) (void);
+ const char* (*print_line) (StringBuf *buf, const char *p, const char *mark, int line);
+ void (*errorwarning_sub) (StringBuf *buf, const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos);
+ int (*set_reg) (struct script_state *st, TBL_PC *sd, int64 num, const char *name, const void *value, struct reg_db *ref);
+ void (*stack_expand) (struct script_stack *stack);
+ struct script_data* (*push_retinfo) (struct script_stack *stack, struct script_retinfo *ri, struct reg_db *ref);
+ void (*op_3) (struct script_state *st, int op);
+ void (*op_2str) (struct script_state *st, int op, const char *s1, const char *s2);
+ void (*op_2num) (struct script_state *st, int op, int i1, int i2);
+ void (*op_2) (struct script_state *st, int op);
+ void (*op_1) (struct script_state *st, int op);
+ void (*check_buildin_argtype) (struct script_state *st, int func);
+ void (*detach_state) (struct script_state *st, bool dequeue_event);
+ int (*db_free_code_sub) (DBKey key, DBData *data, va_list ap);
+ void (*add_autobonus) (const char *autobonus);
+ int (*menu_countoptions) (const char *str, int max_count, int *total);
+ int (*buildin_areawarp_sub) (struct block_list *bl, va_list ap);
+ int (*buildin_areapercentheal_sub) (struct block_list *bl, va_list ap);
+ void (*buildin_delitem_delete) (struct map_session_data *sd, int idx, int *amount, bool delete_items);
+ bool (*buildin_delitem_search) (struct map_session_data *sd, struct item *it, bool exact_match);
+ int (*buildin_killmonster_sub_strip) (struct block_list *bl, va_list ap);
+ int (*buildin_killmonster_sub) (struct block_list *bl, va_list ap);
+ int (*buildin_killmonsterall_sub_strip) (struct block_list *bl, va_list ap);
+ int (*buildin_killmonsterall_sub) (struct block_list *bl, va_list ap);
+ int (*buildin_announce_sub) (struct block_list *bl, va_list ap);
+ int (*buildin_getareausers_sub) (struct block_list *bl, va_list ap);
+ int (*buildin_getareadropitem_sub) (struct block_list *bl, va_list ap);
+ int (*mapflag_pvp_sub) (struct block_list *bl, va_list ap);
+ int (*buildin_pvpoff_sub) (struct block_list *bl, va_list ap);
+ int (*buildin_maprespawnguildid_sub_pc) (struct map_session_data *sd, va_list ap);
+ int (*buildin_maprespawnguildid_sub_mob) (struct block_list *bl, va_list ap);
+ int (*buildin_mobcount_sub) (struct block_list *bl, va_list ap);
+ int (*playbgm_sub) (struct block_list *bl, va_list ap);
+ int (*playbgm_foreachpc_sub) (struct map_session_data *sd, va_list args);
+ int (*soundeffect_sub) (struct block_list *bl, va_list ap);
+ int (*buildin_query_sql_sub) (struct script_state *st, Sql *handle);
+ int (*buildin_instance_warpall_sub) (struct block_list *bl, va_list ap);
+ int (*buildin_mobuseskill_sub) (struct block_list *bl, va_list ap);
+ int (*cleanfloor_sub) (struct block_list *bl, va_list ap);
+ int (*run_func) (struct script_state *st);
+ const char *(*getfuncname) (struct script_state *st);
+ // for ENABLE_CASE_CHECK
+ unsigned int (*calc_hash_ci) (const char *p);
+ struct casecheck_data local_casecheck;
+ struct casecheck_data global_casecheck;
+ // end ENABLE_CASE_CHECK
+ /**
+ * Array Handling
+ **/
+ struct reg_db *(*array_src) (struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref);
+ void (*array_update) (struct reg_db *src, int64 num, bool empty);
+ void (*array_delete) (struct reg_db *src, struct script_array *sa);
+ void (*array_remove_member) (struct reg_db *src, struct script_array *sa, unsigned int idx);
+ void (*array_add_member) (struct script_array *sa, unsigned int idx);
+ unsigned int (*array_size) (struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref);
+ unsigned int (*array_highest_key) (struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref);
+ int (*array_free_db) (DBKey key, DBData *data, va_list ap);
+ void (*array_ensure_zero) (struct script_state *st, struct map_session_data *sd, int64 uid, struct reg_db *ref);
+ /* */
+ void (*reg_destroy_single) (struct map_session_data *sd, int64 reg, struct script_reg_state *data);
+ int (*reg_destroy) (DBKey key, DBData *data, va_list ap);
+ /* */
+ void (*generic_ui_array_expand) (unsigned int plus);
+ unsigned int *(*array_cpy_list) (struct script_array *sa);
+ /* */
+ void (*hardcoded_constants) (void);
+ unsigned short (*mapindexname2id) (struct script_state *st, const char* name);
+};
struct script_interface *script;
void script_defaults(void);
-#endif /* _SCRIPT_H_ */
+#endif /* MAP_SCRIPT_H */
diff --git a/src/map/searchstore.c b/src/map/searchstore.c
index 3cda77e4a..72b28aacd 100644
--- a/src/map/searchstore.c
+++ b/src/map/searchstore.c
@@ -2,43 +2,19 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
+#define HERCULES_CORE
+
+#include "searchstore.h" // struct s_search_store_info
+
+#include "battle.h" // battle_config.*
+#include "clif.h" // clif->open_search_store_info, clif->search_store_info_*
+#include "pc.h" // struct map_session_data
#include "../common/cbasetypes.h"
#include "../common/malloc.h" // aMalloc, aRealloc, aFree
#include "../common/showmsg.h" // ShowError, ShowWarning
#include "../common/strlib.h" // safestrncpy
-#include "battle.h" // battle_config.*
-#include "clif.h" // clif->open_search_store_info, clif->search_store_info_*
-#include "pc.h" // struct map_session_data
-#include "searchstore.h" // struct s_search_store_info
-
-
-/// failure constants for clif functions
-enum e_searchstore_failure {
- SSI_FAILED_NOTHING_SEARCH_ITEM = 0, // "No matching stores were found."
- SSI_FAILED_OVER_MAXCOUNT = 1, // "There are too many results. Please enter more detailed search term."
- SSI_FAILED_SEARCH_CNT = 2, // "You cannot search anymore."
- SSI_FAILED_LIMIT_SEARCH_TIME = 3, // "You cannot search yet."
- SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE = 4, // "No sale (purchase) information available."
-};
-
-
-enum e_searchstore_searchtype {
- SEARCHTYPE_VENDING = 0,
- SEARCHTYPE_BUYING_STORE = 1,
-};
-
-
-enum e_searchstore_effecttype {
- EFFECTTYPE_NORMAL = 0,
- EFFECTTYPE_CASH = 1,
- EFFECTTYPE_MAX
-};
-
-
-/// type for shop search function
-typedef bool (*searchstore_search_t)(struct map_session_data* sd, unsigned short nameid);
-typedef bool (*searchstore_searchall_t)(struct map_session_data* sd, const struct s_search_store_search* s);
+struct searchstore_interface searchstore_s;
/// retrieves search function by type
static inline searchstore_search_t searchstore_getsearchfunc(unsigned char type) {
@@ -135,14 +111,14 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
// validate lists
for( i = 0; i < item_count; i++ ) {
- if( !itemdb_exists(itemlist[i]) ) {
+ if( !itemdb->exists(itemlist[i]) ) {
ShowWarning("searchstore_query: Client resolved item %hu is not known.\n", itemlist[i]);
clif->search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
return;
}
}
for( i = 0; i < card_count; i++ ) {
- if( !itemdb_exists(cardlist[i]) ) {
+ if( !itemdb->exists(cardlist[i]) ) {
ShowWarning("searchstore_query: Client resolved card %hu is not known.\n", cardlist[i]);
clif->search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM);
return;
@@ -273,7 +249,7 @@ void searchstore_click(struct map_session_data* sd, int account_id, int store_id
return;
}
- if( ( pl_sd = iMap->id2sd(account_id) ) == NULL ) {// no longer online
+ if( ( pl_sd = map->id2sd(account_id) ) == NULL ) {// no longer online
clif->search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE);
return;
}
diff --git a/src/map/searchstore.h b/src/map/searchstore.h
index 61e65c7d2..d8abde615 100644
--- a/src/map/searchstore.h
+++ b/src/map/searchstore.h
@@ -2,11 +2,45 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _SEARCHSTORE_H_
-#define _SEARCHSTORE_H_
+#ifndef MAP_SEARCHSTORE_H
+#define MAP_SEARCHSTORE_H
+#include <time.h>
+
+#include "map.h" // MESSAGE_SIZE
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h" // MAX_SLOTS
+
+/**
+ * Defines
+ **/
#define SEARCHSTORE_RESULTS_PER_PAGE 10
+/**
+ * Enumerations
+ **/
+enum e_searchstore_searchtype {
+ SEARCHTYPE_VENDING = 0,
+ SEARCHTYPE_BUYING_STORE = 1,
+};
+
+enum e_searchstore_effecttype {
+ EFFECTTYPE_NORMAL = 0,
+ EFFECTTYPE_CASH = 1,
+ EFFECTTYPE_MAX
+};
+/// failure constants for clif functions
+enum e_searchstore_failure {
+ SSI_FAILED_NOTHING_SEARCH_ITEM = 0, // "No matching stores were found."
+ SSI_FAILED_OVER_MAXCOUNT = 1, // "There are too many results. Please enter more detailed search term."
+ SSI_FAILED_SEARCH_CNT = 2, // "You cannot search anymore."
+ SSI_FAILED_LIMIT_SEARCH_TIME = 3, // "You cannot search yet."
+ SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE = 4, // "No sale (purchase) information available."
+};
+
+/**
+ * Structures
+ **/
/// information about the search being performed
struct s_search_store_search {
struct map_session_data* search_sd; // sd of the searching player
@@ -41,6 +75,13 @@ struct s_search_store_info {
bool open;
};
+/// type for shop search function
+typedef bool (*searchstore_search_t)(struct map_session_data* sd, unsigned short nameid);
+typedef bool (*searchstore_searchall_t)(struct map_session_data* sd, const struct s_search_store_search* s);
+
+/**
+ * Interface
+ **/
struct searchstore_interface {
bool (*open) (struct map_session_data* sd, unsigned int uses, unsigned short effect);
void (*query) (struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count);
@@ -52,10 +93,10 @@ struct searchstore_interface {
bool (*queryremote) (struct map_session_data* sd, int account_id);
void (*clearremote) (struct map_session_data* sd);
bool (*result) (struct map_session_data* sd, unsigned int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short* card, unsigned char refine);
-} searchstore_s;
+};
struct searchstore_interface *searchstore;
void searchstore_defaults (void);
-#endif // _SEARCHSTORE_H_
+#endif /* MAP_SEARCHSTORE_H */
diff --git a/src/map/skill.c b/src/map/skill.c
index 685fec353..b82c47a69 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -2,122 +2,67 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/malloc.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
-#include "../common/ers.h"
+#define HERCULES_CORE
-#include "map.h"
-#include "path.h"
-#include "clif.h"
-#include "pc.h"
-#include "status.h"
+#include "../config/core.h" // DBPATH, MAGIC_REFLECTION_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_CAST, VARCAST_REDUCTION()
#include "skill.h"
-#include "pet.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "battle.h"
+#include "battleground.h"
+#include "chrif.h"
+#include "clif.h"
+#include "date.h"
+#include "elemental.h"
+#include "guild.h"
#include "homunculus.h"
+#include "intif.h"
+#include "itemdb.h"
+#include "log.h"
+#include "map.h"
#include "mercenary.h"
-#include "elemental.h"
#include "mob.h"
#include "npc.h"
-#include "battle.h"
-#include "battleground.h"
#include "party.h"
-#include "itemdb.h"
+#include "path.h"
+#include "pc.h"
+#include "pet.h"
#include "script.h"
-#include "intif.h"
-#include "log.h"
-#include "chrif.h"
-#include "guild.h"
-#include "date.h"
+#include "status.h"
#include "unit.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <math.h>
-
+#include "../common/cbasetypes.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
#define SKILLUNITTIMER_INTERVAL 100
// ranges reserved for mapping skill ids to skilldb offsets
-#define HM_SKILLRANGEMIN 700
-#define HM_SKILLRANGEMAX HM_SKILLRANGEMIN + MAX_HOMUNSKILL
-#define MC_SKILLRANGEMIN HM_SKILLRANGEMAX + 1
-#define MC_SKILLRANGEMAX MC_SKILLRANGEMIN + MAX_MERCSKILL
-#define EL_SKILLRANGEMIN MC_SKILLRANGEMAX + 1
-#define EL_SKILLRANGEMAX EL_SKILLRANGEMIN + MAX_ELEMENTALSKILL
-#define GD_SKILLRANGEMIN EL_SKILLRANGEMAX + 1
-#define GD_SKILLRANGEMAX GD_SKILLRANGEMIN + MAX_GUILDSKILL
+#define HM_SKILLRANGEMIN 750
+#define HM_SKILLRANGEMAX (HM_SKILLRANGEMIN + MAX_HOMUNSKILL)
+#define MC_SKILLRANGEMIN (HM_SKILLRANGEMAX + 1)
+#define MC_SKILLRANGEMAX (MC_SKILLRANGEMIN + MAX_MERCSKILL)
+#define EL_SKILLRANGEMIN (MC_SKILLRANGEMAX + 1)
+#define EL_SKILLRANGEMAX (EL_SKILLRANGEMIN + MAX_ELEMENTALSKILL)
+#define GD_SKILLRANGEMIN (EL_SKILLRANGEMAX + 1)
+#define GD_SKILLRANGEMAX (GD_SKILLRANGEMIN + MAX_GUILDSKILL)
#if GD_SKILLRANGEMAX > 999
#error GD_SKILLRANGEMAX is greater than 999
#endif
-static struct eri *skill_unit_ers = NULL; //For handling skill_unit's [Skotlex]
-static struct eri *skill_timer_ers = NULL; //For handling skill_timerskills [Skotlex]
-
-DBMap* skillunit_db = NULL; // int id -> struct skill_unit*
-
-/**
- * Skill Cool Down Delay Saving
- * Struct skill_cd is not a member of struct map_session_data
- * to keep cooldowns in memory between player log-ins.
- * All cooldowns are reset when server is restarted.
- **/
-DBMap* skillcd_db = NULL; // char_id -> struct skill_cd
-struct skill_cd {
- int duration[MAX_SKILL_TREE];//milliseconds
- short skidx[MAX_SKILL_TREE];//the skill index entries belong to
- short nameid[MAX_SKILL_TREE];//skill id
- unsigned char cursor;
-};
-
-/**
- * Skill Unit Persistency during endack routes (mostly for songs see bugreport:4574)
- **/
-DBMap* skillusave_db = NULL; // char_id -> struct skill_usave
-struct skill_usave {
- uint16 skill_id, skill_lv;
-};
-
-struct s_skill_db skill_db[MAX_SKILL_DB];
-struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB];
-struct s_skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB];
-struct s_skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB];
-struct s_skill_improvise_db {
- uint16 skill_id;
- short per;//1-10000
-};
-struct s_skill_improvise_db skill_improvise_db[MAX_SKILL_IMPROVISE_DB];
-bool skill_reproduce_db[MAX_SKILL_DB];
-struct s_skill_changematerial_db {
- int itemid;
- short rate;
- int qty[5];
- short qty_rate[5];
-};
-struct s_skill_changematerial_db skill_changematerial_db[MAX_SKILL_PRODUCE_DB];
-
-//Warlock
-struct s_skill_spellbook_db {
- int nameid;
- uint16 skill_id;
- int point;
-};
-struct s_skill_spellbook_db skill_spellbook_db[MAX_SKILL_SPELLBOOK_DB];
-//Guillotine Cross
-struct s_skill_magicmushroom_db skill_magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB];
+struct skill_interface skill_s;
-struct s_skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT];
-int firewall_unit_pos;
-int icewall_unit_pos;
-int earthstrain_unit_pos;
//Since only mob-casted splash skills can hit ice-walls
static inline int splash_target(struct block_list* bl) {
#ifndef RENEWAL
@@ -132,7 +77,7 @@ int skill_name2id(const char* name) {
if( name == NULL )
return 0;
- return strdb_iget(skilldb_name2id, name);
+ return strdb_iget(skill->name2id_db, name);
}
/// Maps skill ids to skill db offsets.
@@ -176,90 +121,91 @@ int skill_get_index( uint16 skill_id ) {
}
const char* skill_get_name( uint16 skill_id ) {
- return skill_db[skill->get_index(skill_id)].name;
+ return skill->db[skill->get_index(skill_id)].name;
}
const char* skill_get_desc( uint16 skill_id ) {
- return skill_db[skill->get_index(skill_id)].desc;
+ return skill->db[skill->get_index(skill_id)].desc;
}
// out of bounds error checking [celest]
-void skill_chk(int16* skill_id) {
+void skill_chk(uint16* skill_id) {
*skill_id = skill->get_index(*skill_id); // checks/adjusts id
}
-#define skill_get(var,id) { skill->chk(&id); if(!id) return 0; return var; }
-#define skill_get2(var,id,lv) { \
- skill->chk(&id); \
- if(!id) return 0; \
- if( lv >= MAX_SKILL_LEVEL && var > 1 ) { \
- int lv2 = lv; lv = skill_db[id].max; \
- return (var) + (lv2-lv);\
+#define skill_get(var,id) do { skill->chk(&(id)); if(!(id)) return 0; return (var); } while(0)
+#define skill_get2(var,id,lv) do { \
+ skill->chk(&(id)); \
+ if(!(id)) return 0; \
+ if( (lv) > MAX_SKILL_LEVEL && (var) > 1 ) { \
+ int lv2__ = (lv); (lv) = skill->db[(id)].max; \
+ return (var) + ((lv2__-(lv))/2);\
} \
- return var;\
-}
-#define skill_glv(lv) min(lv,MAX_SKILL_LEVEL-1)
+ return (var);\
+} while(0)
+#define skill_glv(lv) min((lv),MAX_SKILL_LEVEL-1)
// Skill DB
-int skill_get_hit( uint16 skill_id ) { skill_get (skill_db[skill_id].hit, skill_id); }
-int skill_get_inf( uint16 skill_id ) { skill_get (skill_db[skill_id].inf, skill_id); }
-int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { skill_get (skill_db[skill_id].element[skill_glv(skill_lv-1)], skill_id); }
-int skill_get_nk( uint16 skill_id ) { skill_get (skill_db[skill_id].nk, skill_id); }
-int skill_get_max( uint16 skill_id ) { skill_get (skill_db[skill_id].max, skill_id); }
-int skill_get_range( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill_db[skill_id].range[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { skill_get2 ( (skill_db[skill_id].splash[skill_glv(skill_lv-1)]>=0?skill_db[skill_id].splash[skill_glv(skill_lv-1)]:AREA_SIZE), skill_id, skill_lv); }
-int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].hp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].sp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].hp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].sp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_state(uint16 skill_id) { skill_get (skill_db[skill_id].state, skill_id); }
-int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { skill_get2 (skill_db[skill_id].spiritball[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill_db[skill_id].itemid[idx], skill_id); }
-int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill_db[skill_id].amount[idx], skill_id); }
-int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].zeny[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].num[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].cast[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].delay[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].walkdelay[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].upkeep_time[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].upkeep_time2[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_castdef( uint16 skill_id ) { skill_get (skill_db[skill_id].cast_def_rate, skill_id); }
-int skill_get_weapontype( uint16 skill_id ) { skill_get (skill_db[skill_id].weapon, skill_id); }
-int skill_get_ammotype( uint16 skill_id ) { skill_get (skill_db[skill_id].ammo, skill_id); }
-int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].ammo_qty[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_inf2( uint16 skill_id ) { skill_get (skill_db[skill_id].inf2, skill_id); }
-int skill_get_castcancel( uint16 skill_id ) { skill_get (skill_db[skill_id].castcancel, skill_id); }
-int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].maxcount[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].blewcount[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].mhp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].castnodex[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].delaynodex[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_type( uint16 skill_id ) { skill_get (skill_db[skill_id].skill_type, skill_id); }
-int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill_db[skill_id].unit_id[flag], skill_id); }
-int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_interval, skill_id); }
-int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].unit_range[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_unit_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BCT_ALL, skill_id); }
-int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BL_ALL, skill_id); }
-int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_flag, skill_id); }
-int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].unit_layout_type[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].cooldown[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_hit( uint16 skill_id ) { skill_get (skill->db[skill_id].hit, skill_id); }
+int skill_get_inf( uint16 skill_id ) { skill_get (skill->db[skill_id].inf, skill_id); }
+int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { skill_get (skill->db[skill_id].element[skill_glv(skill_lv-1)], skill_id); }
+int skill_get_nk( uint16 skill_id ) { skill_get (skill->db[skill_id].nk, skill_id); }
+int skill_get_max( uint16 skill_id ) { skill_get (skill->db[skill_id].max, skill_id); }
+int skill_get_range( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill->db[skill_id].range[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { skill_get2 ( (skill->db[skill_id].splash[skill_glv(skill_lv-1)]>=0?skill->db[skill_id].splash[skill_glv(skill_lv-1)]:AREA_SIZE), skill_id, skill_lv); }
+int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].hp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].sp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].hp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].sp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_state(uint16 skill_id) { skill_get (skill->db[skill_id].state, skill_id); }
+int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { skill_get2 (skill->db[skill_id].spiritball[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill->db[skill_id].itemid[idx], skill_id); }
+int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill->db[skill_id].amount[idx], skill_id); }
+int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].zeny[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].num[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].cast[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].delay[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].walkdelay[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].upkeep_time[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].upkeep_time2[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_castdef( uint16 skill_id ) { skill_get (skill->db[skill_id].cast_def_rate, skill_id); }
+int skill_get_weapontype( uint16 skill_id ) { skill_get (skill->db[skill_id].weapon, skill_id); }
+int skill_get_ammotype( uint16 skill_id ) { skill_get (skill->db[skill_id].ammo, skill_id); }
+int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].ammo_qty[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_inf2( uint16 skill_id ) { skill_get (skill->db[skill_id].inf2, skill_id); }
+int skill_get_castcancel( uint16 skill_id ) { skill_get (skill->db[skill_id].castcancel, skill_id); }
+int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].maxcount[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].blewcount[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].mhp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].castnodex[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill->db[skill_id].delaynodex[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_type( uint16 skill_id ) { skill_get (skill->db[skill_id].skill_type, skill_id); }
+int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill->db[skill_id].unit_id[flag], skill_id); }
+int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_interval, skill_id); }
+int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].unit_range[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_unit_target( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_target&BCT_ALL, skill_id); }
+int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_target&BL_ALL, skill_id); }
+int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_flag, skill_id); }
+int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill->db[skill_id].unit_layout_type[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].cooldown[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ) {
#ifdef RENEWAL_CAST
-int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].fixed_cast[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+ skill_get2 (skill->db[skill_id].fixed_cast[skill_glv(skill_lv-1)], skill_id, skill_lv);
+#else
+ return 0;
#endif
+}
int skill_tree_get_max(uint16 skill_id, int b_class)
{
int i;
b_class = pc->class2idx(b_class);
- ARR_FIND( 0, MAX_SKILL_TREE, i, skill_tree[b_class][i].id == 0 || skill_tree[b_class][i].id == skill_id );
- if( i < MAX_SKILL_TREE && skill_tree[b_class][i].id == skill_id )
- return skill_tree[b_class][i].max;
+ ARR_FIND( 0, MAX_SKILL_TREE, i, pc->skill_tree[b_class][i].id == 0 || pc->skill_tree[b_class][i].id == skill_id );
+ if( i < MAX_SKILL_TREE && pc->skill_tree[b_class][i].id == skill_id )
+ return pc->skill_tree[b_class][i].max;
else
return skill->get_max(skill_id);
}
-int enchant_eff[5] = { 10, 14, 17, 19, 20 };
-int deluge_eff[5] = { 5, 9, 12, 14, 15 };
-
int skill_get_casttype (uint16 skill_id) {
int inf = skill->get_inf(skill_id);
if (inf&(INF_GROUND_SKILL))
@@ -277,17 +223,17 @@ int skill_get_casttype (uint16 skill_id) {
}
int skill_get_casttype2 (uint16 index) {
- int inf = skill_db[index].inf;
+ int inf = skill->db[index].inf;
if (inf&(INF_GROUND_SKILL))
return CAST_GROUND;
if (inf&INF_SUPPORT_SKILL)
return CAST_NODAMAGE;
if (inf&INF_SELF_SKILL) {
- if(skill_db[index].inf2&INF2_NO_TARGET_SELF)
+ if(skill->db[index].inf2&INF2_NO_TARGET_SELF)
return CAST_DAMAGE; //Combo skill.
return CAST_NODAMAGE;
}
- if (skill_db[index].nk&NK_NO_DAMAGE)
+ if (skill->db[index].nk&NK_NO_DAMAGE)
return CAST_NODAMAGE;
return CAST_DAMAGE;
}
@@ -379,18 +325,20 @@ int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
}
int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, bool heal) {
- int skill, hp;
+ int skill2_lv, hp;
struct map_session_data *sd = BL_CAST(BL_PC, src);
struct map_session_data *tsd = BL_CAST(BL_PC, target);
struct status_change* sc;
+ nullpo_ret(src);
+
switch( skill_id ) {
case BA_APPLEIDUN:
- #ifdef RENEWAL
+#ifdef RENEWAL
hp = 100+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery
- #else
+#else // not RENEWAL
hp = 30+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery
- #endif
+#endif // RENEWAL
if( sd )
hp += 5*pc->checkskill(sd,BA_MUSICALLESSON);
break;
@@ -403,32 +351,37 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
default:
if (skill_lv >= battle_config.max_heal_lv)
return battle_config.max_heal;
- #ifdef RENEWAL
- /**
- * Renewal Heal Formula
- * Formula: ( [(Base Level + INT) / 5] ? 30 ) ? (Heal Level / 10) ? (Modifiers) + MATK
- **/
- hp = (status_get_lv(src) + status_get_int(src)) / 5 * 30 * skill_lv / 10;
- #else
- hp = ( status_get_lv(src) + status_get_int(src) ) / 8 * (4 + ( skill_id == AB_HIGHNESSHEAL ? ( sd ? pc->checkskill(sd,AL_HEAL) : 10 ) : skill_lv ) * 8);
- #endif
- if( sd && ((skill = pc->checkskill(sd, HP_MEDITATIO)) > 0) )
- hp += hp * skill * 2 / 100;
- else if( src->type == BL_HOM && (skill = homun->checkskill(((TBL_HOM*)src), HLIF_BRAIN)) > 0 )
- hp += hp * skill * 2 / 100;
+#ifdef RENEWAL
+ /**
+ * Renewal Heal Formula
+ * Formula: ( [(Base Level + INT) / 5] ? 30 ) ? (Heal Level / 10) ? (Modifiers) + MATK
+ **/
+ hp = (status->get_lv(src) + status_get_int(src)) / 5 * 30 * skill_lv / 10;
+#else // not RENEWAL
+ hp = ( status->get_lv(src) + status_get_int(src) ) / 8 * (4 + ( skill_id == AB_HIGHNESSHEAL ? ( sd ? pc->checkskill(sd,AL_HEAL) : 10 ) : skill_lv ) * 8);
+#endif // RENEWAL
+ if( sd && ((skill2_lv = pc->checkskill(sd, HP_MEDITATIO)) > 0) )
+ hp += hp * skill2_lv * 2 / 100;
+ else if( src->type == BL_HOM && (skill2_lv = homun->checkskill(((TBL_HOM*)src), HLIF_BRAIN)) > 0 )
+ hp += hp * skill2_lv * 2 / 100;
break;
}
if( ( (target && target->type == BL_MER) || !heal ) && skill_id != NPC_EVILLAND )
hp >>= 1;
- if( sd && (skill = pc->skillheal_bonus(sd, skill_id)) )
- hp += hp*skill/100;
+ if( sd && (skill2_lv = pc->skillheal_bonus(sd, skill_id)) )
+ hp += hp*skill2_lv/100;
- if( tsd && (skill = pc->skillheal2_bonus(tsd, skill_id)) )
- hp += hp*skill/100;
+ if( tsd && (skill2_lv = pc->skillheal2_bonus(tsd, skill_id)) )
+ hp += hp*skill2_lv/100;
- sc = status_get_sc(target);
+ sc = status->get_sc(src);
+ if( sc && sc->count && sc->data[SC_OFFERTORIUM] ) {
+ if( skill_id == AB_HIGHNESSHEAL || skill_id == AB_CHEAL || skill_id == PR_SANCTUARY || skill_id == AL_HEAL )
+ hp += hp * sc->data[SC_OFFERTORIUM]->val2 / 100;
+ }
+ sc = status->get_sc(target);
if( sc && sc->count ) {
if( sc->data[SC_CRITICALWOUND] && heal ) // Critical Wound has no effect on offensive heal. [Inkfish]
hp -= hp * sc->data[SC_CRITICALWOUND]->val2/100;
@@ -438,20 +391,22 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
hp += hp * sc->data[SC_HEALPLUS]->val1/100; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish]
if( sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2)
hp += hp / 10;
- if( sc->data[SC_OFFERTORIUM] && (skill_id == AB_HIGHNESSHEAL || skill_id == AB_CHEAL || skill_id == PR_SANCTUARY || skill_id == AL_HEAL) )
- hp += hp * sc->data[SC_OFFERTORIUM]->val2 / 100;
+ if ( sc && sc->data[SC_VITALITYACTIVATION] )
+ hp = hp * 150 / 100;
}
#ifdef RENEWAL
- // MATK part of the RE heal formula [malufett]
- // Note: in this part matk bonuses from items or skills are not applied
+ // MATK part of the RE heal formula [malufett]
+ // Note: in this part matk bonuses from items or skills are not applied
switch( skill_id ) {
- case BA_APPLEIDUN: case PR_SANCTUARY:
- case NPC_EVILLAND: break;
+ case BA_APPLEIDUN:
+ case PR_SANCTUARY:
+ case NPC_EVILLAND:
+ break;
default:
- hp += status_get_matk(src, 3);
+ hp += status->get_matk(src, 3);
}
-#endif
+#endif // RENEWAL
return hp;
}
@@ -478,10 +433,14 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b
return 0;
// Couldn't preserve 3rd Class skills except only when using Reproduce skill. [Jobbie]
- if( !(sd->sc.data[SC__REPRODUCE]) && (skill_id >= RK_ENCHANTBLADE && skill_id <= SR_RIDEINLIGHTNING) )
+ if( !(sd->sc.data[SC__REPRODUCE]) && ((skill_id >= RK_ENCHANTBLADE && skill_id <= SR_RIDEINLIGHTNING) || (skill_id >= KO_YAMIKUMO && skill_id <= OB_AKAITSUKI)))
return 0;
// Reproduce will only copy skills according on the list. [Jobbie]
- else if( sd->sc.data[SC__REPRODUCE] && !skill_reproduce_db[skill->get_index(skill_id)] )
+ else if( sd->sc.data[SC__REPRODUCE] && !skill->reproduce_db[skill->get_index(skill_id)] )
+ return 0;
+
+ //Never copy new 3rd class skills By OmegaRed
+ if(skill_id >= GC_DARKCROW && skill_id <= ALL_FULL_THROTTLE)
return 0;
return 1;
@@ -509,12 +468,12 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
// allowing a skill to be cast. This is to prevent no-delay ACT files from spamming skills such as
// AC_DOUBLE which do not have a skill delay and are not regarded in terms of attack motion.
if( !sd->state.autocast && sd->skillitem != skill_id && sd->canskill_tick &&
- DIFF_TICK(iTimer->gettick(), sd->canskill_tick) < (sd->battle_status.amotion * (battle_config.skill_amotion_leniency) / 100) )
+ DIFF_TICK(timer->gettick(), sd->canskill_tick) < (sd->battle_status.amotion * (battle_config.skill_amotion_leniency) / 100) )
{// attempted to cast a skill before the attack motion has finished
return 1;
}
- if (sd->blockskill[idx] > 0) {
+ if (sd->blockskill[idx]) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0);
return 1;
}
@@ -533,7 +492,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
case AL_WARP:
case RETURN_TO_ELDICASTES:
case ALL_GUARDIAN_RECALL:
- if(map[m].flag.nowarp) {
+ if(map->list[m].flag.nowarp) {
clif->skill_mapinfomessage(sd,0);
return 1;
}
@@ -541,7 +500,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
case AL_TELEPORT:
case SC_FATALMENACE:
case SC_DIMENSIONDOOR:
- if(map[m].flag.noteleport) {
+ if(map->list[m].flag.noteleport) {
clif->skill_mapinfomessage(sd,0);
return 1;
}
@@ -549,17 +508,17 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
case WE_CALLPARTNER:
case WE_CALLPARENT:
case WE_CALLBABY:
- if (map[m].flag.nomemo) {
+ if (map->list[m].flag.nomemo) {
clif->skill_mapinfomessage(sd,1);
return 1;
}
break;
case MC_VENDING:
case ALL_BUYING_STORE:
- if( npc_isnear(&sd->bl) ) {
+ if( npc->isnear(&sd->bl) ) {
// uncomment for more verbose message.
//char output[150];
- //sprintf(output, msg_txt(662), battle_config.min_npc_vendchat_distance);
+ //sprintf(output, msg_txt(862), battle_config.min_npc_vendchat_distance); // "You're too close to a NPC, you must be at least %d cells away from any NPC."
//clif->message(sd->fd, output);
clif->skill_fail(sd,skill_id,USESKILL_FAIL_THERE_ARE_NPC_AROUND,0);
return 1;
@@ -568,50 +527,31 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
return 0; // always allowed
case WZ_ICEWALL:
// noicewall flag [Valaris]
- if (map[m].flag.noicewall) {
+ if (map->list[m].flag.noicewall) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 1;
}
break;
case GC_DARKILLUSION:
- if( map_flag_gvg(m) ) {
+ if( map_flag_gvg2(m) ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 1;
}
break;
case GD_EMERGENCYCALL:
- if (
- !(battle_config.emergency_call&((iMap->agit_flag || iMap->agit2_flag)?2:1)) ||
- !(battle_config.emergency_call&(map[m].flag.gvg || map[m].flag.gvg_castle?8:4)) ||
- (battle_config.emergency_call&16 && map[m].flag.nowarpto && !map[m].flag.gvg_castle)
- ) {
+ if( !(battle_config.emergency_call&((map->agit_flag || map->agit2_flag)?2:1))
+ || !(battle_config.emergency_call&(map->list[m].flag.gvg || map->list[m].flag.gvg_castle?8:4))
+ || (battle_config.emergency_call&16 && map->list[m].flag.nowarpto && !map->list[m].flag.gvg_castle)
+ ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 1;
}
break;
- case BS_GREED:
- case WS_CARTBOOST:
- case BS_HAMMERFALL:
- case BS_ADRENALINE:
- case MC_CARTREVOLUTION:
- case MC_MAMMONITE:
- case WS_MELTDOWN:
- case MG_SIGHT:
- case TF_HIDING:
- /**
- * These skills cannot be used while in mado gear (credits to Xantara)
- **/
- if( pc_ismadogear(sd) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR_RIDE,0);
- return 1;
- }
- break;
- case WM_SIRCLEOFNATURE:
- case WM_SOUND_OF_DESTRUCTION:
case SC_MANHOLE:
- case WM_LULLABY_DEEPSLEEP:
+ case WM_SOUND_OF_DESTRUCTION:
case WM_SATURDAY_NIGHT_FEVER:
+ case WM_LULLABY_DEEPSLEEP:
if( !map_flag_vs(m) ) {
clif->skill_mapinfomessage(sd,2); // This skill uses this msg instead of skill fails.
return 1;
@@ -619,7 +559,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
break;
}
- return (map[m].flag.noskill);
+ return (map->list[m].flag.noskill);
}
int skillnotok_hom(uint16 skill_id, struct homun_data *hd)
@@ -634,12 +574,12 @@ int skillnotok_hom(uint16 skill_id, struct homun_data *hd)
return 1;
switch(skill_id){
case MH_LIGHT_OF_REGENE:
- if(hd->homunculus.intimacy <= 750) //if not cordial
- return 1;
- break;
- case MH_OVERED_BOOST:
- if(hd->homunculus.hunger <= 1) //if we starving
- return 1;
+ if( homun->get_intimacy_grade(hd) != 4 ){
+ if( hd->master )
+ clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_RELATIONGRADE, 0);
+ return 1;
+ }
+ break;
case MH_GOLDENE_FERSE: //can be used with angriff
if(hd->sc.data[SC_ANGRIFFS_MODUS])
return 1;
@@ -676,32 +616,30 @@ struct s_skill_unit_layout* skill_get_unit_layout (uint16 skill_id, uint16 skill
}
if (pos != -1) // simple single-definition layout
- return &skill_unit_layout[pos];
+ return &skill->unit_layout[pos];
- dir = (src->x == x && src->y == y) ? 6 : iMap->calc_dir(src,x,y); // 6 - default aegis direction
+ dir = (src->x == x && src->y == y) ? 6 : map->calc_dir(src,x,y); // 6 - default aegis direction
if (skill_id == MG_FIREWALL)
- return &skill_unit_layout [firewall_unit_pos + dir];
+ return &skill->unit_layout [skill->firewall_unit_pos + dir];
else if (skill_id == WZ_ICEWALL)
- return &skill_unit_layout [icewall_unit_pos + dir];
+ return &skill->unit_layout [skill->icewall_unit_pos + dir];
else if( skill_id == WL_EARTHSTRAIN ) //Warlock
- return &skill_unit_layout [earthstrain_unit_pos + dir];
+ return &skill->unit_layout [skill->earthstrain_unit_pos + dir];
ShowError("skill_get_unit_layout: unknown unit layout for skill %d (level %d)\n", skill_id, skill_lv);
- return &skill_unit_layout[0]; // default 1x1 layout
+ return &skill->unit_layout[0]; // default 1x1 layout
}
/*==========================================
*
*------------------------------------------*/
-int skill_additional_effect (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int dmg_lv, unsigned int tick)
-{
+int skill_additional_effect(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int dmg_lv, int64 tick) {
struct map_session_data *sd, *dstsd;
struct mob_data *md, *dstmd;
struct status_data *sstatus, *tstatus;
struct status_change *sc, *tsc;
- enum sc_type status;
int temp;
int rate;
@@ -718,10 +656,10 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
dstsd = BL_CAST(BL_PC, bl);
dstmd = BL_CAST(BL_MOB, bl);
- sc = status_get_sc(src);
- tsc = status_get_sc(bl);
- sstatus = status_get_status_data(src);
- tstatus = status_get_status_data(bl);
+ sc = status->get_sc(src);
+ tsc = status->get_sc(bl);
+ sstatus = status->get_status_data(src);
+ tstatus = status->get_status_data(bl);
if (!tsc) //skill additional effect is about adding effects to the target...
//So if the target can't be inflicted with statuses, this is pointless.
return 0;
@@ -754,13 +692,13 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
}
type = sd->addeff[i].id;
- temp = skill->get_time2(status_sc2skill(type),7);
+ temp = skill->get_time2(status->sc2skill(type),7);
if (sd->addeff[i].flag&ATF_TARGET)
- status_change_start(bl,type,rate,7,0,0,0,temp,0);
+ status->change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,0);
if (sd->addeff[i].flag&ATF_SELF)
- status_change_start(src,type,rate,7,0,0,0,temp,0);
+ status->change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,0);
}
}
@@ -772,12 +710,12 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
if( skill_id != sd->addeff3[i].skill || !sd->addeff3[i].rate )
continue;
type = sd->addeff3[i].id;
- temp = skill->get_time2(status_sc2skill(type),7);
+ temp = skill->get_time2(status->sc2skill(type),7);
if( sd->addeff3[i].target&ATF_TARGET )
- status_change_start(bl,type,sd->addeff3[i].rate,7,0,0,0,temp,0);
+ status->change_start(src,bl,type,sd->addeff3[i].rate,7,0,0,0,temp,0);
if( sd->addeff3[i].target&ATF_SELF )
- status_change_start(src,type,sd->addeff3[i].rate,7,0,0,0,temp,0);
+ status->change_start(src,src,type,sd->addeff3[i].rate,7,0,0,0,temp,0);
}
}
}
@@ -811,15 +749,18 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
// Chance to trigger Taekwon kicks [Dralnu]
if(sc && !sc->data[SC_COMBOATTACK]) {
if(sc->data[SC_STORMKICK_READY] &&
- sc_start(src,SC_COMBOATTACK, 15, TK_STORMKICK,
+ sc_start4(src,src,SC_COMBOATTACK, 15, TK_STORMKICK,
+ bl->id, 2, 0,
(2000 - 4*sstatus->agi - 2*sstatus->dex)))
; //Stance triggered
else if(sc->data[SC_DOWNKICK_READY] &&
- sc_start(src,SC_COMBOATTACK, 15, TK_DOWNKICK,
+ sc_start4(src,src,SC_COMBOATTACK, 15, TK_DOWNKICK,
+ bl->id, 2, 0,
(2000 - 4*sstatus->agi - 2*sstatus->dex)))
; //Stance triggered
else if(sc->data[SC_TURNKICK_READY] &&
- sc_start(src,SC_COMBOATTACK, 15, TK_TURNKICK,
+ sc_start4(src,src,SC_COMBOATTACK, 15, TK_TURNKICK,
+ bl->id, 2, 0,
(2000 - 4*sstatus->agi - 2*sstatus->dex)))
; //Stance triggered
else if (sc->data[SC_COUNTERKICK_READY]) { //additional chance from SG_FRIEND [Komurka]
@@ -828,7 +769,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100;
status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER);
}
- sc_start2(src, SC_COMBOATTACK, rate, TK_COUNTER, bl->id,
+ sc_start2(src, src, SC_COMBOATTACK, rate, TK_COUNTER, bl->id,
(2000 - 4*sstatus->agi - 2*sstatus->dex));
}
}
@@ -840,26 +781,24 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
struct status_change_entry *sce;
// Enchant Poison gives a chance to poison attacked enemies
if((sce=sc->data[SC_ENCHANTPOISON])) //Don't use sc_start since chance comes in 1/10000 rate.
- status_change_start(bl,SC_POISON,sce->val2, sce->val1,src->id,0,0,
+ status->change_start(src,bl,SC_POISON,sce->val2, sce->val1,src->id,0,0,
skill->get_time2(AS_ENCHANTPOISON,sce->val1),0);
// Enchant Deadly Poison gives a chance to deadly poison attacked enemies
if((sce=sc->data[SC_EDP]))
- sc_start4(bl,SC_DPOISON,sce->val2, sce->val1,src->id,0,0,
+ sc_start4(src,bl,SC_DPOISON,sce->val2, sce->val1,src->id,0,0,
skill->get_time2(ASC_EDP,sce->val1));
}
}
break;
case SM_BASH:
- if( sd && skill_lv > 5 && pc->checkskill(sd,SM_FATALBLOW)>0 ){
- //TODO: How much % per base level it actually is?
- sc_start(bl,SC_STUN,(5*(skill_lv-5)+(int)sd->status.base_level/10),
- skill_lv,skill->get_time2(SM_FATALBLOW,skill_lv));
- }
+ if( sd && skill_lv > 5 && pc->checkskill(sd,SM_FATALBLOW)>0 )
+ status->change_start(src,bl,SC_STUN,500*(skill_lv-5)*sd->status.base_level/50,
+ skill_lv,0,0,0,skill->get_time2(SM_FATALBLOW,skill_lv),0);
break;
case MER_CRASH:
- sc_start(bl,SC_STUN,(6*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,(6*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case AS_VENOMKNIFE:
@@ -867,30 +806,32 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
skill_lv = pc->checkskill(sd, TF_POISON);
case TF_POISON:
case AS_SPLASHER:
- if(!sc_start2(bl,SC_POISON,(4*skill_lv+10),skill_lv,src->id,skill->get_time2(skill_id,skill_lv))
+ if(!sc_start2(src,bl,SC_POISON,(4*skill_lv+10),skill_lv,src->id,skill->get_time2(skill_id,skill_lv))
&& sd && skill_id==TF_POISON
)
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
case AS_SONICBLOW:
- sc_start(bl,SC_STUN,(2*skill_lv+10),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,(2*skill_lv+10),skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case WZ_FIREPILLAR:
- unit_set_walkdelay(bl, tick, skill->get_time2(skill_id, skill_lv), 1);
+ unit->set_walkdelay(bl, tick, skill->get_time2(skill_id, skill_lv), 1);
break;
case MG_FROSTDIVER:
#ifndef RENEWAL
case WZ_FROSTNOVA:
#endif
- sc_start(bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill->get_time2(skill_id,skill_lv));
+ if( !sc_start(src,bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill->get_time2(skill_id,skill_lv))
+ && sd && skill_id == MG_FROSTDIVER )
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
#ifdef RENEWAL
case WZ_FROSTNOVA:
- sc_start(bl,SC_FREEZE,skill_lv*5+33,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_FREEZE,skill_lv*5+33,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
#endif
@@ -899,11 +840,11 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
* Storm Gust counter was dropped in renewal
**/
#ifdef RENEWAL
- sc_start(bl,SC_FREEZE,65-(5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_FREEZE,65-(5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
#else
- //Tharis pointed out that this is normal freeze chance with a base of 300%
+ // [Tharis] pointed out that this is normal freeze chance with a base of 300%
if(tsc->sg_counter >= 3 &&
- sc_start(bl,SC_FREEZE,300,skill_lv,skill->get_time2(skill_id,skill_lv)))
+ sc_start(src,bl,SC_FREEZE,300,skill_lv,skill->get_time2(skill_id,skill_lv)))
tsc->sg_counter = 0;
/**
* being it only resets on success it'd keep stacking and eventually overflowing on mvps, so we reset at a high value
@@ -914,25 +855,25 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
break;
case WZ_METEOR:
- sc_start(bl,SC_STUN,3*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,3*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case WZ_VERMILION:
- sc_start(bl,SC_BLIND,4*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_BLIND,4*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case HT_FREEZINGTRAP:
case MA_FREEZINGTRAP:
- sc_start(bl,SC_FREEZE,(3*skill_lv+35),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_FREEZE,(3*skill_lv+35),skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case HT_FLASHER:
- sc_start(bl,SC_BLIND,(10*skill_lv+30),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_BLIND,(10*skill_lv+30),skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case HT_LANDMINE:
case MA_LANDMINE:
- sc_start(bl,SC_STUN,(5*skill_lv+30),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,(5*skill_lv+30),skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case HT_SHOCKWAVE:
@@ -941,33 +882,32 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
case HT_SANDMAN:
case MA_SANDMAN:
- sc_start(bl,SC_SLEEP,(10*skill_lv+40),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_SLEEP,(10*skill_lv+40),skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case TF_SPRINKLESAND:
- sc_start(bl,SC_BLIND,20,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_BLIND,20,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case TF_THROWSTONE:
- sc_start(bl,SC_STUN,3,skill_lv,skill->get_time(skill_id,skill_lv));
- sc_start(bl,SC_BLIND,3,skill_lv,skill->get_time2(skill_id,skill_lv));
+ if( !sc_start(src,bl,SC_STUN,3,skill_lv,skill->get_time(skill_id,skill_lv)) )
+ sc_start(src,bl,SC_BLIND,3,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case NPC_DARKCROSS:
case CR_HOLYCROSS:
- sc_start(bl,SC_BLIND,3*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_BLIND,3*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case CR_GRANDCROSS:
case NPC_GRANDDARKNESS:
//Chance to cause blind status vs demon and undead element, but not against players
if(!dstsd && (battle->check_undead(tstatus->race,tstatus->def_ele) || tstatus->race == RC_DEMON))
- sc_start(bl,SC_BLIND,100,skill_lv,skill->get_time2(skill_id,skill_lv));
- attack_type |= BF_WEAPON;
+ sc_start(src,bl,SC_BLIND,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case AM_ACIDTERROR:
- sc_start2(bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
+ sc_start2(src,bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
if (skill->break_equip(bl, EQP_ARMOR, 100*skill->get_time(skill_id,skill_lv), BCT_ENEMY))
clif->emotion(bl,E_OMG);
break;
@@ -977,7 +917,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
break;
case CR_SHIELDCHARGE:
- sc_start(bl,SC_STUN,(15+skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,(15+skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case PA_PRESSURE:
@@ -985,28 +925,28 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
break;
case RG_RAID:
- sc_start(bl,SC_STUN,(10+3*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv));
- sc_start(bl,SC_BLIND,(10+3*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,(10+3*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_BLIND,(10+3*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
#ifdef RENEWAL
- sc_start(bl,SC_RAID,100,7,5000);
+ sc_start(src,bl,SC_RAID,100,7,5000);
break;
case RG_BACKSTAP:
- sc_start(bl,SC_STUN,(5+2*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,(5+2*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv));
#endif
break;
case BA_FROSTJOKER:
- sc_start(bl,SC_FREEZE,(15+5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_FREEZE,(15+5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case DC_SCREAM:
- sc_start(bl,SC_STUN,(25+5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,(25+5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case BD_LULLABY:
- sc_start(bl,SC_SLEEP,15,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_SLEEP,15,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case DC_UGLYDANCE:
@@ -1017,11 +957,11 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
break;
case SL_STUN:
if (tstatus->size==SZ_MEDIUM) //Only stuns mid-sized mobs.
- sc_start(bl,SC_STUN,(30+10*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,(30+10*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv));
break;
case NPC_PETRIFYATTACK:
- sc_start4(bl,status_skill2sc(skill_id),50+10*skill_lv,
+ sc_start4(src,bl,status->skill2sc(skill_id),50+10*skill_lv,
skill_lv,0,0,skill->get_time(skill_id,skill_lv),
skill->get_time2(skill_id,skill_lv));
break;
@@ -1032,19 +972,20 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
case NPC_SILENCEATTACK:
case NPC_STUNATTACK:
case NPC_HELLPOWER:
- sc_start(bl,status_skill2sc(skill_id),50+10*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,status->skill2sc(skill_id),50+10*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case NPC_ACIDBREATH:
case NPC_ICEBREATH:
- sc_start(bl,status_skill2sc(skill_id),70,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,status->skill2sc(skill_id),70,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case NPC_BLEEDING:
- sc_start2(bl,SC_BLOODING,(20*skill_lv),skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
+ sc_start2(src,bl,SC_BLOODING,(20*skill_lv),skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
break;
case NPC_MENTALBREAKER:
- { //Based on observations by Tharis, Mental Breaker should do SP damage
+ {
+ //Based on observations by [Tharis], Mental Breaker should do SP damage
//equal to Matk*skLevel.
- rate = status_get_matk(src, 2);
+ rate = status->get_matk(src, 2);
rate*=skill_lv;
status_zap(bl, 0, rate);
break;
@@ -1064,32 +1005,32 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
break;
case CH_TIGERFIST:
- sc_start(bl,SC_STOP,(10+skill_lv*10),0,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STOP,(10+skill_lv*10),0,skill->get_time2(skill_id,skill_lv));
break;
case LK_SPIRALPIERCE:
case ML_SPIRALPIERCE:
- sc_start(bl,SC_STOP,(15+skill_lv*5),0,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_ANKLESNARE,100,0,skill->get_time2(skill_id,skill_lv));
break;
case ST_REJECTSWORD:
- sc_start(bl,SC_AUTOCOUNTER,(skill_lv*15),skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_AUTOCOUNTER,(skill_lv*15),skill_lv,skill->get_time(skill_id,skill_lv));
break;
case PF_FOGWALL:
if (src != bl && !tsc->data[SC_DELUGE])
- sc_start(bl,SC_BLIND,100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_BLIND,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
- case LK_HEADCRUSH: //Headcrush has chance of causing Bleeding status, except on demon and undead element
+ case LK_HEADCRUSH: // Headcrush has chance of causing Bleeding status, except on demon and undead element
if (!(battle->check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON))
- sc_start2(bl, SC_BLOODING,50, skill_lv, src->id, skill->get_time2(skill_id,skill_lv));
+ sc_start2(src, bl, SC_BLOODING,50, skill_lv, src->id, skill->get_time2(skill_id,skill_lv));
break;
case LK_JOINTBEAT:
- status = status_skill2sc(skill_id);
if (tsc->jb_flag) {
- sc_start4(bl,status,(5*skill_lv+5),skill_lv,tsc->jb_flag&BREAK_FLAGS,src->id,0,skill->get_time2(skill_id,skill_lv));
+ enum sc_type type = status->skill2sc(skill_id);
+ sc_start4(src,bl,type,(5*skill_lv+5),skill_lv,tsc->jb_flag&BREAK_FLAGS,src->id,0,skill->get_time2(skill_id,skill_lv));
tsc->jb_flag = 0;
}
break;
@@ -1097,22 +1038,22 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
//Any enemies hit by this skill will receive Stun, Darkness, or external bleeding status ailment with a 5%+5*skill_lv% chance.
switch(rnd()%3) {
case 0:
- sc_start(bl,SC_BLIND,(5+skill_lv*5),skill_lv,skill->get_time2(skill_id,1));
+ sc_start(src,bl,SC_BLIND,(5+skill_lv*5),skill_lv,skill->get_time2(skill_id,1));
break;
case 1:
- sc_start(bl,SC_STUN,(5+skill_lv*5),skill_lv,skill->get_time2(skill_id,2));
+ sc_start(src,bl,SC_STUN,(5+skill_lv*5),skill_lv,skill->get_time2(skill_id,2));
break;
default:
- sc_start2(bl,SC_BLOODING,(5+skill_lv*5),skill_lv,src->id,skill->get_time2(skill_id,3));
+ sc_start2(src,bl,SC_BLOODING,(5+skill_lv*5),skill_lv,src->id,skill->get_time2(skill_id,3));
}
break;
case HW_NAPALMVULCAN:
- sc_start(bl,SC_CURSE,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_CURSE,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case WS_CARTTERMINATION: // Cart termination
- sc_start(bl,SC_STUN,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case CR_ACIDDEMONSTRATION:
@@ -1120,7 +1061,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
break;
case TK_DOWNKICK:
- sc_start(bl,SC_STUN,100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case TK_JUMPKICK:
@@ -1137,20 +1078,20 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
case TK_TURNKICK:
case MO_BALKYOUNG: //Note: attack_type is passed as BF_WEAPON for the actual target, BF_MISC for the splash-affected mobs.
if(attack_type&BF_MISC) //70% base stun chance...
- sc_start(bl,SC_STUN,70,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN,70,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case GS_BULLSEYE: //0.1% coma rate.
if(tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN)
- status_change_start(bl,SC_COMA,10,skill_lv,0,src->id,0,0,0);
+ status->change_start(src,bl,SC_COMA,10,skill_lv,0,src->id,0,0,0);
break;
case GS_PIERCINGSHOT:
- sc_start2(bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
+ sc_start2(src,bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
break;
case NJ_HYOUSYOURAKU:
- sc_start(bl,SC_FREEZE,(10+10*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_FREEZE,(10+10*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case GS_FLING:
- sc_start(bl,SC_FLING,100, sd?sd->spiritball_old:5,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_FLING,100, sd?sd->spiritball_old:5,skill->get_time(skill_id,skill_lv));
break;
case GS_DISARM:
rate = 3*skill_lv;
@@ -1160,112 +1101,132 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
case NPC_EVILLAND:
- sc_start(bl,SC_BLIND,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_BLIND,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case NPC_HELLJUDGEMENT:
- sc_start(bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case NPC_CRITICALWOUND:
- sc_start(bl,SC_CRITICALWOUND,100,skill_lv,skill->get_time2(skill_id,skill_lv));
- break;
- case RK_HUNDREDSPEAR:
- if( !sd || pc->checkskill(sd,KN_SPEARBOOMERANG) == 0 )
- break; // Spear Boomerang auto cast chance only works if you have mastered Spear Boomerang.
- rate = 10 + 3 * skill_lv;
- if( rnd()%100 < rate )
- skill->castend_damage_id(src,bl,KN_SPEARBOOMERANG,1,tick,0);
+ sc_start(src,bl,SC_CRITICALWOUND,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case RK_WINDCUTTER:
- sc_start(bl,SC_FEAR,3+2*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_FEAR,3+2*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case RK_DRAGONBREATH:
- sc_start4(bl,SC_BURNING,5+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv));
+ sc_start4(src,bl,SC_BURNING,15,skill_lv,1000,src->id,0,skill->get_time(skill_id,skill_lv));
break;
case RK_DRAGONBREATH_WATER:
- sc_start4(bl,SC_FROSTMISTY,5+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv));
+ sc_start4(src,bl,SC_FROSTMISTY,15,skill_lv,1000,src->id,0,skill->get_time(skill_id,skill_lv));
break;
case AB_ADORAMUS:
if( tsc && !tsc->data[SC_DEC_AGI] ) //Prevent duplicate agi-down effect.
- sc_start(bl, SC_ADORAMUS, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, bl, SC_ADORAMUS, skill_lv * 4 + (sd? sd->status.job_level:50)/2, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case WL_CRIMSONROCK:
- sc_start(bl, SC_STUN, 40, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, bl, SC_STUN, 40, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case WL_COMET:
- sc_start4(bl,SC_BURNING,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv));
+ sc_start4(src,bl,SC_BURNING,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv));
break;
case WL_EARTHSTRAIN:
{
- // lv 1 & 2 = Strip Helm, lv 3 = Strip Armor, lv 4 = Strip Weapon and lv 5 = Strip Accessory. [malufett]
- const int pos[5] = { EQP_HELM, EQP_HELM, EQP_ARMOR, EQP_WEAPON, EQP_ACC };
- skill->strip_equip(bl, pos[skill_lv], 6 * skill_lv + status_get_lv(src) / 4 + status_get_dex(src) / 10,
- skill_lv, skill->get_time2(skill_id,skill_lv));
+ int i;
+ const int pos[5] = { EQP_WEAPON, EQP_HELM, EQP_SHIELD, EQP_ARMOR, EQP_ACC };
+
+ for( i = 0; i < skill_lv; i++ )
+ skill->strip_equip(bl,pos[i], (5 + skill_lv) * skill_lv,
+ skill_lv,skill->get_time2(skill_id,skill_lv));
}
break;
case WL_JACKFROST:
- sc_start(bl,SC_FREEZE,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_FREEZE,100,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case WL_FROSTMISTY:
- sc_start(bl,SC_FROSTMISTY,25 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_FROSTMISTY,25 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case RA_WUGBITE:
- sc_start(bl, SC_WUGBITE, (sd ? pc->checkskill(sd,RA_TOOTHOFWUG)*2 : 0), skill_lv, (skill->get_time(skill_id,skill_lv) + (sd ? pc->checkskill(sd,RA_TOOTHOFWUG)*500 : 0)) );
+ rate = 50 + 10 * skill_lv + 2 * (sd ? pc->checkskill(sd,RA_TOOTHOFWUG) : 0) - tstatus->agi / 4;
+ if ( rate < 50 )
+ rate = 50;
+ sc_start(src,bl,SC_WUGBITE, rate, skill_lv, skill->get_time(skill_id, skill_lv) + (sd ? pc->checkskill(sd,RA_TOOTHOFWUG) * 500 : 0));
break;
case RA_SENSITIVEKEEN:
if( rnd()%100 < 8 * skill_lv )
skill->castend_damage_id(src, bl, RA_WUGBITE, sd ? pc->checkskill(sd, RA_WUGBITE):skill_lv, tick, SD_ANIMATION);
break;
+ case RA_MAGENTATRAP:
+ case RA_COBALTTRAP:
+ case RA_MAIZETRAP:
+ case RA_VERDURETRAP:
+ if( dstmd && !(dstmd->status.mode&MD_BOSS) )
+ sc_start2(src,bl,SC_ARMOR_PROPERTY,100,skill_lv,skill->get_ele(skill_id,skill_lv),skill->get_time2(skill_id,skill_lv));
+ break;
case RA_FIRINGTRAP:
case RA_ICEBOUNDTRAP:
- sc_start4(bl, (skill_id == RA_FIRINGTRAP) ? SC_BURNING:SC_FROSTMISTY, 40 + 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv));
+ sc_start4(src, bl, (skill_id == RA_FIRINGTRAP) ? SC_BURNING:SC_FROSTMISTY, 50 + 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv));
break;
case NC_PILEBUNKER:
- if( rnd()%100 < 5 + 15*skill_lv )
- { //Deactivatable Statuses: Kyrie Eleison, Auto Guard, Steel Body, Assumptio, and Millennium Shield
+ if( rnd()%100 < 25 + 15 *skill_lv ) {
+ //Deactivatable Statuses: Kyrie Eleison, Auto Guard, Steel Body, Assumptio, and Millennium Shield
status_change_end(bl, SC_KYRIE, INVALID_TIMER);
- status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER);
- status_change_end(bl, SC_STEELBODY, INVALID_TIMER);
status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
+ status_change_end(bl, SC_STEELBODY, INVALID_TIMER);
+ status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER);
+ status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER);
+ status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER);
+ status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER);
+ status_change_end(bl, SC_DEFENDER, INVALID_TIMER);
+ status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER);
+ status_change_end(bl, SC_PRESTIGE, INVALID_TIMER);
+ status_change_end(bl, SC_BANDING, INVALID_TIMER);
status_change_end(bl, SC_MILLENNIUMSHIELD, INVALID_TIMER);
}
break;
case NC_FLAMELAUNCHER:
- sc_start4(bl, SC_BURNING, 50 + 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv));
+ sc_start4(src, bl, SC_BURNING, 20 + 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv));
break;
case NC_COLDSLOWER:
- sc_start(bl, SC_FREEZE, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
- sc_start(bl, SC_FROSTMISTY, 20 + 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, bl, SC_FREEZE, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
+ if ( tsc && !tsc->data[SC_FREEZE] )
+ sc_start(src, bl, SC_FROSTMISTY, 20 + 10 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv));
break;
case NC_POWERSWING:
- sc_start(bl, SC_STUN, 5*skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
+ // Use flag=2, the stun duration is not vit-reduced.
+ status->change_start(src, bl, SC_STUN, 5*skill_lv*100, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), 2);
if( rnd()%100 < 5*skill_lv )
skill->castend_damage_id(src, bl, NC_AXEBOOMERANG, pc->checkskill(sd, NC_AXEBOOMERANG), tick, 1);
break;
case NC_MAGMA_ERUPTION:
- sc_start4(bl, SC_BURNING, 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv));
- sc_start(bl, SC_STUN, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start4(src, bl, SC_BURNING, 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv));
+ sc_start(src, bl, SC_STUN, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case GC_WEAPONCRUSH:
skill->castend_nodamage_id(src,bl,skill_id,skill_lv,tick,BCT_ENEMY);
break;
case GC_DARKCROW:
- sc_start(bl, SC_DARKCROW, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, bl, SC_DARKCROW, 100, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case LG_SHIELDPRESS:
- sc_start(bl, SC_STUN, 30 + 8 * skill_lv, skill_lv, skill->get_time(skill_id,skill_lv));
+ rate = 30 + 8 * skill_lv + sstatus->dex / 10 + (sd? sd->status.job_level:0) / 4;
+ sc_start(src, bl, SC_STUN, rate, skill_lv, skill->get_time(skill_id,skill_lv));
break;
case LG_PINPOINTATTACK:
- rate = 30 + (((5 * (sd?pc->checkskill(sd,LG_PINPOINTATTACK):skill_lv)) + (sstatus->agi + status_get_lv(src))) / 10);
+ rate = 30 + 5 * (sd ? pc->checkskill(sd,LG_PINPOINTATTACK) : 1) + (sstatus->agi + status->get_lv(src)) / 10;
switch( skill_lv ) {
case 1:
- sc_start2(bl,SC_BLOODING,rate,skill_lv,src->id,skill->get_time(skill_id,skill_lv));
+ sc_start(src, bl,SC_BLOODING,rate,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case 2:
- if( dstsd && dstsd->spiritball && rnd()%100 < rate )
- pc->delspiritball(dstsd, dstsd->spiritball, 0);
+ skill->break_equip(bl, EQP_HELM, rate*100, BCT_ENEMY);
break;
- default:
- skill->break_equip(bl,(skill_lv == 3) ? EQP_SHIELD : (skill_lv == 4) ? EQP_ARMOR : EQP_WEAPON,rate * 100,BCT_ENEMY);
+ case 3:
+ skill->break_equip(bl, EQP_SHIELD, rate*100, BCT_ENEMY);
+ break;
+ case 4:
+ skill->break_equip(bl, EQP_ARMOR, rate*100, BCT_ENEMY);
+ break;
+ case 5:
+ skill->break_equip(bl, EQP_WEAPON, rate*100, BCT_ENEMY);
break;
}
break;
@@ -1274,149 +1235,123 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
if( rnd()%100 < rate && dstsd ) // Uses skill->addtimerskill to avoid damage and setsit packet overlaping. Officially clif->setsit is received about 500 ms after damage packet.
skill->addtimerskill(src,tick+500,bl->id,0,0,skill_id,skill_lv,BF_WEAPON,0);
else if( dstmd && !is_boss(bl) )
- sc_start(bl,SC_STOP,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src, bl,SC_STOP,100,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case LG_RAYOFGENESIS: // 50% chance to cause Blind on Undead and Demon monsters.
if ( battle->check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON )
- sc_start(bl, SC_BLIND,50, skill_lv, skill->get_time(skill_id,skill_lv));
+ sc_start(src, bl, SC_BLIND,50, skill_lv, skill->get_time(skill_id,skill_lv));
break;
case LG_EARTHDRIVE:
- skill->break_equip(src, EQP_SHIELD, 500, BCT_SELF);
- sc_start(bl, SC_EARTHDRIVE, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ skill->break_equip(src, EQP_SHIELD, 100 * skill_lv, BCT_SELF);
+ sc_start(src, bl, SC_EARTHDRIVE, 100, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case SR_DRAGONCOMBO:
- sc_start(bl, SC_STUN, 1 + skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, bl, SC_STUN, 1 + skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case SR_FALLENEMPIRE:
- sc_start(bl, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, bl, SC_FALLENEMPIRE, 100, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case SR_WINDMILL:
if( dstsd )
skill->addtimerskill(src,tick+status_get_amotion(src),bl->id,0,0,skill_id,skill_lv,BF_WEAPON,0);
else if( dstmd && !is_boss(bl) )
- sc_start(bl, SC_STUN, 100, skill_lv, 1000 + 1000 * (rnd() %3));
+ sc_start(src, bl, SC_STUN, 100, skill_lv, 1000 + 1000 * (rnd() %3));
break;
case SR_GENTLETOUCH_QUIET: // [(Skill Level x 5) + (Caster?s DEX + Caster?s Base Level) / 10]
- sc_start(bl, SC_SILENCE, 5 * skill_lv + (sstatus->dex + status_get_lv(src)) / 10, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, bl, SC_SILENCE, 5 * skill_lv + (sstatus->dex + status->get_lv(src)) / 10, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case SR_EARTHSHAKER:
- sc_start(bl,SC_STUN, 25 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src, bl,SC_STUN, 25 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case SR_HOWLINGOFLION:
- sc_start(bl, SC_FEAR, 5 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
- break;
- case WM_SOUND_OF_DESTRUCTION:
- if( rnd()%100 < 5 + 5 * skill_lv ) { // Temporarly Check Until We Get the Official Formula
- status_change_end(bl, SC_DANCING, INVALID_TIMER);
- status_change_end(bl, SC_RICHMANKIM, INVALID_TIMER);
- status_change_end(bl, SC_ETERNALCHAOS, INVALID_TIMER);
- status_change_end(bl, SC_DRUMBATTLE, INVALID_TIMER);
- status_change_end(bl, SC_NIBELUNGEN, INVALID_TIMER);
- status_change_end(bl, SC_INTOABYSS, INVALID_TIMER);
- status_change_end(bl, SC_SIEGFRIED, INVALID_TIMER);
- status_change_end(bl, SC_WHISTLE, INVALID_TIMER);
- status_change_end(bl, SC_ASSNCROS, INVALID_TIMER);
- status_change_end(bl, SC_POEMBRAGI, INVALID_TIMER);
- status_change_end(bl, SC_APPLEIDUN, INVALID_TIMER);
- status_change_end(bl, SC_HUMMING, INVALID_TIMER);
- status_change_end(bl, SC_FORTUNE, INVALID_TIMER);
- status_change_end(bl, SC_SERVICEFORYOU, INVALID_TIMER);
- status_change_end(bl, SC_LONGING, INVALID_TIMER);
- status_change_end(bl, SC_SWING, INVALID_TIMER);
- status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
- status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
- status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
- status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
- status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
- status_change_end(bl, SC_DC_WINKCHARM, INVALID_TIMER);
- status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
- status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
- status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
- status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
- status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
- status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER);
- }
+ sc_start(src, bl, SC_FEAR, 5 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case SO_EARTHGRAVE:
- sc_start2(bl, SC_BLOODING, 5 * skill_lv, skill_lv, src->id, skill->get_time2(skill_id, skill_lv)); // Need official rate. [LimitLine]
+ sc_start2(src, bl, SC_BLOODING, 5 * skill_lv, skill_lv, src->id, skill->get_time2(skill_id, skill_lv)); // Need official rate. [LimitLine]
break;
case SO_DIAMONDDUST:
rate = 5 + 5 * skill_lv;
if( sc && sc->data[SC_COOLER_OPTION] )
- rate += rate * sc->data[SC_COOLER_OPTION]->val2 / 100;
- sc_start(bl, SC_CRYSTALIZE, rate, skill_lv, skill->get_time2(skill_id, skill_lv));
+ rate += sc->data[SC_COOLER_OPTION]->val3 / 5;
+ sc_start(src, bl, SC_COLD, rate, skill_lv, skill->get_time2(skill_id, skill_lv));
break;
case SO_VARETYR_SPEAR:
- sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv));
+ sc_start(src, bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case GN_SLINGITEM_RANGEMELEEATK:
if( sd ) {
switch( sd->itemid ) { // Starting SCs here instead of do it in skill->additional_effect to simplify the code.
- case 13261:
- sc_start(bl, SC_STUN, 100, skill_lv, skill->get_time2(GN_SLINGITEM, skill_lv));
- sc_start2(bl, SC_BLOODING, 100, skill_lv, src->id, skill->get_time2(GN_SLINGITEM, skill_lv));
+ case ITEMID_COCONUT_BOMB:
+ sc_start(src, bl, SC_STUN, 100, skill_lv, 5000); // 5 seconds until I get official
+ sc_start(src, bl, SC_BLOODING, 100, skill_lv, 10000);
break;
- case 13262:
- sc_start(bl, SC_MELON_BOMB, 100, skill_lv, skill->get_time(GN_SLINGITEM, skill_lv)); // Reduces ASPD and moviment speed
+ case ITEMID_MELON_BOMB:
+ sc_start(src, bl, SC_MELON_BOMB, 100, skill_lv, 60000); // Reduces ASPD and movement speed
break;
- case 13264:
- sc_start(bl, SC_BANANA_BOMB, 100, skill_lv, skill->get_time(GN_SLINGITEM, skill_lv)); // Reduces LUK ??Needed confirm it, may be it's bugged in kRORE?
- sc_start(bl, SC_BANANA_BOMB_SITDOWN_POSTDELAY, 75, skill_lv, skill->get_time(GN_SLINGITEM_RANGEMELEEATK,skill_lv)); // Sitdown for 3 seconds.
+ case ITEMID_BANANA_BOMB:
+ sc_start(src, bl, SC_BANANA_BOMB, 100, skill_lv, 60000); // Reduces LUK? Needed confirm it, may be it's bugged in kRORE?
+ sc_start(src, bl, SC_BANANA_BOMB_SITDOWN_POSTDELAY, (sd? sd->status.job_level:0) + sstatus->dex / 6 + tstatus->agi / 4 - tstatus->luk / 5 - status->get_lv(bl) + status->get_lv(src), skill_lv, 1000); // Sit down for 3 seconds.
break;
}
sd->itemid = -1;
}
break;
case GN_HELLS_PLANT_ATK:
- sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv));
- sc_start2(bl, SC_BLOODING, 20 + 10 * skill_lv, skill_lv, src->id,skill->get_time2(skill_id, skill_lv));
+ sc_start(src, bl, SC_STUN, 20 + 10 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv));
+ sc_start2(src, bl, SC_BLOODING, 5 + 5 * skill_lv, skill_lv, src->id,skill->get_time2(skill_id, skill_lv));
break;
case EL_WIND_SLASH: // Non confirmed rate.
- sc_start2(bl, SC_BLOODING, 25, skill_lv, src->id, skill->get_time(skill_id,skill_lv));
+ sc_start2(src, bl, SC_BLOODING, 25, skill_lv, src->id, skill->get_time(skill_id,skill_lv));
break;
case EL_STONE_HAMMER:
rate = 10 * skill_lv;
- sc_start(bl, SC_STUN, rate, skill_lv, skill->get_time(skill_id,skill_lv));
+ sc_start(src, bl, SC_STUN, rate, skill_lv, skill->get_time(skill_id,skill_lv));
break;
case EL_ROCK_CRUSHER:
case EL_ROCK_CRUSHER_ATK:
- sc_start(bl,status_skill2sc(skill_id),50,skill_lv,skill->get_time(EL_ROCK_CRUSHER,skill_lv));
+ sc_start(src, bl,status->skill2sc(skill_id),50,skill_lv,skill->get_time(EL_ROCK_CRUSHER,skill_lv));
break;
case EL_TYPOON_MIS:
- sc_start(bl,SC_SILENCE,10*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src, bl,SC_SILENCE,10*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case KO_JYUMONJIKIRI:
- sc_start(bl,SC_KO_JYUMONJIKIRI,90,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src, bl,SC_KO_JYUMONJIKIRI,90,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case KO_MAKIBISHI:
- sc_start(bl, SC_STUN, 10 * skill_lv, skill_lv, 1000 * (skill_lv / 2 + 2));
+ sc_start(src, bl, SC_STUN, 10 * skill_lv, skill_lv, 1000 * (skill_lv / 2 + 2));
break;
case MH_LAVA_SLIDE:
- if (tsc && !tsc->data[SC_BURNING]) sc_start4(bl, SC_BURNING, 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time(skill_id, skill_lv));
+ if (tsc && !tsc->data[SC_BURNING]) sc_start4(src, bl, SC_BURNING, 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time(skill_id, skill_lv));
break;
case MH_STAHL_HORN:
- sc_start(bl, SC_STUN, (20 + 4 * (skill_lv-1)), skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, bl, SC_STUN, (20 + 4 * (skill_lv-1)), skill_lv, skill->get_time(skill_id, skill_lv));
break;
case MH_NEEDLE_OF_PARALYZE:
- sc_start(bl, SC_NEEDLE_OF_PARALYZE, 40 + (5*skill_lv), skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, bl, SC_NEEDLE_OF_PARALYZE, 40 + (5*skill_lv), skill_lv, skill->get_time(skill_id, skill_lv));
+ break;
+ case GN_ILLUSIONDOPING:
+ if( sc_start(src, bl, SC_ILLUSIONDOPING, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)) ) //custom rate.
+ sc_start(src, bl, SC_ILLUSION, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ break;
+ case MH_XENO_SLASHER:
+ sc_start2(src, bl, SC_BLOODING, 10 * skill_lv, skill_lv, src->id, skill->get_time(skill_id,skill_lv));
break;
}
- if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai)
- { //Pass heritage to Master for status causing effects. [Skotlex]
- sd = iMap->id2sd(md->master_id);
+ if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai) {
+ //Pass heritage to Master for status causing effects. [Skotlex]
+ sd = map->id2sd(md->master_id);
src = sd?&sd->bl:src;
}
- if( attack_type&BF_WEAPON )
- { // Coma, Breaking Equipment
- if( sd && sd->special_state.bonus_coma )
- {
+ if( attack_type&BF_WEAPON && skill_id != CR_REFLECTSHIELD ) {
+ // Coma, Breaking Equipment
+ if( sd && sd->special_state.bonus_coma ) {
rate = sd->weapon_coma_ele[tstatus->def_ele];
rate += sd->weapon_coma_race[tstatus->race];
rate += sd->weapon_coma_race[tstatus->mode&MD_BOSS?RC_BOSS:RC_NONBOSS];
if (rate)
- status_change_start(bl, SC_COMA, rate, 0, 0, src->id, 0, 0, 0);
+ status->change_start(src, bl, SC_COMA, rate, 0, 0, src->id, 0, 0, 0);
}
if( sd && battle_config.equip_self_break_rate )
{ // Self weapon breaking
@@ -1453,10 +1388,18 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
if( rate )
skill->break_equip(bl, EQP_ARMOR, rate, BCT_ENEMY);
}
+ if (sd && !skill_id && bl->type == BL_PC) { // This effect does not work with skills.
+ if (sd->def_set_race[tstatus->race].rate)
+ status->change_start(src,bl, SC_DEFSET, sd->def_set_race[tstatus->race].rate, sd->def_set_race[tstatus->race].value,
+ 0, 0, 0, sd->def_set_race[tstatus->race].tick, 2);
+ if (sd->def_set_race[tstatus->race].rate)
+ status->change_start(src,bl, SC_MDEFSET, sd->mdef_set_race[tstatus->race].rate, sd->mdef_set_race[tstatus->race].value,
+ 0, 0, 0, sd->mdef_set_race[tstatus->race].tick, 2);
+ }
}
- if( sd && sd->ed && sc && !status_isdead(bl) && !skill_id ){
- struct unit_data *ud = unit_bl2ud(src);
+ if( sd && sd->ed && sc && !status->isdead(bl) && !skill_id ) {
+ struct unit_data *ud = unit->bl2ud(src);
if( sc->data[SC_WILD_STORM_OPTION] )
temp = sc->data[SC_WILD_STORM_OPTION]->val2;
@@ -1484,11 +1427,10 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
}
// Autospell when attacking
- if( sd && !status_isdead(bl) && sd->autospell[0].id )
- {
+ if( sd && !status->isdead(bl) && sd->autospell[0].id ) {
struct block_list *tbl;
struct unit_data *ud;
- int i, skill_lv, type, notok;
+ int i, auto_skill_lv, type, notok;
for (i = 0; i < ARRAYLENGTH(sd->autospell) && sd->autospell[i].id; i++) {
@@ -1506,8 +1448,8 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
if ( notok )
continue;
- skill_lv = sd->autospell[i].lv?sd->autospell[i].lv:1;
- if (skill_lv < 0) skill_lv = 1+rnd()%(-skill_lv);
+ auto_skill_lv = sd->autospell[i].lv?sd->autospell[i].lv:1;
+ if (auto_skill_lv < 0) auto_skill_lv = 1+rnd()%(-auto_skill_lv);
rate = (!sd->state.arrow_atk) ? sd->autospell[i].rate : sd->autospell[i].rate / 2;
@@ -1520,18 +1462,18 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
int maxcount = 0;
if( !(BL_PC&battle_config.skill_reiteration) &&
skill->get_unit_flag(temp)&UF_NOREITERATION &&
- skill->check_unit_range(src,tbl->x,tbl->y,temp,skill_lv)
+ skill->check_unit_range(src,tbl->x,tbl->y,temp,auto_skill_lv)
) {
continue;
}
if( BL_PC&battle_config.skill_nofootset &&
skill->get_unit_flag(temp)&UF_NOFOOTSET &&
- skill->check_unit_range2(src,tbl->x,tbl->y,temp,skill_lv)
+ skill->check_unit_range2(src,tbl->x,tbl->y,temp,auto_skill_lv)
) {
continue;
}
if( BL_PC&battle_config.land_skill_limit &&
- (maxcount = skill->get_maxcount(temp, skill_lv)) > 0
+ (maxcount = skill->get_maxcount(temp, auto_skill_lv)) > 0
) {
int v;
for(v=0;v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount;v++) {
@@ -1544,7 +1486,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
}
}
if( battle_config.autospell_check_range &&
- !battle->check_range(src, tbl, skill->get_range2(src, temp,skill_lv) + (temp == RG_CLOSECONFINE?0:1)) )
+ !battle->check_range(src, tbl, skill->get_range2(src, temp,auto_skill_lv) + (temp == RG_CLOSECONFINE?0:1)) )
continue;
if (temp == AS_SONICBLOW)
@@ -1553,24 +1495,24 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
type = CAST_GROUND;
sd->state.autocast = 1;
- skill->consume_requirement(sd,temp,skill_lv,1);
+ skill->consume_requirement(sd,temp,auto_skill_lv,1);
skill->toggle_magicpower(src, temp);
switch (type) {
case CAST_GROUND:
- skill->castend_pos2(src, tbl->x, tbl->y, temp, skill_lv, tick, 0);
+ skill->castend_pos2(src, tbl->x, tbl->y, temp, auto_skill_lv, tick, 0);
break;
case CAST_NODAMAGE:
- skill->castend_nodamage_id(src, tbl, temp, skill_lv, tick, 0);
+ skill->castend_nodamage_id(src, tbl, temp, auto_skill_lv, tick, 0);
break;
case CAST_DAMAGE:
- skill->castend_damage_id(src, tbl, temp, skill_lv, tick, 0);
+ skill->castend_damage_id(src, tbl, temp, auto_skill_lv, tick, 0);
break;
}
sd->state.autocast = 0;
//Set canact delay. [Skotlex]
- ud = unit_bl2ud(src);
+ ud = unit->bl2ud(src);
if (ud) {
- rate = skill->delay_fix(src, temp, skill_lv);
+ rate = skill->delay_fix(src, temp, auto_skill_lv);
if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){
ud->canact_tick = tick+rate;
if ( battle_config.display_status_timers && sd )
@@ -1603,27 +1545,27 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
dstmd && !(tstatus->mode&MD_BOSS) &&
(rnd()%10000 < sd->bonus.classchange))
{
- struct mob_db *mob;
+ struct mob_db *monster;
int class_;
temp = 0;
do {
do {
class_ = rnd() % MAX_MOB_DB;
- } while (!mobdb_checkid(class_));
+ } while (!mob->db_checkid(class_));
rate = rnd() % 1000000;
- mob = mob_db(class_);
+ monster = mob->db(class_);
} while (
- (mob->status.mode&(MD_BOSS|MD_PLANT) || mob->summonper[0] <= rate) &&
+ (monster->status.mode&(MD_BOSS|MD_PLANT) || monster->summonper[0] <= rate) &&
(temp++) < 2000);
if (temp < 2000)
- mob_class_change(dstmd,class_);
+ mob->class_change(dstmd,class_);
}
return 0;
}
-int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint16 skill_id, unsigned int tick) {
+int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint16 skill_id, int64 tick) {
int temp, skill_lv, i, type, notok;
struct block_list *tbl;
@@ -1713,8 +1655,7 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1
return 1;
}
-
-/* Splitted off from skill->additional_effect, which is never called when the
+/* Split off from skill->additional_effect, which is never called when the
* attack skill kills the enemy. Place in this function counter status effects
* when using skills (eg: Asura's sp regen penalty, or counter-status effects
* from cards) that will take effect on the source, not the target. [Skotlex]
@@ -1722,8 +1663,7 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1
* type of skills, so not every instance of skill->additional_effect needs a call
* to this one.
*/
-int skill_counter_additional_effect (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, unsigned int tick)
-{
+int skill_counter_additional_effect(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int64 tick) {
int rate;
struct map_session_data *sd=NULL;
struct map_session_data *dstsd=NULL;
@@ -1731,47 +1671,46 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
nullpo_ret(src);
nullpo_ret(bl);
- if(skill_id > 0 && !skill_lv) return 0; // don't forget auto attacks! - celest
+ if(skill_id > 0 && !skill_lv) return 0; // don't forget auto attacks! [celest]
sd = BL_CAST(BL_PC, src);
dstsd = BL_CAST(BL_PC, bl);
- if(dstsd && attack_type&BF_WEAPON)
- { //Counter effects.
+ if(dstsd && attack_type&BF_WEAPON) {
+ //Counter effects.
enum sc_type type;
int i, time;
- for(i=0; i < ARRAYLENGTH(dstsd->addeff2) && dstsd->addeff2[i].flag; i++)
- {
+ for(i=0; i < ARRAYLENGTH(dstsd->addeff2) && dstsd->addeff2[i].flag; i++) {
rate = dstsd->addeff2[i].rate;
if (attack_type&BF_LONG)
rate+=dstsd->addeff2[i].arrow_rate;
if (!rate) continue;
- if ((dstsd->addeff2[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT))
- { //Trigger has range consideration.
+ if ((dstsd->addeff2[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT)) {
+ //Trigger has range consideration.
if((dstsd->addeff2[i].flag&ATF_LONG && !(attack_type&BF_LONG)) ||
(dstsd->addeff2[i].flag&ATF_SHORT && !(attack_type&BF_SHORT)))
continue; //Range Failed.
}
type = dstsd->addeff2[i].id;
- time = skill->get_time2(status_sc2skill(type),7);
+ time = skill->get_time2(status->sc2skill(type),7);
if (dstsd->addeff2[i].flag&ATF_TARGET)
- status_change_start(src,type,rate,7,0,0,0,time,0);
+ status->change_start(bl,src,type,rate,7,0,0,0,time,0);
- if (dstsd->addeff2[i].flag&ATF_SELF && !status_isdead(bl))
- status_change_start(bl,type,rate,7,0,0,0,time,0);
+ if (dstsd->addeff2[i].flag&ATF_SELF && !status->isdead(bl))
+ status->change_start(bl,bl,type,rate,7,0,0,0,time,0);
}
}
switch(skill_id){
case MO_EXTREMITYFIST:
- sc_start(src,SC_EXTREMITYFIST,100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,src,SC_EXTREMITYFIST,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case GS_FULLBUSTER:
- sc_start(src,SC_BLIND,2*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,src,SC_BLIND,2*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
- case HFLI_SBR44: //[orn]
+ case HFLI_SBR44: // [orn]
case HVAN_EXPLOSION:
if(src->type == BL_HOM){
TBL_HOM *hd = (TBL_HOM*)src;
@@ -1786,20 +1725,25 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
break;
}
- if(sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR &&
- rnd()%10000 < battle_config.sg_miracle_skill_ratio) //SG_MIRACLE [Komurka]
- sc_start(src,SC_MIRACLE,100,1,battle_config.sg_miracle_skill_duration);
+ if( sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
+ && rnd()%10000 < battle_config.sg_miracle_skill_ratio) // SG_MIRACLE [Komurka]
+ sc_start(src,src,SC_MIRACLE,100,1,battle_config.sg_miracle_skill_duration);
- if(sd && skill_id && attack_type&BF_MAGIC && status_isdead(bl) &&
- !(skill->get_inf(skill_id)&(INF_GROUND_SKILL|INF_SELF_SKILL)) &&
- (rate=pc->checkskill(sd,HW_SOULDRAIN))>0
- ){ //Soul Drain should only work on targetted spells [Skotlex]
- if (pc_issit(sd)) pc->setstand(sd); //Character stuck in attacking animation while 'sitting' fix. [Skotlex]
- clif->skill_nodamage(src,bl,HW_SOULDRAIN,rate,1);
- status_heal(src, 0, status_get_lv(bl)*(95+15*rate)/100, 2);
+ if( sd && skill_id && attack_type&BF_MAGIC && status->isdead(bl)
+ && !(skill->get_inf(skill_id)&(INF_GROUND_SKILL|INF_SELF_SKILL))
+ && (rate=pc->checkskill(sd,HW_SOULDRAIN)) > 0
+ ) {
+ // Soul Drain should only work on targeted spells [Skotlex]
+ if( pc_issit(sd) ) pc->setstand(sd); // Character stuck in attacking animation while 'sitting' fix. [Skotlex]
+ if( skill->get_nk(skill_id)&NK_SPLASH && skill->area_temp[1] != bl->id )
+ ;
+ else {
+ clif->skill_nodamage(src,bl,HW_SOULDRAIN,rate,1);
+ status->heal(src, 0, status->get_lv(bl)*(95+15*rate)/100, 2);
+ }
}
- if( sd && status_isdead(bl) ) {
+ if( sd && status->isdead(bl) ) {
int sp = 0, hp = 0;
if( attack_type&BF_WEAPON ) {
sp += sd->bonus.sp_gain_value;
@@ -1810,26 +1754,28 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
if( attack_type&BF_MAGIC ) {
sp += sd->bonus.magic_sp_gain_value;
hp += sd->bonus.magic_hp_gain_value;
- if( skill_id == WZ_WATERBALL ) {//(bugreport:5303)
+ if( skill_id == WZ_WATERBALL ) {// (bugreport:5303)
struct status_change *sc = NULL;
- if( ( sc = status_get_sc(src) ) ) {
- if(sc->data[SC_SOULLINK] &&
- sc->data[SC_SOULLINK]->val2 == SL_WIZARD &&
- sc->data[SC_SOULLINK]->val3 == WZ_WATERBALL)
- sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check.
+ if( ( sc = status->get_sc(src) ) ) {
+ if( sc->data[SC_SOULLINK]
+ && sc->data[SC_SOULLINK]->val2 == SL_WIZARD
+ && sc->data[SC_SOULLINK]->val3 == WZ_WATERBALL
+ )
+ sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check.
}
}
}
- if( hp || sp ) { // updated to force healing to allow healing through berserk
- status_heal(src, hp, sp, battle_config.show_hp_sp_gain ? 3 : 1);
+ if( hp || sp ) {
+ // updated to force healing to allow healing through berserk
+ status->heal(src, hp, sp, battle_config.show_hp_sp_gain ? 3 : 1);
}
}
// Trigger counter-spells to retaliate against damage causing skills.
- if(dstsd && !status_isdead(bl) && dstsd->autospell2[0].id && !(skill_id && skill->get_nk(skill_id)&NK_NO_DAMAGE)) {
+ if(dstsd && !status->isdead(bl) && dstsd->autospell2[0].id && !(skill_id && skill->get_nk(skill_id)&NK_NO_DAMAGE)) {
struct block_list *tbl;
struct unit_data *ud;
- int i, skill_id, skill_lv, rate, type, notok;
+ int i, auto_skill_id, auto_skill_lv, type, notok;
for (i = 0; i < ARRAYLENGTH(dstsd->autospell2) && dstsd->autospell2[i].id; i++) {
@@ -1838,16 +1784,16 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
dstsd->autospell2[i].flag&attack_type&BF_SKILLMASK))
continue; // one or more trigger conditions were not fulfilled
- skill_id = (dstsd->autospell2[i].id > 0) ? dstsd->autospell2[i].id : -dstsd->autospell2[i].id;
- skill_lv = dstsd->autospell2[i].lv?dstsd->autospell2[i].lv:1;
- if (skill_lv < 0) skill_lv = 1+rnd()%(-skill_lv);
+ auto_skill_id = (dstsd->autospell2[i].id > 0) ? dstsd->autospell2[i].id : -dstsd->autospell2[i].id;
+ auto_skill_lv = dstsd->autospell2[i].lv?dstsd->autospell2[i].lv:1;
+ if (auto_skill_lv < 0) auto_skill_lv = 1+rnd()%(-auto_skill_lv);
rate = dstsd->autospell2[i].rate;
if (attack_type&BF_LONG)
rate>>=1;
dstsd->state.autocast = 1;
- notok = skill->not_ok(skill_id, dstsd);
+ notok = skill->not_ok(auto_skill_id, dstsd);
dstsd->state.autocast = 0;
if ( notok )
@@ -1858,26 +1804,26 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
tbl = (dstsd->autospell2[i].id < 0) ? bl : src;
- if( (type = skill->get_casttype(skill_id)) == CAST_GROUND ) {
+ if( (type = skill->get_casttype(auto_skill_id)) == CAST_GROUND ) {
int maxcount = 0;
if( !(BL_PC&battle_config.skill_reiteration) &&
- skill->get_unit_flag(skill_id)&UF_NOREITERATION &&
- skill->check_unit_range(bl,tbl->x,tbl->y,skill_id,skill_lv)
+ skill->get_unit_flag(auto_skill_id)&UF_NOREITERATION &&
+ skill->check_unit_range(bl,tbl->x,tbl->y,auto_skill_id,auto_skill_lv)
) {
continue;
}
if( BL_PC&battle_config.skill_nofootset &&
- skill->get_unit_flag(skill_id)&UF_NOFOOTSET &&
- skill->check_unit_range2(bl,tbl->x,tbl->y,skill_id,skill_lv)
+ skill->get_unit_flag(auto_skill_id)&UF_NOFOOTSET &&
+ skill->check_unit_range2(bl,tbl->x,tbl->y,auto_skill_id,auto_skill_lv)
) {
continue;
}
if( BL_PC&battle_config.land_skill_limit &&
- (maxcount = skill->get_maxcount(skill_id, skill_lv)) > 0
+ (maxcount = skill->get_maxcount(auto_skill_id, auto_skill_lv)) > 0
) {
int v;
for(v=0;v<MAX_SKILLUNITGROUP && dstsd->ud.skillunit[v] && maxcount;v++) {
- if(dstsd->ud.skillunit[v]->skill_id == skill_id)
+ if(dstsd->ud.skillunit[v]->skill_id == auto_skill_id)
maxcount--;
}
if( maxcount == 0 ) {
@@ -1886,27 +1832,27 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
}
}
- if( !battle->check_range(src, tbl, skill->get_range2(src, skill_id,skill_lv) + (skill_id == RG_CLOSECONFINE?0:1)) && battle_config.autospell_check_range )
+ if( !battle->check_range(src, tbl, skill->get_range2(src, auto_skill_id,auto_skill_lv) + (auto_skill_id == RG_CLOSECONFINE?0:1)) && battle_config.autospell_check_range )
continue;
dstsd->state.autocast = 1;
- skill->consume_requirement(dstsd,skill_id,skill_lv,1);
+ skill->consume_requirement(dstsd,auto_skill_id,auto_skill_lv,1);
switch (type) {
case CAST_GROUND:
- skill->castend_pos2(bl, tbl->x, tbl->y, skill_id, skill_lv, tick, 0);
+ skill->castend_pos2(bl, tbl->x, tbl->y, auto_skill_id, auto_skill_lv, tick, 0);
break;
case CAST_NODAMAGE:
- skill->castend_nodamage_id(bl, tbl, skill_id, skill_lv, tick, 0);
+ skill->castend_nodamage_id(bl, tbl, auto_skill_id, auto_skill_lv, tick, 0);
break;
case CAST_DAMAGE:
- skill->castend_damage_id(bl, tbl, skill_id, skill_lv, tick, 0);
+ skill->castend_damage_id(bl, tbl, auto_skill_id, auto_skill_lv, tick, 0);
break;
}
dstsd->state.autocast = 0;
- //Set canact delay. [Skotlex]
- ud = unit_bl2ud(bl);
+ // Set canact delay. [Skotlex]
+ ud = unit->bl2ud(bl);
if (ud) {
- rate = skill->delay_fix(bl, skill_id, skill_lv);
+ rate = skill->delay_fix(bl, auto_skill_id, auto_skill_lv);
if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){
ud->canact_tick = tick+rate;
if ( battle_config.display_status_timers && dstsd )
@@ -1917,7 +1863,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
}
//Autobonus when attacked
- if( dstsd && !status_isdead(bl) && dstsd->autobonus2[0].rate && !(skill_id && skill->get_nk(skill_id)&NK_NO_DAMAGE) ) {
+ if( dstsd && !status->isdead(bl) && dstsd->autobonus2[0].rate && !(skill_id && skill->get_nk(skill_id)&NK_NO_DAMAGE) ) {
int i;
for( i = 0; i < ARRAYLENGTH(dstsd->autobonus2); i++ ) {
if( rnd()%1000 >= dstsd->autobonus2[i].rate )
@@ -1944,7 +1890,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in
const int where_list[4] = {EQP_WEAPON, EQP_ARMOR, EQP_SHIELD, EQP_HELM};
const enum sc_type scatk[4] = {SC_NOEQUIPWEAPON, SC_NOEQUIPARMOR, SC_NOEQUIPSHIELD, SC_NOEQUIPHELM};
const enum sc_type scdef[4] = {SC_PROTECTWEAPON, SC_PROTECTARMOR, SC_PROTECTSHIELD, SC_PROTECTHELM};
- struct status_change *sc = status_get_sc(bl);
+ struct status_change *sc = status->get_sc(bl);
int i,j;
TBL_PC *sd;
sd = BL_CAST(BL_PC, bl);
@@ -1986,7 +1932,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in
else if (rnd()%10000 >= rate)
where&=~where_list[i];
else if (!sd && !(status_get_mode(bl)&MD_BOSS)) //Cause Strip effect.
- sc_start(bl,scatk[i],100,0,skill->get_time(status_sc2skill(scatk[i]),1));
+ sc_start(bl,bl,scatk[i],100,0,skill->get_time(status->sc2skill(scatk[i]),1));
}
}
if (!where) //Nothing to break.
@@ -2040,8 +1986,8 @@ int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int
if (rnd()%100 >= rate)
return 0;
- sc = status_get_sc(bl);
- if (!sc || sc->option&OPTION_MADOGEAR ) //Mado Gear cannot be divested [Ind]
+ sc = status->get_sc(bl);
+ if (!sc || sc->option&OPTION_MADOGEAR ) // Mado Gear cannot be divested [Ind]
return 0;
for (i = 0; i < ARRAYLENGTH(pos); i++) {
@@ -2051,13 +1997,11 @@ int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int
if (!where) return 0;
for (i = 0; i < ARRAYLENGTH(pos); i++) {
- if (where&pos[i] && !sc_start(bl, sc_atk[i], 100, lv, time))
+ if (where&pos[i] && !sc_start(bl, bl, sc_atk[i], 100, lv, time))
where&=~pos[i];
}
return where?1:0;
}
-//Early declaration
-static int skill_area_temp[8];
/*=========================================================================
Used to knock back players, monsters, traps, etc
- 'count' is the number of squares to knock back
@@ -2071,17 +2015,17 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in
nullpo_ret(src);
- if (src != target && map[src->m].flag.noknockback)
- return 0; //No knocking
+ if (src != target && map->list[src->m].flag.noknockback)
+ return 0; // No knocking
if (count == 0)
- return 0; //Actual knockback distance is 0.
+ return 0; // Actual knockback distance is 0.
switch (target->type) {
case BL_MOB: {
struct mob_data* md = BL_CAST(BL_MOB, target);
if( md->class_ == MOBID_EMPERIUM )
return 0;
- if(src != target && is_boss(target)) //Bosses can't be knocked-back
+ if(src != target && is_boss(target)) // Bosses can't be knocked-back
return 0;
}
break;
@@ -2095,13 +2039,13 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in
break;
case BL_SKILL:
su = (struct skill_unit *)target;
- if( su && su->group && su->group->unit_id == UNT_ANKLESNARE )
+ if( su && su->group && (su->group->unit_id == UNT_ANKLESNARE || su->group->unit_id == UNT_REVERBERATION))
return 0; // ankle snare cannot be knocked back
break;
}
if (dir == -1) // <optimized>: do the computation here instead of outside
- dir = iMap->calc_dir(target, src->x, src->y); // direction from src to target, reversed
+ dir = map->calc_dir(target, src->x, src->y); // direction from src to target, reversed
if (dir >= 0 && dir < 8)
{ // take the reversed 'direction' and reverse it
@@ -2109,14 +2053,19 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in
dy = -diry[dir];
}
- return unit_blown(target, dx, dy, count, flag); // send over the proper flag
+ return unit->blown(target, dx, dy, count, flag); // send over the proper flag
}
-//Checks if 'bl' should reflect back a spell cast by 'src'.
-//type is the type of magic attack: 0: indirect (aoe), 1: direct (targetted)
+/*
+ Checks if 'bl' should reflect back a spell cast by 'src'.
+ type is the type of magic attack: 0: indirect (aoe), 1: direct (targeted)
+ In case of success returns type of reflection, otherwise 0
+ 1 - Regular reflection (Maya)
+ 2 - SL_KAITE reflection
+*/
int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type) {
- struct status_change *sc = status_get_sc(bl);
+ struct status_change *sc = status->get_sc(bl);
struct map_session_data* sd = BL_CAST(BL_PC, bl);
if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability
@@ -2136,7 +2085,7 @@ int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type)
if( sc->data[SC_MAGICMIRROR] && rnd()%100 < sc->data[SC_MAGICMIRROR]->val2 )
return 1;
- if( sc->data[SC_KAITE] && (src->type == BL_PC || status_get_lv(src) <= 80) )
+ if( sc->data[SC_KAITE] && (src->type == BL_PC || status->get_lv(src) <= 80) )
{// Kaite only works against non-players if they are low-level.
clif->specialeffect(bl, 438, AREA);
if( --sc->data[SC_KAITE]->val2 <= 0 )
@@ -2161,38 +2110,46 @@ int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type)
* flag&0x2000 is used to signal that the skill_lv should be passed as -1 to the
* client (causes player characters to not scream skill name)
*-------------------------------------------------------------------------*/
-int skill_attack (int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag)
-{
+int skill_attack(int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
struct Damage dmg;
struct status_data *sstatus, *tstatus;
struct status_change *sc;
struct map_session_data *sd, *tsd;
- int type,damage;
- int8 rmdamage=0;//magic reflected
- bool additional_effects = true;
+ int type;
+ int64 damage;
+ bool rmdamage = false;//magic reflected
+ bool additional_effects = true, shadow_flag = false;
if(skill_id > 0 && !skill_lv) return 0;
- nullpo_ret(src); //Source is the master behind the attack (player/mob/pet)
- nullpo_ret(dsrc); //dsrc is the actual originator of the damage, can be the same as src, or a skill casted by src.
+ nullpo_ret(src); // Source is the master behind the attack (player/mob/pet)
+ nullpo_ret(dsrc); // dsrc is the actual originator of the damage, can be the same as src, or a skill casted by src.
nullpo_ret(bl); //Target to be attacked.
if (src != dsrc) {
//When caster is not the src of attack, this is a ground skill, and as such, do the relevant target checking. [Skotlex]
- if (!status_check_skilluse(battle_config.skill_caster_check?src:NULL, bl, skill_id, 2))
+ if (!status->check_skilluse(battle_config.skill_caster_check?src:NULL, bl, skill_id, 2))
return 0;
} else if ((flag&SD_ANIMATION) && skill->get_nk(skill_id)&NK_SPLASH) {
- //Note that splash attacks often only check versus the targetted mob, those around the splash area normally don't get checked for being hidden/cloaked/etc. [Skotlex]
- if (!status_check_skilluse(src, bl, skill_id, 2))
+ //Note that splash attacks often only check versus the targeted mob, those around the splash area normally don't get checked for being hidden/cloaked/etc. [Skotlex]
+ if (!status->check_skilluse(src, bl, skill_id, 2))
return 0;
}
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, bl);
- sstatus = status_get_status_data(src);
- tstatus = status_get_status_data(bl);
- sc= status_get_sc(bl);
+ // To block skills that aren't called via battle_check_target [Panikon]
+ // issue: 8203
+ if( sd
+ && ( (bl->type == BL_MOB && pc_has_permission(sd, PC_PERM_DISABLE_PVM))
+ || (bl->type == BL_PC && pc_has_permission(sd, PC_PERM_DISABLE_PVP)) )
+ )
+ return 0;
+
+ sstatus = status->get_status_data(src);
+ tstatus = status->get_status_data(bl);
+ sc = status->get_sc(bl);
if (sc && !sc->count) sc = NULL; //Don't need it.
// Is this check really needed? FrostNova won't hurt you if you step right where the caster is?
@@ -2220,28 +2177,29 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
}
}
- if( dmg.flag&BF_MAGIC && ( skill_id != NPC_EARTHQUAKE || (battle_config.eq_single_target_reflectable && (flag&0xFFF) == 1) ) )
- { // Earthquake on multiple targets is not counted as a target skill. [Inkfish]
- if( (dmg.damage || dmg.damage2) && (type = skill->magic_reflect(src, bl, src==dsrc)) )
- { //Magic reflection, switch caster/target
+ if( dmg.flag&BF_MAGIC && ( skill_id != NPC_EARTHQUAKE || (battle_config.eq_single_target_reflectable && (flag&0xFFF) == 1) ) ) {
+ // Earthquake on multiple targets is not counted as a target skill. [Inkfish]
+ if( (dmg.damage || dmg.damage2) && (type = skill->magic_reflect(src, bl, src==dsrc)) ) {
+ //Magic reflection, switch caster/target
struct block_list *tbl = bl;
- rmdamage = 1;
+ rmdamage = true;
bl = src;
src = tbl;
dsrc = tbl;
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, bl);
- sc = status_get_sc(bl);
+ sc = status->get_sc(bl);
if (sc && !sc->count)
sc = NULL; //Don't need it.
/* bugreport:2564 flag&2 disables double casting trigger */
flag |= 2;
-
+ /* bugreport:7859 magical reflected zeroes blow count */
+ dmg.blewcount = 0;
//Spirit of Wizard blocks Kaite's reflection
- if( type == 2 && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_WIZARD )
- { //Consume one Fragment per hit of the casted skill? [Skotlex]
- type = tsd?pc->search_inventory (tsd, 7321):0;
- if (type >= 0) {
+ if (type == 2 && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_WIZARD) {
+ //Consume one Fragment per hit of the casted skill? [Skotlex]
+ type = tsd ? pc->search_inventory(tsd, ITEMID_FRAGMENT_OF_CRYSTAL) : 0;
+ if (type != INDEX_NOT_FOUND) {
if ( tsd ) pc->delitem(tsd, type, 1, 0, 1, LOG_TYPE_CONSUME);
dmg.damage = dmg.damage2 = 0;
dmg.dmg_lv = ATK_MISS;
@@ -2255,31 +2213,38 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
* Official Magic Reflection Behavior : damage reflected depends on gears caster wears, not target
**/
#if MAGIC_REFLECTION_TYPE
- if( dmg.dmg_lv != ATK_MISS ){ //Wiz SL cancelled and consumed fragment
+
+ #ifdef RENEWAL
+ if( dmg.dmg_lv != ATK_MISS ) // Wiz SL canceled and consumed fragment
+ #else
+ // issue:6415 in pre-renewal Kaite reflected the entire damage received
+ // regardless of caster's equipment (Aegis 11.1)
+ if( dmg.dmg_lv != ATK_MISS && type == 1 ) //Wiz SL canceled and consumed fragment
+ #endif
+ {
short s_ele = skill->get_ele(skill_id, skill_lv);
if (s_ele == -1) // the skill takes the weapon's element
s_ele = sstatus->rhw.ele;
else if (s_ele == -2) //Use status element
- s_ele = status_get_attack_sc_element(src,status_get_sc(src));
+ s_ele = status_get_attack_sc_element(src,status->get_sc(src));
else if( s_ele == -3 ) //Use random element
s_ele = rnd()%ELE_MAX;
dmg.damage = battle->attr_fix(bl, bl, dmg.damage, s_ele, status_get_element(bl), status_get_element_level(bl));
if( sc && sc->data[SC_ENERGYCOAT] ) {
- struct status_data *status = status_get_status_data(bl);
- int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval
+ struct status_data *st = status->get_status_data(bl);
+ int per = 100*st->sp / st->max_sp -1; //100% should be counted as the 80~99% interval
per /=20; //Uses 20% SP intervals.
//SP Cost: 1% + 0.5% per every 20% SP
- if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000))
+ if (!status->charge(bl, 0, (10+5*per)*st->max_sp/1000))
status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER);
//Reduction: 6% + 6% every 20%
dmg.damage -= dmg.damage * (6 * (1+per)) / 100;
}
-
}
- #endif
+ #endif /* MAGIC_REFLECTION_TYPE */
}
if(sc && sc->data[SC_MAGICROD] && src == dsrc) {
int sp = skill->get_sp(skill_id,skill_lv);
@@ -2288,7 +2253,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
sp = sp * sc->data[SC_MAGICROD]->val2 / 100;
if(skill_id == WZ_WATERBALL && skill_lv > 1)
sp = sp/((skill_lv|1)*(skill_lv|1)); //Estimate SP cost of a single water-ball
- status_heal(bl, 0, sp, 2);
+ status->heal(bl, 0, sp, 2);
}
}
@@ -2327,7 +2292,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
}
if(sd) {
- int flag = 0; //Used to signal if this skill can be combo'ed later on.
+ int combo = 0; //Used to signal if this skill can be combo'ed later on.
struct status_change_entry *sce;
if ((sce = sd->sc.data[SC_COMBOATTACK])) {//End combo state after skill is invoked. [Skotlex]
switch (skill_id) {
@@ -2339,11 +2304,11 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
sce->val1 = skill_id; //Update combo-skill
sce->val3 = skill_id;
if( sce->timer != INVALID_TIMER )
- iTimer->delete_timer(sce->timer, status_change_timer);
- sce->timer = iTimer->add_timer(tick+sce->val4, status_change_timer, src->id, SC_COMBOATTACK);
+ timer->delete(sce->timer, status->change_timer);
+ sce->timer = timer->add(tick+sce->val4, status->change_timer, src->id, SC_COMBOATTACK);
break;
}
- unit_cancel_combo(src); // Cancel combo wait
+ unit->cancel_combo(src); // Cancel combo wait
break;
default:
if( src == dsrc ) // Ground skills are exceptions. [Inkfish]
@@ -2353,29 +2318,30 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
switch(skill_id) {
case MO_TRIPLEATTACK:
if (pc->checkskill(sd, MO_CHAINCOMBO) > 0 || pc->checkskill(sd, SR_DRAGONCOMBO) > 0)
- flag=1;
+ combo=1;
break;
case MO_CHAINCOMBO:
if(pc->checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0)
- flag=1;
+ combo=1;
break;
case MO_COMBOFINISH:
if (sd->status.party_id>0) //bonus from SG_FRIEND [Komurka]
party->skill_check(sd, sd->status.party_id, MO_COMBOFINISH, skill_lv);
if (pc->checkskill(sd, CH_TIGERFIST) > 0 && sd->spiritball > 0)
- flag=1;
+ combo=1;
case CH_TIGERFIST:
- if (!flag && pc->checkskill(sd, CH_CHAINCRUSH) > 0 && sd->spiritball > 1)
- flag=1;
+ if (!combo && pc->checkskill(sd, CH_CHAINCRUSH) > 0 && sd->spiritball > 1)
+ combo=1;
case CH_CHAINCRUSH:
- if (!flag && pc->checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball > 0 && sd->sc.data[SC_EXPLOSIONSPIRITS])
- flag=1;
+ if (!combo && pc->checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball > 0 && sd->sc.data[SC_EXPLOSIONSPIRITS])
+ combo=1;
break;
case AC_DOUBLE:
- if( (tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT) && pc->checkskill(sd, HT_POWER))
- {
- //TODO: This code was taken from Triple Blows, is this even how it should be? [Skotlex]
- sc_start2(src,SC_COMBOATTACK,100,HT_POWER,bl->id,2000);
+ // AC_DOUBLE can start the combo with other monster types, but the
+ // monster that's going to be hit by HT_POWER should be RC_BRUTE or RC_INSECT [Panikon]
+ if( pc->checkskill(sd, HT_POWER) )
+ {
+ sc_start4(NULL,src,SC_COMBOATTACK,100,HT_POWER,0,1,0,2000);
clif->combo_delay(src,2000);
}
break;
@@ -2389,7 +2355,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
case SL_STIN:
case SL_STUN:
if (skill_lv >= 7 && !sd->sc.data[SC_SMA_READY])
- sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA, skill_lv));
+ sc_start(src, src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA, skill_lv));
break;
case GS_FULLBUSTER:
//Can't attack nor use items until skill's delay expires. [Skotlex]
@@ -2397,21 +2363,21 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
break;
case TK_DODGE:
if( pc->checkskill(sd, TK_JUMPKICK) > 0 )
- flag = 1;
+ combo = 1;
break;
case SR_DRAGONCOMBO:
if( pc->checkskill(sd, SR_FALLENEMPIRE) > 0 )
- flag = 1;
+ combo = 1;
break;
case SR_FALLENEMPIRE:
if( pc->checkskill(sd, SR_TIGERCANNON) > 0 || pc->checkskill(sd, SR_GATEOFHELL) > 0 )
- flag = 1;
+ combo = 1;
break;
} //Switch End
- if (flag) { //Possible to chain
- if ( (flag = DIFF_TICK(sd->ud.canact_tick, tick)) < 50 ) flag = 50;/* less is a waste. */
- sc_start2(src,SC_COMBOATTACK,100,skill_id,bl->id,flag);
- clif->combo_delay(src, flag);
+ if (combo) { //Possible to chain
+ if ( (combo = DIFF_TICK32(sd->ud.canact_tick, tick)) < 50 ) combo = 50;/* less is a waste. */
+ sc_start2(NULL,src,SC_COMBOATTACK,100,skill_id,bl->id,combo);
+ clif->combo_delay(src, combo);
}
}
@@ -2431,7 +2397,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
case NPC_CRITICALSLASH:
case TF_DOUBLE:
case GS_CHAINACTION:
- dmg.dmotion = clif->damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,dmg.type,dmg.damage2);
+ dmg.dmotion = clif->damage(src,bl,dmg.amotion,dmg.dmotion,damage,dmg.div_,dmg.type,dmg.damage2);
break;
case AS_SPLASHER:
@@ -2456,7 +2422,11 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,6);
break;
case LG_OVERBRAND_BRANDISH:
+ case LG_OVERBRAND:
+ dmg.amotion = status_get_amotion(src) * 2;
case LG_OVERBRAND_PLUSATK:
+ dmg.dmotion = clif->skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,5);
+ break;
case EL_FIRE_BOMB:
case EL_FIRE_BOMB_ATK:
case EL_FIRE_WAVE:
@@ -2473,19 +2443,26 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
case EL_ROCK_CRUSHER_ATK:
case EL_HURRICANE:
case EL_HURRICANE_ATK:
+ case EL_TYPOON_MIS:
+ case EL_TYPOON_MIS_ATK:
case KO_BAKURETSU:
- case GN_CRAZYWEED_ATK:
case NC_MAGMA_ERUPTION:
dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,5);
break;
case GN_SLINGITEM_RANGEMELEEATK:
dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,6);
break;
+ case SC_FEINTBOMB:
+ dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,skill_lv,5);
+ break;
+ case GN_CRAZYWEED_ATK:
+ dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id, -2, 6);
+ break;
case EL_STONE_RAIN:
dmg.dmotion = clif->skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?8:5);
break;
case WM_SEVERE_RAINSTORM_MELEE:
- dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,skill_lv,5);
+ dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,-2,6);
break;
case WM_REVERBERATION_MELEE:
case WM_REVERBERATION_MAGIC:
@@ -2528,7 +2505,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
break;
}
- iMap->freeblock_lock();
+ map->freeblock_lock();
if(damage > 0 && dmg.flag&BF_SKILL && tsd
&& pc->checkskill(tsd,RG_PLAGIARISM)
@@ -2537,7 +2514,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
{ //Updated to not be able to copy skills if the blow will kill you. [Skotlex]
int copy_skill = skill_id, cidx = 0;
/**
- * Copy Referal: dummy skills should point to their source upon copying
+ * Copy Referral: dummy skills should point to their source upon copying
**/
switch( skill_id ) {
case AB_DUPLELIGHT_MELEE:
@@ -2560,6 +2537,9 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
case GN_HELLS_PLANT_ATK:
copy_skill = GN_HELLS_PLANT;
break;
+ case GN_SLINGITEM_RANGEMELEEATK:
+ copy_skill = GN_SLINGITEM;
+ break;
case LG_OVERBRAND_BRANDISH:
case LG_OVERBRAND_PLUSATK:
copy_skill = LG_OVERBRAND;
@@ -2585,8 +2565,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
}
tsd->reproduceskill_id = copy_skill;
- pc_setglobalreg(tsd, "REPRODUCE_SKILL", copy_skill);
- pc_setglobalreg(tsd, "REPRODUCE_SKILL_LV", lv);
+ pc_setglobalreg(tsd, script->add_str("REPRODUCE_SKILL"), copy_skill);
+ pc_setglobalreg(tsd, script->add_str("REPRODUCE_SKILL_LV"), lv);
tsd->status.skill[cidx].id = copy_skill;
tsd->status.skill[cidx].lv = lv;
@@ -2608,8 +2588,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
lv = type;
tsd->cloneskill_id = copy_skill;
- pc_setglobalreg(tsd, "CLONE_SKILL", copy_skill);
- pc_setglobalreg(tsd, "CLONE_SKILL_LV", lv);
+ pc_setglobalreg(tsd, script->add_str("CLONE_SKILL"), copy_skill);
+ pc_setglobalreg(tsd, script->add_str("CLONE_SKILL_LV"), lv);
tsd->status.skill[cidx].id = copy_skill;
tsd->status.skill[cidx].lv = lv;
@@ -2622,76 +2602,74 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
if (dmg.dmg_lv >= ATK_MISS && (type = skill->get_walkdelay(skill_id, skill_lv)) > 0) {
//Skills with can't walk delay also stop normal attacking for that
//duration when the attack connects. [Skotlex]
- struct unit_data *ud = unit_bl2ud(src);
+ struct unit_data *ud = unit->bl2ud(src);
if (ud && DIFF_TICK(ud->attackabletime, tick + type) < 0)
ud->attackabletime = tick + type;
}
+
+ shadow_flag = skill->check_shadowform(bl, damage, dmg.div_);
if( !dmg.amotion ) {
//Instant damage
- if( !sc || (!sc->data[SC_DEVOTION] && skill_id != CR_REFLECTSHIELD) )
+ if( (!sc || (!sc->data[SC_DEVOTION] && skill_id != CR_REFLECTSHIELD)) && !shadow_flag)
status_fix_damage(src,bl,damage,dmg.dmotion); //Deal damage before knockback to allow stuff like firewall+storm gust combo.
- if( !status_isdead(bl) && additional_effects )
+ if( !status->isdead(bl) && additional_effects )
skill->additional_effect(src,bl,skill_id,skill_lv,dmg.flag,dmg.dmg_lv,tick);
if( damage > 0 ) //Counter status effects [Skotlex]
skill->counter_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,tick);
}
// Hell Inferno burning status only starts if Fire part hits.
if( skill_id == WL_HELLINFERNO && dmg.damage > 0 && !(flag&ELE_DARK) )
- sc_start4(bl,SC_BURNING,55+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv));
+ sc_start4(src,bl,SC_BURNING,55+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv));
// Apply knock back chance in SC_TRIANGLESHOT skill.
else if( skill_id == SC_TRIANGLESHOT && rnd()%100 > (1 + skill_lv) )
dmg.blewcount = 0;
//Only knockback if it's still alive, otherwise a "ghost" is left behind. [Skotlex]
//Reflected spells do not bounce back (bl == dsrc since it only happens for direct skills)
- if (dmg.blewcount > 0 && bl!=dsrc && !status_isdead(bl)) {
+ if (dmg.blewcount > 0 && bl!=dsrc && !status->isdead(bl)) {
int8 dir = -1; // default
switch(skill_id) {//direction
case MG_FIREWALL:
case PR_SANCTUARY:
case SC_TRIANGLESHOT:
- case LG_OVERBRAND:
case SR_KNUCKLEARROW:
case GN_WALLOFTHORN:
case EL_FIRE_MANTLE:
- dir = unit_getdir(bl);// backwards
+ dir = unit->getdir(bl);// backwards
break;
// This ensures the storm randomly pushes instead of exactly a cell backwards per official mechanics.
case WZ_STORMGUST:
- dir = rand()%8;
+ dir = rnd()%8;
break;
case WL_CRIMSONROCK:
- dir = iMap->calc_dir(bl,skill_area_temp[4],skill_area_temp[5]);
+ dir = map->calc_dir(bl,skill->area_temp[4],skill->area_temp[5]);
+ break;
+ case MC_CARTREVOLUTION:
+ dir = 6; // Official servers push target to the West
break;
}
+
+ /* monsters with skill lv higher than MAX_SKILL_LEVEL may get this value beyond the max depending on conditions, we cap to the system's limit */
+ if( dsrc && dsrc->type == BL_MOB && skill_lv > MAX_SKILL_LEVEL && dmg.blewcount > 25 )
+ dmg.blewcount = 25;
+
//blown-specific handling
switch( skill_id ) {
- case LG_OVERBRAND:
- if( skill->blown(dsrc,bl,dmg.blewcount,dir,0) ) {
- short dir_x, dir_y;
- dir_x = dirx[(dir+4)%8];
- dir_y = diry[(dir+4)%8];
- if( iMap->getcell(bl->m, bl->x+dir_x, bl->y+dir_y, CELL_CHKNOPASS) != 0 )
- skill->addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skill_lv, BF_WEAPON, flag );
- } else
- skill->addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skill_lv, BF_WEAPON, flag );
+ case LG_OVERBRAND_BRANDISH:
+ if( skill->blown(dsrc,bl,dmg.blewcount,dir,0) < dmg.blewcount )
+ skill->addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skill_lv, BF_WEAPON, flag|SD_ANIMATION);
break;
case SR_KNUCKLEARROW:
if( skill->blown(dsrc,bl,dmg.blewcount,dir,0) && !(flag&4) ) {
short dir_x, dir_y;
dir_x = dirx[(dir+4)%8];
dir_y = diry[(dir+4)%8];
- if( iMap->getcell(bl->m, bl->x+dir_x, bl->y+dir_y, CELL_CHKNOPASS) != 0 )
+ if( map->getcell(bl->m, bl->x+dir_x, bl->y+dir_y, CELL_CHKNOPASS) != 0 )
skill->addtimerskill(src, tick + 300 * ((flag&2) ? 1 : 2), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|4);
}
break;
- case GN_WALLOFTHORN:
- unit_stop_walking(bl,1);
- skill->blown(dsrc,bl,dmg.blewcount,dir, 0x2 );
- clif->fixpos(bl);
- break;
default:
skill->blown(dsrc,bl,dmg.blewcount,dir, 0x0 );
if ( !dmg.blewcount && bl->type == BL_SKILL && damage > 0 ){
@@ -2704,12 +2682,19 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
}
//Delayed damage must be dealt after the knockback (it needs to know actual position of target)
- if (dmg.amotion)
- battle->delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion, additional_effects);
+ if (dmg.amotion){
+ if( shadow_flag ){
+ if( !status->isdead(bl) && additional_effects )
+ skill->additional_effect(src,bl,skill_id,skill_lv,dmg.flag,dmg.dmg_lv,tick);
+ if( dmg.flag > ATK_BLOCK )
+ skill->counter_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,tick);
+ }else
+ battle->delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion, additional_effects);
+ }
if( sc && sc->data[SC_DEVOTION] && skill_id != PA_PRESSURE ) {
struct status_change_entry *sce = sc->data[SC_DEVOTION];
- struct block_list *d_bl = iMap->id2bl(sce->val1);
+ struct block_list *d_bl = map->id2bl(sce->val1);
if( d_bl && (
(d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == bl->id) ||
@@ -2717,12 +2702,12 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
) && check_distance_bl(bl, d_bl, sce->val3) )
{
if(!rmdamage){
- clif->damage(d_bl,d_bl, iTimer->gettick(), 0, 0, damage, 0, 0, 0);
+ clif->damage(d_bl,d_bl, 0, 0, damage, 0, 0, 0);
status_fix_damage(NULL,d_bl, damage, 0);
} else{ //Reflected magics are done directly on the target not on paladin
//This check is only for magical skill.
//For BF_WEAPON skills types track var rdamage and function battle_calc_return_damage
- clif->damage(bl,bl, iTimer->gettick(), 0, 0, damage, 0, 0, 0);
+ clif->damage(bl,bl, 0, 0, damage, 0, 0, 0);
status_fix_damage(bl,bl, damage, 0);
}
}
@@ -2736,11 +2721,11 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
if(damage > 0 && !(tstatus->mode&MD_BOSS)) {
if( skill_id == RG_INTIMIDATE ) {
int rate = 50 + skill_lv * 5;
- rate = rate + (status_get_lv(src) - status_get_lv(bl));
+ rate = rate + (status->get_lv(src) - status->get_lv(bl));
if(rnd()%100 < rate)
skill->addtimerskill(src,tick + 800,bl->id,0,0,skill_id,skill_lv,0,flag);
} else if( skill_id == SC_FATALMENACE )
- skill->addtimerskill(src,tick + 800,bl->id,skill_area_temp[4],skill_area_temp[5],skill_id,skill_lv,0,flag);
+ skill->addtimerskill(src,tick + 800,bl->id,skill->area_temp[4],skill->area_temp[5],skill_id,skill_lv,0,flag);
}
if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS)
@@ -2761,17 +2746,18 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
* Post-damage effects
**/
switch( skill_id ) {
- case RK_CRUSHSTRIKE:
- skill->break_equip(src,EQP_WEAPON,2000,BCT_SELF); // 20% chance to destroy the weapon.
- break;
- case GC_VENOMPRESSURE: {
- struct status_change *ssc = status_get_sc(src);
- if( ssc && ssc->data[SC_POISONINGWEAPON] && rnd()%100 < 70 + 5*skill_lv ) {
- sc_start(bl,ssc->data[SC_POISONINGWEAPON]->val2,100,ssc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON, 1));
- status_change_end(src,SC_POISONINGWEAPON,INVALID_TIMER);
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- }
+ case GC_VENOMPRESSURE:
+ {
+ struct status_change *ssc = status->get_sc(src);
+ if( ssc && ssc->data[SC_POISONINGWEAPON] && rnd()%100 < 70 + 5*skill_lv ) {
+ short rate = 100;
+ if ( ssc->data[SC_POISONINGWEAPON]->val1 == 9 )// Oblivion Curse gives a 2nd success chance after the 1st one passes which is reducible. [Rytech]
+ rate = 100 - tstatus->int_ * 4 / 5;
+ sc_start(src, bl,ssc->data[SC_POISONINGWEAPON]->val2,rate,ssc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000);
+ status_change_end(src,SC_POISONINGWEAPON,-1);
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
}
+ }
break;
case WM_METALICSOUND:
status_zap(bl, 0, damage*100/(100*(110-pc->checkskill(sd,WM_LESSON)*10)));
@@ -2784,52 +2770,49 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
skill->onskillusage(sd, bl, skill_id, tick);
}
- if (!(flag&2) &&
- (
- skill_id == MG_COLDBOLT || skill_id == MG_FIREBOLT || skill_id == MG_LIGHTNINGBOLT
- ) &&
- (sc = status_get_sc(src)) &&
- sc->data[SC_DOUBLECASTING] &&
- rnd() % 100 < sc->data[SC_DOUBLECASTING]->val2)
- {
-// skill->addtimerskill(src, tick + dmg.div_*dmg.amotion, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag|2);
+ if (!(flag&2)
+ && (skill_id == MG_COLDBOLT || skill_id == MG_FIREBOLT || skill_id == MG_LIGHTNINGBOLT)
+ && (sc = status->get_sc(src))
+ && sc->data[SC_DOUBLECASTING]
+ && rnd() % 100 < sc->data[SC_DOUBLECASTING]->val2
+ ) {
+ //skill->addtimerskill(src, tick + dmg.div_*dmg.amotion, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag|2);
skill->addtimerskill(src, tick + dmg.amotion, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag|2);
}
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
- return damage;
+ return (int)cap_value(damage,INT_MIN,INT_MAX);
}
/*==========================================
- * sub fonction for recursive skill call.
- * Checking bl battle flag and display dammage
+ * sub function for recursive skill call.
+ * Checking bl battle flag and display damage
* then call func with source,target,skill_id,skill_lv,tick,flag
*------------------------------------------*/
-typedef int (*SkillFunc)(struct block_list *, struct block_list *, int, int, unsigned int, int);
-int skill_area_sub (struct block_list *bl, va_list ap) {
+int skill_area_sub(struct block_list *bl, va_list ap) {
struct block_list *src;
uint16 skill_id,skill_lv;
int flag;
- unsigned int tick;
+ int64 tick;
SkillFunc func;
nullpo_ret(bl);
- src=va_arg(ap,struct block_list *);
- skill_id=va_arg(ap,int);
- skill_lv=va_arg(ap,int);
- tick=va_arg(ap,unsigned int);
- flag=va_arg(ap,int);
- func=va_arg(ap,SkillFunc);
+ src = va_arg(ap,struct block_list *);
+ skill_id = va_arg(ap,int);
+ skill_lv = va_arg(ap,int);
+ tick = va_arg(ap,int64);
+ flag = va_arg(ap,int);
+ func = va_arg(ap,SkillFunc);
if(battle->check_target(src,bl,flag) > 0) {
// several splash skills need this initial dummy packet to display correctly
- if (flag&SD_PREAMBLE && skill_area_temp[2] == 0)
+ if (flag&SD_PREAMBLE && skill->area_temp[2] == 0)
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
if (flag&(SD_SPLASH|SD_PREAMBLE))
- skill_area_temp[2]++;
+ skill->area_temp[2]++;
return func(src,bl,skill_id,skill_lv,tick,flag);
}
@@ -2837,26 +2820,27 @@ int skill_area_sub (struct block_list *bl, va_list ap) {
}
int skill_check_unit_range_sub (struct block_list *bl, va_list ap) {
- struct skill_unit *unit;
+ struct skill_unit *su;
uint16 skill_id,g_skill_id;
- unit = (struct skill_unit *)bl;
+ su = (struct skill_unit *)bl;
if(bl->prev == NULL || bl->type != BL_SKILL)
return 0;
- if(!unit->alive)
+ if(!su->alive)
return 0;
skill_id = va_arg(ap,int);
- g_skill_id = unit->group->skill_id;
+ g_skill_id = su->group->skill_id;
switch (skill_id) {
case MH_STEINWAND:
case MG_SAFETYWALL:
case AL_PNEUMA:
case SC_MAELSTROM:
- if(g_skill_id != MH_STEINWAND && g_skill_id != MG_SAFETYWALL && g_skill_id != AL_PNEUMA && g_skill_id != SC_MAELSTROM)
+ case SO_ELEMENTAL_SHIELD:
+ if(g_skill_id != MH_STEINWAND && g_skill_id != MG_SAFETYWALL && g_skill_id != AL_PNEUMA && g_skill_id != SC_MAELSTROM && g_skill_id != SO_ELEMENTAL_SHIELD)
return 0;
break;
case AL_WARP:
@@ -2885,6 +2869,8 @@ int skill_check_unit_range_sub (struct block_list *bl, va_list ap) {
case RA_ICEBOUNDTRAP:
case SC_DIMENSIONDOOR:
case SC_BLOODYLUST:
+ case SC_CHAOSPANIC:
+ case GN_HELLS_PLANT:
//Non stackable on themselves and traps (including venom dust which does not has the trap inf2 set)
if (skill_id != g_skill_id && !(skill->get_inf2(g_skill_id)&INF2_TRAP) && g_skill_id != AS_VENOMDUST && g_skill_id != MH_POISON_MIST)
return 0;
@@ -2908,7 +2894,7 @@ int skill_check_unit_range (struct block_list *bl, int x, int y, uint16 skill_id
}
range += layout_type;
- return iMap->foreachinarea(skill->check_unit_range_sub,bl->m,x-range,y-range,x+range,y+range,BL_SKILL,skill_id);
+ return map->foreachinarea(skill->check_unit_range_sub,bl->m,x-range,y-range,x+range,y+range,BL_SKILL,skill_id);
}
int skill_check_unit_range2_sub (struct block_list *bl, va_list ap) {
@@ -2919,7 +2905,7 @@ int skill_check_unit_range2_sub (struct block_list *bl, va_list ap) {
skill_id = va_arg(ap,int);
- if( status_isdead(bl) && skill_id != AL_WARP )
+ if( status->isdead(bl) && skill_id != AL_WARP )
return 0;
if( skill_id == HP_BASILICA && bl->type == BL_PC )
@@ -2937,6 +2923,12 @@ int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_i
case WZ_ICEWALL:
range = 2;
break;
+ case SC_MANHOLE:
+ range = 0;
+ break;
+ case GN_HELLS_PLANT:
+ range = 0;
+ break;
default: {
int layout_type = skill->get_unit_layout_type(skill_id,skill_lv);
if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) {
@@ -2955,27 +2947,9 @@ int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_i
else
type = BL_PC;
- return iMap->foreachinarea(skill->check_unit_range2_sub, bl->m,
- x - range, y - range, x + range, y + range,
- type, skill_id);
-}
-
-int skill_guildaura_sub (struct map_session_data* sd, int id, int strvit, int agidex)
-{
- if(id == sd->bl.id && battle_config.guild_aura&16)
- return 0; // Do not affect guild leader
-
- if (sd->sc.data[SC_GUILDAURA]) {
- struct status_change_entry *sce = sd->sc.data[SC_GUILDAURA];
- if( sce->val3 != strvit || sce->val4 != agidex ) {
- sce->val3 = strvit;
- sce->val4 = agidex;
- status_calc_bl(&sd->bl, status_sc2scb_flag(SC_GUILDAURA));
- }
- return 0;
- }
- sc_start4(&sd->bl, SC_GUILDAURA,100, 1, id, strvit, agidex, 1000);
- return 1;
+ return map->foreachinarea(skill->check_unit_range2_sub, bl->m,
+ x - range, y - range, x + range, y + range,
+ type, skill_id);
}
/*==========================================
@@ -2985,7 +2959,7 @@ int skill_guildaura_sub (struct map_session_data* sd, int id, int strvit, int ag
* &2: picked menu entry (Warp Portal, Teleport and other menu based skills)
*------------------------------------------*/
int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, int type) {
- struct status_data *status;
+ struct status_data *st;
struct map_session_data *sd = NULL;
int i, hp, sp, hp_rate, sp_rate, state, mhp;
uint16 idx;
@@ -2995,39 +2969,38 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
return 0;
nullpo_ret(bl);
- switch( bl->type )
- {
+ switch( bl->type ) {
case BL_HOM: sd = ((TBL_HOM*)bl)->master; break;
case BL_MER: sd = ((TBL_MER*)bl)->master; break;
}
- status = status_get_status_data(bl);
+ st = status->get_status_data(bl);
if( (idx = skill->get_index(skill_id)) == 0 )
return 0;
- // Requeriments
+ // Requirements
for( i = 0; i < ARRAYLENGTH(itemid); i++ )
{
- itemid[i] = skill_db[idx].itemid[i];
- amount[i] = skill_db[idx].amount[i];
- }
- hp = skill_db[idx].hp[lv-1];
- sp = skill_db[idx].sp[lv-1];
- hp_rate = skill_db[idx].hp_rate[lv-1];
- sp_rate = skill_db[idx].sp_rate[lv-1];
- state = skill_db[idx].state;
- if( (mhp = skill_db[idx].mhp[lv-1]) > 0 )
- hp += (status->max_hp * mhp) / 100;
+ itemid[i] = skill->db[idx].itemid[i];
+ amount[i] = skill->db[idx].amount[i];
+ }
+ hp = skill->db[idx].hp[lv-1];
+ sp = skill->db[idx].sp[lv-1];
+ hp_rate = skill->db[idx].hp_rate[lv-1];
+ sp_rate = skill->db[idx].sp_rate[lv-1];
+ state = skill->db[idx].state;
+ if( (mhp = skill->db[idx].mhp[lv-1]) > 0 )
+ hp += (st->max_hp * mhp) / 100;
if( hp_rate > 0 )
- hp += (status->hp * hp_rate) / 100;
+ hp += (st->hp * hp_rate) / 100;
else
- hp += (status->max_hp * (-hp_rate)) / 100;
+ hp += (st->max_hp * (-hp_rate)) / 100;
if( sp_rate > 0 )
- sp += (status->sp * sp_rate) / 100;
+ sp += (st->sp * sp_rate) / 100;
else
- sp += (status->max_sp * (-sp_rate)) / 100;
+ sp += (st->max_sp * (-sp_rate)) / 100;
- if( bl->type == BL_HOM ) { // Intimacy Requeriments
+ if( bl->type == BL_HOM ) { // Intimacy Requirements
struct homun_data *hd = BL_CAST(BL_HOM, bl);
switch( skill_id ) {
case HFLI_SBR44:
@@ -3042,11 +3015,11 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
}
if( !(type&2) ) {
- if( hp > 0 && status->hp <= (unsigned int)hp ) {
+ if( hp > 0 && st->hp <= (unsigned int)hp ) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_HP_INSUFFICIENT, 0);
return 0;
}
- if( sp > 0 && status->sp <= (unsigned int)sp ) {
+ if( sp > 0 && st->sp <= (unsigned int)sp ) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SP_INSUFFICIENT, 0);
return 0;
}
@@ -3055,7 +3028,7 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
if( !type )
switch( state ) {
case ST_MOVE_ENABLE:
- if( !unit_can_move(bl) ) {
+ if( !unit->can_move(bl) ) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
return 0;
}
@@ -3065,22 +3038,20 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
return 1;
// Check item existences
- for( i = 0; i < ARRAYLENGTH(itemid); i++ )
- {
- index[i] = -1;
- if( itemid[i] < 1 ) continue; // No item
+ for (i = 0; i < ARRAYLENGTH(itemid); i++) {
+ index[i] = INDEX_NOT_FOUND;
+ if (itemid[i] < 1) continue; // No item
index[i] = pc->search_inventory(sd, itemid[i]);
- if( index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i] )
- {
+ if (index[i] == INDEX_NOT_FOUND || sd->status.inventory[index[i]].amount < amount[i]) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_NEED_ITEM, amount[i]|(itemid[i] << 16));
return 0;
}
}
// Consume items
- for( i = 0; i < ARRAYLENGTH(itemid); i++ )
- {
- if( index[i] >= 0 ) pc->delitem(sd, index[i], amount[i], 0, 1, LOG_TYPE_CONSUME);
+ for (i = 0; i < ARRAYLENGTH(itemid); i++) {
+ if (index[i] != INDEX_NOT_FOUND)
+ pc->delitem(sd, index[i], amount[i], 0, 1, LOG_TYPE_CONSUME);
}
if( type&2 )
@@ -3095,16 +3066,16 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv,
/*==========================================
* what the hell it doesn't need to receive this many params, it doesn't do anything ~_~
*------------------------------------------*/
-int skill_area_sub_count (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) {
+int skill_area_sub_count(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
return 1;
}
/*==========================================
*
*------------------------------------------*/
-int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) {
- struct block_list *src = iMap->id2bl(id),*target;
- struct unit_data *ud = unit_bl2ud(src);
+int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
+ struct block_list *src = map->id2bl(id),*target;
+ struct unit_data *ud = unit->bl2ud(src);
struct skill_timerskill *skl;
int range;
@@ -3118,7 +3089,7 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) {
if(src->prev == NULL)
break; // Source not on Map
if(skl->target_id) {
- target = iMap->id2bl(skl->target_id);
+ target = map->id2bl(skl->target_id);
if( ( skl->skill_id == RG_INTIMIDATE || skl->skill_id == SC_FATALMENACE ) && (!target || target->prev == NULL || !check_distance_bl(src,target,AREA_SIZE)) )
target = src; //Required since it has to warp.
if(target == NULL)
@@ -3127,42 +3098,61 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) {
break; // Target not on Map
if(src->m != target->m)
break; // Different Maps
- if(status_isdead(src))
- break; // Caster is Dead
- if(status_isdead(target) && skl->skill_id != RG_INTIMIDATE && skl->skill_id != WZ_WATERBALL)
+ if(status->isdead(src)){
+ // Exceptions
+ switch(skl->skill_id){
+ case WL_CHAINLIGHTNING_ATK:
+ case WL_TETRAVORTEX_FIRE:
+ case WL_TETRAVORTEX_WATER:
+ case WL_TETRAVORTEX_WIND:
+ case WL_TETRAVORTEX_GROUND:
+ // SR_FLASHCOMBO
+ case SR_DRAGONCOMBO:
+ case SR_FALLENEMPIRE:
+ case SR_TIGERCANNON:
+ case SR_SKYNETBLOW:
+ break;
+ default:
+ continue; // Caster is Dead
+ }
+ }
+ if(status->isdead(target) && skl->skill_id != RG_INTIMIDATE && skl->skill_id != WZ_WATERBALL)
break;
switch(skl->skill_id) {
case RG_INTIMIDATE:
- if (unit_warp(src,-1,-1,-1,CLR_TELEPORT) == 0) {
+ if (unit->warp(src,-1,-1,-1,CLR_TELEPORT) == 0) {
short x,y;
- iMap->search_freecell(src, 0, &x, &y, 1, 1, 0);
- if (target != src && !status_isdead(target))
- unit_warp(target, -1, x, y, CLR_TELEPORT);
+ map->search_freecell(src, 0, &x, &y, 1, 1, 0);
+ if (target != src && !status->isdead(target))
+ unit->warp(target, -1, x, y, CLR_TELEPORT);
}
break;
case BA_FROSTJOKER:
case DC_SCREAM:
range= skill->get_splash(skl->skill_id, skl->skill_lv);
- iMap->foreachinarea(skill->frostjoke_scream,skl->map,skl->x-range,skl->y-range,
- skl->x+range,skl->y+range,BL_CHAR,src,skl->skill_id,skl->skill_lv,tick);
+ map->foreachinarea(skill->frostjoke_scream,skl->map,skl->x-range,skl->y-range,
+ skl->x+range,skl->y+range,BL_CHAR,src,skl->skill_id,skl->skill_lv,tick);
+ break;
+ case KN_AUTOCOUNTER:
+ clif->skill_nodamage(src,target,skl->skill_id,skl->skill_lv,1);
break;
case NPC_EARTHQUAKE:
if( skl->type > 1 )
skill->addtimerskill(src,tick+250,src->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag);
- skill_area_temp[0] = iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, src, skl->skill_id, skl->skill_lv, tick, BCT_ENEMY, skill->area_sub_count);
- skill_area_temp[1] = src->id;
- skill_area_temp[2] = 0;
- iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skl->skill_id, skl->skill_lv), splash_target(src), src, skl->skill_id, skl->skill_lv, tick, skl->flag, skill->castend_damage_id);
+ skill->area_temp[0] = map->foreachinrange(skill->area_sub, src, skill->get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, src, skl->skill_id, skl->skill_lv, tick, BCT_ENEMY, skill->area_sub_count);
+ skill->area_temp[1] = src->id;
+ skill->area_temp[2] = 0;
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skl->skill_id, skl->skill_lv), splash_target(src), src, skl->skill_id, skl->skill_lv, tick, skl->flag, skill->castend_damage_id);
break;
case WZ_WATERBALL:
skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify
- if (!status_isdead(target))
+ if (!status->isdead(target))
skill->attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
- if (skl->type>1 && !status_isdead(target) && !status_isdead(src)) {
+ if (skl->type>1 && !status->isdead(target) && !status->isdead(src)) {
skill->addtimerskill(src,tick+125,target->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag);
} else {
- struct status_change *sc = status_get_sc(src);
+ struct status_change *sc = status->get_sc(src);
if(sc) {
if(sc->data[SC_SOULLINK] &&
sc->data[SC_SOULLINK]->val2 == SL_WIZARD &&
@@ -3185,7 +3175,7 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) {
BL_CHAR|BL_SKILL, target->id); // Search for a new Target around current one...
if( nbl == NULL)
skl->x++;
- else
+ else
skl->x = 0;
skill->addtimerskill(src, tick + 651, (nbl?nbl:target)->id, skl->x, 0, WL_CHAINLIGHTNING_ATK, skl->skill_lv, skl->type + 1, skl->flag);
@@ -3197,25 +3187,25 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) {
case WL_TETRAVORTEX_WIND:
case WL_TETRAVORTEX_GROUND:
clif->skill_nodamage(src, target, skl->skill_id, skl->skill_lv, 1);
- skill_attack(BF_MAGIC, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag);
+ skill->attack(BF_MAGIC, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag);
skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify
- if( skl->type == 4 ){
+ if( skl->type == 4 ){
const enum sc_type scs[] = { SC_BURNING, SC_BLOODING, SC_FROSTMISTY, SC_STUN }; // status inflicts are depend on what summoned element is used.
int rate = skl->y, index = skl->x-1;
- sc_start2(target, scs[index], rate, skl->skill_lv, src->id, skill->get_time(WL_TETRAVORTEX,index));
+ sc_start2(src,target, scs[index], rate, skl->skill_lv, src->id, skill->get_time(WL_TETRAVORTEX,index+1));
}
break;
case WM_REVERBERATION_MELEE:
case WM_REVERBERATION_MAGIC:
- skill->castend_damage_id(src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL); // damage should split among targets
+ skill->attack(skill->get_type(skl->skill_id),src, src, target, skl->skill_id, skl->skill_lv, 0, SD_LEVEL);
break;
case SC_FATALMENACE:
if( src == target ) // Casters Part
- unit_warp(src, -1, skl->x, skl->y, 3);
+ unit->warp(src, -1, skl->x, skl->y, CLR_TELEPORT);
else { // Target's Part
short x = skl->x, y = skl->y;
- iMap->search_freecell(NULL, target->m, &x, &y, 2, 2, 1);
- unit_warp(target,-1,x,y,3);
+ map->search_freecell(NULL, target->m, &x, &y, 2, 2, 1);
+ unit->warp(target,-1,x,y,CLR_TELEPORT);
}
break;
case LG_MOONSLASHER:
@@ -3229,38 +3219,55 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) {
}
}
break;
- case LG_OVERBRAND_BRANDISH:
- case LG_OVERBRAND_PLUSATK:
case SR_KNUCKLEARROW:
skill->attack(BF_WEAPON, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL);
break;
case GN_SPORE_EXPLOSION:
- iMap->foreachinrange(skill->area_sub, target, skill->get_splash(skl->skill_id, skl->skill_lv), BL_CHAR,
- src, skl->skill_id, skl->skill_lv, 0, skl->flag|1|BCT_ENEMY, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, target, skill->get_splash(skl->skill_id, skl->skill_lv), BL_CHAR,
+ src, skl->skill_id, skl->skill_lv, (int64)0, skl->flag|1|BCT_ENEMY, skill->castend_damage_id);
break;
- case SR_FLASHCOMBO_ATK_STEP1:
- case SR_FLASHCOMBO_ATK_STEP2:
- case SR_FLASHCOMBO_ATK_STEP3:
- case SR_FLASHCOMBO_ATK_STEP4:
- if( src->type == BL_PC ) {
- struct map_session_data *sd = NULL;
- const enum e_skill combos[] = {SR_DRAGONCOMBO, SR_FALLENEMPIRE, SR_TIGERCANNON, SR_SKYNETBLOW};
- if( (sd = ((TBL_PC*)src)) ){
- uint16 cid = combos[skl->skill_id-SR_FLASHCOMBO_ATK_STEP1];
- skill->castend_damage_id(src, target, cid, pc->checkskill(sd, cid), tick, 0);
- }
+ // SR_FLASHCOMBO
+ case SR_DRAGONCOMBO:
+ case SR_FALLENEMPIRE:
+ case SR_TIGERCANNON:
+ case SR_SKYNETBLOW:
+ {
+ struct map_session_data *sd = NULL;
+
+ if( src->type == BL_PC && (sd = ((TBL_PC*)src)) ) {
+ if( distance_xy(src->x, src->y, target->x, target->y) >= 3 )
+ break;
+
+ skill->castend_damage_id(src, target, skl->skill_id, pc->checkskill(sd, skl->skill_id), tick, 0);
+ }
+ break;
+ }
+ case SC_ESCAPE:
+ if( skl->type < 4+skl->skill_lv ){
+ clif->skill_damage(src,src,tick,0,0,-30000,1,skl->skill_id,skl->skill_lv,5);
+ skill->blown(src,src,1,unit->getdir(src),0);
+ skill->addtimerskill(src,tick+80,src->id,0,0,skl->skill_id,skl->skill_lv,skl->type+1,0);
}
break;
+ case RK_HUNDREDSPEAR:
+ if(src->type == BL_PC) {
+ int skill_lv = pc->checkskill((TBL_PC *)src, KN_SPEARBOOMERANG);
+ if(skill_lv > 0)
+ skill->attack(BF_WEAPON, src, src, target, KN_SPEARBOOMERANG, skill_lv, tick, skl->flag);
+ } else
+ skill->attack(BF_WEAPON, src, src, target, KN_SPEARBOOMERANG, 1, tick, skl->flag);
+ break;
case CH_PALMSTRIKE:
- {
- struct status_change* tsc = status_get_sc(target);
- struct status_change* sc = status_get_sc(src);
- if( ( tsc && tsc->option&OPTION_HIDE ) ||
- ( sc && sc->option&OPTION_HIDE ) ){
- skill->blown(src,target,skill->get_blewcount(skl->skill_id, skl->skill_lv), -1, 0x0 );
- break;
- }
+ {
+ struct status_change* tsc = status->get_sc(target);
+ struct status_change* sc = status->get_sc(src);
+ if( (tsc && tsc->option&OPTION_HIDE)
+ || (sc && sc->option&OPTION_HIDE)
+ ) {
+ skill->blown(src,target,skill->get_blewcount(skl->skill_id, skl->skill_lv), -1, 0x0 );
+ break;
}
+ }
default:
skill->attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
break;
@@ -3272,48 +3279,56 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) {
case WZ_METEOR:
if( skl->type >= 0 ) {
int x = skl->type>>16, y = skl->type&0xFFFF;
- if( path_search_long(NULL, src->m, src->x, src->y, x, y, CELL_CHKWALL) )
+ if( path->search_long(NULL, src->m, src->x, src->y, x, y, CELL_CHKWALL) )
skill->unitsetting(src,skl->skill_id,skl->skill_lv,x,y,skl->flag);
- if( path_search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
+ if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
clif->skill_poseffect(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,tick);
}
- else if( path_search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
+ else if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
skill->unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,skl->flag);
break;
- case GN_CRAZYWEED_ATK: {
- int dummy = 1, i = skill->get_unit_range(skl->skill_id,skl->skill_lv);
- iMap->foreachinarea(skill->cell_overlap, src->m, skl->x-i, skl->y-i, skl->x+i, skl->y+i, BL_SKILL, skl->skill_id, &dummy, src);
- }
+ // fall through ...
case WL_EARTHSTRAIN:
skill->unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,(skl->type<<16)|skl->flag);
break;
-
+ case LG_OVERBRAND_BRANDISH:
+ skill->area_temp[1] = 0;
+ map->foreachinpath(skill->attack_area,src->m,src->x,src->y,skl->x,skl->y,4,2,BL_CHAR,
+ skill->get_type(skl->skill_id),src,src,skl->skill_id,skl->skill_lv,tick,skl->flag,BCT_ENEMY);
+ break;
+ case GN_CRAZYWEED:
+ if( skl->type >= 0 ) {
+ int x = skl->type>>16, y = skl->type&0xFFFF;
+ if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
+ skill->castend_pos2(src, x, y, GN_CRAZYWEED_ATK, skl->skill_lv, tick, skl->flag);
+ } else if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
+ skill->castend_pos2(src, skl->x, skl->y, GN_CRAZYWEED_ATK, skl->skill_lv, tick, skl->flag);
+ break;
}
}
} while (0);
//Free skl now that it is no longer needed.
- ers_free(skill_timer_ers, skl);
+ ers_free(skill->timer_ers, skl);
return 0;
}
/*==========================================
*
*------------------------------------------*/
-int skill_addtimerskill (struct block_list *src, unsigned int tick, int target, int x,int y, uint16 skill_id, uint16 skill_lv, int type, int flag)
-{
+int skill_addtimerskill(struct block_list *src, int64 tick, int target, int x,int y, uint16 skill_id, uint16 skill_lv, int type, int flag) {
int i;
struct unit_data *ud;
nullpo_retr(1, src);
if (src->prev == NULL)
return 0;
- ud = unit_bl2ud(src);
+ ud = unit->bl2ud(src);
nullpo_retr(1, ud);
ARR_FIND( 0, MAX_SKILLTIMERSKILL, i, ud->skilltimerskill[i] == 0 );
if( i == MAX_SKILLTIMERSKILL ) return 1;
- ud->skilltimerskill[i] = ers_alloc(skill_timer_ers, struct skill_timerskill);
- ud->skilltimerskill[i]->timer = iTimer->add_timer(tick, skill->timerskill, src->id, i);
+ ud->skilltimerskill[i] = ers_alloc(skill->timer_ers, struct skill_timerskill);
+ ud->skilltimerskill[i]->timer = timer->add(tick, skill->timerskill, src->id, i);
ud->skilltimerskill[i]->src_id = src->id;
ud->skilltimerskill[i]->target_id = target;
ud->skilltimerskill[i]->skill_id = skill_id;
@@ -3334,26 +3349,40 @@ int skill_cleartimerskill (struct block_list *src)
int i;
struct unit_data *ud;
nullpo_ret(src);
- ud = unit_bl2ud(src);
+ ud = unit->bl2ud(src);
nullpo_ret(ud);
for(i=0;i<MAX_SKILLTIMERSKILL;i++) {
if(ud->skilltimerskill[i]) {
- iTimer->delete_timer(ud->skilltimerskill[i]->timer, skill->timerskill);
- ers_free(skill_timer_ers, ud->skilltimerskill[i]);
+ switch(ud->skilltimerskill[i]->skill_id){
+ case WL_TETRAVORTEX_FIRE:
+ case WL_TETRAVORTEX_WATER:
+ case WL_TETRAVORTEX_WIND:
+ case WL_TETRAVORTEX_GROUND:
+ // SR_FLASHCOMBO
+ case SR_DRAGONCOMBO:
+ case SR_FALLENEMPIRE:
+ case SR_TIGERCANNON:
+ case SR_SKYNETBLOW:
+ continue;
+ }
+ timer->delete(ud->skilltimerskill[i]->timer, skill->timerskill);
+ ers_free(skill->timer_ers, ud->skilltimerskill[i]);
ud->skilltimerskill[i]=NULL;
}
}
return 1;
}
-int skill_activate_reverbetion( struct block_list *bl, va_list ap) {
+int skill_activate_reverberation(struct block_list *bl, va_list ap) {
struct skill_unit *su = (TBL_SKILL*)bl;
struct skill_unit_group *sg;
if( bl->type != BL_SKILL )
return 0;
- if( su->alive && (sg = su->group) && sg->skill_id == WM_REVERBERATION ) {
- iMap->foreachinrange(skill->trap_splash, bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, iTimer->gettick());
- su->limit=DIFF_TICK(iTimer->gettick(),sg->tick);
+ if( su->alive && (sg = su->group) && sg->skill_id == WM_REVERBERATION && sg->unit_id == UNT_REVERBERATION ) {
+ int64 tick = timer->gettick();
+ clif->changetraplook(bl,UNT_USED_TRAPS);
+ map->foreachinrange(skill->trap_splash, bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, tick);
+ su->limit = DIFF_TICK32(tick,sg->tick)+1500;
sg->unit_id = UNT_USED_TRAPS;
}
return 0;
@@ -3364,7 +3393,7 @@ int skill_reveal_trap (struct block_list *bl, va_list ap) {
if (su->alive && su->group && skill->get_inf2(su->group->skill_id)&INF2_TRAP) { //Reveal trap.
//Change look is not good enough, the client ignores it as an actual trap still. [Skotlex]
//clif->changetraplook(bl, su->group->unit_id);
- clif->skill_setunit(su);
+ clif->getareachar_skillunit(&su->bl,su,AREA);
return 1;
}
return 0;
@@ -3374,8 +3403,7 @@ int skill_reveal_trap (struct block_list *bl, va_list ap) {
*
*
*------------------------------------------*/
-int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag)
-{
+int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
struct map_session_data *sd = NULL;
struct status_data *tstatus;
struct status_change *sc;
@@ -3393,25 +3421,25 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
sd = BL_CAST(BL_PC, src);
- if (status_isdead(bl))
+ if (status->isdead(bl))
return 1;
- if (skill_id && skill->get_type(skill_id) == BF_MAGIC && status_isimmune(bl) == 100) {
- //GTB makes all targetted magic display miss with a single bolt.
- sc_type sct = status_skill2sc(skill_id);
+ if (skill_id && skill->get_type(skill_id) == BF_MAGIC && status->isimmune(bl) == 100) {
+ //GTB makes all targeted magic display miss with a single bolt.
+ sc_type sct = status->skill2sc(skill_id);
if(sct != SC_NONE)
status_change_end(bl, sct, INVALID_TIMER);
clif->skill_damage(src, bl, tick, status_get_amotion(src), status_get_dmotion(bl), 0, 1, skill_id, skill_lv, skill->get_hit(skill_id));
return 1;
}
- sc = status_get_sc(src);
+ sc = status->get_sc(src);
if (sc && !sc->count)
sc = NULL; //Unneeded
- tstatus = status_get_status_data(bl);
+ tstatus = status->get_status_data(bl);
- iMap->freeblock_lock();
+ map->freeblock_lock();
switch(skill_id) {
case MER_CRASH:
@@ -3480,7 +3508,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case WS_CARTTERMINATION: // Cart Termination
case AS_VENOMKNIFE:
case HT_PHANTASMIC:
- case HT_POWER:
case TK_DOWNKICK:
case TK_COUNTER:
case GS_CHAINACTION:
@@ -3503,9 +3530,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case NPC_CRITICALWOUND:
case NPC_HELLPOWER:
case RK_SONICWAVE:
- case RK_HUNDREDSPEAR:
case RK_STORMBLAST:
- case RK_CRUSHSTRIKE:
case AB_DUPLELIGHT_MELEE:
case RA_AIMEDBOLT:
case NC_AXEBOOMERANG:
@@ -3525,10 +3550,13 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case SR_GENTLETOUCH_QUIET:
case WM_SEVERE_RAINSTORM_MELEE:
case WM_GREAT_ECHO:
+ case GN_CRAZYWEED_ATK:
case GN_SLINGITEM_RANGEMELEEATK:
case KO_JYUMONJIKIRI:
case KO_SETSUDAN:
case GC_DARKCROW:
+ case LG_OVERBRAND_BRANDISH:
+ case LG_OVERBRAND:
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
break;
@@ -3537,9 +3565,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
**/
case NC_BOOSTKNUCKLE:
case NC_PILEBUNKER:
- case NC_VULCANARM:
case NC_COLDSLOWER:
- case NC_ARMSCANNON:
if (sd) pc->overheat(sd,1);
case RK_WINDCUTTER:
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION);
@@ -3555,46 +3581,46 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case 5: flag |= BREAK_NECK; break;
}
//TODO: is there really no cleaner way to do this?
- sc = status_get_sc(bl);
+ sc = status->get_sc(bl);
if (sc) sc->jb_flag = flag;
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
break;
case MO_COMBOFINISH:
- if (!(flag&1) && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_MONK)
- { //Becomes a splash attack when Soul Linked.
- iMap->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv),splash_target(src),
- src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
- skill->castend_damage_id);
+ if (!(flag&1) && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_MONK) {
+ //Becomes a splash attack when Soul Linked.
+ map->foreachinrange(skill->area_sub, bl,
+ skill->get_splash(skill_id, skill_lv),splash_target(src),
+ src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
+ skill->castend_damage_id);
} else
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
break;
case TK_STORMKICK: // Taekwon kicks [Dralnu]
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- skill_area_temp[1] = 0;
- iMap->foreachinrange(skill->attack_area, src,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
- BF_WEAPON, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
+ skill->area_temp[1] = 0;
+ map->foreachinrange(skill->attack_area, src,
+ skill->get_splash(skill_id, skill_lv), splash_target(src),
+ BF_WEAPON, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
break;
case KN_CHARGEATK: {
- bool path = path_search_long(NULL, src->m, src->x, src->y, bl->x, bl->y,CELL_CHKWALL);
+ bool path_exists = path->search_long(NULL, src->m, src->x, src->y, bl->x, bl->y,CELL_CHKWALL);
unsigned int dist = distance_bl(src, bl);
- uint8 dir = iMap->calc_dir(bl, src->x, src->y);
+ uint8 dir = map->calc_dir(bl, src->x, src->y);
// teleport to target (if not on WoE grounds)
- if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 0, 1) )
+ if( !map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground && unit->movepos(src, bl->x, bl->y, 0, 1) )
clif->slide(src, bl->x, bl->y);
// cause damage and knockback if the path to target was a straight one
- if( path ) {
+ if( path_exists ) {
skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, dist);
skill->blown(src, bl, dist, dir, 0);
//HACK: since knockback officially defaults to the left, the client also turns to the left... therefore,
// make the caster look in the direction of the target
- unit_setdir(src, (dir+4)%8);
+ unit->setdir(src, (dir+4)%8);
}
}
@@ -3608,10 +3634,10 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case LG_CANNONSPEAR:
//It won't shoot through walls since on castend there has to be a direct
//line of sight between caster and target.
- skill_area_temp[1] = bl->id;
- iMap->foreachinpath (skill->attack_area,src->m,src->x,src->y,bl->x,bl->y,
- skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), splash_target(src),
- skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
+ skill->area_temp[1] = bl->id;
+ map->foreachinpath(skill->attack_area,src->m,src->x,src->y,bl->x,bl->y,
+ skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), splash_target(src),
+ skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
break;
case NPC_ACIDBREATH:
@@ -3619,10 +3645,10 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case NPC_FIREBREATH:
case NPC_ICEBREATH:
case NPC_THUNDERBREATH:
- skill_area_temp[1] = bl->id;
- iMap->foreachinpath(skill->attack_area,src->m,src->x,src->y,bl->x,bl->y,
- skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), splash_target(src),
- skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
+ skill->area_temp[1] = bl->id;
+ map->foreachinpath(skill->attack_area,src->m,src->x,src->y,bl->x,bl->y,
+ skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), splash_target(src),
+ skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
break;
case MO_INVESTIGATE:
@@ -3632,12 +3658,12 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case RG_BACKSTAP:
{
- uint8 dir = iMap->calc_dir(src, bl->x, bl->y), t_dir = unit_getdir(bl);
- if ((!check_distance_bl(src, bl, 0) && !iMap->check_dir(dir, t_dir)) || bl->type == BL_SKILL) {
+ uint8 dir = map->calc_dir(src, bl->x, bl->y), t_dir = unit->getdir(bl);
+ if ((!check_distance_bl(src, bl, 0) && !map->check_dir(dir, t_dir)) || bl->type == BL_SKILL) {
status_change_end(src, SC_HIDING, INVALID_TIMER);
skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest]
- unit_setdir(bl,dir);
+ unit->setdir(bl,dir);
}
else if (sd)
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
@@ -3668,43 +3694,46 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
- if( skill_id == MO_EXTREMITYFIST )
- {
+ if( skill_id == MO_EXTREMITYFIST ) {
mbl = src;
i = 3; // for Asura(from caster)
- status_set_sp(src, 0, 0);
+ status->set_sp(src, 0, 0);
status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER);
status_change_end(src, SC_BLADESTOP, INVALID_TIMER);
- #ifdef RENEWAL
- sc_start(src,SC_EXTREMITYFIST2,100,skill_lv,skill->get_time(skill_id,skill_lv));
- #endif
- }else{
+#ifdef RENEWAL
+ sc_start(src, src,SC_EXTREMITYFIST2,100,skill_lv,skill->get_time(skill_id,skill_lv));
+#endif // RENEWAL
+ } else {
status_change_end(src, SC_NJ_NEN, INVALID_TIMER);
status_change_end(src, SC_HIDING, INVALID_TIMER);
- status_set_hp(src,
- #ifdef RENEWAL
- max(status_get_max_hp(src)/100, 1)
- #else
- 1
- #endif
- , 0);
+#ifdef RENEWAL
+ status->set_hp(src, max(status_get_max_hp(src)/100, 1), 0);
+#else // not RENEWAL
+ status->set_hp(src, 1, 0);
+#endif // RENEWAL
}
- dir = iMap->calc_dir(src,bl->x,bl->y);
+ dir = map->calc_dir(src,bl->x,bl->y);
if( dir > 0 && dir < 4) x = -i;
else if( dir > 4 ) x = i;
else x = 0;
if( dir > 2 && dir < 6 ) y = -i;
else if( dir == 7 || dir < 2 ) y = i;
else y = 0;
- if( (mbl == src || (!map_flag_gvg(src->m) && !map[src->m].flag.battleground) ) && // only NJ_ISSEN don't have slide effect in GVG
- unit_movepos(src, mbl->x+x, mbl->y+y, 1, 1) ) {
+ if( (mbl == src || (!map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground) ) // only NJ_ISSEN don't have slide effect in GVG
+ && unit->movepos(src, mbl->x+x, mbl->y+y, 1, 1)
+ ) {
clif->slide(src, src->x, src->y);
- //uncomment this if you want to remove MO_EXTREMITYFIST glitchy walking effect. [malufett]
- //clif->fixpos(src);
+ clif->fixpos(src);
+ clif->spiritball(src);
}
}
break;
+ case HT_POWER:
+ if( tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT )
+ skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
+ break;
+
//Splash attack skills.
case AS_GRIMTOOTH:
case MC_CARTREVOLUTION:
@@ -3737,6 +3766,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case WL_JACKFROST:
case RA_ARROWSTORM:
case RA_WUGDASH:
+ case NC_VULCANARM:
+ case NC_ARMSCANNON:
case NC_SELFDESTRUCTION:
case NC_AXETORNADO:
case GC_ROLLINGCUTTER:
@@ -3748,9 +3779,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case SR_SKYNETBLOW:
case SR_WINDMILL:
case SR_RIDEINLIGHTNING:
- case WM_SOUND_OF_DESTRUCTION:
- case WM_REVERBERATION_MELEE:
- case WM_REVERBERATION_MAGIC:
+ case WM_REVERBERATION:
case SO_VARETYR_SPEAR:
case GN_CART_TORNADO:
case GN_CARTCANNON:
@@ -3758,20 +3787,22 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case KO_HUUMARANKA:
case KO_MUCHANAGE:
case KO_BAKURETSU:
+ case GN_ILLUSIONDOPING:
+ case MH_XENO_SLASHER:
if( flag&1 ) {//Recursive invocation
- // skill_area_temp[0] holds number of targets in area
- // skill_area_temp[1] holds the id of the original target
- // skill_area_temp[2] counts how many targets have already been processed
- int sflag = skill_area_temp[0] & 0xFFF, heal;
+ // skill->area_temp[0] holds number of targets in area
+ // skill->area_temp[1] holds the id of the original target
+ // skill->area_temp[2] counts how many targets have already been processed
+ int sflag = skill->area_temp[0] & 0xFFF, heal;
if( flag&SD_LEVEL )
sflag |= SD_LEVEL; // -1 will be used in packets instead of the skill level
- if( (skill_area_temp[1] != bl->id && !(skill->get_inf2(skill_id)&INF2_NPC_SKILL)) || flag&SD_ANIMATION )
+ if( (skill->area_temp[1] != bl->id && !(skill->get_inf2(skill_id)&INF2_NPC_SKILL)) || flag&SD_ANIMATION )
sflag |= SD_ANIMATION; // original target gets no animation (as well as all NPC skills)
heal = skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, sflag);
if( skill_id == NPC_VAMPIRE_GIFT && heal > 0 ) {
clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
- status_heal(src,heal,0,0);
+ status->heal(src,heal,0,0);
}
} else {
switch ( skill_id ) {
@@ -3781,8 +3812,11 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
case SR_TIGERCANNON:
+ case GC_COUNTERSLASH:
+ case GC_ROLLINGCUTTER:
flag |= SD_ANIMATION;
case LG_MOONSLASHER:
+ case MH_XENO_SLASHER:
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
break;
case NPC_EARTHQUAKE://FIXME: Isn't EarthQuake a ground skill after all?
@@ -3791,30 +3825,32 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
break;
}
- skill_area_temp[0] = 0;
- skill_area_temp[1] = bl->id;
- skill_area_temp[2] = 0;
+ skill->area_temp[0] = 0;
+ skill->area_temp[1] = bl->id;
+ skill->area_temp[2] = 0;
if( skill_id == WL_CRIMSONROCK ) {
- skill_area_temp[4] = bl->x;
- skill_area_temp[5] = bl->y;
+ skill->area_temp[4] = bl->x;
+ skill->area_temp[5] = bl->y;
}
- if( skill_id == WM_REVERBERATION_MELEE || skill_id == WM_REVERBERATION_MAGIC )
- skill_area_temp[1] = 0;
+
+ if( skill_id == NC_VULCANARM )
+ if (sd) pc->overheat(sd,1);
+
// if skill damage should be split among targets, count them
//SD_LEVEL -> Forced splash damage for Auto Blitz-Beat -> count targets
//special case: Venom Splasher uses a different range for searching than for splashing
if( flag&SD_LEVEL || skill->get_nk(skill_id)&NK_SPLASHSPLIT )
- skill_area_temp[0] = iMap->foreachinrange(skill->area_sub, bl, (skill_id == AS_SPLASHER)?1:skill->get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count);
+ skill->area_temp[0] = map->foreachinrange(skill->area_sub, bl, (skill_id == AS_SPLASHER)?1:skill->get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count);
// recursive invocation of skill->castend_damage_id() with flag|1
- iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), ( skill_id == WM_REVERBERATION_MELEE || skill_id == WM_REVERBERATION_MAGIC )?BL_CHAR:splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
}
break;
case KN_BRANDISHSPEAR:
case ML_BRANDISH:
//Coded apart for it needs the flag passed to the damage calculation.
- if (skill_area_temp[1] != bl->id)
+ if (skill->area_temp[1] != bl->id)
skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION);
else
skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
@@ -3822,50 +3858,95 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case KN_BOWLINGBASH:
case MS_BOWLINGBASH:
- if(flag&1){
- if(bl->id==skill_area_temp[1])
- break;
- //two hits for 500%
- skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION);
- skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION);
- } else {
- int i,c;
- c = skill->get_blewcount(skill_id,skill_lv);
- // keep moving target in the direction that src is looking, square by square
- for(i=0;i<c;i++){
- if (!skill->blown(src,bl,1,(unit_getdir(src)+4)%8,0x1))
- break; //Can't knockback
- skill_area_temp[0] = iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count);
- if( skill_area_temp[0] > 1 ) break; // collision
- }
- clif->blown(bl); //Update target pos.
- if (i!=c) { //Splash
- skill_area_temp[1] = bl->id;
- iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
+ {
+ int min_x,max_x,min_y,max_y,i,c,dir,tx,ty;
+ // Chain effect and check range gets reduction by recursive depth, as this can reach 0, we don't use blowcount
+ c = (skill_lv-(flag&0xFFF)+1)/2;
+ // Determine the Bowling Bash area depending on configuration
+ if (battle_config.bowling_bash_area == 0) {
+ // Gutter line system
+ min_x = ((src->x)-c) - ((src->x)-c)%40;
+ if(min_x < 0) min_x = 0;
+ max_x = min_x + 39;
+ min_y = ((src->y)-c) - ((src->y)-c)%40;
+ if(min_y < 0) min_y = 0;
+ max_y = min_y + 39;
+ } else if (battle_config.bowling_bash_area == 1) {
+ // Gutter line system without demi gutter bug
+ min_x = src->x - (src->x)%40;
+ max_x = min_x + 39;
+ min_y = src->y - (src->y)%40;
+ max_y = min_y + 39;
+ } else {
+ // Area around caster
+ min_x = src->x - battle_config.bowling_bash_area;
+ max_x = src->x + battle_config.bowling_bash_area;
+ min_y = src->y - battle_config.bowling_bash_area;
+ max_y = src->y + battle_config.bowling_bash_area;
+ }
+ // Initialization, break checks, direction
+ if((flag&0xFFF) > 0) {
+ // Ignore monsters outside area
+ if(bl->x < min_x || bl->x > max_x || bl->y < min_y || bl->y > max_y)
+ break;
+ // Ignore monsters already in list
+ if(idb_exists(skill->bowling_db, bl->id))
+ break;
+ // Random direction
+ dir = rnd()%8;
+ } else {
+ // Create an empty list of already hit targets
+ db_clear(skill->bowling_db);
+ // Direction is walkpath
+ dir = (unit->getdir(src)+4)%8;
+ }
+ // Add current target to the list of already hit targets
+ idb_put(skill->bowling_db, bl->id, bl);
+ // Keep moving target in direction square by square
+ tx = bl->x;
+ ty = bl->y;
+ for(i=0;i<c;i++) {
+ // Target coordinates (get changed even if knockback fails)
+ tx -= dirx[dir];
+ ty -= diry[dir];
+ // If target cell is a wall then break
+ if(map->getcell(bl->m,tx,ty,CELL_CHKWALL))
+ break;
+ skill_blown(src,bl,1,dir,0);
+ // Splash around target cell, but only cells inside area; we first have to check the area is not negative
+ if((max(min_x,tx-1) <= min(max_x,tx+1)) &&
+ (max(min_y,ty-1) <= min(max_y,ty+1)) &&
+ (map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count))) {
+ // Recursive call
+ map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), splash_target(src), src, skill_id, skill_lv, tick, (flag|BCT_ENEMY)+1, skill->castend_damage_id);
+ // Self-collision
+ if(bl->x >= min_x && bl->x <= max_x && bl->y >= min_y && bl->y <= max_y)
+ skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,(flag&0xFFF)>0?SD_ANIMATION:0);
+ break;
+ }
}
- //Weirdo dual-hit property, two attacks for 500%
- skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0);
- skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0);
+ // Original hit or chain hit depending on flag
+ skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,(flag&0xFFF)>0?SD_ANIMATION:0);
}
break;
case KN_SPEARSTAB:
if(flag&1) {
- if (bl->id==skill_area_temp[1])
+ if (bl->id==skill->area_temp[1])
break;
if (skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION))
- skill->blown(src,bl,skill_area_temp[2],-1,0);
+ skill->blown(src,bl,skill->area_temp[2],-1,0);
} else {
int x=bl->x,y=bl->y,i,dir;
- dir = iMap->calc_dir(bl,src->x,src->y);
- skill_area_temp[1] = bl->id;
- skill_area_temp[2] = skill->get_blewcount(skill_id,skill_lv);
+ dir = map->calc_dir(bl,src->x,src->y);
+ skill->area_temp[1] = bl->id;
+ skill->area_temp[2] = skill->get_blewcount(skill_id,skill_lv);
// all the enemies between the caster and the target are hit, as well as the target
if (skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0))
- skill->blown(src,bl,skill_area_temp[2],-1,0);
+ skill->blown(src,bl,skill->area_temp[2],-1,0);
for (i=0;i<4;i++) {
- iMap->foreachincell(skill->area_sub,bl->m,x,y,BL_CHAR,
- src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ map->foreachincell(skill->area_sub,bl->m,x,y,BL_CHAR,src,skill_id,skill_lv,
+ tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
x += dirx[dir];
y += diry[dir];
}
@@ -3875,17 +3956,17 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case TK_TURNKICK:
case MO_BALKYOUNG: //Active part of the attack. Skill-attack [Skotlex]
{
- skill_area_temp[1] = bl->id; //NOTE: This is used in skill->castend_nodamage_id to avoid affecting the target.
+ skill->area_temp[1] = bl->id; //NOTE: This is used in skill->castend_nodamage_id to avoid affecting the target.
if (skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag))
- iMap->foreachinrange(skill->area_sub,bl,
- skill->get_splash(skill_id, skill_lv),BL_CHAR,
- src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,
- skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub,bl,
+ skill->get_splash(skill_id, skill_lv),BL_CHAR,
+ src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,
+ skill->castend_nodamage_id);
}
break;
case CH_PALMSTRIKE: // Palm Strike takes effect 1sec after casting. [Skotlex]
// clif->skill_nodamage(src,bl,skill_id,skill_lv,0); //Can't make this one display the correct attack animation delay :/
- clif->damage(src,bl,tick,status_get_amotion(src),0,-1,1,4,0); //Display an absorbed damage attack.
+ clif->damage(src,bl,status_get_amotion(src),0,-1,1,4,0); //Display an absorbed damage attack.
skill->addtimerskill(src, tick + (1000+status_get_amotion(src)), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
break;
@@ -3925,7 +4006,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case NPC_MAGICALATTACK:
skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag);
- sc_start(src,status_skill2sc(skill_id),100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src, src,status->skill2sc(skill_id),100,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case HVAN_CAPRICE: //[blackhole89]
@@ -3948,10 +4029,9 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
int maxlv = skill->get_max(skill_id); // learnable level
int count = 0;
int x, y;
- struct skill_unit* unit;
+ struct skill_unit *su;
- if( skill_lv > maxlv )
- {
+ if( skill_lv > maxlv ) {
if( src->type == BL_MOB && skill_lv == 10 )
range = 4;
else
@@ -3959,16 +4039,14 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
}
for( y = src->y - range; y <= src->y + range; ++y )
- for( x = src->x - range; x <= src->x + range; ++x )
- {
- if( !iMap->find_skill_unit_oncell(src,x,y,SA_LANDPROTECTOR,NULL,1) )
- {
- if( src->type != BL_PC || iMap->getcell(src->m,x,y,CELL_CHKWATER) ) // non-players bypass the water requirement
+ for( x = src->x - range; x <= src->x + range; ++x ) {
+ if( !map->find_skill_unit_oncell(src,x,y,SA_LANDPROTECTOR,NULL,1) ) {
+ if( src->type != BL_PC || map->getcell(src->m,x,y,CELL_CHKWATER) ) // non-players bypass the water requirement
count++; // natural water cell
- else if( (unit = iMap->find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL,1)) != NULL || (unit = iMap->find_skill_unit_oncell(src,x,y,NJ_SUITON,NULL,1)) != NULL )
- {
+ else if( (su = map->find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL,1)) != NULL
+ || (su = map->find_skill_unit_oncell(src,x,y,NJ_SUITON,NULL,1)) != NULL ) {
count++; // skill-induced water cell
- skill->delunit(unit); // consume cell
+ skill->delunit(su); // consume cell
}
}
}
@@ -3990,7 +4068,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case SL_STIN:
case SL_STUN:
if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
- status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,10);
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,10);
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
@@ -4017,18 +4095,18 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
* Rune Knight
**/
case RK_DRAGONBREATH_WATER:
- case RK_DRAGONBREATH: {
- struct status_change *tsc = NULL;
- if( (tsc = status_get_sc(bl)) && (tsc->data[SC_HIDING] )) {
- clif->skill_nodamage(src,src,skill_id,skill_lv,1);
- } else
- skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag);
- }
+ case RK_DRAGONBREATH:
+ {
+ struct status_change *tsc = NULL;
+ if( (tsc = status->get_sc(bl)) && (tsc->data[SC_HIDING] )) {
+ clif->skill_nodamage(src,src,skill_id,skill_lv,1);
+ } else
+ skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag);
+ }
break;
-
case NPC_SELFDESTRUCTION: {
struct status_change *tsc = NULL;
- if( (tsc = status_get_sc(bl)) && tsc->data[SC_HIDING] )
+ if( (tsc = status->get_sc(bl)) && tsc->data[SC_HIDING] )
break;
}
case HVAN_EXPLOSION:
@@ -4036,7 +4114,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag);
break;
- // Celest
+ // [Celest]
case PF_SOULBURN:
if (rnd()%100 < (skill_lv < 5 ? 30 + skill_lv * 10 : 70)) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -4053,14 +4131,14 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case NPC_BLOODDRAIN:
case NPC_ENERGYDRAIN:
- {
- int heal = skill->attack( (skill_id == NPC_BLOODDRAIN) ? BF_WEAPON : BF_MAGIC,
- src, src, bl, skill_id, skill_lv, tick, flag);
- if (heal > 0){
- clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
- status_heal(src, heal, 0, 0);
- }
+ {
+ int heal = skill->attack( (skill_id == NPC_BLOODDRAIN) ? BF_WEAPON : BF_MAGIC,
+ src, src, bl, skill_id, skill_lv, tick, flag);
+ if (heal > 0){
+ clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
+ status->heal(src, heal, 0, 0);
}
+ }
break;
case GS_BULLSEYE:
@@ -4069,32 +4147,47 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case NJ_KASUMIKIRI:
if (skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag) > 0)
- sc_start(src,SC_HIDING,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,src,SC_HIDING,100,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case NJ_KIRIKAGE:
- if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground )
- { //You don't move on GVG grounds.
+ if( !map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground ) {
+ //You don't move on GVG grounds.
short x, y;
- iMap->search_freecell(bl, 0, &x, &y, 1, 1, 0);
- if (unit_movepos(src, x, y, 0, 0))
+ map->search_freecell(bl, 0, &x, &y, 1, 1, 0);
+ if (unit->movepos(src, x, y, 0, 0))
clif->slide(src,src->x,src->y);
}
status_change_end(src, SC_HIDING, INVALID_TIMER);
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
break;
+ case RK_HUNDREDSPEAR:
+ skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
+ if(rnd()%100 < (10 + 3*skill_lv)) {
+ if( !sd || pc->checkskill(sd,KN_SPEARBOOMERANG) == 0 )
+ break; // Spear Boomerang auto cast chance only works if you have mastered Spear Boomerang.
+ skill->blown(src,bl,6,-1,0);
+ skill->addtimerskill(src,tick+800,bl->id,0,0,skill_id,skill_lv,BF_WEAPON,flag);
+ skill->castend_damage_id(src,bl,KN_SPEARBOOMERANG,1,tick,0);
+ }
+ break;
case RK_PHANTOMTHRUST:
- unit_setdir(src,iMap->calc_dir(src, bl->x, bl->y));
+ {
+ struct map_session_data *tsd = BL_CAST(BL_PC, bl);
+ unit->setdir(src,map->calc_dir(src, bl->x, bl->y));
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- skill->blown(src,bl,distance_bl(src,bl)-1,unit_getdir(src),0);
- if( battle->check_target(src,bl,BCT_ENEMY) > 0 )
+ skill->blown(src,bl,distance_bl(src,bl)-1,unit->getdir(src),0);
+ if( sd && tsd && sd->status.party_id && sd->status.party_id && sd->status.party_id == tsd->status.party_id ) // Don't damage party members.
+ ; // No damage to Members
+ else
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
+ }
break;
case GC_DARKILLUSION:
{
short x, y;
- short dir = iMap->calc_dir(src,bl->x,bl->y);
+ short dir = map->calc_dir(src,bl->x,bl->y);
if( dir > 0 && dir < 4) x = 2;
else if( dir > 4 ) x = -2;
@@ -4103,10 +4196,10 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
else if( dir == 7 || dir < 2 ) y = -2;
else y = 0;
- if( unit_movepos(src, bl->x+x, bl->y+y, 1, 1) )
+ if( unit->movepos(src, bl->x+x, bl->y+y, 1, 1) )
{
clif->slide(src,bl->x+x,bl->y+y);
- clif->fixpos(src); // the official server send these two packts.
+ clif->fixpos(src); // the official server send these two packets.
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
if( rnd()%100 < 4 * skill_lv )
skill->castend_damage_id(src,bl,GC_CROSSIMPACT,skill_lv,tick,flag);
@@ -4132,9 +4225,9 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
break;
case GC_PHANTOMMENACE:
- if( flag&1 )
- { // Only Hits Invisible Targets
- struct status_change *tsc = status_get_sc(bl);
+ if( flag&1 ) {
+ // Only Hits Invisible Targets
+ struct status_change *tsc = status->get_sc(bl);
if(tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY]) )
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
}
@@ -4144,27 +4237,26 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
skill->addtimerskill(src,tick+status_get_amotion(src),bl->id,0,0,WL_CHAINLIGHTNING_ATK,skill_lv,0,flag);
break;
case WL_DRAINLIFE:
- {
- int heal = skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
- int rate = 70 + 5 * skill_lv;
+ {
+ int heal = skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
+ int rate = 70 + 5 * skill_lv;
- heal = heal * (5 + 5 * skill_lv) / 100;
+ heal = heal * (5 + 5 * skill_lv) / 100;
- if( bl->type == BL_SKILL || status_get_hp(src) == status_get_max_hp(src)) // Don't absorb when caster was in full HP
- heal = 0; // Don't absorb heal from Ice Walls or other skill units.
+ if( bl->type == BL_SKILL || status_get_hp(src) == status_get_max_hp(src)) // Don't absorb when caster was in full HP
+ heal = 0; // Don't absorb heal from Ice Walls or other skill units.
- if( heal && rnd()%100 < rate )
- {
- status_heal(src, heal, 0, 0);
- clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
- }
+ if( heal && rnd()%100 < rate ) {
+ status->heal(src, heal, 0, 0);
+ clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1);
}
+ }
break;
case WL_TETRAVORTEX:
if( sc ){
int i = SC_SUMMON5, x = 0;
- int types[][2] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
+ int types[][2] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
for(; i >= SC_SUMMON1; i--){
if( sc->data[i] ){
int skillid = WL_TETRAVORTEX_FIRE + (sc->data[i]->val1 - WLS_FIRE) + (sc->data[i]->val1 == WLS_WIND) - (sc->data[i]->val1 == WLS_WATER), sc_index = 0, rate = 0;
@@ -4173,7 +4265,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
types[x][1] = 25; // 25% each for equal sharing
if( x == 3 ){
x = 0;
- sc_index = types[rand()%4][0];
+ sc_index = types[rnd()%4][0];
for(; x < 4; x++)
if(types[x][0] == sc_index)
rate += types[x][1];
@@ -4194,7 +4286,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
skill->toggle_magicpower(src, skill_id);
// Priority is to release SpellBook
if( sc && sc->data[SC_READING_SB] ) { // SpellBook
- uint16 skill_id, skill_lv, point, s = 0;
+ uint16 spell_skill_id, spell_skill_lv, point, s = 0;
int spell[SC_SPELLBOOK7-SC_SPELLBOOK1 + 1];
for(i = SC_SPELLBOOK7; i >= SC_SPELLBOOK1; i--) // List all available spell to be released
@@ -4203,10 +4295,10 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
if ( s == 0 )
break;
- i = spell[s==1?0:rand()%s];// Random select of spell to be released.
+ i = spell[s==1?0:rnd()%s];// Random select of spell to be released.
if( s && sc->data[i] ){// Now extract the data from the preserved spell
- skill_id = sc->data[i]->val1;
- skill_lv = sc->data[i]->val2;
+ spell_skill_id = sc->data[i]->val1;
+ spell_skill_lv = sc->data[i]->val2;
point = sc->data[i]->val3;
status_change_end(src, (sc_type)i, INVALID_TIMER);
}else //something went wrong :(
@@ -4217,36 +4309,35 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
else // Last spell to be released
status_change_end(src, SC_READING_SB, INVALID_TIMER);
- if( !skill->check_condition_castbegin(sd, skill_id, skill_lv) )
+ if( !skill->check_condition_castbegin(sd, spell_skill_id, spell_skill_lv) )
break;
- switch( skill->get_casttype(skill_id) ) {
+ switch( skill->get_casttype(spell_skill_id) ) {
case CAST_GROUND:
- skill->castend_pos2(src, bl->x, bl->y, skill_id, skill_lv, tick, 0);
+ skill->castend_pos2(src, bl->x, bl->y, spell_skill_id, spell_skill_lv, tick, 0);
break;
case CAST_NODAMAGE:
- skill->castend_nodamage_id(src, bl, skill_id, skill_lv, tick, 0);
+ skill->castend_nodamage_id(src, bl, spell_skill_id, spell_skill_lv, tick, 0);
break;
case CAST_DAMAGE:
- skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, 0);
+ skill->castend_damage_id(src, bl, spell_skill_id, spell_skill_lv, tick, 0);
break;
}
- sd->ud.canact_tick = tick + skill->delay_fix(src, skill_id, skill_lv);
- clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, skill_id, skill_lv), 0, 0, 0);
+ sd->ud.canact_tick = tick + skill->delay_fix(src, spell_skill_id, spell_skill_lv);
+ clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, spell_skill_id, spell_skill_lv), 0, 0, 0);
- cooldown = skill_get_cooldown(skill_id, skill_lv);
+ cooldown = skill->get_cooldown(spell_skill_id, spell_skill_lv);
for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) {
- if (sd->skillcooldown[i].id == skill_id){
+ if (sd->skillcooldown[i].id == spell_skill_id){
cooldown += sd->skillcooldown[i].val;
break;
- }
+ }
}
if(cooldown)
- skill->blockpc_start(sd, skill_id, cooldown, false);
+ skill->blockpc_start(sd, spell_skill_id, cooldown);
}else if( sc ){ // Summon Balls
- int i = SC_SUMMON5;
- for(; i >= SC_SUMMON1; i--){
+ for(i = SC_SUMMON5; i >= SC_SUMMON1; i--){
if( sc->data[i] ){
int skillid = WL_SUMMON_ATK_FIRE + (sc->data[i]->val1 - WLS_FIRE);
skill->addtimerskill(src, tick + status_get_adelay(src) * (SC_SUMMON5 - i), bl->id, 0, 0, skillid, skill_lv, BF_MAGIC, flag);
@@ -4260,7 +4351,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
break;
case WL_FROSTMISTY:
// Doesn't deal damage through non-shootable walls.
- if( path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKWALL) )
+ if( path->search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKWALL) )
skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION);
break;
case WL_HELLINFERNO:
@@ -4271,9 +4362,9 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
if( sd && pc_isridingwug(sd) ){
short x[8]={0,-1,-1,-1,0,1,1,1};
short y[8]={1,1,0,-1,-1,-1,0,1};
- uint8 dir = iMap->calc_dir(bl, src->x, src->y);
+ uint8 dir = map->calc_dir(bl, src->x, src->y);
- if( unit_movepos(src, bl->x+x[dir], bl->y+y[dir], 1, 1) )
+ if( unit->movepos(src, bl->x+x[dir], bl->y+y[dir], 1, 1) )
{
clif->slide(src, bl->x+x[dir], bl->y+y[dir]);
clif->fixpos(src);
@@ -4282,7 +4373,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
break;
}
case RA_WUGBITE:
- if( path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKNOREACH) ) {
+ if( path->search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKNOREACH) ) {
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
}else if( sd && skill_id == RA_WUGBITE ) // Only RA_WUGBITE has the skill fail message.
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
@@ -4291,91 +4382,78 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case RA_SENSITIVEKEEN:
if( bl->type != BL_SKILL ) { // Only Hits Invisible Targets
- struct status_change * tsc = status_get_sc(bl);
+ struct status_change * tsc = status->get_sc(bl);
if( tsc && tsc->option&(OPTION_HIDE|OPTION_CLOAK) ){
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
}
- }
- else
- {
+ } else {
struct skill_unit *su = BL_CAST(BL_SKILL,bl);
struct skill_unit_group* sg;
- if( su && (sg=su->group) && skill->get_inf2(sg->skill_id)&INF2_TRAP )
- {
- if( !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) )
- {
+ if( su && (sg=su->group) && skill->get_inf2(sg->skill_id)&INF2_TRAP ) {
+ if( !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) {
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = sg->item_id?sg->item_id:ITEMID_TRAP;
item_tmp.identify = 1;
if( item_tmp.nameid )
- iMap->addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0);
+ map->addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0);
}
skill->delunit(su);
}
}
break;
case NC_INFRAREDSCAN:
- if( flag&1 )
- { //TODO: Need a confirmation if the other type of hidden status is included to be scanned. [Jobbie]
- if( rnd()%100 < 50 )
- sc_start(bl, SC_INFRAREDSCAN, 10000, skill_lv, skill->get_time(skill_id, skill_lv));
+ if( flag&1 ) {
+ //TODO: Need a confirmation if the other type of hidden status is included to be scanned. [Jobbie]
+ sc_start(src, bl, SC_INFRAREDSCAN, 10000, skill_lv, skill->get_time(skill_id, skill_lv));
status_change_end(bl, SC_HIDING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); // Need confirm it.
- }
- else
- {
- iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+ } else {
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
if( sd ) pc->overheat(sd,1);
}
break;
case NC_MAGNETICFIELD:
- sc_start2(bl,SC_MAGNETICFIELD,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv));
+ sc_start2(src,bl,SC_MAGNETICFIELD,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv));
break;
case SC_FATALMENACE:
if( flag&1 )
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
- else
- {
+ else {
short x, y;
- iMap->search_freecell(src, 0, &x, &y, -1, -1, 0);
+ map->search_freecell(src, 0, &x, &y, -1, -1, 0);
// Destination area
- skill_area_temp[4] = x;
- skill_area_temp[5] = y;
- iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
+ skill->area_temp[4] = x;
+ skill->area_temp[5] = y;
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
skill->addtimerskill(src,tick + 800,src->id,x,y,skill_id,skill_lv,0,flag); // To teleport Self
clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6);
}
break;
case LG_PINPOINTATTACK:
- if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 1, 1) )
+ if( !map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground && unit->movepos(src, bl->x, bl->y, 1, 1) )
clif->slide(src,bl->x,bl->y);
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
break;
case LG_SHIELDSPELL:
- // flag&1: Phisycal Attack, flag&2: Magic Attack.
- skill->attack((flag&1)?BF_WEAPON:BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag);
- break;
-
- case LG_OVERBRAND:
- skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag|SD_LEVEL);
+ if ( skill_lv == 1 )
+ skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
+ else if ( skill_lv == 2 )
+ skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag);
break;
- case LG_OVERBRAND_BRANDISH:
- skill->addtimerskill(src, tick + status_get_amotion(src)*8/10, bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|SD_LEVEL);
- break;
case SR_DRAGONCOMBO:
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
break;
case SR_KNUCKLEARROW:
- if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 1, 1) ) {
+ if( !map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground && unit->movepos(src, bl->x, bl->y, 1, 1) ) {
clif->slide(src,bl->x,bl->y);
clif->fixpos(src); // Aegis send this packet too.
}
@@ -4393,9 +4471,13 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
+ status_change_end(bl, SC_SIREN, INVALID_TIMER);
+ status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER);
- status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER);
+ status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
+ status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
+ status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER);
status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
@@ -4409,28 +4491,61 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
status_change_end(bl, SC_HIDING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
} else{
- iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- }
+ }
break;
- case SO_POISON_BUSTER: {
- struct status_change *tsc = status_get_sc(bl);
- if( tsc && tsc->data[SC_POISON] ) {
- skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
- status_change_end(bl, SC_POISON, INVALID_TIMER);
- }
- else if( sd )
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
- }
+ case WM_SOUND_OF_DESTRUCTION:
+ {
+ struct status_change *tsc = status->get_sc(bl);
+ if( tsc && tsc->count && ( tsc->data[SC_SWING] || tsc->data[SC_SYMPHONY_LOVE] || tsc->data[SC_MOONLIT_SERENADE] ||
+ tsc->data[SC_RUSH_WINDMILL] || tsc->data[SC_ECHOSONG] || tsc->data[SC_HARMONIZE] ||
+ tsc->data[SC_SIREN] || tsc->data[SC_DEEP_SLEEP] || tsc->data[SC_SIRCLEOFNATURE] ||
+ tsc->data[SC_GLOOMYDAY] || tsc->data[SC_SONG_OF_MANA] ||
+ tsc->data[SC_DANCE_WITH_WUG] || tsc->data[SC_SATURDAY_NIGHT_FEVER] || tsc->data[SC_LERADS_DEW] ||
+ tsc->data[SC_MELODYOFSINK] || tsc->data[SC_BEYOND_OF_WARCRY] || tsc->data[SC_UNLIMITED_HUMMING_VOICE] ) &&
+ rnd()%100 < 4 * skill_lv + 2 * (sd ? pc->checkskill(sd,WM_LESSON) : 10) + 10 * battle->calc_chorusbonus(sd)) {
+ skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag);
+ status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),8);
+ status_change_end(bl, SC_SWING, INVALID_TIMER);
+ status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
+ status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
+ status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
+ status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
+ status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
+ status_change_end(bl, SC_SIREN, INVALID_TIMER);
+ status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
+ status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER);
+ status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
+ status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
+ status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
+ status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER);
+ status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
+ status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
+ status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
+ status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER);
+ }
+ }
+ break;
+
+ case SO_POISON_BUSTER:
+ {
+ struct status_change *tsc = status->get_sc(bl);
+ if( tsc && tsc->data[SC_POISON] ) {
+ skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
+ status_change_end(bl, SC_POISON, INVALID_TIMER);
+ } else if( sd )
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ }
break;
case GN_SPORE_EXPLOSION:
if( flag&1 )
- skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
+ skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
else {
clif->skill_nodamage(src, bl, skill_id, 0, 1);
- skill->addtimerskill(src, iTimer->gettick() + skill->get_time(skill_id, skill_lv) - 1000, bl->id, 0, 0, skill_id, skill_lv, 0, 0);
+ skill->addtimerskill(src, timer->gettick() + skill->get_time(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, 0, 0);
}
break;
@@ -4446,7 +4561,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1);
clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
if( rnd()%100 < 30 )
- iMap->foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
else
skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
}
@@ -4469,7 +4584,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1);
clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
if( rnd()%100 < 30 )
- iMap->foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
else
skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
}
@@ -4487,34 +4602,33 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case EL_TIDAL_WEAPON:
if( src->type == BL_ELEM ) {
struct elemental_data *ele = BL_CAST(BL_ELEM,src);
- struct status_change *sc = status_get_sc(&ele->bl);
- struct status_change *tsc = status_get_sc(bl);
- sc_type type = status_skill2sc(skill_id), type2;
+ struct status_change *esc = status->get_sc(&ele->bl);
+ struct status_change *tsc = status->get_sc(bl);
+ sc_type type = status->skill2sc(skill_id), type2;
type2 = type-1;
clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1);
clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) {
- elemental_clean_single_effect(ele, skill_id);
+ if( (esc && esc->data[type2]) || (tsc && tsc->data[type]) ) {
+ elemental->clean_single_effect(ele, skill_id);
}
if( rnd()%100 < 50 )
skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
else {
- sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv));
- sc_start(battle->get_master(src),type,100,ele->bl.id,skill->get_time(skill_id,skill_lv));
+ sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src, battle->get_master(src),type,100,ele->bl.id,skill->get_time(skill_id,skill_lv));
}
clif->skill_nodamage(src,src,skill_id,skill_lv,1);
}
break;
- //recursive homon skill
+ // Recursive homun skill
case MH_MAGMA_FLOW:
- case MH_XENO_SLASHER:
case MH_HEILIGE_STANGE:
if(flag & 1)
skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
else {
- iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill->castend_damage_id);
}
break;
@@ -4523,7 +4637,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
break;
case MH_TINDER_BREAKER:
- if (unit_movepos(src, bl->x, bl->y, 1, 1)) {
+ if (unit->movepos(src, bl->x, bl->y, 1, 1)) {
#if PACKETVER >= 20111005
clif->snap(src, bl->x, bl->y);
#else
@@ -4531,21 +4645,21 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
#endif
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start4(bl,SC_RG_CCONFINE_S,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv)));
+ sc_start4(src,bl,SC_RG_CCONFINE_S,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv)));
skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
break;
case 0:/* no skill - basic/normal attack */
if(sd) {
if (flag & 3){
- if (bl->id != skill_area_temp[1])
+ if (bl->id != skill->area_temp[1])
skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, SD_LEVEL|flag);
} else {
- skill_area_temp[1] = bl->id;
- iMap->foreachinrange(skill->area_sub, bl,
- sd->bonus.splash_range, BL_CHAR,
- src, skill_id, skill_lv, tick, flag | BCT_ENEMY | 1,
- skill->castend_damage_id);
+ skill->area_temp[1] = bl->id;
+ map->foreachinrange(skill->area_sub, bl,
+ sd->bonus.splash_range, BL_CHAR,
+ src, skill_id, skill_lv, tick, flag | BCT_ENEMY | 1,
+ skill->castend_damage_id);
flag|=1; //Set flag to 1 so ammo is not double-consumed. [Skotlex]
}
}
@@ -4556,18 +4670,18 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
clif->skill_damage(src, bl, tick, status_get_amotion(src), tstatus->dmotion,
0, abs(skill->get_num(skill_id, skill_lv)),
skill_id, skill_lv, skill->get_hit(skill_id));
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] ) //Should only remove after the skill has been casted.
status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
if( sd && !(flag&1) )
{// ensure that the skill last-cast tick is recorded
- sd->canskill_tick = iTimer->gettick();
+ sd->canskill_tick = timer->gettick();
if( sd->state.arrow_atk )
{// consume arrow on last invocation to this skill.
@@ -4584,8 +4698,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
/*==========================================
*
*------------------------------------------*/
-int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
-{
+int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
struct block_list *target, *src;
struct map_session_data *sd;
struct mob_data *md;
@@ -4593,14 +4706,14 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
struct status_change *sc = NULL;
int inf,inf2,flag = 0;
- src = iMap->id2bl(id);
+ src = map->id2bl(id);
if( src == NULL )
{
ShowDebug("skill_castend_id: src == NULL (tid=%d, id=%d)\n", tid, id);
return 0;// not found
}
- ud = unit_bl2ud(src);
+ ud = unit->bl2ud(src);
if( ud == NULL )
{
ShowDebug("skill_castend_id: ud == NULL (tid=%d, id=%d)\n", tid, id);
@@ -4615,7 +4728,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
return 0;
}
- if(ud->skill_id != SA_CASTCANCEL && ud->skill_id != SO_SPELLFIST) {// otherwise handled in unit_skillcastcancel()
+ if(ud->skill_id != SA_CASTCANCEL && ud->skill_id != SO_SPELLFIST) {// otherwise handled in unit->skillcastcancel()
if( ud->skilltimer != tid ) {
ShowError("skill_castend_id: Timer mismatch %d!=%d!\n", ud->skilltimer, tid);
ud->skilltimer = INVALID_TIMER;
@@ -4634,13 +4747,13 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
if (ud->skilltarget == id)
target = src;
else
- target = iMap->id2bl(ud->skilltarget);
+ target = map->id2bl(ud->skilltarget);
// Use a do so that you can break out of it when the skill fails.
do {
if(!target || target->prev==NULL) break;
- if(src->m != target->m || status_isdead(src)) break;
+ if(src->m != target->m || status->isdead(src)) break;
switch (ud->skill_id) {
//These should become skill_castend_pos
@@ -4654,7 +4767,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
inf2 = skill->get_splash(ud->skill_id, ud->skill_lv);
ud->skillx = target->x + inf2;
ud->skilly = target->y + inf2;
- if (inf2 && !iMap->random_dir(target, &ud->skillx, &ud->skilly)) {
+ if (inf2 && !map->random_dir(target, &ud->skillx, &ud->skilly)) {
ud->skillx = target->x;
ud->skilly = target->y;
}
@@ -4668,26 +4781,25 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
}
if(ud->skill_id == RG_BACKSTAP) {
- uint8 dir = iMap->calc_dir(src,target->x,target->y),t_dir = unit_getdir(target);
- if(check_distance_bl(src, target, 0) || iMap->check_dir(dir,t_dir)) {
+ uint8 dir = map->calc_dir(src,target->x,target->y),t_dir = unit->getdir(target);
+ if(check_distance_bl(src, target, 0) || map->check_dir(dir,t_dir)) {
break;
}
}
if( ud->skill_id == PR_TURNUNDEAD ) {
- struct status_data *tstatus = status_get_status_data(target);
+ struct status_data *tstatus = status->get_status_data(target);
if( !battle->check_undead(tstatus->race, tstatus->def_ele) )
break;
}
if( ud->skill_id == RA_WUGSTRIKE ){
- if( !path_search(NULL,src->m,src->x,src->y,target->x,target->y,1,CELL_CHKNOREACH))
+ if( !path->search(NULL,src->m,src->x,src->y,target->x,target->y,1,CELL_CHKNOREACH))
break;
}
- if( ud->skill_id == PR_LEXDIVINA || ud->skill_id == MER_LEXDIVINA )
- {
- sc = status_get_sc(target);
+ if( ud->skill_id == PR_LEXDIVINA || ud->skill_id == MER_LEXDIVINA ) {
+ sc = status->get_sc(target);
if( battle->check_target(src,target, BCT_ENEMY) <= 0 && (!sc || !sc->data[SC_SILENCE]) )
{ //If it's not an enemy, and not silenced, you can't use the skill on them. [Skotlex]
clif->skill_nodamage (src, target, ud->skill_id, ud->skill_lv, 0);
@@ -4717,10 +4829,10 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
inf &= ~BCT_NEUTRAL;
}
- if( sd && (inf2&INF2_CHORUS_SKILL) && skill->check_pc_partner(sd, ud->skill_id, &ud->skill_lv, 1, 0) < 1 ) {
- clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_NEED_HELPER, 0);
- break;
- }
+ if( sd && (inf2&INF2_CHORUS_SKILL) && skill->check_pc_partner(sd, ud->skill_id, &ud->skill_lv, 1, 0) < 1 ) {
+ clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_NEED_HELPER, 0);
+ break;
+ }
if( ud->skill_id >= SL_SKE && ud->skill_id <= SL_SKA && target->type == BL_MOB )
{
@@ -4730,18 +4842,23 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
else if (inf && battle->check_target(src, target, inf) <= 0){
if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0);
break;
+ } else if( ud->skill_id == RK_PHANTOMTHRUST && target->type != BL_MOB ) {
+ if( !map_flag_vs(src->m) && battle->check_target(src,target,BCT_PARTY) <= 0 )
+ break; // You can use Phantom Thurst on party members in normal maps too. [pakpil]
}
- if(inf&BCT_ENEMY && (sc = status_get_sc(target)) &&
- sc->data[SC_FOGWALL] &&
- rnd() % 100 < 75) { //Fogwall makes all offensive-type targetted skills fail at 75%
- if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0);
- break;
+ if( inf&BCT_ENEMY
+ && (sc = status->get_sc(target)) && sc->data[SC_FOGWALL]
+ && rnd() % 100 < 75
+ ) {
+ // Fogwall makes all offensive-type targeted skills fail at 75%
+ if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0);
+ break;
}
}
//Avoid doing double checks for instant-cast skills.
- if (tid != INVALID_TIMER && !status_check_skilluse(src, target, ud->skill_id, 1))
+ if (tid != INVALID_TIMER && !status->check_skilluse(src, target, ud->skill_id, 1))
break;
if(md) {
@@ -4769,7 +4886,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,1);
}
#ifdef OFFICIAL_WALKPATH
- if( !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) )
+ if( !path->search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) )
break;
#endif
if( (src->type == BL_MER || src->type == BL_HOM) && !skill->check_condition_mercenary(src, ud->skill_id, ud->skill_lv, 1) )
@@ -4782,11 +4899,11 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
}
if (ud->walktimer != INVALID_TIMER && ud->skill_id != TK_RUN && ud->skill_id != RA_WUGDASH)
- unit_stop_walking(src,1);
+ unit->stop_walking(src,1);
if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) )
- ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv); //Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish]
- if (sd) { //Cooldown application
+ ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv); // Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish]
+ if (sd) { // Cooldown application
int i, cooldown = skill->get_cooldown(ud->skill_id, ud->skill_lv);
for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses.
if (sd->skillcooldown[i].id == ud->skill_id){
@@ -4795,7 +4912,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
}
}
if(cooldown)
- skill->blockpc_start(sd, ud->skill_id, cooldown, false);
+ skill->blockpc_start(sd, ud->skill_id, cooldown);
}
if( battle_config.display_status_timers && sd )
clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0);
@@ -4808,45 +4925,48 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
break;
case CR_GRANDCROSS:
case NPC_GRANDDARKNESS:
- if( (sc = status_get_sc(src)) && sc->data[SC_NOEQUIPSHIELD] )
- {
- const struct TimerData *timer = iTimer->get_timer(sc->data[SC_NOEQUIPSHIELD]->timer);
- if( timer && timer->func == status_change_timer && DIFF_TICK(timer->tick,iTimer->gettick()+skill->get_time(ud->skill_id, ud->skill_lv)) > 0 )
+ if( (sc = status->get_sc(src)) && sc->data[SC_NOEQUIPSHIELD] ) {
+ const struct TimerData *td = timer->get(sc->data[SC_NOEQUIPSHIELD]->timer);
+ if( td && td->func == status->change_timer && DIFF_TICK(td->tick,timer->gettick()+skill->get_time(ud->skill_id, ud->skill_lv)) > 0 )
break;
}
- sc_start2(src, SC_NOEQUIPSHIELD, 100, 0, 1, skill->get_time(ud->skill_id, ud->skill_lv));
+ sc_start2(src,src, SC_NOEQUIPSHIELD, 100, 0, 1, skill->get_time(ud->skill_id, ud->skill_lv));
break;
}
}
if (skill->get_state(ud->skill_id) != ST_MOVE_ENABLE)
- unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill->get_walkdelay(ud->skill_id, ud->skill_lv), 1);
+ unit->set_walkdelay(src, tick, battle_config.default_walk_delay+skill->get_walkdelay(ud->skill_id, ud->skill_lv), 1);
if(battle_config.skill_log && battle_config.skill_log&src->type)
ShowInfo("Type %d, ID %d skill castend id [id =%d, lv=%d, target ID %d]\n",
src->type, src->id, ud->skill_id, ud->skill_lv, target->id);
- iMap->freeblock_lock();
+ map->freeblock_lock();
// SC_MAGICPOWER needs to switch states before any damage is actually dealt
skill->toggle_magicpower(src, ud->skill_id);
+
+ /* On aegis damage skills are also increase by camouflage. Need confirmation on kRO.
if( ud->skill_id != RA_CAMOUFLAGE ) // only normal attack and auto cast skills benefit from its bonuses
status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);
+ */
if (skill->get_casttype(ud->skill_id) == CAST_NODAMAGE)
skill->castend_nodamage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag);
else
skill->castend_damage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag);
- sc = status_get_sc(src);
+ sc = status->get_sc(src);
if(sc && sc->count) {
- if(sc->data[SC_SOULLINK] &&
- sc->data[SC_SOULLINK]->val2 == SL_WIZARD &&
- sc->data[SC_SOULLINK]->val3 == ud->skill_id &&
- ud->skill_id != WZ_WATERBALL)
+ if( sc->data[SC_SOULLINK]
+ && sc->data[SC_SOULLINK]->val2 == SL_WIZARD
+ && sc->data[SC_SOULLINK]->val3 == ud->skill_id
+ && ud->skill_id != WZ_WATERBALL
+ )
sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check.
if( sc->data[SC_DANCING] && skill->get_inf2(ud->skill_id)&INF2_SONG_DANCE && sd )
- skill->blockpc_start(sd,BD_ADAPTATION,3000, false);
+ skill->blockpc_start(sd,BD_ADAPTATION,3000);
}
if( sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish]
@@ -4857,39 +4977,39 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
else ud->skill_id = 0; //mobs can't clear this one as it is used for skill condition 'afterskill'
ud->skill_lv = ud->skilltarget = 0;
}
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
} while(0);
//Skill failed.
- if (ud->skill_id == MO_EXTREMITYFIST && sd && !(sc && sc->data[SC_FOGWALL]))
- { //When Asura fails... (except when it fails from Fog of Wall)
+ if (ud->skill_id == MO_EXTREMITYFIST && sd && !(sc && sc->data[SC_FOGWALL])) {
+ //When Asura fails... (except when it fails from Fog of Wall)
//Consume SP/spheres
skill->consume_requirement(sd,ud->skill_id, ud->skill_lv,1);
- status_set_sp(src, 0, 0);
+ status->set_sp(src, 0, 0);
sc = &sd->sc;
if (sc->count)
{ //End states
status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER);
status_change_end(src, SC_BLADESTOP, INVALID_TIMER);
#ifdef RENEWAL
- sc_start(src, SC_EXTREMITYFIST2, 100, ud->skill_lv, skill->get_time(ud->skill_id, ud->skill_lv));
+ sc_start(src, src, SC_EXTREMITYFIST2, 100, ud->skill_lv, skill->get_time(ud->skill_id, ud->skill_lv));
#endif
}
- if (target && target->m == src->m)
- { //Move character to target anyway.
+ if (target && target->m == src->m) {
+ //Move character to target anyway.
int dir, x, y;
- dir = iMap->calc_dir(src,target->x,target->y);
+ dir = map->calc_dir(src,target->x,target->y);
if( dir > 0 && dir < 4) x = -2;
else if( dir > 4 ) x = 2;
else x = 0;
if( dir > 2 && dir < 6 ) y = -2;
else if( dir == 7 || dir < 2 ) y = 2;
else y = 0;
- if (unit_movepos(src, src->x+x, src->y+y, 1, 1))
+ if (unit->movepos(src, src->x+x, src->y+y, 1, 1))
{ //Display movement + animation.
clif->slide(src,src->x,src->y);
- clif->skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skill_id, ud->skill_lv, 5);
+ clif->spiritball(src);
}
clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0);
}
@@ -4911,8 +5031,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
/*==========================================
*
*------------------------------------------*/
-int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag)
-{
+int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
struct map_session_data *sd, *dstsd;
struct mob_data *md, *dstmd;
struct homun_data *hd;
@@ -4921,10 +5040,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
struct status_change *tsc;
struct status_change_entry *tsce;
- int i = 0;
+ int element = 0;
enum sc_type type;
- if(skill_id > 0 && !skill_lv) return 0; // celest
+ if(skill_id > 0 && !skill_lv) return 0; // [Celest]
nullpo_retr(1, src);
nullpo_retr(1, bl);
@@ -4942,10 +5061,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if(bl->prev == NULL)
return 1;
- if(status_isdead(src))
+ if(status->isdead(src))
return 1;
- if( src != bl && status_isdead(bl) ) {
+ if( src != bl && status->isdead(bl) ) {
/**
* Skills that may be cast on dead targets
**/
@@ -4960,41 +5079,94 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
}
}
- tstatus = status_get_status_data(bl);
- sstatus = status_get_status_data(src);
+ // Supportive skills that can't be cast in users with mado
+ if( sd && dstsd && pc_ismadogear(dstsd) ) {
+ switch( skill_id ) {
+ case AL_HEAL:
+ case AL_INCAGI:
+ case AL_DECAGI:
+ case AB_RENOVATIO:
+ case AB_HIGHNESSHEAL:
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0);
+ return 0;
+ default:
+ break;
+ }
+ }
+
+ tstatus = status->get_status_data(bl);
+ sstatus = status->get_status_data(src);
//Check for undead skills that convert a no-damage skill into a damage one. [Skotlex]
switch (skill_id) {
- case HLIF_HEAL: //[orn]
+ case HLIF_HEAL: // [orn]
if (bl->type != BL_HOM) {
if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0) ;
break ;
}
case AL_HEAL:
- case ALL_RESURRECTION:
- case PR_ASPERSIO:
+
/**
* Arch Bishop
**/
case AB_RENOVATIO:
case AB_HIGHNESSHEAL:
+ case AL_INCAGI:
+ case ALL_RESURRECTION:
+ case PR_ASPERSIO:
//Apparently only player casted skills can be offensive like this.
- if (sd && battle->check_undead(tstatus->race,tstatus->def_ele)) {
+ if (sd && battle->check_undead(tstatus->race,tstatus->def_ele) && skill_id != AL_INCAGI) {
if (battle->check_target(src, bl, BCT_ENEMY) < 1) {
//Offensive heal does not works on non-enemies. [Skotlex]
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
- return skill->castend_damage_id (src, bl, skill_id, skill_lv, tick, flag);
+ return skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, flag);
+ }
+ break;
+ case SO_ELEMENTAL_SHIELD:
+ {
+ struct party_data *p;
+ short ret = 0;
+ int x0, y0, x1, y1, range, i;
+
+ if(sd == NULL || !sd->ed)
+ break;
+ if((p = party->search(sd->status.party_id)) == NULL)
+ break;
+
+ range = skill_get_splash(skill_id,skill_lv);
+ x0 = sd->bl.x - range;
+ y0 = sd->bl.y - range;
+ x1 = sd->bl.x + range;
+ y1 = sd->bl.y + range;
+
+ elemental->delete(sd->ed,0);
+
+ if(!skill->check_unit_range(src,src->x,src->y,skill_id,skill_lv))
+ ret = skill->castend_pos2(src,src->x,src->y,skill_id,skill_lv,tick,flag);
+ for(i = 0; i < MAX_PARTY; i++) {
+ struct map_session_data *psd = p->data[i].sd;
+ if(!psd)
+ continue;
+ if(psd->bl.m != sd->bl.m || !psd->bl.prev)
+ continue;
+ if(range && (psd->bl.x < x0 || psd->bl.y < y0 ||
+ psd->bl.x > x1 || psd->bl.y > y1))
+ continue;
+ if(!skill->check_unit_range(bl,psd->bl.x,psd->bl.y,skill_id,skill_lv))
+ ret |= skill->castend_pos2(bl,psd->bl.x,psd->bl.y,skill_id,skill_lv,tick,flag);
+ }
+ return ret;
}
break;
case NPC_SMOKING: //Since it is a self skill, this one ends here rather than in damage_id. [Skotlex]
- return skill->castend_damage_id (src, bl, skill_id, skill_lv, tick, flag);
+ return skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, flag);
case MH_STEINWAND: {
struct block_list *s_src = battle->get_master(src);
short ret = 0;
if(!skill->check_unit_range(src, src->x, src->y, skill_id, skill_lv)) //prevent reiteration
- ret = skill->castend_pos2(src,src->x,src->y,skill_id,skill_lv,tick,flag); //cast on homon
+ ret = skill->castend_pos2(src,src->x,src->y,skill_id,skill_lv,tick,flag); //cast on homun
if(s_src && !skill->check_unit_range(s_src, s_src->x, s_src->y, skill_id, skill_lv))
ret |= skill->castend_pos2(s_src,s_src->x,s_src->y,skill_id,skill_lv,tick,flag); //cast on master
if (hd)
@@ -5012,9 +5184,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case RK_FIGHTINGSPIRIT:
case RK_ABUNDANCE:
if( sd && !pc->checkskill(sd, RK_RUNEMASTERY) ){
- if( status_change_start(&sd->bl, (sc_type)(rnd()%SC_CONFUSION), 1000, 1, 0, 0, 0, skill->get_time2(skill_id,skill_lv),8) ){
+ if( status->change_start(src,&sd->bl, (sc_type)(rnd()%SC_CONFUSION), 1000, 1, 0, 0, 0, skill->get_time2(skill_id,skill_lv),8) ){
skill->consume_requirement(sd,skill_id,skill_lv,2);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
}
@@ -5025,19 +5197,19 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
return skill->castend_pos2(src,bl->x,bl->y,skill_id,skill_lv,tick,0);
}
- type = status_skill2sc(skill_id);
- tsc = status_get_sc(bl);
+ type = status->skill2sc(skill_id);
+ tsc = status->get_sc(bl);
tsce = (tsc && type != -1)?tsc->data[type]:NULL;
if (src!=bl && type > -1 &&
- (i = skill->get_ele(skill_id, skill_lv)) > ELE_NEUTRAL &&
+ (element = skill->get_ele(skill_id, skill_lv)) > ELE_NEUTRAL &&
skill->get_inf(skill_id) != INF_SUPPORT_SKILL &&
- battle->attr_fix(NULL, NULL, 100, i, tstatus->def_ele, tstatus->ele_lv) <= 0)
+ battle->attr_fix(NULL, NULL, 100, element, tstatus->def_ele, tstatus->ele_lv) <= 0)
return 1; //Skills that cause an status should be blocked if the target element blocks its element.
- iMap->freeblock_lock();
+ map->freeblock_lock();
switch(skill_id) {
- case HLIF_HEAL: //[orn]
+ case HLIF_HEAL: // [orn]
case AL_HEAL:
/**
* Arch Bishop
@@ -5046,13 +5218,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
{
int heal = skill->calc_heal(src, bl, (skill_id == AB_HIGHNESSHEAL)?AL_HEAL:skill_id, (skill_id == AB_HIGHNESSHEAL)?10:skill_lv, true);
int heal_get_jobexp;
- //Highness Heal: starts at 1.5 boost + 0.5 for each level
+ //Highness Heal: starts at 1.7 boost + 0.3 for each level
if( skill_id == AB_HIGHNESSHEAL ) {
- heal = heal * ( 15 + 5 * skill_lv ) / 10;
+ heal = heal * ( 17 + 3 * skill_lv ) / 10;
}
- if( status_isimmune(bl) ||
- (dstmd && (dstmd->class_ == MOBID_EMPERIUM || mob_is_battleground(dstmd))) ||
- (dstsd && pc_ismadogear(dstsd)) )//Mado is immune to heal
+ if( status->isimmune(bl) ||
+ (dstmd && (dstmd->class_ == MOBID_EMPERIUM || mob_is_battleground(dstmd))) )
heal=0;
if( sd && dstsd && sd->status.partner_id == dstsd->status.char_id && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0 )
@@ -5071,13 +5242,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
dstsd = sd;
}
}
- else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAY_NIGHT_FEVER] || tsc->data[SC__BLOODYLUST])
+ else if (tsc->data[SC_BERSERK])
heal = 0; //Needed so that it actually displays 0 when healing.
}
clif->skill_nodamage (src, bl, skill_id, heal, 1);
if( tsc && tsc->data[SC_AKAITSUKI] && heal && skill_id != HLIF_HEAL )
heal = ~heal + 1;
- heal_get_jobexp = status_heal(bl,heal,0,0);
+ heal_get_jobexp = status->heal(bl,heal,0,0);
if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){
heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100;
@@ -5094,45 +5265,45 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
- skill_area_temp[0] = 0;
- party_foreachsamemap(skill->area_sub,
+ skill->area_temp[0] = 0;
+ party->foreachsamemap(skill->area_sub,
sd,skill->get_splash(skill_id, skill_lv),
src,skill_id,skill_lv,tick, flag|BCT_PARTY|1,
skill->castend_nodamage_id);
- if (skill_area_temp[0] == 0) {
+ if (skill->area_temp[0] == 0) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
- skill_area_temp[0] = 5 - skill_area_temp[0]; // The actual penalty...
- if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty) { //Apply penalty
- sd->status.base_exp -= min(sd->status.base_exp, pc->nextbaseexp(sd) * skill_area_temp[0] * 2/1000); //0.2% penalty per each.
- sd->status.job_exp -= min(sd->status.job_exp, pc->nextjobexp(sd) * skill_area_temp[0] * 2/1000);
+ skill->area_temp[0] = 5 - skill->area_temp[0]; // The actual penalty...
+ if (skill->area_temp[0] > 0 && !map->list[src->m].flag.noexppenalty) { //Apply penalty
+ sd->status.base_exp -= min(sd->status.base_exp, pc->nextbaseexp(sd) * skill->area_temp[0] * 2/1000); //0.2% penalty per each.
+ sd->status.job_exp -= min(sd->status.job_exp, pc->nextjobexp(sd) * skill->area_temp[0] * 2/1000);
clif->updatestatus(sd,SP_BASEEXP);
clif->updatestatus(sd,SP_JOBEXP);
}
- status_set_hp(src, 1, 0);
- status_set_sp(src, 0, 0);
+ status->set_hp(src, 1, 0);
+ status->set_sp(src, 0, 0);
break;
- } else if (status_isdead(bl) && flag&1) { //Revive
- skill_area_temp[0]++; //Count it in, then fall-through to the Resurrection code.
+ } else if (status->isdead(bl) && flag&1) { //Revive
+ skill->area_temp[0]++; //Count it in, then fall-through to the Resurrection code.
skill_lv = 3; //Resurrection level 3 is used
} else //Invalid target, skip resurrection.
break;
case ALL_RESURRECTION:
- if(sd && (map_flag_gvg(bl->m) || map[bl->m].flag.battleground))
- { //No reviving in WoE grounds!
+ if(sd && (map_flag_gvg2(bl->m) || map->list[bl->m].flag.battleground)) {
+ //No reviving in WoE grounds!
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
- if (!status_isdead(bl))
+ if (!status->isdead(bl))
break;
{
int per = 0, sper = 0;
if (tsc && tsc->data[SC_HELLPOWER])
break;
- if (map[bl->m].flag.pvp && dstsd && dstsd->pvp_point < 0)
+ if (map->list[bl->m].flag.pvp && dstsd && dstsd->pvp_point < 0)
break;
switch(skill_lv){
@@ -5143,7 +5314,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
}
if(dstsd && dstsd->special_state.restart_full_recover)
per = sper = 100;
- if (status_revive(bl, per, sper))
+ if (status->revive(bl, per, sper))
{
clif->skill_nodamage(src,bl,ALL_RESURRECTION,skill_lv,1); //Both Redemptio and Res show this skill-animation.
if(sd && dstsd && battle_config.resurrection_exp > 0)
@@ -5166,17 +5337,24 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case AL_DECAGI:
- case MER_DECAGI:
clif->skill_nodamage (src, bl, skill_id, skill_lv,
- sc_start(bl, type, (40 + skill_lv * 2 + (status_get_lv(src) + sstatus->int_)/5), skill_lv, skill->get_time(skill_id,skill_lv)));
+ sc_start(src, bl, type, (40 + skill_lv * 2 + (status->get_lv(src) + sstatus->int_)/5), skill_lv,
+ /* monsters using lvl 48 get the rate benefit but the duration of lvl 10 */
+ ( src->type == BL_MOB && skill_lv == 48 ) ? skill->get_time(skill_id,10) : skill->get_time(skill_id,skill_lv)));
+ break;
+
+ case MER_DECAGI:
+ if( tsc && !tsc->data[SC_ADORAMUS] ) //Prevent duplicate agi-down effect.
+ clif->skill_nodamage(src, bl, skill_id, skill_lv,
+ sc_start(src, bl, type, (40 + skill_lv * 2 + (status->get_lv(src) + sstatus->int_)/5), skill_lv, skill->get_time(skill_id,skill_lv)));
break;
case AL_CRUCIS:
if (flag&1)
- sc_start(bl,type, 23+skill_lv*4 +status_get_lv(src) -status_get_lv(bl), skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src, bl,type, 23+skill_lv*4 +status->get_lv(src) -status->get_lv(bl), skill_lv,skill->get_time(skill_id,skill_lv));
else {
- iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR,
- src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR,
+ src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
}
break;
@@ -5186,19 +5364,19 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( tsce )
status_change_end(bl,type, INVALID_TIMER);
else
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
clif->skill_nodamage (src, bl, skill_id, skill_lv, 1);
break;
case SA_ABRACADABRA:
{
- int abra_skill_id = 0, abra_skill_lv;
+ int abra_skill_id = 0, abra_skill_lv, abra_idx;
do {
- i = rnd() % MAX_SKILL_ABRA_DB;
- abra_skill_id = skill_abra_db[i].skill_id;
+ abra_idx = rnd() % MAX_SKILL_ABRA_DB;
+ abra_skill_id = skill->abra_db[abra_idx].skill_id;
} while (abra_skill_id == 0 ||
- skill_abra_db[i].req_lv > skill_lv || //Required lv for it to appear
- rnd()%10000 >= skill_abra_db[i].per
+ skill->abra_db[abra_idx].req_lv > skill_lv || //Required lv for it to appear
+ rnd()%10000 >= skill->abra_db[abra_idx].per
);
abra_skill_lv = min(skill_lv, skill->get_max(abra_skill_id));
clif->skill_nodamage (src, bl, skill_id, skill_lv, 1);
@@ -5212,14 +5390,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
}
else
{// mob-casted
- struct unit_data *ud = unit_bl2ud(src);
+ struct unit_data *ud = unit->bl2ud(src);
int inf = skill->get_inf(abra_skill_id);
if (!ud) break;
if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) {
if (src->type == BL_PET)
bl = (struct block_list*)((TBL_PET*)src)->msd;
if (!bl) bl = src;
- unit_skilluse_id(src, bl->id, abra_skill_id, abra_skill_lv);
+ unit->skilluse_id(src, bl->id, abra_skill_id, abra_skill_lv);
} else { //Assume offensive skills
int target_id = 0;
if (ud->target)
@@ -5231,11 +5409,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (!target_id)
break;
if (skill->get_casttype(abra_skill_id) == CAST_GROUND) {
- bl = iMap->id2bl(target_id);
+ bl = map->id2bl(target_id);
if (!bl) bl = src;
- unit_skilluse_pos(src, bl->x, bl->y, abra_skill_id, abra_skill_lv);
+ unit->skilluse_pos(src, bl->x, bl->y, abra_skill_id, abra_skill_lv);
} else
- unit_skilluse_id(src, target_id, abra_skill_id, abra_skill_lv);
+ unit->skilluse_id(src, target_id, abra_skill_id, abra_skill_lv);
}
}
}
@@ -5243,31 +5421,31 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SA_COMA:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv)));
+ sc_start(src, bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv)));
break;
case SA_FULLRECOVERY:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if (status_isimmune(bl))
+ if (status->isimmune(bl))
break;
status_percent_heal(bl, 100, 100);
break;
case NPC_ALLHEAL:
- {
- int heal;
- if( status_isimmune(bl) )
- break;
- heal = status_percent_heal(bl, 100, 0);
- clif->skill_nodamage(NULL, bl, AL_HEAL, heal, 1);
- if( dstmd )
- { // Reset Damage Logs
- memset(dstmd->dmglog, 0, sizeof(dstmd->dmglog));
- dstmd->tdmg = 0;
- }
+ {
+ int heal;
+ if( status->isimmune(bl) )
+ break;
+ heal = status_percent_heal(bl, 100, 0);
+ clif->skill_nodamage(NULL, bl, AL_HEAL, heal, 1);
+ if( dstmd ) {
+ // Reset Damage Logs
+ memset(dstmd->dmglog, 0, sizeof(dstmd->dmglog));
+ dstmd->tdmg = 0;
}
+ }
break;
case SA_SUMMONMONSTER:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if (sd) mob_once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_SMALL, AI_NONE);
+ if (sd) mob->once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_MEDIUM, AI_NONE);
break;
case SA_LEVELUP:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -5275,7 +5453,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case SA_INSTANTDEATH:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- status_set_hp(bl,1,0);
+ status->set_hp(bl,1,0);
break;
case SA_QUESTION:
case SA_GRAVITY:
@@ -5291,11 +5469,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
- class_ = skill_id==SA_MONOCELL?1002:mob_get_random_id(4, 1, 0);
+ class_ = skill_id==SA_MONOCELL?1002:mob->get_random_id(4, 1, 0);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- mob_class_change(dstmd,class_);
+ mob->class_change(dstmd,class_);
if( tsc && dstmd->status.mode&MD_BOSS )
{
+ int i;
const enum sc_type scs[] = { SC_QUAGMIRE, SC_PROVOKE, SC_ROKISWEIL, SC_GRAVITATION, SC_NJ_SUITON, SC_NOEQUIPWEAPON, SC_NOEQUIPSHIELD, SC_NOEQUIPARMOR, SC_NOEQUIPHELM, SC_BLADESTOP };
for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++)
if (tsc->data[i]) status_change_end(bl, (sc_type)i, INVALID_TIMER);
@@ -5314,19 +5493,21 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
status_kill(bl);
break;
case SA_REVERSEORCISH:
+ case ALL_REVERSEORCISH:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)));
+ sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)));
break;
case SA_FORTUNE:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if(sd) pc->getzeny(sd,status_get_lv(bl)*100,LOG_TYPE_STEAL,NULL);
+ if(sd) pc->getzeny(sd,status->get_lv(bl)*100,LOG_TYPE_STEAL,NULL);
break;
case SA_TAMINGMONSTER:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
if (sd && dstmd) {
- ARR_FIND( 0, MAX_PET_DB, i, dstmd->class_ == pet_db[i].class_ );
+ int i;
+ ARR_FIND( 0, MAX_PET_DB, i, dstmd->class_ == pet->db[i].class_ );
if( i < MAX_PET_DB )
- pet_catch_process1(sd, dstmd->class_);
+ pet->catch_process1(sd, dstmd->class_);
}
break;
@@ -5334,46 +5515,39 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if(sd && dstsd){ //Check they are not another crusader [Skotlex]
if ((dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
break;
case CG_MARIONETTE:
{
- struct status_change* sc = status_get_sc(src);
+ struct status_change* sc = status->get_sc(src);
- if( sd && dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && dstsd->status.sex == sd->status.sex )
- {// Cannot cast on another bard/dancer-type class of the same gender as caster
+ if( sd && dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && dstsd->status.sex == sd->status.sex ) {
+ // Cannot cast on another bard/dancer-type class of the same gender as caster
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
- if( sc && tsc )
- {
- if( !sc->data[SC_MARIONETTE_MASTER] && !tsc->data[SC_MARIONETTE] )
- {
- sc_start(src,SC_MARIONETTE_MASTER,100,bl->id,skill->get_time(skill_id,skill_lv));
- sc_start(bl,SC_MARIONETTE,100,src->id,skill->get_time(skill_id,skill_lv));
+ if( sc && tsc ) {
+ if( !sc->data[SC_MARIONETTE_MASTER] && !tsc->data[SC_MARIONETTE] ) {
+ sc_start(src,src,SC_MARIONETTE_MASTER,100,bl->id,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_MARIONETTE,100,src->id,skill->get_time(skill_id,skill_lv));
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- }
- else
- if( sc->data[SC_MARIONETTE_MASTER ] && sc->data[SC_MARIONETTE_MASTER ]->val1 == bl->id &&
- tsc->data[SC_MARIONETTE] && tsc->data[SC_MARIONETTE]->val1 == src->id )
- {
+ } else if( sc->data[SC_MARIONETTE_MASTER ] && sc->data[SC_MARIONETTE_MASTER ]->val1 == bl->id
+ && tsc->data[SC_MARIONETTE] && tsc->data[SC_MARIONETTE]->val1 == src->id
+ ) {
status_change_end(src, SC_MARIONETTE_MASTER, INVALID_TIMER);
status_change_end(bl, SC_MARIONETTE, INVALID_TIMER);
- }
- else
- {
+ } else {
if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
-
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
}
@@ -5382,7 +5556,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case RG_CLOSECONFINE:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start4(bl,type,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv)));
+ sc_start4(src,bl,type,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv)));
break;
case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris]
case SA_FROSTWEAPON:
@@ -5391,7 +5565,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (dstsd) {
if(dstsd->status.weapon == W_FIST ||
(dstsd->sc.count && !dstsd->sc.data[type] &&
- ( //Allow re-enchanting to lenghten time. [Skotlex]
+ ( //Allow re-enchanting to lengthen time. [Skotlex]
dstsd->sc.data[SC_PROPERTYFIRE] ||
dstsd->sc.data[SC_PROPERTYWATER] ||
dstsd->sc.data[SC_PROPERTYWIND] ||
@@ -5407,11 +5581,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
}
}
// 100% success rate at lv4 & 5, but lasts longer at lv5
- if(!clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,type,(60+skill_lv*10),skill_lv, skill->get_time(skill_id,skill_lv)))) {
+ if(!clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src,bl,type,(60+skill_lv*10),skill_lv, skill->get_time(skill_id,skill_lv)))) {
if (sd)
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
if (skill->break_equip(bl, EQP_WEAPON, 10000, BCT_PARTY) && sd && sd != dstsd)
- clif->message(sd->fd, msg_txt(669));
+ clif->message(sd->fd, msg_txt(869)); // "You broke the target's weapon."
}
break;
@@ -5421,12 +5595,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
break;
case ITEM_ENCHANTARMS:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start2(bl,type,100,skill_lv,
+ sc_start2(src,bl,type,100,skill_lv,
skill->get_ele(skill_id,skill_lv), skill->get_time(skill_id,skill_lv)));
break;
@@ -5441,37 +5615,37 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case ELE_HOLY : type = SC_ASPERSIO; break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
- sc_start2(bl,SC_TK_SEVENWIND,100,skill_lv,skill->get_ele(skill_id,skill_lv),skill->get_time(skill_id,skill_lv));
+ sc_start2(src,bl,SC_TK_SEVENWIND,100,skill_lv,skill->get_ele(skill_id,skill_lv),skill->get_time(skill_id,skill_lv));
break;
case PR_KYRIE:
case MER_KYRIE:
clif->skill_nodamage(bl,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
break;
//Passive Magnum, should had been casted on yourself.
case SM_MAGNUM:
case MS_MAGNUM:
- skill_area_temp[1] = 0;
- iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_SKILL|BL_CHAR,
- src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
+ skill->area_temp[1] = 0;
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_SKILL|BL_CHAR,
+ src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
clif->skill_nodamage (src,src,skill_id,skill_lv,1);
// Initiate 10% of your damage becomes fire element.
- sc_start4(src,SC_WATK_ELEMENT,100,3,20,0,0,skill->get_time2(skill_id, skill_lv));
+ sc_start4(src,src,SC_SUB_WEAPONPROPERTY,100,3,20,0,0,skill->get_time2(skill_id, skill_lv));
if( sd )
- skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv), false);
+ skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv));
else if( bl->type == BL_MER )
skill->blockmerc_start((TBL_MER*)bl, skill_id, skill->get_time(skill_id, skill_lv));
break;
case TK_JUMPKICK:
- /* Check if the target is an enemy; if not, skill should fail so the character doesn't unit_movepos (exploitable) */
+ /* Check if the target is an enemy; if not, skill should fail so the character doesn't unit->movepos (exploitable) */
if( battle->check_target(src, bl, BCT_ENEMY) > 0 )
{
- if( unit_movepos(src, bl->x, bl->y, 1, 1) )
+ if( unit->movepos(src, bl->x, bl->y, 1, 1) )
{
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
clif->slide(src,bl->x,bl->y);
@@ -5496,7 +5670,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case PR_BENEDICTIO:
case LK_BERSERK:
case MS_BERSERK:
- case KN_AUTOCOUNTER:
case KN_TWOHANDQUICKEN:
case KN_ONEHAND:
case MER_QUICKEN:
@@ -5548,6 +5721,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NC_SHAPESHIFT:
case WL_RECOGNIZEDSPELL:
case GC_VENOMIMPRESS:
+ case SC_INVISIBILITY:
case SC_DEADLYINFECT:
case LG_EXEEDBREAK:
case LG_PRESTIGE:
@@ -5564,8 +5738,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case RK_VITALITYACTIVATION:
case RK_ABUNDANCE:
case RK_CRUSHSTRIKE:
+ case ALL_ODINS_POWER:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ break;
+
+ case KN_AUTOCOUNTER:
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ skill->addtimerskill(src, tick + 100, bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
break;
case SO_STRIKING:
@@ -5574,7 +5754,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
bonus += (pc->checkskill(sd, SA_FLAMELAUNCHER)+pc->checkskill(sd, SA_FROSTWEAPON)+pc->checkskill(sd, SA_LIGHTNINGLOADER)+pc->checkskill(sd, SA_SEISMICWEAPON))*5;
clif->skill_nodamage( src, bl, skill_id, skill_lv,
battle->check_target(src,bl,BCT_PARTY) > 0 ?
- sc_start2(bl, type, 100, skill_lv, bonus, skill->get_time(skill_id,skill_lv)) :
+ sc_start2(src, bl, type, 100, skill_lv, bonus, skill->get_time(skill_id,skill_lv)) :
0
);
}
@@ -5582,15 +5762,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NPC_STOP:
if( clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)) ) )
- sc_start2(src,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv));
+ sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)) ) )
+ sc_start2(src,src,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv));
break;
case HP_ASSUMPTIO:
if( sd && dstmd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
else
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
break;
case MG_SIGHT:
case MER_SIGHT:
@@ -5600,40 +5780,48 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NPC_STONESKIN:
case NPC_ANTIMAGIC:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start2(bl,type,100,skill_lv,skill_id,skill->get_time(skill_id,skill_lv)));
+ sc_start2(src,bl,type,100,skill_lv,skill_id,skill->get_time(skill_id,skill_lv)));
break;
case HLIF_AVOID:
case HAMI_DEFENCE:
- i = skill->get_time(skill_id,skill_lv);
- clif->skill_nodamage(bl,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,i)); // Master
- clif->skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,type,100,skill_lv,i)); // Homunc
+ {
+ int duration = skill->get_time(skill_id,skill_lv);
+ clif->skill_nodamage(bl,bl,skill_id,skill_lv,sc_start(src,bl,type,100,skill_lv,duration)); // Master
+ clif->skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,src,type,100,skill_lv,duration)); // Homun
+ }
break;
case NJ_BUNSINJYUTSU:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
status_change_end(bl, SC_NJ_NEN, INVALID_TIMER);
break;
- /* Was modified to only affect targetted char. [Skotlex]
+#if 0 /* Was modified to only affect targetted char. [Skotlex] */
case HP_ASSUMPTIO:
if (flag&1)
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- else
- {
- iMap->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv), BL_PC,
- src, skill_id, skill_lv, tick, flag|BCT_ALL|1,
- skill->castend_nodamage_id);
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ else {
+ map->foreachinrange(skill->area_sub, bl,
+ skill->get_splash(skill_id, skill_lv), BL_PC,
+ src, skill_id, skill_lv, tick, flag|BCT_ALL|1,
+ skill->castend_nodamage_id);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
}
break;
- */
+#endif // 0
case SM_ENDURE:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
if (sd)
- skill->blockpc_start (sd, skill_id, skill->get_time2(skill_id,skill_lv), false);
+ skill->blockpc_start (sd, skill_id, skill->get_time2(skill_id,skill_lv));
break;
+ case ALL_ANGEL_PROTECT:
+ if( dstsd )
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ else if( sd )
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ break;
case AS_ENCHANTPOISON: // Prevent spamming [Valaris]
if (sd && dstsd && dstsd->sc.count) {
if (dstsd->sc.data[SC_PROPERTYFIRE] ||
@@ -5650,12 +5838,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
}
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
break;
case LK_TENSIONRELAX:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start4(bl,type,100,skill_lv,0,0,skill->get_time2(skill_id,skill_lv),
+ sc_start4(src,bl,type,100,skill_lv,0,0,skill->get_time2(skill_id,skill_lv),
skill->get_time(skill_id,skill_lv)));
break;
@@ -5671,48 +5859,48 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
- id = mob_get_random_id(0,0xF, sd->status.base_level);
+ id = mob->get_random_id(0,0xF, sd->status.base_level);
if (!id) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
sd->mission_mobid = id;
sd->mission_count = 0;
- pc_setglobalreg(sd,"TK_MISSION_ID", id);
+ pc_setglobalreg(sd,script->add_str("TK_MISSION_ID"), id);
clif->mission_info(sd, id, 0);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
}
break;
case AC_CONCENTRATION:
- {
- clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
- iMap->foreachinrange( status_change_timer_sub, src,
- skill->get_splash(skill_id, skill_lv), BL_CHAR,
- src,NULL,type,tick);
- }
+ {
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ map->foreachinrange(status->change_timer_sub, src,
+ skill->get_splash(skill_id, skill_lv), BL_CHAR,
+ src,NULL,type,tick);
+ }
break;
case SM_PROVOKE:
case SM_SELFPROVOKE:
case MER_PROVOKE:
- if( (tstatus->mode&MD_BOSS) || battle->check_undead(tstatus->race,tstatus->def_ele) )
- {
- iMap->freeblock_unlock();
+ {
+ int failure;
+ if( (tstatus->mode&MD_BOSS) || battle->check_undead(tstatus->race,tstatus->def_ele) ) {
+ map->freeblock_unlock();
return 1;
}
//TODO: How much does base level affects? Dummy value of 1% per level difference used. [Skotlex]
clif->skill_nodamage(src,bl,skill_id == SM_SELFPROVOKE ? SM_PROVOKE : skill_id,skill_lv,
- (i = sc_start(bl,type, skill_id == SM_SELFPROVOKE ? 100:( 50 + 3*skill_lv + status_get_lv(src) - status_get_lv(bl)), skill_lv, skill->get_time(skill_id,skill_lv))));
- if( !i )
- {
+ (failure = sc_start(src,bl,type, skill_id == SM_SELFPROVOKE ? 100:( 50 + 3*skill_lv + status->get_lv(src) - status->get_lv(bl)), skill_lv, skill->get_time(skill_id,skill_lv))));
+ if( !failure ) {
if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
- unit_skillcastcancel(bl, 2);
+ unit->skillcastcancel(bl, 2);
if( tsc && tsc->count )
{
@@ -5726,14 +5914,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( dstmd )
{
dstmd->state.provoke_flag = src->id;
- mob_target(dstmd, src, skill->get_range2(src,skill_id,skill_lv));
+ mob->target(dstmd, src, skill->get_range2(src,skill_id,skill_lv));
}
+ }
break;
case ML_DEVOTION:
case CR_DEVOTION:
{
- int count, lv;
+ int count, lv, i;
if( !dstsd || (!sd && !mer) )
{ // Only players can be devoted
if( sd )
@@ -5741,7 +5930,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
}
- if( (lv = status_get_lv(src) - dstsd->status.base_level) < 0 )
+ if( (lv = status->get_lv(src) - dstsd->status.base_level) < 0 )
lv = -lv;
if( lv > battle_config.devotion_level_difference || // Level difference requeriments
(dstsd->sc.data[type] && dstsd->sc.data[type]->val1 != src->id) || // Cannot Devote a player devoted from another source
@@ -5751,7 +5940,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
{
if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
@@ -5763,10 +5952,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( i == count )
{
ARR_FIND(0, count, i, sd->devotion[i] == 0 );
- if( i == count )
- { // No free slots, skill Fail
+ if( i == count ) {
+ // No free slots, skill Fail
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
}
@@ -5777,7 +5966,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
mer->devotion_flag = 1; // Mercenary Devoting Owner
clif->skill_nodamage(src, bl, skill_id, skill_lv,
- sc_start4(bl, type, 100, src->id, i, skill->get_range2(src,skill_id,skill_lv),0, skill->get_time2(skill_id, skill_lv)));
+ sc_start4(src, bl, type, 100, src->id, i, skill->get_range2(src,skill_id,skill_lv),0, skill->get_time2(skill_id, skill_lv)));
clif->devotion(src, NULL);
}
break;
@@ -5794,7 +5983,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case CH_SOULCOLLECT:
if(sd) {
- int limit = 5;
+ int limit = 5, i;
if( sd->sc.data[SC_RAISINGDRAGON] )
limit += sd->sc.data[SC_RAISINGDRAGON]->val1;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -5804,32 +5993,34 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case MO_KITRANSLATION:
- if(dstsd && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) {
+ if(dstsd && ((dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK)!=MAPID_REBELLION)) {
pc->addspiritball(dstsd,skill->get_time(skill_id,skill_lv),5);
}
break;
case TK_TURNKICK:
case MO_BALKYOUNG: //Passive part of the attack. Splash knock-back+stun. [Skotlex]
- if (skill_area_temp[1] != bl->id) {
+ if (skill->area_temp[1] != bl->id) {
skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),-1,0);
skill->additional_effect(src,bl,skill_id,skill_lv,BF_MISC,ATK_DEF,tick); //Use Misc rather than weapon to signal passive pushback
}
break;
case MO_ABSORBSPIRITS:
- i = 0;
- if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER)
+ {
+ int sp = 0;
+ if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m) || (sd->duel_group && sd->duel_group == dstsd->duel_group)) && ((dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK)!=MAPID_REBELLION))
{ // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen]
- i = dstsd->spiritball * 7;
+ sp = dstsd->spiritball * 7;
pc->delspiritball(dstsd,dstsd->spiritball,0);
} else if (dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20)
{ // check if target is a monster and not a Boss, for the 20% chance to absorb 2 SP per monster's level [Reddozen]
- i = 2 * dstmd->level;
- mob_target(dstmd,src,0);
+ sp = 2 * dstmd->level;
+ mob->target(dstmd,src,0);
}
- if (i) status_heal(src, 0, i, 3);
- clif->skill_nodamage(src,bl,skill_id,skill_lv,i?1:0);
+ if (sp) status->heal(src, 0, sp, 3);
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sp?1:0);
+ }
break;
case AC_MAKINGARROW:
@@ -5855,15 +6046,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case BS_HAMMERFALL:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,SC_STUN,(20 + 10 * skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)));
+ sc_start(src,bl,SC_STUN,(20 + 10 * skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)));
break;
case RG_RAID:
- skill_area_temp[1] = 0;
+ skill->area_temp[1] = 0;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
- src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
- skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl,
+ skill->get_splash(skill_id, skill_lv), splash_target(src),
+ src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
+ skill->castend_damage_id);
status_change_end(src, SC_HIDING, INVALID_TIMER);
break;
@@ -5876,12 +6067,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SR_RAMPAGEBLASTER:
case SR_HOWLINGOFLION:
case KO_HAPPOKUNAI:
- skill_area_temp[1] = 0;
+ {
+ int count = 0;
+ skill->area_temp[1] = 0;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- i = iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src),
- src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
- if( !i && ( skill_id == NC_AXETORNADO || skill_id == SR_SKYNETBLOW || skill_id == KO_HAPPOKUNAI ) )
+ count = map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src),
+ src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+ if( !count && ( skill_id == NC_AXETORNADO || skill_id == SR_SKYNETBLOW || skill_id == KO_HAPPOKUNAI ) )
clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
+ }
break;
case NC_EMERGENCYCOOL:
@@ -5911,36 +6105,38 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
//Passive side of the attack.
status_change_end(src, SC_SIGHT, INVALID_TIMER);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinrange(skill->area_sub,src,
- skill->get_splash(skill_id, skill_lv),BL_CHAR|BL_SKILL,
- src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
- skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub,src,
+ skill->get_splash(skill_id, skill_lv),BL_CHAR|BL_SKILL,
+ src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
+ skill->castend_damage_id);
break;
case NJ_HYOUSYOURAKU:
case NJ_RAIGEKISAI:
case WZ_FROSTNOVA:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- skill_area_temp[1] = 0;
- iMap->foreachinrange(skill->attack_area, src,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
- BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
+ skill->area_temp[1] = 0;
+ map->foreachinrange(skill->attack_area, src,
+ skill->get_splash(skill_id, skill_lv), splash_target(src),
+ BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
break;
- case HVAN_EXPLOSION: //[orn]
+ case HVAN_EXPLOSION: // [orn]
case NPC_SELFDESTRUCTION:
+ {
//Self Destruction hits everyone in range (allies+enemies)
//Except for Summoned Marine spheres on non-versus maps, where it's just enemy.
- i = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))?
+ int targetmask = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))?
BCT_ENEMY:BCT_ALL;
clif->skill_nodamage(src, src, skill_id, -1, 1);
- iMap->delblock(src); //Required to prevent chain-self-destructions hitting back.
- iMap->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
- src, skill_id, skill_lv, tick, flag|i,
- skill->castend_damage_id);
- iMap->addblock(src);
- status_damage(src, src, sstatus->max_hp,0,0,1);
+ map->delblock(src); //Required to prevent chain-self-destructions hitting back.
+ map->foreachinrange(skill->area_sub, bl,
+ skill->get_splash(skill_id, skill_lv), splash_target(src),
+ src, skill_id, skill_lv, tick, flag|targetmask,
+ skill->castend_damage_id);
+ map->addblock(src);
+ status->damage(src, src, sstatus->max_hp,0,0,1);
+ }
break;
case AL_ANGELUS:
@@ -5952,18 +6148,18 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case CASH_ASSUMPTIO:
case WM_FRIGG_SONG:
if( sd == NULL || sd->status.party_id == 0 || (flag & 1) )
- clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
else if( sd )
- party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
+ party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
break;
case MER_MAGNIFICAT:
if( mer != NULL )
{
- clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
if( mer->master && mer->master->status.party_id != 0 && !(flag&1) )
- party_foreachsamemap(skill->area_sub, mer->master, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
+ party->foreachsamemap(skill->area_sub, mer->master, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
else if( mer->master && !(flag&1) )
- clif->skill_nodamage(src, &mer->master->bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(src, &mer->master->bl, skill_id, skill_lv, sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
}
break;
@@ -5973,9 +6169,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case BS_OVERTHRUST:
if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) {
clif->skill_nodamage(bl,bl,skill_id,skill_lv,
- sc_start2(bl,type,100,skill_lv,(src == bl)? 1:0,skill->get_time(skill_id,skill_lv)));
+ sc_start2(src,bl,type,100,skill_lv,(src == bl)? 1:0,skill->get_time(skill_id,skill_lv)));
} else if (sd) {
- party_foreachsamemap(skill->area_sub,
+ party->foreachsamemap(skill->area_sub,
sd,skill->get_splash(skill_id, skill_lv),
src,skill_id,skill_lv,tick, flag|BCT_PARTY|1,
skill->castend_nodamage_id);
@@ -5999,10 +6195,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( tsce )
{
clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER));
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
- clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
break;
case SL_KAITE:
case SL_KAAHI:
@@ -6010,75 +6206,80 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SL_KAUPE:
if (sd) {
if (!dstsd || !(
- (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_SOULLINKER) ||
- (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER ||
- dstsd->status.char_id == sd->status.char_id ||
- dstsd->status.char_id == sd->status.partner_id ||
- dstsd->status.char_id == sd->status.child
- )) {
- status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,8);
+ (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_SOULLINKER)
+ || (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER
+ || dstsd->status.char_id == sd->status.char_id
+ || dstsd->status.char_id == sd->status.partner_id
+ || dstsd->status.char_id == sd->status.child
+ )
+ ) {
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,8);
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)));
break;
case SM_AUTOBERSERK:
case MER_AUTOBERSERK:
+ {
+ int failure;
if( tsce )
- i = status_change_end(bl, type, INVALID_TIMER);
+ failure = status_change_end(bl, type, INVALID_TIMER);
else
- i = sc_start(bl,type,100,skill_lv,60000);
- clif->skill_nodamage(src,bl,skill_id,skill_lv,i);
+ failure = sc_start(src,bl,type,100,skill_lv,60000);
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,failure);
+ }
break;
case TF_HIDING:
case ST_CHASEWALK:
case KO_YAMIKUMO:
- if (tsce)
- {
+ if (tsce) {
clif->skill_nodamage(src,bl,skill_id,-1,status_change_end(bl, type, INVALID_TIMER)); //Hide skill-scream animation.
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
} else if( tsc && tsc->option&OPTION_MADOGEAR ) {
//Mado Gear cannot hide
if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
- clif->skill_nodamage(src,bl,skill_id,-1,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(src,bl,skill_id,-1,sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
break;
case TK_RUN:
- if (tsce)
- {
+ if (tsce) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER));
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
- clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit_getdir(bl),0,0,0));
- if (sd) // If the client receives a skill-use packet inmediately before a walkok packet, it will discard the walk packet! [Skotlex]
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,bl,type,100,skill_lv,unit->getdir(bl),0,0,0));
+ if (sd) // If the client receives a skill-use packet immediately before a walkok packet, it will discard the walk packet! [Skotlex]
clif->walkok(sd); // So aegis has to resend the walk ok.
break;
case AS_CLOAKING:
case GC_CLOAKINGEXCEED:
case LG_FORCEOFVANGUARD:
case SC_REPRODUCE:
- case SC_INVISIBILITY:
if (tsce) {
- i = status_change_end(bl, type, INVALID_TIMER);
- if( i )
- clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,i);
+ int failure = status_change_end(bl, type, INVALID_TIMER);
+ if( failure )
+ clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure);
else if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ if ( skill_id == LG_FORCEOFVANGUARD )
+ break;
+ map->freeblock_unlock();
return 0;
}
case RA_CAMOUFLAGE:
- i = sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- if( i )
- clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,i);
+ {
+ int failure = sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ if( failure )
+ clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure);
else if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ }
break;
case BD_ADAPTATION:
@@ -6097,27 +6298,25 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
// custom hack to make the mob display the skill, because these skills don't show the skill use text themselves
//NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches)
char temp[70];
- snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill_db[skill_id].desc);
+ snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill->db[skill_id].desc);
clif->disp_overhead(&md->bl,temp);
}
break;
case BA_PANGVOICE:
- clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,50,7,skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src,bl,SC_CONFUSION,50,7,skill->get_time(skill_id,skill_lv)));
break;
case DC_WINKCHARM:
if( dstsd )
- clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,30,7,skill->get_time2(skill_id,skill_lv)));
- else
- if( dstmd )
- {
- if( status_get_lv(src) > status_get_lv(bl)
- && (tstatus->race == RC_DEMON || tstatus->race == RC_DEMIHUMAN || tstatus->race == RC_ANGEL)
- && !(tstatus->mode&MD_BOSS) )
- clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start2(bl,type,70,skill_lv,src->id,skill->get_time(skill_id,skill_lv)));
- else
- {
+ clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src,bl,SC_CONFUSION,30,7,skill->get_time2(skill_id,skill_lv)));
+ else if( dstmd ) {
+ if( status->get_lv(src) > status->get_lv(bl)
+ && (tstatus->race == RC_DEMON || tstatus->race == RC_DEMIHUMAN || tstatus->race == RC_ANGEL)
+ && !(tstatus->mode&MD_BOSS)
+ ) {
+ clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start2(src,bl,type,70,skill_lv,src->id,skill->get_time(skill_id,skill_lv)));
+ } else {
clif->skill_nodamage(src,bl,skill_id,skill_lv,0);
if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
}
@@ -6135,15 +6334,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case RG_STEALCOIN:
if(sd) {
- if(pc->steal_coin(sd,bl))
- {
+ int amount = pc->steal_coin(sd, bl);
+ if( amount > 0 ) {
dstmd->state.provoke_flag = src->id;
- mob_target(dstmd, src, skill->get_range2(src,skill_id,skill_lv));
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ mob->target(dstmd, src, skill->get_range2(src, skill_id, skill_lv));
+ clif->skill_nodamage(src, bl, skill_id, amount, 1);
- }
- else
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ } else
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
}
break;
@@ -6154,7 +6352,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
- if(status_isimmune(bl) || !tsc)
+ if(status->isimmune(bl) || !tsc)
break;
if (sd && sd->sc.data[SC_PETROLOGY_OPTION])
@@ -6165,16 +6363,16 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
- if (sc_start4(bl,SC_STONE,(skill_lv*4+20)+brate,
+ if (sc_start4(src,bl,SC_STONE,(skill_lv*4+20)+brate,
skill_lv, 0, 0, skill->get_time(skill_id, skill_lv),
skill->get_time2(skill_id,skill_lv)))
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
else if(sd) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
// Level 6-10 doesn't consume a red gem if it fails [celest]
- if (skill_lv > 5)
- { // not to consume items
- iMap->freeblock_unlock();
+ if (skill_lv > 5) {
+ // not to consume items
+ map->freeblock_unlock();
return 0;
}
}
@@ -6183,11 +6381,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NV_FIRSTAID:
clif->skill_nodamage(src,bl,skill_id,5,1);
- status_heal(bl,5,0,0);
+ status->heal(bl,5,0,0);
break;
case AL_CURE:
- if(status_isimmune(bl)) {
+ if(status->isimmune(bl)) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,0);
break;
}
@@ -6204,7 +6402,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case PR_STRECOVERY:
- if(status_isimmune(bl)) {
+ if(status->isimmune(bl)) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,0);
break;
}
@@ -6217,14 +6415,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
}
//Is this equation really right? It looks so... special.
if( battle->check_undead(tstatus->race,tstatus->def_ele) ) {
- status_change_start(bl, SC_BLIND,
- 100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)),
- 1,0,0,0,
- skill->get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,0);
+ status->change_start(src, bl, SC_BLIND,
+ 100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)), 1,0,0,0,
+ skill->get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,0);
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
if(dstmd)
- mob_unlocktarget(dstmd,tick);
+ mob->unlocktarget(dstmd,tick);
break;
// Mercenary Supportive Skills
@@ -6258,10 +6455,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case MER_SCAPEGOAT:
- if( mer && mer->master )
- {
- status_heal(&mer->master->bl, mer->battle_status.hp, 0, 2);
- status_damage(src, src, mer->battle_status.max_hp, 0, 0, 1);
+ if( mer && mer->master ) {
+ status->heal(&mer->master->bl, mer->battle_status.hp, 0, 2);
+ status->damage(src, src, mer->battle_status.max_hp, 0, 0, 1);
}
break;
@@ -6294,11 +6490,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case MC_IDENTIFY:
if(sd) {
clif->item_identify_list(sd);
- if( sd->menuskill_id != MC_IDENTIFY ) {/* failed, dont consume anything, return */
- iMap->freeblock_unlock();
+ if( sd->menuskill_id != MC_IDENTIFY ) {/* failed, don't consume anything, return */
+ map->freeblock_unlock();
return 1;
}
- status_zap(src,0,skill_db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded
+ status_zap(src,0,skill->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded
}
break;
@@ -6313,7 +6509,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case MC_VENDING:
if(sd)
{ //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex]
- if ( !pc->can_give_items(sd) )
+ if ( !pc_can_give_items(sd) )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
else {
sd->state.prevend = sd->state.workinprogress = 3;
@@ -6323,9 +6519,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case AL_TELEPORT:
- if(sd)
- {
- if (map[bl->m].flag.noteleport && skill_lv <= 2) {
+ if(sd) {
+ if (map->list[bl->m].flag.noteleport && skill_lv <= 2) {
clif->skill_mapinfomessage(sd,0);
break;
}
@@ -6350,12 +6545,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
else
clif->skill_warppoint(sd,skill_id,skill_lv, (unsigned short)-1,sd->status.save_point.map,0,0);
} else
- unit_warp(bl,-1,-1,-1,CLR_TELEPORT);
+ unit->warp(bl,-1,-1,-1,CLR_TELEPORT);
break;
case NPC_EXPULSION:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- unit_warp(bl,-1,-1,-1,CLR_TELEPORT);
+ unit->warp(bl,-1,-1,-1,CLR_TELEPORT);
break;
case AL_HOLYWATER:
@@ -6382,7 +6577,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
eflag = pc->additem(sd,&item_tmp,1,LOG_TYPE_PRODUCE);
if(eflag) {
clif->additem(sd,0,0,eflag);
- iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
break;
@@ -6401,18 +6596,18 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case GC_WEAPONCRUSH:
case SC_STRIPACCESSARY: {
unsigned short location = 0;
- int d = 0;
+ int d = 0, rate;
//Rate in percent
if ( skill_id == ST_FULLSTRIP ) {
- i = 5 + 2*skill_lv + (sstatus->dex - tstatus->dex)/5;
+ rate = 5 + 2*skill_lv + (sstatus->dex - tstatus->dex)/5;
} else if( skill_id == SC_STRIPACCESSARY ) {
- i = 12 + 2 * skill_lv + (sstatus->dex - tstatus->dex)/5;
+ rate = 12 + 2 * skill_lv + (sstatus->dex - tstatus->dex)/5;
} else {
- i = 5 + 5*skill_lv + (sstatus->dex - tstatus->dex)/5;
+ rate = 5 + 5*skill_lv + (sstatus->dex - tstatus->dex)/5;
}
- if (i < 5) i = 5; //Minimum rate 5%
+ if (rate < 5) rate = 5; //Minimum rate 5%
//Duration in ms
if( skill_id == GC_WEAPONCRUSH){
@@ -6456,78 +6651,82 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
}
//Attempts to strip at rate i and duration d
- if( (i = skill->strip_equip(bl, location, i, skill_lv, d)) || (skill_id != ST_FULLSTRIP && skill_id != GC_WEAPONCRUSH ) )
- clif->skill_nodamage(src,bl,skill_id,skill_lv,i);
+ if( (rate = skill->strip_equip(bl, location, rate, skill_lv, d)) || (skill_id != ST_FULLSTRIP && skill_id != GC_WEAPONCRUSH ) )
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,rate);
//Nothing stripped.
- if( sd && !i )
+ if( sd && !rate )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
case AM_BERSERKPITCHER:
- case AM_POTIONPITCHER: {
+ case AM_POTIONPITCHER:
+ {
int i,sp = 0;
int64 hp = 0;
if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) {
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
if( sd ) {
- int x,bonus=100;
+ int x,bonus=100, potion = min(500+skill_lv,505);
x = skill_lv%11 - 1;
- i = pc->search_inventory(sd,skill_db[skill_id].itemid[x]);
- if( i < 0 || skill_db[skill_id].itemid[x] <= 0 ) {
+ i = pc->search_inventory(sd,skill->db[skill_id].itemid[x]);
+ if (i == INDEX_NOT_FOUND || skill->db[skill_id].itemid[x] <= 0) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
- if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skill_id].amount[x]) {
+ if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill->db[skill_id].amount[x]) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
if( skill_id == AM_BERSERKPITCHER ) {
if( dstsd && dstsd->status.base_level < (unsigned int)sd->inventory_data[i]->elv ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
}
- potion_flag = 1;
- potion_hp = potion_sp = potion_per_hp = potion_per_sp = 0;
- potion_target = bl->id;
- run_script(sd->inventory_data[i]->script,0,sd->bl.id,0);
- potion_flag = potion_target = 0;
+ script->potion_flag = 1;
+ script->potion_hp = script->potion_sp = script->potion_per_hp = script->potion_per_sp = 0;
+ script->potion_target = bl->id;
+ script->run(sd->inventory_data[i]->script,0,sd->bl.id,0);
+ script->potion_flag = script->potion_target = 0;
if( sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_ALCHEMIST )
bonus += sd->status.base_level;
- if( potion_per_hp > 0 || potion_per_sp > 0 ) {
- hp = tstatus->max_hp * potion_per_hp / 100;
+ if( script->potion_per_hp > 0 || script->potion_per_sp > 0 ) {
+ hp = tstatus->max_hp * script->potion_per_hp / 100;
hp = hp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
if( dstsd ) {
- sp = dstsd->status.max_sp * potion_per_sp / 100;
+ sp = dstsd->status.max_sp * script->potion_per_sp / 100;
sp = sp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
}
} else {
- if( potion_hp > 0 ) {
- hp = potion_hp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
+ if( script->potion_hp > 0 ) {
+ hp = script->potion_hp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
hp = hp * (100 + (tstatus->vit<<1)) / 100;
if( dstsd )
hp = hp * (100 + pc->checkskill(dstsd,SM_RECOVERY)*10) / 100;
}
- if( potion_sp > 0 ) {
- sp = potion_sp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
+ if( script->potion_sp > 0 ) {
+ sp = script->potion_sp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
sp = sp * (100 + (tstatus->int_<<1)) / 100;
if( dstsd )
sp = sp * (100 + pc->checkskill(dstsd,MG_SRECOVERY)*10) / 100;
}
}
- if (sd->itemgrouphealrate[IG_POTION]>0) {
- hp += hp * sd->itemgrouphealrate[IG_POTION] / 100;
- sp += sp * sd->itemgrouphealrate[IG_POTION] / 100;
+ for(i = 0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid; i++) {
+ if (sd->itemhealrate[i].nameid == potion) {
+ hp += hp * sd->itemhealrate[i].rate / 100;
+ sp += sp * sd->itemhealrate[i].rate / 100;
+ break;
+ }
}
-
+
if( (i = pc->skillheal_bonus(sd, skill_id)) ) {
hp += hp * i / 100;
sp += sp * i / 100;
@@ -6565,31 +6764,53 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( tsc && tsc->data[SC_EXTREMITYFIST2] )
sp = 0;
#endif
- status_heal(bl,(int)hp,sp,0);
+ status->heal(bl,(int)hp,sp,0);
}
break;
case AM_CP_WEAPON:
- case AM_CP_SHIELD:
- case AM_CP_ARMOR:
- case AM_CP_HELM:
- {
- unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP};
-
- if( sd && ( bl->type != BL_PC || ( dstsd && pc->checkequip(dstsd,equip[skill_id - AM_CP_WEAPON]) < 0 ) ) ){
+ if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_HAND_R]])
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ else {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ return 0;
+ }
+ break;
+ case AM_CP_SHIELD: {
+ int i;
+ if(dstsd && (i=dstsd->equip_index[EQI_HAND_L])>=0 && dstsd->inventory_data[i] &&
+ dstsd->inventory_data[i]->type==IT_ARMOR)
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ else {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock(); // Don't consume item requirements
return 0;
}
-
+ }
+ break;
+ case AM_CP_ARMOR:
+ if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_ARMOR]])
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ else {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ return 0;
+ }
+ break;
+ case AM_CP_HELM:
+ if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_HEAD_TOP]])
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ else {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ return 0;
}
break;
case AM_TWILIGHT1:
if (sd) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
//Prepare 200 White Potions.
- if (!skill->produce_mix(sd, skill_id, 504, 0, 0, 0, 200))
+ if (!skill->produce_mix(sd, skill_id, ITEMID_WHITE_POTION, 0, 0, 0, 200))
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
}
break;
@@ -6597,56 +6818,57 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (sd) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
//Prepare 200 Slim White Potions.
- if (!skill->produce_mix(sd, skill_id, 547, 0, 0, 0, 200))
+ if (!skill->produce_mix(sd, skill_id, ITEMID_WHITE_SLIM_POTION, 0, 0, 0, 200))
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
}
break;
case AM_TWILIGHT3:
if (sd) {
- int ebottle = pc->search_inventory(sd,713);
- if( ebottle >= 0 )
+ int ebottle = pc->search_inventory(sd,ITEMID_EMPTY_BOTTLE);
+ if (ebottle != INDEX_NOT_FOUND)
ebottle = sd->status.inventory[ebottle].amount;
//check if you can produce all three, if not, then fail:
- if (!skill->can_produce_mix(sd,970,-1, 100) //100 Alcohol
- || !skill->can_produce_mix(sd,7136,-1, 50) //50 Acid Bottle
- || !skill->can_produce_mix(sd,7135,-1, 50) //50 Flame Bottle
+ if (!skill->can_produce_mix(sd,ITEMID_ALCHOL,-1, 100) //100 Alcohol
+ || !skill->can_produce_mix(sd,ITEMID_ACID_BOTTLE,-1, 50) //50 Acid Bottle
+ || !skill->can_produce_mix(sd,ITEMID_FIRE_BOTTLE,-1, 50) //50 Flame Bottle
|| ebottle < 200 //200 empty bottle are required at total.
) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- skill->produce_mix(sd, skill_id, 970, 0, 0, 0, 100);
- skill->produce_mix(sd, skill_id, 7136, 0, 0, 0, 50);
- skill->produce_mix(sd, skill_id, 7135, 0, 0, 0, 50);
+ skill->produce_mix(sd, skill_id, ITEMID_ALCHOL, 0, 0, 0, 100);
+ skill->produce_mix(sd, skill_id, ITEMID_ACID_BOTTLE, 0, 0, 0, 50);
+ skill->produce_mix(sd, skill_id, ITEMID_FIRE_BOTTLE, 0, 0, 0, 50);
}
break;
case SA_DISPELL:
- if (flag&1 || (i = skill->get_splash(skill_id, skill_lv)) < 1)
- {
+ {
+ int splash;
+ if (flag&1 || (splash = skill->get_splash(skill_id, skill_lv)) < 1) {
+ int i;
+ if( sd && dstsd && !map_flag_vs(sd->bl.m)
+ && (sd->status.party_id == 0 || sd->status.party_id != dstsd->status.party_id) ) {
+ // Outside PvP it should only affect party members and no skill fail message.
+ break;
+ }
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER)
- || (tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_ROGUE) //Rogue's spirit defends againt dispel.
+ || (tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_ROGUE) //Rogue's spirit defends against dispel.
+ || (dstsd && pc_ismadogear(dstsd))
|| rnd()%100 >= 50+10*skill_lv )
{
if (sd)
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
- if(status_isimmune(bl) || !tsc || !tsc->count)
- break;
-
- if( sd && dstsd && !map_flag_vs(sd->bl.m) && sd->status.guild_id == dstsd->status.guild_id ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if(status->isimmune(bl) || !tsc || !tsc->count)
break;
- }
-
- for(i = 0; i < SC_MAX; i++)
- {
+ for(i = 0; i < SC_MAX; i++) {
if ( !tsc->data[i] )
continue;
- if( SC_COMMON_MAX < i ){
- if ( status_get_sc_type(i)&SC_NO_DISPELL )
+ if( SC_COMMON_MAX < i ) {
+ if ( status->get_sc_type(i)&SC_NO_DISPELL )
continue;
}
switch (i) {
@@ -6676,25 +6898,28 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
status_change_end(bl, (sc_type)i, INVALID_TIMER);
}
break;
+ } else {
+ //Affect all targets on splash area.
+ map->foreachinrange(skill->area_sub, bl, splash, BL_CHAR,
+ src, skill_id, skill_lv, tick, flag|1,
+ skill->castend_damage_id);
}
- //Affect all targets on splash area.
- iMap->foreachinrange(skill->area_sub, bl, i, BL_CHAR,
- src, skill_id, skill_lv, tick, flag|1,
- skill->castend_damage_id);
+ }
break;
case TF_BACKSLIDING: //This is the correct implementation as per packet logging information. [Skotlex]
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),unit_getdir(bl),0);
+ skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),unit->getdir(bl),0);
+ clif->fixpos(bl);
break;
case TK_HIGHJUMP:
{
- int x,y, dir = unit_getdir(src);
+ int x,y, dir = unit->getdir(src);
//Fails on noteleport maps, except for GvG and BG maps [Skotlex]
- if( map[src->m].flag.noteleport &&
- !(map[src->m].flag.battleground || map_flag_gvg2(src->m) )
+ if( map->list[src->m].flag.noteleport
+ && !(map->list[src->m].flag.battleground || map_flag_gvg2(src->m))
) {
x = src->x;
y = src->y;
@@ -6704,9 +6929,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
}
clif->skill_nodamage(src,bl,TK_HIGHJUMP,skill_lv,1);
- if(!iMap->count_oncell(src->m,x,y,BL_PC|BL_NPC|BL_MOB) && iMap->getcell(src->m,x,y,CELL_CHKREACH)) {
+ if(!map->count_oncell(src->m,x,y,BL_PC|BL_NPC|BL_MOB) && map->getcell(src->m,x,y,CELL_CHKREACH)) {
clif->slide(src,x,y);
- unit_movepos(src, x, y, 1, 0);
+ unit->movepos(src, x, y, 1, 0);
}
}
break;
@@ -6714,11 +6939,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SA_CASTCANCEL:
case SO_SPELLFIST:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- unit_skillcastcancel(src,1);
+ unit->skillcastcancel(src,1);
if(sd) {
int sp = skill->get_sp(sd->skill_id_old,sd->skill_lv_old);
if( skill_id == SO_SPELLFIST ){
- sc_start4(src,type,100,skill_lv+1,skill_lv,sd->skill_id_old,sd->skill_lv_old,skill->get_time(skill_id,skill_lv));
+ sc_start4(src,src,type,100,skill_lv+1,skill_lv,sd->skill_id_old,sd->skill_lv_old,skill->get_time(skill_id,skill_lv));
sd->skill_id_old = sd->skill_lv_old = 0;
break;
}
@@ -6734,10 +6959,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
sp = skill->get_sp(skill_id,skill_lv);
sp = sp * tsc->data[SC_MAGICROD]->val2 / 100;
if(sp < 1) sp = 1;
- status_heal(bl,0,sp,2);
+ status->heal(bl,0,sp,2);
status_percent_damage(bl, src, 0, -20, false); //20% max SP damage.
} else {
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
int bl_skill_id=0,bl_skill_lv=0,hp = 0;
if (!ud || ud->skilltimer == INVALID_TIMER)
break; //Nothing to cancel.
@@ -6754,7 +6979,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
hp = tstatus->max_hp/50; //Recover 2% HP [Skotlex]
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- unit_skillcastcancel(bl,0);
+ unit->skillcastcancel(bl,0);
sp = skill->get_sp(bl_skill_id,bl_skill_lv);
status_zap(bl, hp, sp);
@@ -6767,19 +6992,20 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
sp = sp*(25*(skill_lv-1))/100;
if(hp || sp)
- status_heal(src, hp, sp, 2);
+ status->heal(src, hp, sp, 2);
}
}
break;
case SA_MAGICROD:
clif->skill_nodamage(src,src,SA_MAGICROD,skill_lv,1);
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case SA_AUTOSPELL:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if(sd)
+ if(sd){
+ sd->state.workinprogress = 3;
clif->autospell(sd,skill_lv);
- else {
+ }else {
int maxlv=1,spellid=0;
static const int spellarray[3] = { MG_COLDBOLT,MG_FIREBOLT,MG_LIGHTNINGBOLT };
if(skill_lv >= 10) {
@@ -6807,7 +7033,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
maxlv = 3;
}
if(spellid > 0)
- sc_start4(src,SC_AUTOSPELL,100,skill_lv,spellid,maxlv,0,
+ sc_start4(src,src,SC_AUTOSPELL,100,skill_lv,spellid,maxlv,0,
skill->get_time(SA_AUTOSPELL,skill_lv));
}
break;
@@ -6815,8 +7041,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case BS_GREED:
if(sd){
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinrange(skill->greed,bl,
- skill->get_splash(skill_id, skill_lv),BL_ITEM,bl);
+ map->foreachinrange(skill->greed,bl,
+ skill->get_splash(skill_id, skill_lv),BL_ITEM,bl);
}
break;
@@ -6838,7 +7064,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NPC_CHANGEDARKNESS:
case NPC_CHANGETELEKINESIS:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start2(bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv),
+ sc_start2(src, bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv),
skill->get_time(skill_id, skill_lv)));
break;
case NPC_CHANGEUNDEAD:
@@ -6846,22 +7072,22 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
//TO-DO This is ugly, fix it
if(tstatus->def_ele==ELE_UNDEAD || tstatus->def_ele==ELE_DARK) break;
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start2(bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv),
+ sc_start2(src, bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv),
skill->get_time(skill_id, skill_lv)));
break;
case NPC_PROVOCATION:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if (md) mob_unlocktarget(md, tick);
+ if (md) mob->unlocktarget(md, tick);
break;
case NPC_KEEPING:
case NPC_BARRIER:
{
int skill_time = skill->get_time(skill_id,skill_lv);
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
if (clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill_time))
+ sc_start(src,bl,type,100,skill_lv,skill_time))
&& ud) { //Disable attacking/acting/moving for skill's duration.
ud->attackabletime =
ud->canact_tick =
@@ -6873,18 +7099,18 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NPC_REBIRTH:
if( md && md->state.rebirth )
break; // only works once
- sc_start(bl,type,100,skill_lv,-1);
+ sc_start(src,bl,type,100,skill_lv,-1);
break;
case NPC_DARKBLESSING:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start2(bl,type,(50+skill_lv*5),skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)));
+ sc_start2(src,bl,type,(50+skill_lv*5),skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)));
break;
case NPC_LICK:
status_zap(bl, 0, 100);
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,(skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv)));
+ sc_start(src,bl,type,(skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv)));
break;
case NPC_SUICIDE:
@@ -6895,17 +7121,17 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NPC_SUMMONSLAVE:
case NPC_SUMMONMONSTER:
if(md && md->skill_idx >= 0)
- mob_summonslave(md,md->db->skill[md->skill_idx].val,skill_lv,skill_id);
+ mob->summonslave(md,md->db->skill[md->skill_idx].val,skill_lv,skill_id);
break;
case NPC_CALLSLAVE:
- mob_warpslave(src,MOB_SLAVEDISTANCE);
+ mob->warpslave(src,MOB_SLAVEDISTANCE);
break;
case NPC_RANDOMMOVE:
if (md) {
md->next_walktime = tick - 1;
- mob_randomwalk(md,tick);
+ mob->randomwalk(md,tick);
}
break;
@@ -6916,7 +7142,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (i > SC_ATTHASTE_INFINITY)
i = SC_ATTHASTE_INFINITY;
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,(sc_type)i,100,skill_lv,skill_lv * 60000));
+ sc_start(src,bl,(sc_type)i,100,skill_lv,skill_lv * 60000));
}
break;
@@ -6924,32 +7150,32 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
// not really needed... but adding here anyway ^^
if (md && md->master_id > 0) {
struct block_list *mbl, *tbl;
- if ((mbl = iMap->id2bl(md->master_id)) == NULL ||
+ if ((mbl = map->id2bl(md->master_id)) == NULL ||
(tbl = battle->get_targeted(mbl)) == NULL)
break;
md->state.provoke_flag = tbl->id;
- mob_target(md, tbl, sstatus->rhw.range);
+ mob->target(md, tbl, sstatus->rhw.range);
}
break;
case NPC_RUN:
{
const int mask[8][2] = {{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}};
- uint8 dir = (bl == src)?unit_getdir(src):iMap->calc_dir(src,bl->x,bl->y); //If cast on self, run forward, else run away.
- unit_stop_attack(src);
+ uint8 dir = (bl == src)?unit->getdir(src):map->calc_dir(src,bl->x,bl->y); //If cast on self, run forward, else run away.
+ unit->stop_attack(src);
//Run skillv tiles overriding the can-move check.
- if (unit_walktoxy(src, src->x + skill_lv * mask[dir][0], src->y + skill_lv * mask[dir][1], 2) && md)
- md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the ai.
+ if (unit->walktoxy(src, src->x + skill_lv * mask[dir][0], src->y + skill_lv * mask[dir][1], 2) && md)
+ md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the AI.
}
break;
case NPC_TRANSFORMATION:
case NPC_METAMORPHOSIS:
if(md && md->skill_idx >= 0) {
- int class_ = mob_random_class (md->db->skill[md->skill_idx].val,0);
+ int class_ = mob->random_class (md->db->skill[md->skill_idx].val,0);
if (skill_lv > 1) //Multiply the rest of mobs. [Skotlex]
- mob_summonslave(md,md->db->skill[md->skill_idx].val,skill_lv-1,skill_id);
- if (class_) mob_class_change(md, class_);
+ mob->summonslave(md,md->db->skill[md->skill_idx].val,skill_lv-1,skill_id);
+ if (class_) mob->class_change(md, class_);
}
break;
@@ -6968,10 +7194,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
//If mode gets set by NPC_EMOTION then the target should be reset [Playtester]
if(skill_id == NPC_EMOTION && md->db->skill[md->skill_idx].val[1])
- mob_unlocktarget(md,tick);
+ mob->unlocktarget(md,tick);
if(md->db->skill[md->skill_idx].val[1] || md->db->skill[md->skill_idx].val[2])
- sc_start4(src, type, 100, skill_lv,
+ sc_start4(src, src, type, 100, skill_lv,
md->db->skill[md->skill_idx].val[1],
md->db->skill[md->skill_idx].val[2],
md->db->skill[md->skill_idx].val[3],
@@ -6980,21 +7206,21 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case NPC_POWERUP:
- sc_start(bl,SC_INCATKRATE,100,200,skill->get_time(skill_id, skill_lv));
+ sc_start(src,bl,SC_INCATKRATE,100,200,skill->get_time(skill_id, skill_lv));
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,100,skill->get_time(skill_id, skill_lv)));
+ sc_start(src,bl,type,100,100,skill->get_time(skill_id, skill_lv)));
break;
case NPC_AGIUP:
- sc_start(bl,SC_MOVHASTE_INFINITY,100,skill_lv,skill->get_time(skill_id, skill_lv));
+ sc_start(src,bl,SC_MOVHASTE_INFINITY,100,skill_lv,skill->get_time(skill_id, skill_lv));
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,100,skill->get_time(skill_id, skill_lv)));
+ sc_start(src,bl,type,100,100,skill->get_time(skill_id, skill_lv)));
break;
case NPC_INVISIBLE:
//Have val4 passed as 6 is for "infinite cloak" (do not end on attack/skill use).
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start4(bl,type,100,skill_lv,0,0,6,skill->get_time(skill_id,skill_lv)));
+ sc_start4(src,bl,type,100,skill_lv,0,0,6,skill->get_time(skill_id,skill_lv)));
break;
case NPC_SIEGEMODE:
@@ -7003,49 +7229,58 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case WE_MALE:
- {
- int hp_rate=(!skill_lv)? 0:skill_db[skill_id].hp_rate[skill_lv-1];
- int gain_hp= tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it costed the caster. [Skotlex]
- clif->skill_nodamage(src,bl,skill_id,status_heal(bl, gain_hp, 0, 0),1);
- }
+ {
+ int hp_rate = (!skill_lv)? 0:skill->db[skill_id].hp_rate[skill_lv-1];
+ int gain_hp = tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it cost the caster. [Skotlex]
+ clif->skill_nodamage(src,bl,skill_id,status->heal(bl, gain_hp, 0, 0),1);
+ }
break;
case WE_FEMALE:
- {
- int sp_rate=(!skill_lv)? 0:skill_db[skill_id].sp_rate[skill_lv-1];
- int gain_sp=tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it costed the caster. [Skotlex]
- clif->skill_nodamage(src,bl,skill_id,status_heal(bl, 0, gain_sp, 0),1);
- }
+ {
+ int sp_rate = (!skill_lv)? 0:skill->db[skill_id].sp_rate[skill_lv-1];
+ int gain_sp = tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it cost the caster. [Skotlex]
+ clif->skill_nodamage(src,bl,skill_id,status->heal(bl, 0, gain_sp, 0),1);
+ }
break;
// parent-baby skills
case WE_BABY:
- if(sd){
+ if(sd) {
struct map_session_data *f_sd = pc->get_father(sd);
struct map_session_data *m_sd = pc->get_mother(sd);
- // if neither was found
- if(!f_sd && !m_sd){
+ bool we_baby_parents = false;
+ if(m_sd && check_distance_bl(bl,&m_sd->bl,AREA_SIZE)) {
+ sc_start(src,&m_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ clif->specialeffect(&m_sd->bl,408,AREA);
+ we_baby_parents = true;
+ }
+ if(f_sd && check_distance_bl(bl,&f_sd->bl,AREA_SIZE)) {
+ sc_start(src,&f_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ clif->specialeffect(&f_sd->bl,408,AREA);
+ we_baby_parents = true;
+ }
+ if (!we_baby_parents) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
- status_change_start(bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),8);
- if (f_sd) sc_start(&f_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- if (m_sd) sc_start(&m_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ else
+ status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),8);
}
break;
case PF_HPCONVERSION:
- {
- int hp, sp;
- hp = sstatus->max_hp/10;
- sp = hp * 10 * skill_lv / 100;
- if (!status_charge(src,hp,0)) {
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- break;
- }
- clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- status_heal(bl,0,sp,2);
+ {
+ int hp, sp;
+ hp = sstatus->max_hp/10;
+ sp = hp * 10 * skill_lv / 100;
+ if (!status->charge(src,hp,0)) {
+ if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ break;
}
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
+ status->heal(bl,0,sp,2);
+ }
break;
case MA_REMOVETRAP:
@@ -7060,37 +7295,33 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( su && (sg = su->group) && (src->type == BL_MER || sg->src_id == src->id || map_flag_vs(bl->m)) && (skill->get_inf2(sg->skill_id)&INF2_TRAP) )
{
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) )
- { // prevent picking up expired traps
- if( battle_config.skill_removetrap_type )
- { // get back all items used to deploy the trap
- for( i = 0; i < 10; i++ )
- {
- if( skill_db[su->group->skill_id].itemid[i] > 0 )
- {
- int flag;
+ if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) && sg->unit_id != UNT_THORNS_TRAP ) {
+ // prevent picking up expired traps
+ if( battle_config.skill_removetrap_type ) {
+ int i;
+ // get back all items used to deploy the trap
+ for( i = 0; i < 10; i++ ) {
+ if( skill->db[su->group->skill_id].itemid[i] > 0 ) {
+ int success;
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid = skill_db[su->group->skill_id].itemid[i];
+ item_tmp.nameid = skill->db[su->group->skill_id].itemid[i];
item_tmp.identify = 1;
- if( item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i],LOG_TYPE_OTHER)) )
- {
- clif->additem(sd,0,0,flag);
- iMap->addflooritem(&item_tmp,skill_db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ if( item_tmp.nameid && (success=pc->additem(sd,&item_tmp,skill->db[su->group->skill_id].amount[i],LOG_TYPE_OTHER)) ) {
+ clif->additem(sd,0,0,success);
+ map->addflooritem(&item_tmp,skill->db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
}
- }
- else
- { // get back 1 trap
+ } else {
+ // get back 1 trap
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP;
item_tmp.identify = 1;
- if( item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) )
- {
+ if( item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) ) {
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
}
@@ -7111,7 +7342,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
// if it is already trapping something don't spring it,
// remove trap should be used instead
break;
- // otherwise fallthrough to below
+ // otherwise fall through to below
case UNT_BLASTMINE:
case UNT_SKIDTRAP:
case UNT_LANDMINE:
@@ -7123,8 +7354,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case UNT_TALKIEBOX:
su->group->unit_id = UNT_USED_TRAPS;
clif->changetraplook(bl, UNT_USED_TRAPS);
- su->group->limit=DIFF_TICK(tick+1500,su->group->tick);
- su->limit=DIFF_TICK(tick+1500,su->group->tick);
+ su->group->limit=DIFF_TICK32(tick+1500,su->group->tick);
+ su->limit=DIFF_TICK32(tick+1500,su->group->tick);
}
}
}
@@ -7132,53 +7363,51 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case BD_ENCORE:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
if(sd)
- unit_skilluse_id(src,src->id,sd->skill_id_dance,sd->skill_lv_dance);
+ unit->skilluse_id(src,src->id,sd->skill_id_dance,sd->skill_lv_dance);
break;
case AS_SPLASHER:
- if(tstatus->mode&MD_BOSS
- /**
- * Renewal dropped the 3/4 hp requirement
- **/
- #ifndef RENEWAL
- || tstatus-> hp > tstatus->max_hp*3/4
- #endif
- ) {
+ if( tstatus->mode&MD_BOSS
+#ifndef RENEWAL
+ /** Renewal dropped the 3/4 hp requirement **/
+ || tstatus-> hp > tstatus->max_hp*3/4
+#endif // RENEWAL
+ ) {
if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start4(bl,type,100,skill_lv,skill_id,src->id,skill->get_time(skill_id,skill_lv),1000));
+ sc_start4(src,bl,type,100,skill_lv,skill_id,src->id,skill->get_time(skill_id,skill_lv),1000));
#ifndef RENEWAL
- if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000, false);
+ if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000);
#endif
break;
case PF_MINDBREAKER:
{
if(tstatus->mode&MD_BOSS || battle->check_undead(tstatus->race,tstatus->def_ele) ) {
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
- if (tsce)
- { //HelloKitty2 (?) explained that this silently fails when target is
+ if (tsce) {
+ //HelloKitty2 (?) explained that this silently fails when target is
//already inflicted. [Skotlex]
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
//Has a 55% + skill_lv*5% success chance.
if (!clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,55+5*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv))))
- {
+ sc_start(src,bl,type,55+5*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)))
+ ) {
if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
- unit_skillcastcancel(bl,0);
+ unit->skillcastcancel(bl,0);
if(tsc && tsc->count){
status_change_end(bl, SC_FREEZE, INVALID_TIMER);
@@ -7188,7 +7417,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
}
if(dstmd)
- mob_target(dstmd,src,skill->get_range2(src,skill_id,skill_lv));
+ mob->target(dstmd,src,skill->get_range2(src,skill_id,skill_lv));
}
break;
@@ -7202,20 +7431,20 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
}
dstmd->state.soul_change_flag = 1;
sp2 = sstatus->max_sp * 3 /100;
- status_heal(src, 0, sp2, 2);
+ status->heal(src, 0, sp2, 2);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
}
sp1 = sstatus->sp;
sp2 = tstatus->sp;
- #ifdef RENEWAL
- sp1 = sp1 / 2;
- sp2 = sp2 / 2;
- if( tsc && tsc->data[SC_EXTREMITYFIST2] )
- sp1 = tstatus->sp;
- #endif
- status_set_sp(src, sp2, 3);
- status_set_sp(bl, sp1, 3);
+#ifdef RENEWAL
+ sp1 = sp1 / 2;
+ sp2 = sp2 / 2;
+ if( tsc && tsc->data[SC_EXTREMITYFIST2] )
+ sp1 = tstatus->sp;
+#endif // RENEWAL
+ status->set_sp(src, sp2, 3);
+ status->set_sp(bl, sp1, 3);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
}
break;
@@ -7225,8 +7454,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
// Updated to block Slim Pitcher from working on barricades and guardian stones.
if( dstmd && (dstmd->class_ == MOBID_EMPERIUM || (dstmd->class_ >= MOBID_BARRICADE1 && dstmd->class_ <= MOBID_GUARIDAN_STONE2)) )
break;
- if (potion_hp || potion_sp) {
- int hp = potion_hp, sp = potion_sp;
+ if (script->potion_hp || script->potion_sp) {
+ int hp = script->potion_hp, sp = script->potion_sp;
hp = hp * (100 + (tstatus->vit<<1))/100;
sp = sp * (100 + (tstatus->int_<<1))/100;
if (dstsd) {
@@ -7253,29 +7482,34 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
clif->skill_nodamage(NULL,bl,AL_HEAL,hp,1);
if(sp > 0)
clif->skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1);
- status_heal(bl,hp,sp,0);
+ status->heal(bl,hp,sp,0);
}
break;
// Full Chemical Protection
- case CR_FULLPROTECTION:
- {
- unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP};
- int i, s = 0, skilltime = skill->get_time(skill_id,skill_lv);
-
- for (i=0 ; i<4; i++) {
- if( bl->type != BL_PC || ( dstsd && pc->checkequip(dstsd,equip[i]) < 0 ) )
- continue;
- sc_start(bl,(sc_type)(SC_PROTECTWEAPON + i),100,skill_lv,skilltime);
- s++;
- }
- if( sd && !s ){
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock(); // Don't consume item requirements
- return 0;
- }
+ case CR_FULLPROTECTION: {
+ bool iused=false;
+ int i;
+ if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_HAND_R]]) {
+ iused=true;
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,SC_PROTECTWEAPON,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ } if(dstsd && (i=dstsd->equip_index[EQI_HAND_L])>=0 && dstsd->inventory_data[i] &&
+ dstsd->inventory_data[i]->type==IT_ARMOR) {
+ iused=true;
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,SC_PROTECTSHIELD,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ } if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_ARMOR]]) {
+ iused=true;
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,SC_PROTECTARMOR,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ } if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_HEAD_TOP]]) {
+ iused=true;
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,SC_PROTECTHELM,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ } if(iused)
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ else {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ return 0;
}
- break;
+ }
+ break;
case RG_CLEANER: //AppleGirl
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -7287,7 +7521,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
&& (tsce->val1&0xFFFF) != CG_MOONLIT) //Can't use Longing for Freedom while under Moonlight Petals. [Skotlex]
{
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
}
}
break;
@@ -7296,18 +7530,17 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
{
int eff, count = -1;
if( tsc && tsc->data[type] ){
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
- if( rnd() % 100 > skill_lv * 8 || (dstmd && ((dstmd->guardian_data && dstmd->class_ == MOBID_EMPERIUM) || mob_is_battleground(dstmd))) )
- {
+ if( rnd() % 100 > skill_lv * 8 || (dstmd && ((dstmd->guardian_data && dstmd->class_ == MOBID_EMPERIUM) || mob_is_battleground(dstmd))) ) {
if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
- status_zap(src,0,skill_db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish]
+ status_zap(src,0,skill->db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish]
do {
eff = rnd() % 14;
if( eff == 5 )
@@ -7320,70 +7553,70 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
status_percent_damage(src, bl, 0, 100, false);
break;
case 1: // matk halved
- sc_start(bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
break;
case 2: // all buffs removed
- status_change_clear_buffs(bl,1);
+ status->change_clear_buffs(bl,1);
break;
case 3: // 1000 damage, random armor destroyed
{
status_fix_damage(src, bl, 1000, 0);
- clif->damage(src,bl,tick,0,0,1000,0,0,0);
- if( !status_isdead(bl) ) {
+ clif->damage(src,bl,0,0,1000,0,0,0);
+ if( !status->isdead(bl) ) {
int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT };
skill->break_equip(bl, where[rnd()%5], 10000, BCT_ENEMY);
}
}
break;
case 4: // atk halved
- sc_start(bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
break;
case 5: // 2000HP heal, random teleported
- status_heal(src, 2000, 0, 0);
+ status->heal(src, 2000, 0, 0);
if( !map_flag_vs(bl->m) )
- unit_warp(bl, -1,-1,-1, CLR_TELEPORT);
+ unit->warp(bl, -1,-1,-1, CLR_TELEPORT);
break;
case 6: // random 2 other effects
if (count == -1)
count = 3;
else
- count++; //Should not retrigger this one.
+ count++; //Should not re-trigger this one.
break;
case 7: // stop freeze or stoned
{
enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE };
- sc_start(bl,sc[rnd()%3],100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,sc[rnd()%3],100,skill_lv,skill->get_time2(skill_id,skill_lv));
}
break;
case 8: // curse coma and poison
- sc_start(bl,SC_COMA,100,skill_lv,skill->get_time2(skill_id,skill_lv));
- sc_start(bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv));
- sc_start(bl,SC_POISON,100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_COMA,100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_POISON,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case 9: // confusion
- sc_start(bl,SC_CONFUSION,100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_CONFUSION,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case 10: // 6666 damage, atk matk halved, cursed
status_fix_damage(src, bl, 6666, 0);
- clif->damage(src,bl,tick,0,0,6666,0,0,0);
- sc_start(bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
- sc_start(bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
- sc_start(bl,SC_CURSE,skill_lv,100,skill->get_time2(skill_id,skill_lv));
+ clif->damage(src,bl,0,0,6666,0,0,0);
+ sc_start(src,bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_CURSE,skill_lv,100,skill->get_time2(skill_id,skill_lv));
break;
case 11: // 4444 damage
status_fix_damage(src, bl, 4444, 0);
- clif->damage(src,bl,tick,0,0,4444,0,0,0);
+ clif->damage(src,bl,0,0,4444,0,0,0);
break;
case 12: // stun
- sc_start(bl,SC_STUN,100,skill_lv,5000);
+ sc_start(src,bl,SC_STUN,100,skill_lv,5000);
break;
case 13: // atk,matk,hit,flee,def reduced
- sc_start(bl,SC_INCATKRATE,100,-20,skill->get_time2(skill_id,skill_lv));
- sc_start(bl,SC_INCMATKRATE,100,-20,skill->get_time2(skill_id,skill_lv));
- sc_start(bl,SC_INCHITRATE,100,-20,skill->get_time2(skill_id,skill_lv));
- sc_start(bl,SC_INCFLEERATE,100,-20,skill->get_time2(skill_id,skill_lv));
- sc_start(bl,SC_INCDEFRATE,100,-20,skill->get_time2(skill_id,skill_lv));
- sc_start(bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_INCATKRATE,100,-20,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_INCMATKRATE,100,-20,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_INCHITRATE,100,-20,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_INCFLEERATE,100,-20,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_INCDEFRATE,100,-20,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
default:
break;
@@ -7416,13 +7649,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (skill_id == SL_SUPERNOVICE && dstsd && dstsd->die_counter && !(rnd()%100))
{ //Erase death count 1% of the casts
dstsd->die_counter = 0;
- pc_setglobalreg(dstsd,"PC_DIE_COUNTER", 0);
+ pc_setglobalreg(dstsd,script->add_str("PC_DIE_COUNTER"), 0);
clif->specialeffect(bl, 0x152, AREA);
//SC_SOULLINK invokes status_calc_pc for us.
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start4(bl,SC_SOULLINK,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv)));
- sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv));
+ sc_start4(src,bl,SC_SOULLINK,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv));
break;
case SL_HIGH:
if (sd && !(dstsd && (dstsd->class_&JOBL_UPPER) && !(dstsd->class_&JOBL_2) && dstsd->status.base_level < 70)) {
@@ -7430,15 +7663,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start4(bl,type,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv)));
- sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv));
+ sc_start4(src,bl,type,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv));
break;
case SL_SWOO:
if (tsce) {
if(sd)
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,10000,8);
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,10000,8);
status_change_end(bl, SC_SWOO, INVALID_TIMER);
break;
}
@@ -7446,53 +7679,53 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SL_SKE:
if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,10);
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,10);
break;
}
- clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
if (skill_id == SL_SKE)
- sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv));
+ sc_start(src,src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv));
break;
// New guild skills [Celest]
case GD_BATTLEORDER:
if(flag&1) {
- if (status_get_guild_id(src) == status_get_guild_id(bl))
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv));
- } else if (status_get_guild_id(src)) {
+ if (status->get_guild_id(src) == status->get_guild_id(bl))
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv));
+ } else if (status->get_guild_id(src)) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinrange(skill->area_sub, src,
- skill->get_splash(skill_id, skill_lv), BL_PC,
- src,skill_id,skill_lv,tick, flag|BCT_GUILD|1,
- skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, src,
+ skill->get_splash(skill_id, skill_lv), BL_PC,
+ src,skill_id,skill_lv,tick, flag|BCT_GUILD|1,
+ skill->castend_nodamage_id);
if (sd)
guild->block_skill(sd,skill->get_time2(skill_id,skill_lv));
}
break;
case GD_REGENERATION:
if(flag&1) {
- if (status_get_guild_id(src) == status_get_guild_id(bl))
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv));
- } else if (status_get_guild_id(src)) {
+ if (status->get_guild_id(src) == status->get_guild_id(bl))
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv));
+ } else if (status->get_guild_id(src)) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinrange(skill->area_sub, src,
- skill->get_splash(skill_id, skill_lv), BL_PC,
- src,skill_id,skill_lv,tick, flag|BCT_GUILD|1,
- skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, src,
+ skill->get_splash(skill_id, skill_lv), BL_PC,
+ src,skill_id,skill_lv,tick, flag|BCT_GUILD|1,
+ skill->castend_nodamage_id);
if (sd)
guild->block_skill(sd,skill->get_time2(skill_id,skill_lv));
}
break;
case GD_RESTORE:
if(flag&1) {
- if (status_get_guild_id(src) == status_get_guild_id(bl))
+ if (status->get_guild_id(src) == status->get_guild_id(bl))
clif->skill_nodamage(src,bl,AL_HEAL,status_percent_heal(bl,90,90),1);
- } else if (status_get_guild_id(src)) {
+ } else if (status->get_guild_id(src)) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinrange(skill->area_sub, src,
- skill->get_splash(skill_id, skill_lv), BL_PC,
- src,skill_id,skill_lv,tick, flag|BCT_GUILD|1,
- skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, src,
+ skill->get_splash(skill_id, skill_lv), BL_PC,
+ src,skill_id,skill_lv,tick, flag|BCT_GUILD|1,
+ skill->castend_nodamage_id);
if (sd)
guild->block_skill(sd,skill->get_time2(skill_id,skill_lv));
}
@@ -7501,19 +7734,19 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
{
int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0};
int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0};
- int j = 0;
+ int i, j = 0;
struct guild *g;
// i don't know if it actually summons in a circle, but oh well. ;P
- g = sd?sd->state.gmaster_flag:guild->search(status_get_guild_id(src));
+ g = sd ? sd->guild : guild->search(status->get_guild_id(src));
if (!g)
break;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
for(i = 0; i < g->max_member; i++, j++) {
if (j>8) j=0;
if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !dstsd->state.autotrade && !pc_isdead(dstsd)) {
- if (map[dstsd->bl.m].flag.nowarp && !map_flag_gvg2(dstsd->bl.m))
+ if (map->list[dstsd->bl.m].flag.nowarp && !map_flag_gvg2(dstsd->bl.m))
continue;
- if(iMap->getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH))
+ if(map->getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH))
dx[j] = dy[j] = 0;
pc->setpos(dstsd, map_id2index(src->m), src->x+dx[j], src->y+dy[j], CLR_RESPAWN);
}
@@ -7555,28 +7788,32 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
/* per official standards, this skill works on players and mobs. */
if (sd && (dstsd || dstmd))
{
- i =65 -5*distance_bl(src,bl); //Base rate
- if (i < 30) i = 30;
+ int rate = 65 -5*distance_bl(src,bl); //Base rate
+ if (rate < 30) rate = 30;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- sc_start(bl,SC_STUN, i,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,bl,SC_STUN, rate,skill_lv,skill->get_time2(skill_id,skill_lv));
}
break;
- case AM_CALLHOMUN: //[orn]
- if (sd && homun->call(sd))
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ case AM_CALLHOMUN: // [orn]
+ if( sd ) {
+ if (homun->call(sd))
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
+ else
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ }
break;
case AM_REST:
if (sd) {
- if (homun->vaporize(sd,1))
+ if (homun->vaporize(sd,HOM_ST_REST))
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
else
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
}
break;
- case HAMI_CASTLE: //[orn]
+ case HAMI_CASTLE: // [orn]
if(rnd()%100 < 20*skill_lv && src != bl)
{
int x,y;
@@ -7585,18 +7822,18 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (hd)
skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id,skill_lv));
- if (unit_movepos(src,bl->x,bl->y,0,0)) {
- clif->skill_nodamage(src,src,skill_id,skill_lv,1); // Homunc
+ if (unit->movepos(src,bl->x,bl->y,0,0)) {
+ clif->skill_nodamage(src,src,skill_id,skill_lv,1); // Homun
clif->slide(src,bl->x,bl->y) ;
- if (unit_movepos(bl,x,y,0,0))
+ if (unit->movepos(bl,x,y,0,0))
{
clif->skill_nodamage(bl,bl,skill_id,skill_lv,1); // Master
clif->slide(bl,x,y) ;
}
//TODO: Shouldn't also players and the like switch targets?
- iMap->foreachinrange(skill->chastle_mob_changetarget,src,
- AREA_SIZE, BL_MOB, bl, src);
+ map->foreachinrange(skill->chastle_mob_changetarget,src,
+ AREA_SIZE, BL_MOB, bl, src);
}
}
// Failed
@@ -7605,27 +7842,28 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
else if (sd)
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
break;
- case HVAN_CHAOTIC: //[orn]
+ case HVAN_CHAOTIC: // [orn]
{
static const int per[5][2]={{20,50},{50,60},{25,75},{60,64},{34,67}};
int r = rnd()%100;
- i = (skill_lv-1)%5;
- if(r<per[i][0]) //Self
+ int target = (skill_lv-1)%5;
+ int hp;
+ if(r<per[target][0]) //Self
bl = src;
- else if(r<per[i][1]) //Master
+ else if(r<per[target][1]) //Master
bl = battle->get_master(src);
else //Enemy
- bl = iMap->id2bl(battle->get_target(src));
+ bl = map->id2bl(battle->get_target(src));
if (!bl) bl = src;
- i = skill->calc_heal(src, bl, skill_id, 1+rnd()%skill_lv, true);
+ hp = skill->calc_heal(src, bl, skill_id, 1+rnd()%skill_lv, true);
//Eh? why double skill packet?
- clif->skill_nodamage(src,bl,AL_HEAL,i,1);
- clif->skill_nodamage(src,bl,skill_id,i,1);
- status_heal(bl, i, 0, 0);
+ clif->skill_nodamage(src,bl,AL_HEAL,hp,1);
+ clif->skill_nodamage(src,bl,skill_id,hp,1);
+ status->heal(bl, hp, 0, 0);
}
break;
- //Homun single-target support skills [orn]
+ // Homun single-target support skills [orn]
case HAMI_BLOODLUST:
case HFLI_FLEET:
case HFLI_SPEED:
@@ -7633,7 +7871,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case MH_ANGRIFFS_MODUS:
case MH_GOLDENE_FERSE:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
if (hd)
skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id,skill_lv));
break;
@@ -7641,9 +7879,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NPC_DRAGONFEAR:
if (flag&1) {
const enum sc_type sc[] = { SC_STUN, SC_SILENCE, SC_CONFUSION, SC_BLOODING };
- int j;
+ int i, j;
j = i = rnd()%ARRAYLENGTH(sc);
- while ( !sc_start2(bl,sc[i],100,skill_lv,src->id,skill->get_time2(skill_id,i+1)) ) {
+ while ( !sc_start2(src,bl,sc[i],100,skill_lv,src->id,skill->get_time2(skill_id,i+1)) ) {
i++;
if ( i == ARRAYLENGTH(sc) )
i = 0;
@@ -7662,27 +7900,42 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NPC_WIDESTUN:
case NPC_SLOWCAST:
case NPC_WIDEHELLDIGNITY:
- if (flag&1)
- sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
- else {
- skill_area_temp[2] = 0; //For SD_PREAMBLE
+ case NPC_WIDEHEALTHFEAR:
+ case NPC_WIDEBODYBURNNING:
+ case NPC_WIDEFROSTMISTY:
+ case NPC_WIDECOLD:
+ case NPC_WIDE_DEEP_SLEEP:
+ case NPC_WIDESIREN:
+ if (flag&1){
+ switch( type ){
+ case SC_BURNING:
+ sc_start4(src,bl,type,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv));
+ break;
+ case SC_SIREN:
+ sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
+ break;
+ default:
+ sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
+ }
+ } else {
+ skill->area_temp[2] = 0; //For SD_PREAMBLE
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv),BL_CHAR,
- src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1,
- skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, bl,
+ skill->get_splash(skill_id, skill_lv),BL_CHAR,
+ src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1,
+ skill->castend_nodamage_id);
}
break;
case NPC_WIDESOULDRAIN:
if (flag&1)
status_percent_damage(src,bl,0,((skill_lv-1)%5+1)*20,false);
else {
- skill_area_temp[2] = 0; //For SD_PREAMBLE
+ skill->area_temp[2] = 0; //For SD_PREAMBLE
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv),BL_CHAR,
- src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1,
- skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, bl,
+ skill->get_splash(skill_id, skill_lv),BL_CHAR,
+ src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1,
+ skill->castend_nodamage_id);
}
break;
case ALL_PARTYFLEE:
@@ -7693,13 +7946,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
- party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
+ party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
}
else
- clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
break;
case NPC_TALK:
case ALL_WEWISH:
+ case ALL_CATCRY:
+ case ALL_DREAM_SUMMERNIGHT:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
case ALL_BUYING_STORE:
@@ -7710,76 +7965,143 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case RK_ENCHANTBLADE:
clif->skill_nodamage(src,bl,skill_id,skill_lv,// formula not confirmed
- sc_start2(bl,type,100,skill_lv,100+20*skill_lv/*+sstatus->int_/2+status_get_lv(bl)/10*/,skill->get_time(skill_id,skill_lv)));
+ sc_start2(src,bl,type,100,skill_lv,(100+20*skill_lv)*status->get_lv(src)/150+sstatus->int_,skill->get_time(skill_id,skill_lv)));
break;
case RK_DRAGONHOWLING:
if( flag&1)
- sc_start(bl,type,50 + 6 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
- else
- {
- skill_area_temp[2] = 0;
+ sc_start(src,bl,type,50 + 6 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
+ else {
+ skill->area_temp[2] = 0;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinrange(skill->area_sub, src,
- skill->get_splash(skill_id,skill_lv),BL_CHAR,
- src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|1,
- skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, src,
+ skill->get_splash(skill_id,skill_lv),BL_CHAR,
+ src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|1,
+ skill->castend_nodamage_id);
}
break;
case RK_IGNITIONBREAK:
case LG_EARTHDRIVE:
+ {
+ int splash;
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- i = skill->get_splash(skill_id,skill_lv);
+ splash = skill->get_splash(skill_id,skill_lv);
if( skill_id == LG_EARTHDRIVE ) {
int dummy = 1;
- iMap->foreachinarea(skill->cell_overlap, src->m, src->x-i, src->y-i, src->x+i, src->y+i, BL_SKILL, LG_EARTHDRIVE, &dummy, src);
+ map->foreachinarea(skill->cell_overlap, src->m, src->x-splash, src->y-splash, src->x+splash, src->y+splash, BL_SKILL, LG_EARTHDRIVE, &dummy, src);
}
- iMap->foreachinrange(skill->area_sub, bl,i,BL_CHAR,
- src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl,splash,BL_CHAR,
+ src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ }
break;
case RK_STONEHARDSKIN:
- if( sd )
- {
- int heal = sstatus->hp / 4; // 25% HP
- if( status_charge(bl,heal,0) )
- clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start2(bl,type,100,skill_lv,heal,skill->get_time(skill_id,skill_lv)));
+ if( sd ) {
+ int heal = sstatus->hp / 5; // 20% HP
+ if( status->charge(bl,heal,0) )
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start2(src,bl,type,100,skill_lv,heal,skill->get_time(skill_id,skill_lv)));
else
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
}
break;
case RK_REFRESH:
- {
- int heal = status_get_max_hp(bl) * 25 / 100;
- clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
- status_heal(bl,heal,0,1);
- status_change_clear_buffs(bl,4);
- }
+ {
+ int heal = status_get_max_hp(bl) * 25 / 100;
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ status->heal(bl,heal,0,1);
+ status->change_clear_buffs(bl,4);
+ }
break;
case RK_MILLENNIUMSHIELD:
- if( sd ){
- short shields = (rnd()%100<50) ? 4 : ((rnd()%100<80) ? 3 : 2);
- sc_start4(bl,type,100,skill_lv,shields,1000,0,skill->get_time(skill_id,skill_lv));
- clif->millenniumshield(sd,shields);
+ if( sd && pc->checkskill(sd,RK_RUNEMASTERY) >= 9 ) {
+ short chance = 0;
+ short num_shields = 0;
+ chance = rnd()%100 + 1;//Generates a random number between 1 - 100 which is then used to determine how many shields will generate.
+ if ( chance >= 1 && chance <= 20 )//20% chance for 4 shields.
+ num_shields = 4;
+ else if ( chance >= 21 && chance <= 50 )//30% chance for 3 shields.
+ num_shields = 3;
+ else if ( chance >= 51 && chance <= 100 )//50% chance for 2 shields.
+ num_shields = 2;
+ sc_start4(src,bl,type,100,skill_lv,num_shields,1000,0,skill->get_time(skill_id,skill_lv));
+ clif->millenniumshield(src,num_shields);
clif->skill_nodamage(src,bl,skill_id,1,1);
}
break;
case RK_FIGHTINGSPIRIT:
if( flag&1 ) {
+ int atkbonus = 7 * party->foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,BCT_PARTY,skill->area_sub_count);
if( src == bl )
- sc_start2(bl,type,100,skill_area_temp[5],10*(sd?pc->checkskill(sd,RK_RUNEMASTERY):10),skill->get_time(skill_id,skill_lv));
+ sc_start2(src,bl,type,100,atkbonus,10*(sd?pc->checkskill(sd,RK_RUNEMASTERY):10),skill->get_time(skill_id,skill_lv));
else
- sc_start(bl,type,100,skill_area_temp[5]/4,skill->get_time(skill_id,skill_lv));
- } else if( sd ) {
- if( sd->status.party_id ) {
- i = party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,BCT_PARTY,skill->area_sub_count);
- skill_area_temp[5] = 7 * i; // ATK
- party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id);
- } else
- sc_start2(bl,type,100,7,5,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,type,100,atkbonus / 4,skill->get_time(skill_id,skill_lv));
+ } else if( sd && pc->checkskill(sd,RK_RUNEMASTERY) >= 5 ) {
+ if( sd->status.party_id )
+ party->foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id);
+ else
+ sc_start2(src,bl,type,100,7,10*(sd?pc->checkskill(sd,RK_RUNEMASTERY):10),skill->get_time(skill_id,skill_lv));
+ clif->skill_nodamage(src,bl,skill_id,1,1);
+ }
+ break;
+
+ case RK_LUXANIMA:
+ if( sd == NULL || sd->status.party_id == 0 || flag&1 ){
+ if( src == bl )
+ break;
+ while( skill->area_temp[5] >= 0x10 ){
+ int value = 0;
+ type = SC_NONE;
+ if( skill->area_temp[5]&0x10 ){
+ value = (rnd()%100<50) ? 4 : ((rnd()%100<80) ? 3 : 2);
+ clif->millenniumshield(bl,value);
+ skill->area_temp[5] &= ~0x10;
+ type = SC_MILLENNIUMSHIELD;
+ }else if( skill->area_temp[5]&0x20 ){
+ value = status_get_max_hp(bl) * 25 / 100;
+ status->change_clear_buffs(bl,4);
+ skill->area_temp[5] &= ~0x20;
+ status->heal(bl,value,0,1);
+ type = SC_REFRESH;
+ }else if( skill->area_temp[5]&0x40 ){
+ skill->area_temp[5] &= ~0x40;
+ type = SC_GIANTGROWTH;
+ }else if( skill->area_temp[5]&0x80 ){
+ if( dstsd ){
+ value = sstatus->hp / 4;
+ if( status->charge(bl,value,0) )
+ type = SC_STONEHARDSKIN;
+ skill->area_temp[5] &= ~0x80;
+ }
+ }else if( skill->area_temp[5]&0x100 ){
+ skill->area_temp[5] &= ~0x100;
+ type = SC_VITALITYACTIVATION;
+ }else if( skill->area_temp[5]&0x200 ){
+ skill->area_temp[5] &= ~0x200;
+ type = SC_ABUNDANCE;
+ }
+ if( type > SC_NONE )
+ clif->skill_nodamage(bl, bl, skill_id, skill_lv,
+ sc_start4(src,bl, type, 100, skill_lv, value, 0, 1, skill->get_time(skill_id, skill_lv)));
+ }
+ }else if( sd ){
+ if( tsc && tsc->count ){
+ if(tsc->data[SC_MILLENNIUMSHIELD])
+ skill->area_temp[5] |= 0x10;
+ if(tsc->data[SC_REFRESH])
+ skill->area_temp[5] |= 0x20;
+ if(tsc->data[SC_GIANTGROWTH])
+ skill->area_temp[5] |= 0x40;
+ if(tsc->data[SC_STONEHARDSKIN])
+ skill->area_temp[5] |= 0x80;
+ if(tsc->data[SC_VITALITYACTIVATION])
+ skill->area_temp[5] |= 0x100;
+ if(tsc->data[SC_ABUNDANCE])
+ skill->area_temp[5] |= 0x200;
+ }
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
+ party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
}
- clif->skill_nodamage(src,bl,skill_id,1,1);
break;
/**
* Guilotine Cross
@@ -7787,16 +8109,16 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case GC_ROLLINGCUTTER:
{
short count = 1;
- skill_area_temp[2] = 0;
- iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|SD_SPLASH|1,skill->castend_damage_id);
+ skill->area_temp[2] = 0;
+ map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|SD_SPLASH|1,skill->castend_damage_id);
if( tsc && tsc->data[SC_ROLLINGCUTTER] )
{ // Every time the skill is casted the status change is reseted adding a counter.
count += (short)tsc->data[SC_ROLLINGCUTTER]->val1;
if( count > 10 )
- count = 10; // Max coounter
+ count = 10; // Max counter
status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER);
}
- sc_start(bl,SC_ROLLINGCUTTER,100,count,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_ROLLINGCUTTER,100,count,skill->get_time(skill_id,skill_lv));
clif->skill_nodamage(src,src,skill_id,skill_lv,1);
}
break;
@@ -7805,7 +8127,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( tsc && tsc->data[SC_WEAPONBLOCKING] )
status_change_end(bl, SC_WEAPONBLOCKING, INVALID_TIMER);
else
- sc_start(bl,SC_WEAPONBLOCKING,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_WEAPONBLOCKING,100,skill_lv,skill->get_time(skill_id,skill_lv));
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
@@ -7840,25 +8162,29 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case GC_PHANTOMMENACE:
+ {
+ int r;
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,
+ r = skill->get_splash(skill_id, skill_lv);
+ map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,
src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ map->foreachinarea( status->change_timer_sub,
+ src->m, src->x-r, src->y-r, src->x+r, src->y+r, BL_CHAR, src, NULL, SC_SIGHT, tick);
+ }
break;
-
case GC_HALLUCINATIONWALK:
{
- int heal = status_get_max_hp(bl) / 10;
+ int heal = status_get_max_hp(bl) * ( 18 - 2 * skill_lv ) / 100;
if( status_get_hp(bl) < heal ) { // if you haven't enough HP skill fails.
if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0);
break;
}
- if( !status_charge(bl,heal,0) )
- {
+ if( !status->charge(bl,heal,0) ) {
if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0);
break;
}
- clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
}
break;
/**
@@ -7873,57 +8199,72 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case AB_CLEMENTIA:
case AB_CANTO:
- {
- int bless_lv = pc->checkskill(sd,AL_BLESSING) + (sd->status.job_level / 10);
- int agi_lv = pc->checkskill(sd,AL_INCAGI) + (sd->status.job_level / 10);
- if( sd == NULL || sd->status.party_id == 0 || flag&1 )
- clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,
- (skill_id == AB_CLEMENTIA)? bless_lv : (skill_id == AB_CANTO)? agi_lv : skill_lv, skill->get_time(skill_id,skill_lv)));
- else if( sd )
- party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
+ {
+ int level = 0;
+ if( sd )
+ level = skill_id == AB_CLEMENTIA ? pc->checkskill(sd,AL_BLESSING) : pc->checkskill(sd,AL_INCAGI);
+ if( sd == NULL || sd->status.party_id == 0 || flag&1 )
+ clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, level + (sd?(sd->status.job_level / 10):0), skill->get_time(skill_id,skill_lv)));
+ else if( sd ) {
+ if( !level )
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
+ else
+ party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
}
+ }
break;
case AB_PRAEFATIO:
- if( sd == NULL || sd->status.party_id == 0 || flag&1 )
- clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start4(bl, type, 100, skill_lv, 0, 0, 1, skill->get_time(skill_id, skill_lv)));
- else if( sd )
- party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
- break;
+ if( (flag&1) || sd == NULL || sd->status.party_id == 0 ) {
+ int count = 1;
+
+ if( dstsd && dstsd->special_state.no_magic_damage )
+ break;
+
+ if( sd && sd->status.party_id != 0 )
+ count = party->foreachsamemap(party->sub_count, sd, 0);
+ clif->skill_nodamage(bl, bl, skill_id, skill_lv,
+ sc_start4(src, bl, type, 100, skill_lv, 0, 0, count, skill->get_time(skill_id, skill_lv)));
+ } else if( sd )
+ party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
+ break;
case AB_CHEAL:
if( sd == NULL || sd->status.party_id == 0 || flag&1 ) {
- if( sd && tstatus && !battle->check_undead(tstatus->race, tstatus->def_ele) ) {
- i = skill->calc_heal(src, bl, AL_HEAL, pc->checkskill(sd, AL_HEAL), true);
-
- if( (dstsd && pc_ismadogear(dstsd)) || status_isimmune(bl))
- i = 0; // Should heal by 0 or won't do anything?? in iRO it breaks the healing to members.. [malufett]
+ if( sd && tstatus && !battle->check_undead(tstatus->race, tstatus->def_ele) && !tsc->data[SC_BERSERK] ) {
+ int lv = pc->checkskill(sd, AL_HEAL);
+ int heal = skill_calc_heal(src, bl, AL_HEAL, lv, true);
+
+ if( sd->status.party_id ) {
+ int partycount = party->foreachsamemap(party->sub_count, sd, 0);
+ if (partycount > 1)
+ heal += ((heal / 100) * (partycount * 10) / 4);
+ }
+ if( status->isimmune(bl) || (dstsd && pc_ismadogear(dstsd)) )
+ heal = 0;
- clif->skill_nodamage(bl, bl, skill_id, i, 1);
- if( tsc && tsc->data[SC_AKAITSUKI] && i )
- i = ~i + 1;
- status_heal(bl, i, 0, 0);
+ clif->skill_nodamage(bl, bl, skill_id, heal, 1);
+ if( tsc && tsc->data[SC_AKAITSUKI] && heal )
+ heal = ~heal + 1;
+ status->heal(bl, heal, 0, 1);
}
- }
- else if( sd )
- party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
+ } else if( sd )
+ party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
break;
-
case AB_ORATIO:
if( flag&1 )
- sc_start(bl, type, 40 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
- else
- {
- iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR,
+ sc_start(src, bl, type, 40 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
+ else {
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR,
src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
}
break;
case AB_LAUDAAGNUS:
- if( flag&1 || sd == NULL ) {
+ if( (flag&1 || sd == NULL) || !sd->status.party_id) {
if( tsc && (tsc->data[SC_FREEZE] || tsc->data[SC_STONE] || tsc->data[SC_BLIND] ||
- tsc->data[SC_BURNING] || tsc->data[SC_FROSTMISTY] || tsc->data[SC_CRYSTALIZE])) {
+ tsc->data[SC_BURNING] || tsc->data[SC_FROSTMISTY] || tsc->data[SC_COLD])) {
// Success Chance: (40 + 10 * Skill Level) %
if( rnd()%100 > 40+10*skill_lv ) break;
status_change_end(bl, SC_FREEZE, INVALID_TIMER);
@@ -7931,50 +8272,57 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
status_change_end(bl, SC_BLIND, INVALID_TIMER);
status_change_end(bl, SC_BURNING, INVALID_TIMER);
status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER);
- status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER);
+ status_change_end(bl, SC_COLD, INVALID_TIMER);
}else //Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets
clif->skill_nodamage(bl, bl, skill_id, skill_lv,
- sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
} else if( sd )
- party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv),
+ party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv),
src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
break;
case AB_LAUDARAMUS:
- if( flag&1 || sd == NULL ) {
- if( tsc && (tsc->data[SC_SLEEP] || tsc->data[SC_STUN] || tsc->data[SC_MANDRAGORA] || tsc->data[SC_SILENCE]) ){
+ if( (flag&1 || sd == NULL) || !sd->status.party_id ) {
+ if( tsc && (tsc->data[SC_SLEEP] || tsc->data[SC_STUN] || tsc->data[SC_MANDRAGORA] ||
+ tsc->data[SC_SILENCE] || tsc->data[SC_DEEP_SLEEP]) ){
// Success Chance: (40 + 10 * Skill Level) %
if( rnd()%100 > 40+10*skill_lv ) break;
status_change_end(bl, SC_SLEEP, INVALID_TIMER);
status_change_end(bl, SC_STUN, INVALID_TIMER);
status_change_end(bl, SC_MANDRAGORA, INVALID_TIMER);
status_change_end(bl, SC_SILENCE, INVALID_TIMER);
+ status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
}else // Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets
clif->skill_nodamage(bl, bl, skill_id, skill_lv,
- sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
} else if( sd )
- party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv),
+ party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv),
src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
break;
case AB_CLEARANCE:
- if( flag&1 || (i = skill->get_splash(skill_id, skill_lv)) < 1 )
- { //As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie]
+ {
+ int splash;
+ if( flag&1 || (splash = skill->get_splash(skill_id, skill_lv)) < 1 ) {
+ int i;
+ //As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie]
+ if( bl->type != BL_MOB && battle->check_target(src,bl,BCT_PARTY) <= 0 ) // Only affect mob or party.
+ break;
+
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) || rnd()%100 >= 30 + 10 * skill_lv)
- {
+
+ if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) || rnd()%100 >= 60 + 8 * skill_lv) {
if (sd)
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
- if(status_isimmune(bl) || !tsc || !tsc->count)
+ if(status->isimmune(bl) || !tsc || !tsc->count)
break;
- for(i = 0; i < SC_MAX; i++)
- {
+ for(i = 0; i < SC_MAX; i++) {
if ( !tsc->data[i] )
continue;
if( SC_COMMON_MAX > i )
- if ( status_get_sc_type(i)&SC_NO_CLEARANCE )
+ if ( status->get_sc_type(i)&SC_NO_CLEARANCE )
continue;
switch (i) {
case SC_ASSUMPTIO:
@@ -7989,13 +8337,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
status_change_end(bl,(sc_type)i,INVALID_TIMER);
}
break;
+ } else {
+ map->foreachinrange(skill->area_sub, bl, splash, BL_CHAR, src, skill_id, skill_lv, tick, flag|1, skill->castend_damage_id);
}
- iMap->foreachinrange(skill->area_sub, bl, i, BL_CHAR, src, skill_id, skill_lv, tick, flag|1, skill->castend_damage_id);
+ }
break;
case AB_SILENTIUM:
// Should the level of Lex Divina be equivalent to the level of Silentium or should the highest level learned be used? [LimitLine]
- iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR,
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR,
src, PR_LEXDIVINA, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
break;
@@ -8004,10 +8354,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
**/
case WL_STASIS:
if( flag&1 )
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- else
- {
- iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id, skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,(map_flag_vs(src->m)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill->castend_nodamage_id);
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ else {
+ map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id, skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,(map_flag_vs(src->m)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill->castend_nodamage_id);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
}
break;
@@ -8022,12 +8371,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
else rate += 40 + 10 * skill_lv; // On Monsters, (40 + 10 * Skill Level) %
if( sd )
- skill->blockpc_start(sd,skill_id,4000, false);
+ skill->blockpc_start(sd,skill_id,4000);
if( !(tsc && tsc->data[type]) ){
- i = sc_start2(bl,type,rate,skill_lv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill->get_time(skill_id,skill_lv):skill->get_time2(skill_id, skill_lv));
- clif->skill_nodamage(src,bl,skill_id,skill_lv,i);
- if( sd && !i )
+ int failure = sc_start2(src,bl,type,rate,skill_lv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill->get_time(skill_id,skill_lv):skill->get_time2(skill_id, skill_lv));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,failure);
+ if( sd && !failure )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
}
}else
@@ -8036,33 +8385,37 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case WL_FROSTMISTY:
+ if( tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK)))
+ break; // Doesn't hit/cause Freezing to invisible enemy // Really? [Rytech]
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id);
break;
case WL_JACKFROST:
+ if( tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK)))
+ break; // Do not hit invisible enemy
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->foreachinshootrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ map->foreachinshootrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
break;
case WL_MARSHOFABYSS:
clif->skill_nodamage(src, bl, skill_id, skill_lv,
- sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
break;
case WL_SIENNAEXECRATE:
if( flag&1 ) {
- if( status_isimmune(bl) || !tsc )
+ if( status->isimmune(bl) || !tsc )
break;
if( tsc && tsc->data[SC_STONE] )
status_change_end(bl,SC_STONE,INVALID_TIMER);
else
- status_change_start(bl,SC_STONE,10000,skill_lv,0,0,500,skill->get_time(skill_id, skill_lv),2);
+ status->change_start(src,bl,SC_STONE,10000,skill_lv,0,0,500,skill->get_time(skill_id, skill_lv),2);
} else {
int rate = 45 + 5 * skill_lv;
if( rnd()%100 < rate ){
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- iMap->foreachinrange(skill_area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id);
+ map->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id);
}else if( sd ) // Failure on Rate
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
}
@@ -8072,19 +8425,23 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case WL_SUMMONBL:
case WL_SUMMONWB:
case WL_SUMMONSTONE:
+ {
+ int i;
for( i = SC_SUMMON1; i <= SC_SUMMON5; i++ ){
if( tsc && !tsc->data[i] ){ // officially it doesn't work like a stack
int ele = WLS_FIRE + (skill_id - WL_SUMMONFB) - (skill_id == WL_SUMMONSTONE ? 4 : 0);
clif->skill_nodamage(src, bl, skill_id, skill_lv,
- sc_start(bl, (sc_type)i, 100, ele, skill->get_time(skill_id, skill_lv)));
+ sc_start(src, bl, (sc_type)i, 100, ele, skill->get_time(skill_id, skill_lv)));
break;
}
}
+ }
break;
case WL_READING_SB:
if( sd ) {
- struct status_change *sc = status_get_sc(bl);
+ struct status_change *sc = status->get_sc(bl);
+ int i;
for( i = SC_SPELLBOOK1; i <= SC_SPELLBOOK7; i++)
if( sc && !sc->data[i] )
@@ -8094,7 +8451,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
}
- sc_start(bl, SC_STOP, 100, skill_lv, INVALID_TIMER); //Can't move while selecting a spellbook.
+ sc_start(src, bl, SC_STOP, 100, skill_lv, INVALID_TIMER); //Can't move while selecting a spellbook.
clif->spellbook_list(sd);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
}
@@ -8104,7 +8461,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
**/
case RA_FEARBREEZE:
clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
break;
case RA_WUGMASTERY:
@@ -8133,11 +8490,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case RA_WUGDASH:
if( tsce ) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER));
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
if( sd && pc_isridingwug(sd) ) {
- clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit_getdir(bl),0,0,1));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,bl,type,100,skill_lv,unit->getdir(bl),0,0,1));
clif->walkok(sd);
}
break;
@@ -8145,7 +8502,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case RA_SENSITIVEKEEN:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id);
break;
/**
* Mechanic
@@ -8153,7 +8510,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NC_F_SIDESLIDE:
case NC_B_SIDESLIDE:
{
- uint8 dir = (skill_id == NC_F_SIDESLIDE) ? (unit_getdir(src)+4)%8 : unit_getdir(src);
+ uint8 dir = (skill_id == NC_F_SIDESLIDE) ? (unit->getdir(src)+4)%8 : unit->getdir(src);
skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),dir,0);
clif->slide(src,src->x,src->y);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -8166,41 +8523,46 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
pc->setmadogear(sd, 0);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
skill->castend_damage_id(src, src, skill_id, skill_lv, tick, flag);
- status_set_sp(src, 0, 0);
+ status->set_sp(src, 0, 0);
}
break;
case NC_ANALYZE:
clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
clif->skill_nodamage(src, bl, skill_id, skill_lv,
- sc_start(bl,type, 30 + 12 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src,bl,type, 30 + 12 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)));
if( sd ) pc->overheat(sd,1);
break;
case NC_MAGNETICFIELD:
- if( (i = sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))) )
+ {
+ int failure;
+ if( (failure = sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))) )
{
- iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill->castend_damage_id);;
+ map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill->castend_damage_id);;
clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6);
if (sd) pc->overheat(sd,1);
}
- clif->skill_nodamage(src,src,skill_id,skill_lv,i);
+ clif->skill_nodamage(src,src,skill_id,skill_lv,failure);
+ }
break;
case NC_REPAIR:
- if( sd )
- {
- int heal;
- if( dstsd && pc_ismadogear(dstsd) )
- {
- heal = dstsd->status.max_hp * (3+3*skill_lv) / 100;
- status_heal(bl,heal,0,2);
- } else {
- heal = sd->status.max_hp * (3+3*skill_lv) / 100;
- status_heal(src,heal,0,2);
+ if( sd ) {
+ int heal, hp = 0; // % of max hp regen
+ if( !dstsd || !pc_ismadogear(dstsd) ) {
+ clif->skill_fail(sd, skill_id,USESKILL_FAIL_TOTARGET,0);
+ break;
}
-
- clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
+ switch (cap_value(skill_lv, 1, 5)) {
+ case 1: hp = 4; break;
+ case 2: hp = 7; break;
+ case 3: hp = 13; break;
+ case 4: hp = 17; break;
+ case 5: hp = 23; break;
+ }
+ heal = tstatus->max_hp * hp / 100;
+ status->heal(bl,heal,0,2);
clif->skill_nodamage(src, bl, skill_id, skill_lv, heal);
}
break;
@@ -8208,7 +8570,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NC_DISJOINT:
{
if( bl->type != BL_MOB ) break;
- md = iMap->id2md(bl->id);
+ md = map->id2md(bl->id);
if( md && md->class_ >= MOBID_SILVERSNIPER && md->class_ <= MOBID_MAGICDECOY_WIND )
status_kill(bl);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
@@ -8218,7 +8580,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( sd ) {
int idx1 = skill->get_index(sd->reproduceskill_id), idx2 = skill->get_index(sd->cloneskill_id);
if( sd->status.skill[idx1].id || sd->status.skill[idx2].id ) {
- sc_start(src,SC_STOP,100,skill_lv,-1);// The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax]
+ sc_start(src,src,SC_STOP,100,skill_lv,-1);// The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax]
clif->autoshadowspell_list(sd);
clif->skill_nodamage(src,bl,skill_id,1,1);
}
@@ -8229,7 +8591,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SC_SHADOWFORM:
if( sd && dstsd && src != bl && !dstsd->shadowform_id ) {
- if( clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,type,100,skill_lv,bl->id,4+skill_lv,0,skill->get_time(skill_id, skill_lv))) )
+ if( clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,src,type,100,skill_lv,bl->id,4+skill_lv,0,skill->get_time(skill_id, skill_lv))) )
dstsd->shadowform_id = src->id;
}
else if( sd )
@@ -8239,171 +8601,171 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SC_BODYPAINT:
if( flag&1 ) {
if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] ||
- tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] ||
- tsc->data[SC__INVISIBILITY]) ) {
+ tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] ) ) {
status_change_end(bl, SC_HIDING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(bl, SC_CHASEWALK, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
- status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER);
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- sc_start(bl,SC_BLIND,53 + 2 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,type,20 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_BLIND,53 + 2 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
}
} else {
clif->skill_nodamage(src, bl, skill_id, 0, 1);
- iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR,
- src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR,
+ src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
}
break;
case SC_ENERVATION:
case SC_GROOMY:
+ case SC_IGNORANCE:
case SC_LAZINESS:
case SC_UNLUCKY:
case SC_WEAKNESS:
if( !(tsc && tsc->data[type]) ) {
- //((rand(myDEX / 12, myDEX / 4) + myJobLevel + 10 * skLevel) + myLevel / 10) - (targetLevel / 10 + targetLUK / 10 + (targetMaxWeight - targetWeight) / 1000 + rand(targetAGI / 6, targetAGI / 3))
- int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0) + status_get_lv(src)/10
- - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3);
- rate = cap_value(rate, skill_lv+sstatus->dex/20, 100);
- clif->skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv)));
- } else if( sd )
- clif->skill_fail(sd,skill_id,0,0);
- break;
-
- case SC_IGNORANCE:
- if( !(tsc && tsc->data[type]) ) {
- int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0) + status_get_lv(src)/10
- - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3);
- rate = cap_value(rate, skill_lv+sstatus->dex/20, 100);
- if (clif->skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv)))) {
- int sp = 200 * skill_lv;
+ int joblvbonus = 0;
+ int rate = 0;
+ if (is_boss(bl)) break;
+ joblvbonus = ( sd ? sd->status.job_level : 50 );
+ //First we set the success chance based on the caster's build which increases the chance.
+ rate = 10 * skill_lv + rnd_value( sstatus->dex / 12, sstatus->dex / 4 ) + joblvbonus + status->get_lv(src) / 10;
+ // We then reduce the success chance based on the target's build.
+ rate -= rnd_value( tstatus->agi / 6, tstatus->agi / 3 ) + tstatus->luk / 10 + ( dstsd ? (dstsd->max_weight / 10 - dstsd->weight / 10 ) / 100 : 0 ) + status->get_lv(bl) / 10;
+ //Finally we set the minimum success chance cap based on the caster's skill level and DEX.
+ rate = cap_value( rate, skill_lv + sstatus->dex / 20, 100);
+ clif->skill_nodamage(src,bl,skill_id,0,sc_start(src,bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv)));
+ if ( tsc && tsc->data[SC__IGNORANCE] && skill_id == SC_IGNORANCE) {
+ //If the target was successfully inflected with the Ignorance status, drain some of the targets SP.
+ int sp = 100 * skill_lv;
if( dstmd ) sp = dstmd->level * 2;
if( status_zap(bl,0,sp) )
- status_heal(src,0,sp/2,3);
+ status->heal(src,0,sp/2,3);//What does flag 3 do? [Rytech]
+ }
+ if ( tsc && tsc->data[SC__UNLUCKY] && skill_id == SC_UNLUCKY) {
+ //If the target was successfully inflected with the Unlucky status, give 1 of 3 random status's.
+ switch(rnd()%3) {//Targets in the Unlucky status will be affected by one of the 3 random status's regardless of resistance.
+ case 0:
+ status->change_start(src,bl,SC_POISON,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10);
+ break;
+ case 1:
+ status->change_start(src,bl,SC_SILENCE,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10);
+ break;
+ case 2:
+ status->change_start(src,bl,SC_BLIND,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10);
+ }
}
- else if( sd ) clif->skill_fail(sd,skill_id,0,0);
} else if( sd )
- clif->skill_fail(sd,skill_id,0,0);
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
break;
case LG_TRAMPLE:
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- iMap->foreachinrange(skill->destroy_trap,bl,skill->get_splash(skill_id,skill_lv),BL_SKILL,tick);
+ map->foreachinrange(skill->destroy_trap,bl,skill->get_splash(skill_id,skill_lv),BL_SKILL,tick);
break;
case LG_REFLECTDAMAGE:
if( tsc && tsc->data[type] )
status_change_end(bl,type,INVALID_TIMER);
else
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
case LG_SHIELDSPELL:
+ if( !sd )
+ break;
if( flag&1 ) {
- int duration = (sd) ? sd->bonus.shieldmdef * 2000 : 10000;
- sc_start(bl,SC_SILENCE,100,skill_lv,duration);
- } else if( sd ) {
- int opt = skill_lv;
- int rate = rnd()%100;
- int val, brate;
+ sc_start(src,bl,SC_SILENCE,100,skill_lv,sd->bonus.shieldmdef * 30000);
+ } else {
+ int opt = 0, val = 0, splashrange = 0;
+ struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]];
+ if( !shield_data || shield_data->type != IT_ARMOR ) {
+ //Skill will first check if a shield is equipped. If none is found on the caster the skill will fail.
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ break;
+ }
+ //Generates a number between 1 - 3. The number generated will determine which effect will be triggered.
+ opt = rnd()%3 + 1;
switch( skill_lv ) {
case 1:
- {
- struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]];
- if( !shield_data || shield_data->type != IT_ARMOR ) { // No shield?
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ if ( shield_data->def >= 0 && shield_data->def <= 40)
+ splashrange = 1;
+ else if ( shield_data->def >= 41 && shield_data->def <= 80)
+ splashrange = 2;
+ else
+ splashrange = 3;
+ switch( opt ) {
+ case 1:
+ sc_start(src,bl,SC_SHIELDSPELL_DEF,100,opt,INVALID_TIMER); //Splash AoE ATK
+ clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
+ map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER);
+ break;
+ case 2:
+ val = shield_data->def/10; //Damage Reflecting Increase.
+ sc_start2(src,bl,SC_SHIELDSPELL_DEF,100,opt,val,shield_data->def * 1000);
+ break;
+ case 3:
+ //Weapon Attack Increase.
+ val = shield_data->def;
+ sc_start2(src,bl,SC_SHIELDSPELL_DEF,100,opt,val,shield_data->def * 3000);
break;
- }
- brate = shield_data->def * 10;
- if( rate < 50 )
- opt = 1;
- else if( rate < 75 )
- opt = 2;
- else
- opt = 3;
-
- switch( opt ) {
- case 1:
- sc_start(bl,SC_SHIELDSPELL_DEF,100,opt,-1);
- clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- if( rate < brate )
- iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
- status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER);
- break;
- case 2:
- val = shield_data->def / 10; // % Reflected damage.
- sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 1000);
- break;
- case 3:
- val = shield_data->def; // Attack increase.
- sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 3000);
- break;
- }
}
break;
-
case 2:
- brate = sd->bonus.shieldmdef * 20;
- if( rate < 30 )
- opt = 1;
- else if( rate < 60 )
- opt = 2;
+ if( sd->bonus.shieldmdef == 0 )
+ break; // Nothing should happen if the shield has no mdef, not even displaying a message
+ if ( sd->bonus.shieldmdef >= 1 && sd->bonus.shieldmdef <= 3 )
+ splashrange = 1;
+ else if ( sd->bonus.shieldmdef >= 4 && sd->bonus.shieldmdef <= 5 )
+ splashrange = 2;
else
- opt = 3;
+ splashrange = 3;
switch( opt ) {
case 1:
- sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1);
+ sc_start(src,bl,SC_SHIELDSPELL_MDEF,100,opt,INVALID_TIMER); //Splash AoE MATK
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- if( rate < brate )
- iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|2,skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
status_change_end(bl,SC_SHIELDSPELL_MDEF,INVALID_TIMER);
break;
case 2:
- sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1);
- clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- if( rate < brate )
- iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id);
+ sc_start(src,bl,SC_SHIELDSPELL_MDEF,100,opt,sd->bonus.shieldmdef * 2000); //Splash AoE Lex Divina
+ clif->skill_damage(src,bl,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6);
+ map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id);
break;
case 3:
- if( sc_start(bl,SC_SHIELDSPELL_MDEF,brate,opt,sd->bonus.shieldmdef * 30000) )
+ if( sc_start(src,bl,SC_SHIELDSPELL_MDEF,100,opt,sd->bonus.shieldmdef * 30000) ) //Magnificat
clif->skill_nodamage(src,bl,PR_MAGNIFICAT,skill_lv,
- sc_start(bl,SC_MAGNIFICAT,100,1,sd->bonus.shieldmdef * 30000));
+ sc_start(src,bl,SC_MAGNIFICAT,100,1,sd->bonus.shieldmdef * 30000));
break;
}
break;
-
case 3:
{
- struct item *it = &sd->status.inventory[sd->equip_index[EQI_HAND_L]];
- if( !it ) { // No shield?
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- break;
- }
- brate = it->refine * 5;
- if( rate < 25 )
- opt = 1;
- else if( rate < 50 )
- opt = 2;
- else
- opt = 3;
+ int rate = 0;
+ struct item *shield = &sd->status.inventory[sd->equip_index[EQI_HAND_L]];
+
+ if( shield->refine == 0 )
+ break; // Nothing should happen if the shield has no refine, not even displaying a message
+
switch( opt ) {
case 1:
- val = 105 * it->refine / 10;
- sc_start2(bl,SC_SHIELDSPELL_REF,brate,opt,val,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,SC_SHIELDSPELL_REF,100,opt,shield->refine * 30000); //Now breaks Armor at 100% rate
break;
- case 2: case 3:
- if( rate < brate )
- {
- val = sstatus->max_hp * (11 + it->refine) / 100;
- status_heal(bl, val, 0, 3);
- }
+ case 2:
+ val = shield->refine * 10 * status->get_lv(src) / 100; //DEF Increase
+ rate = (shield->refine * 2) + (status_get_luk(src) / 10); //Status Resistance Rate
+ if( sc_start2(src,bl,SC_SHIELDSPELL_REF,100,opt,val,shield->refine * 20000))
+ clif->skill_nodamage(src,bl,SC_SCRESIST,skill_lv,
+ sc_start(src,bl,SC_SCRESIST,100,rate,shield->refine * 30000));
+ break;
+ case 3:
+ sc_start(src,bl,SC_SHIELDSPELL_REF,100,opt,INVALID_TIMER); //HP Recovery
+ val = sstatus->max_hp * ((status->get_lv(src) / 10) + (shield->refine + 1)) / 100;
+ status->heal(bl, val, 0, 2);
+ status_change_end(bl,SC_SHIELDSPELL_REF,INVALID_TIMER);
break;
- /*case 3:
- // Full protection. I need confirm what effect should be here. Moved to case 2 to until we got it.
- break;*/
}
}
break;
@@ -8414,16 +8776,17 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case LG_PIETY:
if( flag&1 )
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
else {
- skill_area_temp[2] = 0;
- iMap->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_PC,src,skill_id,skill_lv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill->castend_nodamage_id);
+ skill->area_temp[2] = 0;
+ map->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_PC,src,skill_id,skill_lv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill->castend_nodamage_id);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
}
break;
case LG_KINGS_GRACE:
if( flag&1 ){
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ int i;
+ sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
for(i=0; i<SC_MAX; i++)
{
if (!tsc->data[i])
@@ -8435,75 +8798,76 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SC_BLOODING: case SC_CURSE:
case SC_CONFUSION: case SC_ILLUSION:
case SC_SILENCE: case SC_BURNING:
- case SC_CRYSTALIZE: case SC_FROSTMISTY:
+ case SC_COLD: case SC_FROSTMISTY:
case SC_DEEP_SLEEP: case SC_FEAR:
- case SC_MANDRAGORA:
+ case SC_MANDRAGORA: case SC__CHAOS:
status_change_end(bl, (sc_type)i, INVALID_TIMER);
}
}
}else {
- skill_area_temp[2] = 0;
+ skill->area_temp[2] = 0;
if( !map_flag_vs(src->m) && !map_flag_gvg(src->m) )
flag |= BCT_GUILD;
- iMap->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_PC,src,skill_id,skill_lv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_PC,src,skill_id,skill_lv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill->castend_nodamage_id);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
}
break;
case LG_INSPIRATION:
- if( sd && !map[sd->bl.m].flag.noexppenalty && sd->status.base_level != MAX_LEVEL ) {
+ if( sd && !map->list[sd->bl.m].flag.noexppenalty && sd->status.base_level != MAX_LEVEL ) {
sd->status.base_exp -= min(sd->status.base_exp, pc->nextbaseexp(sd) * 1 / 100); // 1% penalty.
sd->status.job_exp -= min(sd->status.job_exp, pc->nextjobexp(sd) * 1 / 100);
clif->updatestatus(sd,SP_BASEEXP);
clif->updatestatus(sd,SP_JOBEXP);
}
clif->skill_nodamage(bl,src,skill_id,skill_lv,
- sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
+ sc_start(src,bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
break;
case SR_CURSEDCIRCLE:
if( flag&1 ) {
if( is_boss(bl) ) break;
- if( sc_start2(bl, type, 100, skill_lv, src->id, skill->get_time(skill_id, skill_lv))) {
+ if( sc_start2(src,bl, type, 100, skill_lv, src->id, skill->get_time(skill_id, skill_lv))) {
if( bl->type == BL_MOB )
- mob_unlocktarget((TBL_MOB*)bl,iTimer->gettick());
- unit_stop_attack(bl);
+ mob->unlocktarget((TBL_MOB*)bl,timer->gettick());
+ unit->stop_attack(bl);
clif->bladestop(src, bl->id, 1);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
} else {
int count = 0;
clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- count = iMap->forcountinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv), (sd)?sd->spiritball_old:15, // Assume 15 spiritballs in non-charactors
+ count = map->forcountinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv), (sd)?sd->spiritball_old:15, // Assume 15 spiritballs in non-characters
BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
if( sd ) pc->delspiritball(sd, count, 0);
clif->skill_nodamage(src, src, skill_id, skill_lv,
- sc_start2(src, SC_CURSEDCIRCLE_ATKER, 100, skill_lv, count, skill->get_time(skill_id,skill_lv)));
+ sc_start2(src, src, SC_CURSEDCIRCLE_ATKER, 100, skill_lv, count, skill->get_time(skill_id,skill_lv)));
}
break;
case SR_RAISINGDRAGON:
if( sd ) {
short max = 5 + skill_lv;
- sc_start(bl, SC_EXPLOSIONSPIRITS, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ int i;
+ sc_start(src, bl, SC_EXPLOSIONSPIRITS, 100, skill_lv, skill->get_time(skill_id, skill_lv));
for( i = 0; i < max; i++ ) // Don't call more than max available spheres.
pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), max);
- clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv)));
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv)));
}
break;
case SR_ASSIMILATEPOWER:
if( flag&1 ) {
- i = 0;
+ int sp = 0;
if( dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER )
{
- i = dstsd->spiritball; //1%sp per spiritball.
+ sp = dstsd->spiritball; //1%sp per spiritball.
pc->delspiritball(dstsd, dstsd->spiritball, 0);
+ status_percent_heal(src, 0, sp);
}
- if( i ) status_percent_heal(src, 0, i);
- clif->skill_nodamage(src, bl, skill_id, skill_lv, i ? 1:0);
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, sp ? 1:0);
} else {
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill->castend_nodamage_id);
}
break;
@@ -8511,6 +8875,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( !dstsd )
break;
if( sd && dstsd->spiritball <= 5 ) {
+ int i;
for(i = 0; i <= 5; i++) {
pc->addspiritball(dstsd, skill->get_time(MO_CALLSPIRITS, pc->checkskill(sd,MO_CALLSPIRITS)), i);
pc->delspiritball(sd, sd->spiritball, 0);
@@ -8523,24 +8888,22 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
{
int heal;
- if( status_isimmune(bl) )
- {
+ if( status->isimmune(bl) ) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,0);
break;
}
heal = 120 * skill_lv + status_get_max_hp(bl) * (2 + skill_lv) / 100;
- status_heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, 0);
- if( (tsc && tsc->opt1) && (rnd()%100 < ((skill_lv * 5) + (status_get_dex(src) + status_get_lv(src)) / 4) - (1 + (rnd() % 10))) )
- {
+ if( (tsc && tsc->opt1) && (rnd()%100 < ((skill_lv * 5) + (status_get_dex(src) + status->get_lv(src)) / 4) - (1 + (rnd() % 10))) ) {
status_change_end(bl, SC_STONE, INVALID_TIMER);
status_change_end(bl, SC_FREEZE, INVALID_TIMER);
status_change_end(bl, SC_STUN, INVALID_TIMER);
status_change_end(bl, SC_POISON, INVALID_TIMER);
status_change_end(bl, SC_SILENCE, INVALID_TIMER);
status_change_end(bl, SC_BLIND, INVALID_TIMER);
- status_change_end(bl, SC_ILLUSION, INVALID_TIMER);
+ status_change_end(bl, SC_ILLUSION, INVALID_TIMER);
status_change_end(bl, SC_BURNING, INVALID_TIMER);
status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER);
}
@@ -8551,146 +8914,156 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SR_GENTLETOUCH_CHANGE:
case SR_GENTLETOUCH_REVITALIZE:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)));
+ sc_start2(src,bl,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv)));
break;
case SR_FLASHCOMBO:
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- for(i = SR_FLASHCOMBO_ATK_STEP1; i <= SR_FLASHCOMBO_ATK_STEP4; i++)
- skill->addtimerskill(src, tick + 500 * (i - SR_FLASHCOMBO_ATK_STEP1), bl->id, 0, 0, i, skill_lv, BF_WEAPON, flag|SD_LEVEL);
- break;
- case WA_SWING_DANCE:
- case WA_MOONLIT_SERENADE:
- if( sd == NULL || sd->status.party_id == 0 || (flag & 1) )
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- else if( sd ) { // Only shows effects on caster.
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
- }
- break;
+ {
+ const int combo[] = {
+ SR_DRAGONCOMBO, SR_FALLENEMPIRE, SR_TIGERCANNON, SR_SKYNETBLOW
+ };
+ int i;
+
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,
+ sc_start2(src,bl,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv)));
+
+ for( i = 0; i < ARRAYLENGTH(combo); i++ )
+ skill->addtimerskill(src, tick + 400 * i, bl->id, 0, 0, combo[i], skill_lv, BF_WEAPON, flag|SD_LEVEL);
+ break;
+ }
+ case WA_SWING_DANCE:
case WA_SYMPHONY_OF_LOVER:
+ case WA_MOONLIT_SERENADE:
case MI_RUSH_WINDMILL:
case MI_ECHOSONG:
- if( sd == NULL || sd->status.party_id == 0 || (flag & 1) )
- sc_start4(bl,type,100,skill_lv,6*skill_lv,(sd?pc->checkskill(sd,WM_LESSON):0),(sd?sd->status.job_level:0),skill->get_time(skill_id,skill_lv));
- else if( sd ) { // Only shows effects on caster.
+ if( flag&1 )
+ sc_start2(src,bl,type,100,skill_lv,(sd?pc->checkskill(sd,WM_LESSON):0),skill->get_time(skill_id,skill_lv));
+ else if( sd ) {
+ party->foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id);
+ sc_start2(src,bl,type,100,skill_lv,pc->checkskill(sd,WM_LESSON),skill->get_time(skill_id,skill_lv));
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id);
}
break;
case MI_HARMONIZE:
- if( src != bl )
- clif->skill_nodamage(src, src, skill_id, skill_lv, sc_start(src, type, 100, skill_lv, skill->get_time(skill_id,skill_lv)));
- clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start2(src,bl,type,100,skill_lv,(sd?pc->checkskill(sd,WM_LESSON):1),skill->get_time(skill_id,skill_lv)));
break;
case WM_DEADHILLHERE:
if( bl->type == BL_PC ) {
- if( !status_isdead(bl) )
+ if( !status->isdead(bl) )
break;
if( rnd()%100 < 88 + 2 * skill_lv ) {
- int heal = tstatus->sp;
- if( heal <= 0 )
+ int heal = 0;
+ status_zap(bl, 0, tstatus->sp * (60 - 10 * skill_lv) / 100);
+ heal = tstatus->sp;
+ if ( heal <= 0 )
heal = 1;
- tstatus->hp = heal;
- tstatus->sp -= tstatus->sp * ( 120 - 20 * skill_lv ) / 100;
+ status->fixed_revive(bl, heal, 0);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- pc->revive((TBL_PC*)bl,heal,0);
- clif->resurrection(bl,1);
+ status->set_sp(bl, 0, 0);
}
}
break;
+ case WM_LULLABY_DEEPSLEEP:
+ if ( flag&1 )
+ sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv));
+ else if ( sd ) {
+ int rate = 4 * skill_lv + 2 * pc->checkskill(sd,WM_LESSON) + status->get_lv(src)/15 + sd->status.job_level/5;
+ if ( rnd()%100 < rate ) {
+ flag |= BCT_PARTY|BCT_GUILD;
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_NPC|BL_SKILL, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
+ }
+ }
+ break;
case WM_SIRCLEOFNATURE:
flag |= BCT_SELF|BCT_PARTY|BCT_GUILD;
case WM_VOICEOFSIREN:
if( skill_id != WM_SIRCLEOFNATURE )
flag &= ~BCT_SELF;
if( flag&1 ) {
- sc_start2(bl,type,(skill_id==WM_VOICEOFSIREN)?20+10*skill_lv:100,skill_lv,(skill_id==WM_VOICEOFSIREN)?src->id:0,skill->get_time(skill_id,skill_lv));
- } else {
- iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),(skill_id==WM_VOICEOFSIREN)?BL_CHAR|BL_SKILL:BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ sc_start2(src,bl,type,100,skill_lv,(skill_id==WM_VOICEOFSIREN)?src->id:0,skill->get_time(skill_id,skill_lv));
+ } else if( sd ) {
+ int rate = 6 * skill_lv + pc->checkskill(sd,WM_LESSON) + sd->status.job_level/2;
+ if ( rnd()%100 < rate ) {
+ flag |= BCT_PARTY|BCT_GUILD;
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),(skill_id==WM_VOICEOFSIREN)?BL_CHAR|BL_NPC|BL_SKILL:BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ status_change_end(bl, SC_SIREN, INVALID_TIMER);
+ }
}
break;
case WM_GLOOMYDAY:
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if( dstsd && ( pc->checkskill(dstsd,KN_BRANDISHSPEAR) || pc->checkskill(dstsd,LK_SPIRALPIERCE) ||
- pc->checkskill(dstsd,CR_SHIELDCHARGE) || pc->checkskill(dstsd,CR_SHIELDBOOMERANG) ||
- pc->checkskill(dstsd,PA_SHIELDCHAIN) || pc->checkskill(dstsd,LG_SHIELDPRESS) ) )
- {
- sc_start(bl,SC_GLOOMYDAY_SK,100,skill_lv,skill->get_time(skill_id,skill_lv));
- break;
- }
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- break;
-
- case WM_SATURDAY_NIGHT_FEVER:
- if( flag&1 ) { // Affect to all targets arround the caster and caster too.
- if( !(tsc && tsc->data[type]) )
- sc_start(bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv));
- } else if( flag&2 ) {
- if( src->id != bl->id && battle->check_target(src,bl,BCT_ENEMY) > 0 )
- status_fix_damage(src,bl,9999,clif->damage(src,bl,tick,0,0,9999,0,0,0));
- } else if( sd ) {
- short chance = sstatus->int_/6 + sd->status.job_level/5 + skill_lv*4;
- if( !sd->status.party_id || (rnd()%100 > chance)) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_NEED_HELPER,0);
- break;
- }
- if( iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id,skill_lv),
- BL_PC, src, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count) > 7 )
- flag |= 2;
- else
- flag |= 1;
- iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF, skill->castend_nodamage_id);
- clif->skill_nodamage(src, bl, skill_id, skill_lv,
- sc_start(src,SC_STOP,100,skill_lv,skill->get_time2(skill_id,skill_lv)));
- if( flag&2 ) // Dealed here to prevent conflicts
- status_fix_damage(src,bl,9999,clif->damage(src,bl,tick,0,0,9999,0,0,0));
+ if ( tsc && tsc->data[type] ) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ break;
}
+ // val4 indicates caster's voice lesson level
+ sc_start4(src,bl,type,100,skill_lv, 0, 0, sd?pc->checkskill(sd,WM_LESSON):10, skill->get_time(skill_id,skill_lv));
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
case WM_SONG_OF_MANA:
case WM_DANCE_WITH_WUG:
case WM_LERADS_DEW:
- if( flag&1 ) { // These affect to to all party members near the caster.
- struct status_change *sc = status_get_sc(src);
- if( sc && sc->data[type] ) {
- sc_start2(bl,type,100,skill_lv,sc->data[type]->val2,skill->get_time(skill_id,skill_lv));
- }
- } else if( sd ) {
- short lv = (short)skill_lv;
- int count = skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),1);
- if( sc_start2(bl,type,100,skill_lv,count,skill->get_time(skill_id,skill_lv)) )
- party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id);
+ case WM_UNLIMITED_HUMMING_VOICE:
+ {
+ int chorusbonus = battle->calc_chorusbonus(sd);
+ if( flag&1 )
+ sc_start2(src,bl,type,100,skill_lv,chorusbonus,skill->get_time(skill_id,skill_lv));
+ else if( sd ) {
+ party->foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id);
+ sc_start2(src,bl,type,100,skill_lv,chorusbonus,skill->get_time(skill_id,skill_lv));
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
-
}
+ }
+ break;
+ case WM_SATURDAY_NIGHT_FEVER:
+ {
+ if( flag&1 ) {
+ int madnesscheck = 0;
+ if ( sd )//Required to check if the lord of madness effect will be applied.
+ madnesscheck = map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count);
+ sc_start(src, bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv));
+ if ( madnesscheck >= 8 )//The god of madness deals 9999 fixed unreduceable damage when 8 or more enemy players are affected.
+ status_fix_damage(src, bl, 9999, clif->damage(src, bl, 0, 0, 9999, 0, 0, 0));
+ //skill->attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);//To renable when I can confirm it deals damage like this. Data shows its dealt as reflected damage which I don't have it coded like that yet. [Rytech]
+ } else if( sd ) {
+ int rate = sstatus->int_ / 6 + (sd? sd->status.job_level:0) / 5 + skill_lv * 4;
+ if ( rnd()%100 < rate ) {
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
+ }
+ }
+ }
break;
case WM_MELODYOFSINK:
case WM_BEYOND_OF_WARCRY:
- case WM_UNLIMITED_HUMMING_VOICE:
- if( flag&1 ) {
- sc_start2(bl,type,100,skill_lv,skill_area_temp[0],skill->get_time(skill_id,skill_lv));
- } else { // These affect to all targets arround the caster.
- short lv = (short)skill_lv;
- skill_area_temp[0] = (sd) ? skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),1) : 50; // 50% chance in non BL_PC (clones).
- iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
- clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ {
+ int chorusbonus = battle->calc_chorusbonus(sd);
+ if( flag&1 )
+ sc_start2(src,bl,type,100,skill_lv,chorusbonus,skill->get_time(skill_id,skill_lv));
+ else if( sd ) {
+ if ( rnd()%100 < 15 + 5 * skill_lv + 5 * chorusbonus ) {
+ map->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
+ }
}
+ }
break;
case WM_RANDOMIZESPELL: {
- int improv_skill_id = 0, improv_skill_lv;
+ int improv_skill_id = 0, improv_skill_lv, improv_idx;
do {
- i = rnd() % MAX_SKILL_IMPROVISE_DB;
- improv_skill_id = skill_improvise_db[i].skill_id;
- } while( improv_skill_id == 0 || rnd()%10000 >= skill_improvise_db[i].per );
+ improv_idx = rnd() % MAX_SKILL_IMPROVISE_DB;
+ improv_skill_id = skill->improvise_db[improv_idx].skill_id;
+ } while( improv_skill_id == 0 || rnd()%10000 >= skill->improvise_db[improv_idx].per );
improv_skill_lv = 4 + skill_lv;
clif->skill_nodamage (src, bl, skill_id, skill_lv, 1);
@@ -8700,14 +9073,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
sd->skillitemlv = improv_skill_lv;
clif->item_skill(sd, improv_skill_id, improv_skill_lv);
} else {
- struct unit_data *ud = unit_bl2ud(src);
+ struct unit_data *ud = unit->bl2ud(src);
int inf = skill->get_inf(improv_skill_id);
if (!ud) break;
if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) {
if (src->type == BL_PET)
bl = (struct block_list*)((TBL_PET*)src)->msd;
if (!bl) bl = src;
- unit_skilluse_id(src, bl->id, improv_skill_id, improv_skill_lv);
+ unit->skilluse_id(src, bl->id, improv_skill_id, improv_skill_lv);
} else {
int target_id = 0;
if (ud->target)
@@ -8719,11 +9092,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (!target_id)
break;
if (skill->get_casttype(improv_skill_id) == CAST_GROUND) {
- bl = iMap->id2bl(target_id);
+ bl = map->id2bl(target_id);
if (!bl) bl = src;
- unit_skilluse_pos(src, bl->x, bl->y, improv_skill_id, improv_skill_lv);
+ unit->skilluse_pos(src, bl->x, bl->y, improv_skill_id, improv_skill_lv);
} else
- unit_skilluse_id(src, target_id, improv_skill_id, improv_skill_lv);
+ unit->skilluse_id(src, target_id, improv_skill_id, improv_skill_lv);
}
}
}
@@ -8735,28 +9108,25 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( sd )
{
short x, y; // Destiny position.
- unsigned short mapindex;
+ unsigned short map_index;
- if( skill_id == RETURN_TO_ELDICASTES)
- {
+ if( skill_id == RETURN_TO_ELDICASTES) {
x = 198;
y = 187;
- mapindex = mapindex_name2id(MAP_DICASTES);
- }
- else
- {
+ map_index = mapindex->name2id(MAP_DICASTES);
+ } else {
x = 44;
y = 151;
- mapindex = mapindex_name2id(MAP_MORA);
+ map_index = mapindex->name2id(MAP_MORA);
}
- if(!mapindex)
- { //Given map not found?
+ if(!map_index) {
+ //Given map not found?
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
- pc->setpos(sd, mapindex, x, y, CLR_TELEPORT);
+ pc->setpos(sd, map_index, x, y, CLR_TELEPORT);
}
break;
@@ -8774,23 +9144,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SO_ARRULLO:
{
// [(15 + 5 * Skill Level) + ( Caster?s INT / 5 ) + ( Caster?s Job Level / 5 ) - ( Target?s INT / 6 ) - ( Target?s LUK / 10 )] %
- int rate = (15 + 5 * skill_lv) + status_get_int(src)/5 + (sd ? sd->status.job_level : 0);
+ int rate = (15 + 5 * skill_lv) + status_get_int(src)/5 + (sd? sd->status.job_level:0)/5;
rate -= status_get_int(bl)/6 - status_get_luk(bl)/10;
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- sc_start2(bl, type, rate, skill_lv, 1, skill->get_time(skill_id, skill_lv));
- }
- break;
-
- case WM_LULLABY_DEEPSLEEP:
- if( flag&1 ){
- //[(Skill Level x 4) + (Voice Lessons Skill Level x 2) + (Caster?s Base Level / 15) + (Caster?s Job Level / 5)] %
- int rate = (4 * skill_lv) + ( (sd) ? pc->checkskill(sd,WM_LESSON)*2 + sd->status.job_level/5 : 0 ) + status_get_lv(src) / 15;
- if( bl != src )
- sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv));
- }else {
- clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR,
- src, skill_id, skill_lv, tick, flag|BCT_ALL|1, skill->castend_nodamage_id);
+ sc_start2(src,bl, type, rate, skill_lv, 1, skill->get_time(skill_id, skill_lv));
}
break;
@@ -8801,13 +9158,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( sd ) {
int elemental_class = skill->get_elemental_type(skill_id,skill_lv);
- // Remove previous elemental fisrt.
+ // Remove previous elemental first.
if( sd->ed )
- elemental_delete(sd->ed,0);
+ elemental->delete(sd->ed,0);
// Summoning the new one.
- if( !elemental_create(sd,elemental_class,skill->get_time(skill_id,skill_lv)) ) {
- clif->skill_fail(sd,skill_id,0,0);
+ if( !elemental->create(sd,elemental_class,skill->get_time(skill_id,skill_lv)) ) {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -8821,14 +9178,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if( !sd->ed ) break;
if( skill_lv == 4 ) {// At level 4 delete elementals.
- elemental_delete(sd->ed, 0);
+ elemental->delete(sd->ed, 0);
break;
}
- switch( skill_lv ) {// Select mode bassed on skill level used.
+ switch( skill_lv ) {// Select mode based on skill level used.
case 2: mode = EL_MODE_ASSIST; break;
case 3: mode = EL_MODE_AGGRESSIVE; break;
}
- if( !elemental_change_mode(sd->ed,mode) ) {
+ if( !elemental->change_mode(sd->ed,mode) ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
@@ -8838,22 +9195,26 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SO_EL_ACTION:
if( sd ) {
- int duration = 3000;
- if( !sd->ed ) break;
+ int duration = 3000;
+ if( !sd->ed )
+ break;
+
+ switch(sd->ed->db->class_){
+ case 2115:case 2124:
+ case 2118:case 2121:
+ duration = 6000;
+ break;
+ case 2116:case 2119:
+ case 2122:case 2125:
+ duration = 9000;
+ break;
+ }
+
sd->skill_id_old = skill_id;
- elemental_action(sd->ed, bl, tick);
+ elemental->action(sd->ed, bl, tick);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- switch(sd->ed->db->class_){
- case 2115:case 2124:
- case 2118:case 2121:
- duration = 6000;
- break;
- case 2116:case 2119:
- case 2122:case 2125:
- duration = 9000;
- break;
- }
- skill->blockpc_start(sd, skill_id, duration, false);
+
+ skill->blockpc_start(sd, skill_id, duration);
}
break;
@@ -8864,13 +9225,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
int e_hp, e_sp;
if( !ed ) break;
- if( !status_charge(&sd->bl,s_hp,s_sp) ) {
+ if( !status->charge(&sd->bl,s_hp,s_sp) ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
e_hp = ed->battle_status.max_hp * 10 / 100;
e_sp = ed->battle_status.max_sp * 10 / 100;
- status_heal(&ed->bl,e_hp,e_sp,3);
+ status->heal(&ed->bl,e_hp,e_sp,3);
clif->skill_nodamage(src,&ed->bl,skill_id,skill_lv,1);
}
break;
@@ -8885,7 +9246,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case GN_BLOOD_SUCKER:
{
- struct status_change *sc = status_get_sc(src);
+ struct status_change *sc = status->get_sc(src);
if( sc && sc->bs_counter < skill->get_maxcount( skill_id , skill_lv) ) {
if( tsc && tsc->data[type] ){
@@ -8893,7 +9254,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
status_change_end(src, type, INVALID_TIMER); // the first one cancels and the last one will take effect resetting the timer
}
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- sc_start2(bl, type, 100, skill_lv, src->id, skill->get_time(skill_id,skill_lv));
+ sc_start2(src,bl, type, 100, skill_lv, src->id, skill->get_time(skill_id,skill_lv));
(sc->bs_counter)++;
} else if( sd ) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
@@ -8904,40 +9265,45 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case GN_MANDRAGORA:
if( flag&1 ) {
- if ( clif->skill_nodamage(bl, src, skill_id, skill_lv,
- sc_start(bl, type, 25 + 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv))) )
- status_zap(bl, 0, status_get_max_sp(bl) * (25 + 5 * skill_lv) / 100);
- } else
- iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR,
- src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ int chance = 25 + 10 * skill_lv - (status_get_vit(bl) + status_get_luk(bl)) / 5;
+ if ( chance < 10 )
+ chance = 10;//Minimal chance is 10%.
+ if ( rnd()%100 < chance ) {//Coded to both inflect the status and drain the target's SP only when successful. [Rytech]
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ status_zap(bl, 0, status_get_max_sp(bl) * (25 + 5 * skill_lv) / 100);
+ }
+ } else if ( sd ) {
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR,src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ clif->skill_nodamage(bl, src, skill_id, skill_lv, 1);
+ }
break;
case GN_SLINGITEM:
if( sd ) {
short ammo_id;
- i = sd->equip_index[EQI_AMMO];
- if( i <= 0 )
+ int equip_idx = sd->equip_index[EQI_AMMO];
+ if( equip_idx <= 0 )
break; // No ammo.
- ammo_id = sd->inventory_data[i]->nameid;
+ ammo_id = sd->inventory_data[equip_idx]->nameid;
if( ammo_id <= 0 )
break;
sd->itemid = ammo_id;
if( itemdb_is_GNbomb(ammo_id) ) {
if(battle->check_target(src,bl,BCT_ENEMY) > 0) {// Only attack if the target is an enemy.
- if( ammo_id == 13263 )
- iMap->foreachincell(skill->area_sub,bl->m,bl->x,bl->y,BL_CHAR,src,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ if( ammo_id == ITEMID_PINEAPPLE_BOMB )
+ map->foreachincell(skill->area_sub,bl->m,bl->x,bl->y,BL_CHAR,src,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
else
skill->attack(BF_WEAPON,src,src,bl,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag);
} else //Otherwise, it fails, shows animation and removes items.
clif->skill_fail(sd,GN_SLINGITEM_RANGEMELEEATK,0xa,0);
- } else if( itemdb_is_GNthrowable(ammo_id) ){
- struct script_code *script = sd->inventory_data[i]->script;
- if( !script )
+ } else if( itemdb_is_GNthrowable(ammo_id) ) {
+ struct script_code *scriptroot = sd->inventory_data[equip_idx]->script;
+ if( !scriptroot )
break;
if( dstsd )
- run_script(script,0,dstsd->bl.id,fake_nd->bl.id);
+ script->run(scriptroot,0,dstsd->bl.id,npc->fake_nd->bl.id);
else
- run_script(script,0,src->id,0);
+ script->run(scriptroot,0,src->id,0);
}
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -8975,24 +9341,25 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case EL_WIND_CURTAIN:
case EL_SOLID_SKIN:
case EL_STONE_SHIELD:
- case EL_WIND_STEP: {
- struct elemental_data *ele = BL_CAST(BL_ELEM, src);
- if( ele ) {
- sc_type type2 = type-1;
- struct status_change *sc = status_get_sc(&ele->bl);
-
- if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) {
- elemental_clean_single_effect(ele, skill_id);
- } else {
- clif->skill_nodamage(src,src,skill_id,skill_lv,1);
- clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- if( skill_id == EL_WIND_STEP ) // There aren't teleport, just push the master away.
- skill->blown(src,bl,(rnd()%skill->get_blewcount(skill_id,skill_lv))+1,rand()%8,0);
- sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv));
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- }
+ case EL_WIND_STEP:
+ {
+ struct elemental_data *ele = BL_CAST(BL_ELEM, src);
+ if( ele ) {
+ sc_type type2 = type-1;
+ struct status_change *sc = status->get_sc(&ele->bl);
+
+ if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) {
+ elemental->clean_single_effect(ele, skill_id);
+ } else {
+ clif->skill_nodamage(src,src,skill_id,skill_lv,1);
+ clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
+ if( skill_id == EL_WIND_STEP ) // There aren't teleport, just push the master away.
+ skill->blown(src,bl,(rnd()%skill->get_blewcount(skill_id,skill_lv))+1,rnd()%8,0);
+ sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
}
}
+ }
break;
case EL_FIRE_MANTLE:
@@ -9004,23 +9371,24 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
skill->unitsetting(src,skill_id,skill_lv,bl->x,bl->y,0);
break;
- case EL_WATER_SCREEN: {
- struct elemental_data *ele = BL_CAST(BL_ELEM, src);
- if( ele ) {
- struct status_change *sc = status_get_sc(&ele->bl);
- sc_type type2 = type-1;
+ case EL_WATER_SCREEN:
+ {
+ struct elemental_data *ele = BL_CAST(BL_ELEM, src);
+ if( ele ) {
+ struct status_change *sc = status->get_sc(&ele->bl);
+ sc_type type2 = type-1;
- clif->skill_nodamage(src,src,skill_id,skill_lv,1);
- if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) {
- elemental_clean_single_effect(ele, skill_id);
- } else {
- // This not heals at the end.
- clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv));
- sc_start(bl,type,100,src->id,skill->get_time(skill_id,skill_lv));
- }
+ clif->skill_nodamage(src,src,skill_id,skill_lv,1);
+ if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) {
+ elemental->clean_single_effect(ele, skill_id);
+ } else {
+ // This not heals at the end.
+ clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
+ sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ sc_start(src, bl,type,100,src->id,skill->get_time(skill_id,skill_lv));
}
}
+ }
break;
case KO_KAHU_ENTEN:
@@ -9028,6 +9396,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case KO_KAZEHU_SEIRAN:
case KO_DOHU_KOUKAI:
if(sd) {
+ int i;
int ttype = skill->get_ele(skill_id, skill_lv);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
ARR_FIND(1, 6, i, sd->charm[i] > 0 && ttype != i);
@@ -9038,21 +9407,20 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case KO_ZANZOU:
- if(sd){
- struct mob_data *md;
-
- md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), 2308, "", SZ_SMALL, AI_NONE);
- if( md )
- {
- md->master_id = src->id;
- md->special_state.ai = AI_ZANZOU;
- if( md->deletetimer != INVALID_TIMER )
- iTimer->delete_timer(md->deletetimer, mob_timer_delete);
- md->deletetimer = iTimer->add_timer (iTimer->gettick() + skill->get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0);
- mob_spawn( md );
+ if(sd) {
+ struct mob_data *summon_md;
+
+ summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), 2308, "", SZ_MEDIUM, AI_NONE);
+ if( summon_md ) {
+ summon_md->master_id = src->id;
+ summon_md->special_state.ai = AI_ZANZOU;
+ if( summon_md->deletetimer != INVALID_TIMER )
+ timer->delete(summon_md->deletetimer, mob->timer_delete);
+ summon_md->deletetimer = timer->add(timer->gettick() + skill->get_time(skill_id, skill_lv), mob->timer_delete, summon_md->bl.id, 0);
+ mob->spawn( summon_md );
pc->setinvincibletimer(sd,500);// unlock target lock
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),unit_getdir(bl),0);
+ skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),unit->getdir(bl),0);
}
}
break;
@@ -9060,48 +9428,49 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case KO_KYOUGAKU:
{
int rate = max(5, (45 + 5 * skill_lv - status_get_int(bl) / 10));
- if( sd && !map_flag_gvg(src->m) ){
+ if( sd && !map_flag_gvg2(src->m) ){
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SIZE, 0);
break;
}
if( dstsd && tsc && !tsc->data[type] && rand()%100 < rate ){
clif->skill_nodamage(src, bl, skill_id, skill_lv,
- sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
}else if( sd )
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
}
break;
case KO_JYUSATSU:
- if( dstsd && tsc && !tsc->data[type] &&
- rand()%100 < (10 * (5 * skill_lv - status_get_int(bl) / 2 + 45 + 5 * skill_lv)) ){
+ if( dstsd && tsc && !tsc->data[type]
+ && rand()%100 < (10 * (5 * skill_lv - status_get_int(bl) / 2 + 45 + 5 * skill_lv))
+ ) {
clif->skill_nodamage(src, bl, skill_id, skill_lv,
- status_change_start(bl, type, 10000, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), 1));
+ status->change_start(src, bl, type, 10000, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), 1));
status_zap(bl, tstatus->max_hp * skill_lv * 5 / 100 , 0);
- if( status_get_lv(bl) <= status_get_lv(src) )
- status_change_start(bl, SC_COMA, skill_lv, skill_lv, 0, src->id, 0, 0, 0);
- }else if( sd )
+ if( status->get_lv(bl) <= status->get_lv(src) )
+ status->change_start(src, bl, SC_COMA, skill_lv, skill_lv, 0, src->id, 0, 0, 0);
+ } else if( sd )
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
break;
case KO_GENWAKU:
- if ( !map_flag_gvg(src->m) && ( dstsd || dstmd ) && !(tstatus->mode&MD_PLANT) && battle->check_target(src,bl,BCT_ENEMY) > 0 ) {
+ if ( !map_flag_gvg2(src->m) && ( dstsd || dstmd ) && !(tstatus->mode&MD_PLANT) && battle->check_target(src,bl,BCT_ENEMY) > 0 ) {
int x = src->x, y = src->y;
if( sd && rnd()%100 > max(5, (45 + 5 * skill_lv) - status_get_int(bl) / 10) ){//[(Base chance of success) - ( target's int / 10)]%.
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
break;
}
- if (unit_movepos(src, bl->x, bl->y, 0, 0)) {
+ if (unit->movepos(src, bl->x, bl->y, 0, 0)) {
clif->skill_nodamage(src, src, skill_id, skill_lv, 1);
clif->slide(src, bl->x, bl->y) ;
- sc_start(src, SC_CONFUSION, 25, skill_lv, skill->get_time(skill_id, skill_lv));
- if ( !is_boss(bl) && unit_stop_walking(&sd->bl, 1) && unit_movepos(bl, x, y, 0, 0) )
+ sc_start(src, src, SC_CONFUSION, 25, skill_lv, skill->get_time(skill_id, skill_lv));
+ if ( !is_boss(bl) && unit->stop_walking(&sd->bl, 1) && unit->movepos(bl, x, y, 0, 0) )
{
if( dstsd && pc_issit(dstsd) )
pc->setstand(dstsd);
clif->slide(bl, x, y) ;
- sc_start(bl, SC_CONFUSION, 75, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, bl, SC_CONFUSION, 75, skill_lv, skill->get_time(skill_id, skill_lv));
}
}
}
@@ -9119,7 +9488,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case KG_KYOMU:
case KG_KAGEMUSYA:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
- sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
break;
@@ -9128,8 +9497,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if(tsc && ( tsc->option&(OPTION_CLOAK|OPTION_HIDE) ||
tsc->data[SC_CAMOUFLAGE] || tsc->data[SC__SHADOWFORM] ||
tsc->data[SC_MARIONETTE_MASTER] || tsc->data[SC_HARMONIZE])){
- sc_start(src, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
- sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, src, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
status_change_end(bl, SC_HIDING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
@@ -9138,153 +9507,141 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
status_change_end(bl, SC_MARIONETTE_MASTER, INVALID_TIMER);
status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
}
- if( skill_area_temp[2] == 1 ){
+ if( skill->area_temp[2] == 1 ){
clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- sc_start(src, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, src, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv));
}
- }else{
- skill_area_temp[2] = 0;
- iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_nodamage_id);
+ } else {
+ skill->area_temp[2] = 0;
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_nodamage_id);
}
break;
- case MH_SILENT_BREEZE: {
- struct status_change *ssc = status_get_sc(src);
- struct block_list *m_bl = battle->get_master(src);
- const enum sc_type scs[] = {
- SC_MANDRAGORA, SC_HARMONIZE, SC_DEEP_SLEEP, SC_SIREN, SC_SLEEP, SC_CONFUSION, SC_ILLUSION
- };
- int heal;
- if(tsc){
- for (i = 0; i < ARRAYLENGTH(scs); i++) {
- if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER);
- }
- if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target
- status_change_start(bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8);
+ case MH_LIGHT_OF_REGENE:
+ if( hd && battle->get_master(src) ) {
+ hd->homunculus.intimacy = (751 + rnd()%99) * 100; // random between 751 ~ 850
+ clif->send_homdata(hd->master, SP_INTIMATE, hd->homunculus.intimacy / 100); //refresh intimacy info
+ sc_start(src, battle->get_master(src), type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
}
- heal = status_get_matk_min(src)*4;
- status_heal(bl, heal, 0, 7);
+ break;
- //now inflict silence on everyone
- if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun
- status_change_start(src, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8);
- if(m_bl){
- struct status_change *msc = status_get_sc(m_bl);
- if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master
- status_change_start(m_bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8);
+ case MH_OVERED_BOOST:
+ if ( hd && battle->get_master(src) ) {
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ sc_start(src, battle->get_master(src), type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
}
- if (hd)
- skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv));
- }
- break;
- case MH_OVERED_BOOST:
- if (hd){
- struct block_list *s_bl = battle->get_master(src);
- if(hd->homunculus.hunger>50) //reduce hunger
- hd->homunculus.hunger = hd->homunculus.hunger/2;
- else
- hd->homunculus.hunger = min(1,hd->homunculus.hunger);
- if(s_bl && s_bl->type==BL_PC){
- status_set_sp(s_bl,status_get_max_sp(s_bl)/2,0); //master drain 50% sp
- clif->send_homdata(((TBL_PC *)s_bl), SP_HUNGRY, hd->homunculus.hunger); //refresh hunger info
- sc_start(s_bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); //gene bonus
- }
- sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
- skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv));
- }
- break;
- case MH_GRANITIC_ARMOR:
- case MH_PYROCLASTIC: {
- struct block_list *s_bl = battle->get_master(src);
- if(s_bl)
- sc_start2(s_bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); //start on master
- sc_start2(bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv));
- if (hd)
- skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv));
+ break;
+
+ case MH_SILENT_BREEZE:
+ {
+ const enum sc_type scs[] = {
+ SC_MANDRAGORA, SC_HARMONIZE, SC_DEEP_SLEEP, SC_SIREN, SC_SLEEP, SC_CONFUSION, SC_ILLUSION
+ };
+ int heal;
+ if(tsc){
+ int i;
+ for (i = 0; i < ARRAYLENGTH(scs); i++) {
+ if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER);
}
- break;
+ }
+ heal = 5 * status->get_lv(&hd->bl) + status->base_matk(&hd->battle_status, status->get_lv(&hd->bl));
+ status->heal(bl, heal, 0, 0);
+ clif->skill_nodamage(src, src, skill_id, skill_lv, clif->skill_nodamage(src, bl, AL_HEAL, heal, 1));
+ status->change_start(src, src, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2|8);
+ status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2|8);
+ }
+ break;
- case MH_LIGHT_OF_REGENE:
- if(hd){
- hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750)
- if(sd) clif->send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info
- }
- //don't break need to start status and start block timer
- case MH_STYLE_CHANGE:
- case MH_MAGMA_FLOW:
- case MH_PAIN_KILLER:
- sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
- if (hd)
- skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv));
- break;
- case MH_SUMMON_LEGION:
- {
- int summons[5] = {1004, 1303, 1303, 1994, 1994};
- int qty[5] = {3 , 3 , 4 , 4 , 5};
- struct mob_data *md;
- int i, dummy = 0;
+ case MH_GRANITIC_ARMOR:
+ case MH_PYROCLASTIC:
+ if( hd ){
+ struct block_list *s_bl = battle->get_master(src);
+
+ if(s_bl)
+ sc_start2(src, s_bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); //start on master
+
+ sc_start2(src, bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv));
+
+ skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv));
+ }
+ break;
- i = iMap->foreachinmap(skill->check_condition_mob_master_sub ,hd->bl.m, BL_MOB, hd->bl.id, summons[skill_lv-1], skill_id, &dummy);
- if(i >= qty[skill_lv-1])
- break;
-
- for(i=0; i<qty[skill_lv - 1]; i++){ //easy way
- md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK);
- if (md) {
- md->master_id = src->id;
- if (md->deletetimer != INVALID_TIMER)
- iTimer->delete_timer(md->deletetimer, mob_timer_delete);
- md->deletetimer = iTimer->add_timer(iTimer->gettick() + skill->get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0);
- mob_spawn(md); //Now it is ready for spawning.
- sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_CANATTACK|MD_AGGRESSIVE, 0, 60000);
- }
- }
- if (hd)
- skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv));
- }
+ case MH_MAGMA_FLOW:
+ case MH_PAIN_KILLER:
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv));
+ if (hd)
+ skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv));
+ break;
+ case MH_SUMMON_LEGION:
+ {
+ int summons[5] = {1004, 1303, 1303, 1994, 1994};
+ int qty[5] = {3 , 3 , 4 , 4 , 5};
+ struct mob_data *summon_md;
+ int i, dummy = 0;
+
+ i = map->foreachinmap(skill->check_condition_mob_master_sub, src->m, BL_MOB, src->id, summons[skill_lv-1], skill_id, &dummy);
+ if(i >= qty[skill_lv-1])
break;
+
+ for(i=0; i<qty[skill_lv - 1]; i++){ //easy way
+ summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), summons[skill_lv - 1], "", SZ_MEDIUM, AI_ATTACK);
+ if (summon_md) {
+ summon_md->master_id = src->id;
+ if (summon_md->deletetimer != INVALID_TIMER)
+ timer->delete(summon_md->deletetimer, mob->timer_delete);
+ summon_md->deletetimer = timer->add(timer->gettick() + skill->get_time(skill_id, skill_lv), mob->timer_delete, summon_md->bl.id, 0);
+ mob->spawn(summon_md); //Now it is ready for spawning.
+ sc_start4(src,&summon_md->bl, SC_MODECHANGE, 100, 1, 0, MD_CANATTACK|MD_AGGRESSIVE, 0, 60000);
+ }
+ }
+ if (hd)
+ skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv));
+ }
+ break;
+ case SO_ELEMENTAL_SHIELD:/* somehow its handled outside this switch, so we need a empty case otherwise default would be triggered. */
+ break;
default:
ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skill_id);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
}
- if(skill_id != SR_CURSEDCIRCLE){
- struct status_change *sc = status_get_sc(src);
+ if(skill_id != SR_CURSEDCIRCLE) {
+ struct status_change *sc = status->get_sc(src);
if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] )//Should only remove after the skill had been casted.
status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER);
}
if (dstmd) { //Mob skill event for no damage skills (damage ones are handled in battle_calc_damage) [Skotlex]
- mob_log_damage(dstmd, src, 0); //Log interaction (counts as 'attacker' for the exp bonus)
- mobskill_event(dstmd, src, tick, MSC_SKILLUSED|(skill_id<<16));
+ mob->log_damage(dstmd, src, 0); //Log interaction (counts as 'attacker' for the exp bonus)
+ mob->skill_event(dstmd, src, tick, MSC_SKILLUSED|(skill_id<<16));
}
if( sd && !(flag&1) ) { // ensure that the skill last-cast tick is recorded
- sd->canskill_tick = iTimer->gettick();
+ sd->canskill_tick = timer->gettick();
if( sd->state.arrow_atk ) { // consume arrow on last invocation to this skill.
battle->consume_ammo(sd, skill_id, skill_lv);
}
skill->onskillusage(sd, bl, skill_id, tick);
// perform skill requirement consumption
- skill->consume_requirement(sd,skill_id,skill_lv,2);
+ if( skill_id != NC_SELFDESTRUCTION )
+ skill->consume_requirement(sd,skill_id,skill_lv,2);
}
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
/*==========================================
*
*------------------------------------------*/
-int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct block_list* src = iMap->id2bl(id);
+int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) {
+ struct block_list* src = map->id2bl(id);
int maxcount;
struct map_session_data *sd;
- struct unit_data *ud = unit_bl2ud(src);
+ struct unit_data *ud = unit->bl2ud(src);
struct mob_data *md;
nullpo_ret(ud);
@@ -9312,7 +9669,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
ud->skilltimer = INVALID_TIMER;
do {
- if( status_isdead(src) )
+ if( status->isdead(src) )
break;
if( !(src->type&battle_config.skill_reiteration) &&
@@ -9346,9 +9703,9 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
}
}
- if(tid != INVALID_TIMER)
- { //Avoid double checks on instant cast skills. [Skotlex]
- if (!status_check_skilluse(src, NULL, ud->skill_id, 1))
+ if(tid != INVALID_TIMER) {
+ //Avoid double checks on instant cast skills. [Skotlex]
+ if (!status->check_skilluse(src, NULL, ud->skill_id, 1))
break;
if(battle_config.skill_add_range &&
!check_distance_blxy(src, ud->skillx, ud->skilly, skill->get_range2(src,ud->skill_id,ud->skill_lv)+battle_config.skill_add_range)) {
@@ -9380,7 +9737,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
src->type, src->id, ud->skill_id, ud->skill_lv, ud->skillx, ud->skilly);
if (ud->walktimer != INVALID_TIMER)
- unit_stop_walking(src,1);
+ unit->stop_walking(src,1);
if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) )
ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv);
@@ -9393,7 +9750,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
}
}
if(cooldown)
- skill->blockpc_start(sd, ud->skill_id, cooldown, false);
+ skill->blockpc_start(sd, ud->skill_id, cooldown);
}
if( battle_config.display_status_timers && sd )
clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0);
@@ -9406,9 +9763,9 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
// break;
// }
// }
- unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill->get_walkdelay(ud->skill_id, ud->skill_lv), 1);
+ unit->set_walkdelay(src, tick, battle_config.default_walk_delay+skill->get_walkdelay(ud->skill_id, ud->skill_lv), 1);
status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);// only normal attack and auto cast skills benefit from its bonuses
- iMap->freeblock_lock();
+ map->freeblock_lock();
skill->castend_pos2(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv,tick,0);
if( sd && sd->skillitem != AL_WARP ) // Warp-Portal thru items will clear data in skill_castend_map. [Inkfish]
@@ -9420,7 +9777,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
ud->skill_lv = ud->skillx = ud->skilly = 0;
}
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 1;
} while(0);
@@ -9434,6 +9791,14 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
return 0;
}
+static int check_npc_chaospanic(struct block_list* bl, va_list args) {
+ TBL_NPC* nd = (TBL_NPC*)bl;
+
+ if( nd->option&(OPTION_HIDE|OPTION_INVISIBLE) || nd->class_ != 45 )
+ return 0;
+
+ return 1;
+}
/* skill count without self */
static int skill_count_wos(struct block_list *bl,va_list ap) {
struct block_list* src = va_arg(ap, struct block_list*);
@@ -9446,12 +9811,11 @@ static int skill_count_wos(struct block_list *bl,va_list ap) {
/*==========================================
*
*------------------------------------------*/
-int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char *map)
-{
+int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char *mapname) {
nullpo_ret(sd);
//Simplify skill_failed code.
-#define skill_failed(sd) { sd->menuskill_id = sd->menuskill_val = 0; }
+#define skill_failed(sd) ( (sd)->menuskill_id = (sd)->menuskill_val = 0 )
if(skill_id != sd->menuskill_id)
return 0;
@@ -9470,7 +9834,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
sd->sc.data[SC_AUTOCOUNTER] ||
sd->sc.data[SC_STEELBODY] ||
(sd->sc.data[SC_DANCING] && skill_id < RK_ENCHANTBLADE && !pc->checkskill(sd, WM_LESSON)) ||
- sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] ||
+ sd->sc.data[SC_BERSERK] ||
sd->sc.data[SC_BASILICA] ||
sd->sc.data[SC_MARIONETTE_MASTER] ||
sd->sc.data[SC_WHITEIMPRISON] ||
@@ -9488,19 +9852,24 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
pc_stop_walking(sd,0);
if(battle_config.skill_log && battle_config.skill_log&BL_PC)
- ShowInfo("PC %d skill castend skill =%d map=%s\n",sd->bl.id,skill_id,map);
+ ShowInfo("PC %d skill castend skill =%d map=%s\n",sd->bl.id,skill_id,mapname);
- if(strcmp(map,"cancel")==0) {
+ if(strcmp(mapname,"cancel")==0) {
skill_failed(sd);
return 0;
}
switch(skill_id) {
case AL_TELEPORT:
- if(strcmp(map,"Random")==0)
+ // The storage window is closed automatically by the client when there's
+ // any kind of map change, so we need to restore it automatically
+ // issue: 8027
+ if(strcmp(mapname,"Random")==0)
pc->randomwarp(sd,CLR_TELEPORT);
else if (sd->menuskill_val > 1) //Need lv2 to be able to warp here.
pc->setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
+
+ clif->refresh_storagewindow(sd);
break;
case AL_WARP:
@@ -9510,11 +9879,10 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
int i, lv, wx, wy;
int maxcount=0;
int x,y;
- unsigned short mapindex;
+ unsigned short map_index;
- mapindex = mapindex_name2id((char*)map);
- sd->state.workinprogress = 0;
- if(!mapindex) { //Given map not found?
+ map_index = mapindex->name2id(mapname);
+ if(!map_index) { //Given map not found?
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
skill_failed(sd);
return 0;
@@ -9544,7 +9912,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
if( lv > 4 ) lv = 4; // crash prevention
// check if the chosen map exists in the memo list
- ARR_FIND( 0, lv, i, mapindex == p[i]->map );
+ ARR_FIND( 0, lv, i, map_index == p[i]->map );
if( i < lv ) {
x=p[i]->x;
y=p[i]->y;
@@ -9569,7 +9937,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
group->val1 = (group->val1<<16)|(short)0;
// record the destination coordinates
group->val2 = (x<<16)|y;
- group->val3 = mapindex;
+ group->val3 = map_index;
}
break;
}
@@ -9582,27 +9950,26 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
/*==========================================
*
*------------------------------------------*/
-int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag)
-{
+int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
struct map_session_data* sd;
struct status_change* sc;
struct status_change_entry *sce;
struct skill_unit_group* sg;
enum sc_type type;
- int i;
+ int r;
//if(skill_lv <= 0) return 0;
- if(skill_id > 0 && !skill_lv) return 0; // celest
+ if(skill_id > 0 && !skill_lv) return 0; // [Celest]
nullpo_ret(src);
- if(status_isdead(src))
+ if(status->isdead(src))
return 0;
sd = BL_CAST(BL_PC, src);
- sc = status_get_sc(src);
- type = status_skill2sc(skill_id);
+ sc = status->get_sc(src);
+ type = status->skill2sc(skill_id);
sce = (sc && type != -1)?sc->data[type]:NULL;
switch (skill_id) { //Skill effect.
@@ -9611,6 +9978,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case CR_CULTIVATION:
case HW_GANBANTEIN:
case LG_EARTHDRIVE:
+ case SC_ESCAPE:
break; //Effect is displayed on respective switch case.
default:
if(skill->get_inf(skill_id)&INF_SELF_SKILL)
@@ -9624,50 +9992,49 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
switch(skill_id) {
case PR_BENEDICTIO:
- skill_area_temp[1] = src->id;
- i = skill->get_splash(skill_id, skill_lv);
- iMap->foreachinarea(skill->area_sub,
- src->m, x-i, y-i, x+i, y+i, BL_PC,
- src, skill_id, skill_lv, tick, flag|BCT_ALL|1,
- skill->castend_nodamage_id);
- iMap->foreachinarea(skill->area_sub,
- src->m, x-i, y-i, x+i, y+i, BL_CHAR,
- src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1,
- skill->castend_damage_id);
+ r = skill->get_splash(skill_id, skill_lv);
+ skill->area_temp[1] = src->id;
+ map->foreachinarea(skill->area_sub,
+ src->m, x-r, y-r, x+r, y+r, BL_PC,
+ src, skill_id, skill_lv, tick, flag|BCT_ALL|1,
+ skill->castend_nodamage_id);
+ map->foreachinarea(skill->area_sub,
+ src->m, x-r, y-r, x+r, y+r, BL_CHAR,
+ src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1,
+ skill->castend_damage_id);
break;
case BS_HAMMERFALL:
- i = skill->get_splash(skill_id, skill_lv);
- iMap->foreachinarea (skill->area_sub,
- src->m, x-i, y-i, x+i, y+i, BL_CHAR,
- src, skill_id, skill_lv, tick, flag|BCT_ENEMY|2,
- skill->castend_nodamage_id);
+ r = skill->get_splash(skill_id, skill_lv);
+ map->foreachinarea(skill->area_sub,
+ src->m, x-r, y-r, x+r, y+r, BL_CHAR,
+ src, skill_id, skill_lv, tick, flag|BCT_ENEMY|2,
+ skill->castend_nodamage_id);
break;
case HT_DETECTING:
- i = skill->get_splash(skill_id, skill_lv);
- iMap->foreachinarea( status_change_timer_sub,
- src->m, x-i, y-i, x+i,y+i,BL_CHAR,
- src,NULL,SC_SIGHT,tick);
+ r = skill->get_splash(skill_id, skill_lv);
+ map->foreachinarea(status->change_timer_sub,
+ src->m, x-r, y-r, x+r,y+r,BL_CHAR,
+ src,NULL,SC_SIGHT,tick);
if(battle_config.traps_setting&1)
- iMap->foreachinarea( skill_reveal_trap,
- src->m, x-i, y-i, x+i,y+i,BL_SKILL);
+ map->foreachinarea(skill_reveal_trap,
+ src->m, x-r, y-r, x+r, y+r, BL_SKILL);
break;
case SR_RIDEINLIGHTNING:
- i = skill->get_splash(skill_id, skill_lv);
- iMap->foreachinarea(skill->area_sub, src->m, x-i, y-i, x+i, y+i, BL_CHAR,
- src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
+ r = skill->get_splash(skill_id, skill_lv);
+ map->foreachinarea(skill->area_sub, src->m, x-r, y-r, x+r, y+r, BL_CHAR,
+ src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
break;
case SA_VOLCANO:
case SA_DELUGE:
case SA_VIOLENTGALE:
- { //Does not consumes if the skill is already active. [Skotlex]
- struct skill_unit_group *sg;
+ //Does not consumes if the skill is already active. [Skotlex]
if ((sg= skill->locate_element_field(src)) != NULL && ( sg->skill_id == SA_VOLCANO || sg->skill_id == SA_DELUGE || sg->skill_id == SA_VIOLENTGALE ))
{
- if (sg->limit - DIFF_TICK(iTimer->gettick(), sg->tick) > 0) {
+ if (sg->limit - DIFF_TICK(timer->gettick(), sg->tick) > 0) {
skill->unitsetting(src,skill_id,skill_lv,x,y,0);
return 0; // not to consume items
} else
@@ -9675,7 +10042,14 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
}
skill->unitsetting(src,skill_id,skill_lv,x,y,0);
break;
- }
+
+ case SC_CHAOSPANIC:
+ case SC_MAELSTROM:
+ if (sd && map->foreachinarea(&check_npc_chaospanic,src->m, x-3, y-3, x+3, y+3, BL_NPC) > 0 ) {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ break;
+ }
+
case MG_SAFETYWALL:
case MG_FIREWALL:
case MG_THUNDERSTORM:
@@ -9756,8 +10130,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case RA_ICEBOUNDTRAP:
case SC_MANHOLE:
case SC_DIMENSIONDOOR:
- case SC_CHAOSPANIC:
- case SC_MAELSTROM:
+ case SC_BLOODYLUST:
case WM_REVERBERATION:
case WM_SEVERE_RAINSTORM:
case WM_POEMOFNETHERWORLD:
@@ -9781,10 +10154,14 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case MH_VOLCANIC_ASH:
case MH_POISON_MIST:
case MH_STEINWAND:
- case MH_XENO_SLASHER:
case NC_MAGMA_ERUPTION:
+ case SO_ELEMENTAL_SHIELD:
+ case RL_B_TRAP:
+ case MH_XENO_SLASHER:
flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete).
case GS_GROUNDDRIFT: //Ammo should be deleted right away.
+ if ( skill_id == WM_SEVERE_RAINSTORM )
+ sc_start(src,src,SC_NO_SWITCH_EQUIP,100,0,skill->get_time(skill_id,skill_lv));
skill->unitsetting(src,skill_id,skill_lv,x,y,0);
break;
case RG_GRAFFITI: /* Graffiti [Valaris] */
@@ -9796,7 +10173,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
if( sc->data[SC_BASILICA] )
status_change_end(src, SC_BASILICA, INVALID_TIMER); // Cancel Basilica
else { // Create Basilica. Start SC on caster. Unit timer start SC on others.
- if( iMap->foreachinrange(skill_count_wos, src, 2, BL_MOB|BL_PC, src) ) {
+ if( map->foreachinrange(skill_count_wos, src, 2, BL_MOB|BL_PC, src) ) {
if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
return 1;
@@ -9804,20 +10181,20 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
skill->clear_unitgroup(src);
if( skill->unitsetting(src,skill_id,skill_lv,x,y,0) )
- sc_start4(src,type,100,skill_lv,0,0,src->id,skill->get_time(skill_id,skill_lv));
+ sc_start4(src,src,type,100,skill_lv,0,0,src->id,skill->get_time(skill_id,skill_lv));
flag|=1;
}
break;
case CG_HERMODE:
skill->clear_unitgroup(src);
if ((sg = skill->unitsetting(src,skill_id,skill_lv,x,y,0)))
- sc_start4(src,SC_DANCING,100,
+ sc_start4(src,src,SC_DANCING,100,
skill_id,0,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv));
flag|=1;
break;
case RG_CLEANER: // [Valaris]
- i = skill->get_splash(skill_id, skill_lv);
- iMap->foreachinarea(skill->graffitiremover,src->m,x-i,y-i,x+i,y+i,BL_SKILL);
+ r = skill->get_splash(skill_id, skill_lv);
+ map->foreachinarea(skill->graffitiremover,src->m,x-r,y-r,x+r,y+r,BL_SKILL);
break;
case SO_WARMER:
@@ -9826,16 +10203,18 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
skill->unitsetting(src,skill_id,skill_lv,x,y,0);
break;
- case WZ_METEOR: {
+ case WZ_METEOR:
+ {
int area = skill->get_splash(skill_id, skill_lv);
short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0;
+ int i;
for( i = 0; i < 2 + (skill_lv>>1); i++ ) {
// Creates a random Cell in the Splash Area
tmpx = x - area + rnd()%(area * 2 + 1);
tmpy = y - area + rnd()%(area * 2 + 1);
- if( i == 0 && path_search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL) )
+ if( i == 0 && path->search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL) )
clif->skill_poseffect(src,skill_id,skill_lv,tmpx,tmpy,tick);
if( i > 0 )
@@ -9863,19 +10242,19 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
return 0; // not to consume item.
case MO_BODYRELOCATION:
- if (unit_movepos(src, x, y, 1, 1)) {
+ if (unit->movepos(src, x, y, 1, 1)) {
#if PACKETVER >= 20111005
clif->snap(src, src->x, src->y);
#else
clif->skill_poseffect(src,skill_id,skill_lv,src->x,src->y,tick);
#endif
if (sd)
- skill->blockpc_start (sd, MO_EXTREMITYFIST, 2000, false);
+ skill->blockpc_start (sd, MO_EXTREMITYFIST, 2000);
}
break;
case NJ_SHADOWJUMP:
- if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground ) { //You don't move on GVG grounds.
- unit_movepos(src, x, y, 1, 0);
+ if( !map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground ) { //You don't move on GVG grounds.
+ unit->movepos(src, x, y, 1, 0);
clif->slide(src,x,y);
}
status_change_end(src, SC_HIDING, INVALID_TIMER);
@@ -9888,15 +10267,15 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
int class_ = skill_id==AM_SPHEREMINE?1142:summons[skill_lv-1];
struct mob_data *md;
- // Correct info, don't change any of this! [celest]
- md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, AI_NONE);
+ // Correct info, don't change any of this! [Celest]
+ md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_MEDIUM, AI_NONE);
if (md) {
md->master_id = src->id;
md->special_state.ai = (skill_id == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA;
if( md->deletetimer != INVALID_TIMER )
- iTimer->delete_timer(md->deletetimer, mob_timer_delete);
- md->deletetimer = iTimer->add_timer (iTimer->gettick() + skill->get_time(skill_id,skill_lv), mob_timer_delete, md->bl.id, 0);
- mob_spawn (md); //Now it is ready for spawning.
+ timer->delete(md->deletetimer, mob->timer_delete);
+ md->deletetimer = timer->add(timer->gettick() + skill->get_time(skill_id,skill_lv), mob->timer_delete, md->bl.id, 0);
+ mob->spawn (md); //Now it is ready for spawning.
}
}
break;
@@ -9905,54 +10284,55 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case CR_SLIMPITCHER:
if (sd) {
int i = skill_lv%11 - 1;
- int j = pc->search_inventory(sd,skill_db[skill_id].itemid[i]);
- if( j < 0 || skill_db[skill_id].itemid[i] <= 0 || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < skill_db[skill_id].amount[i] )
- {
+ int j = pc->search_inventory(sd,skill->db[skill_id].itemid[i]);
+ if (j == INDEX_NOT_FOUND || skill->db[skill_id].itemid[i] <= 0
+ || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < skill->db[skill_id].amount[i]
+ ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 1;
}
- potion_flag = 1;
- potion_hp = 0;
- potion_sp = 0;
- run_script(sd->inventory_data[j]->script,0,sd->bl.id,0);
- potion_flag = 0;
+ script->potion_flag = 1;
+ script->potion_hp = 0;
+ script->potion_sp = 0;
+ script->run(sd->inventory_data[j]->script,0,sd->bl.id,0);
+ script->potion_flag = 0;
//Apply skill bonuses
i = pc->checkskill(sd,CR_SLIMPITCHER)*10
+ pc->checkskill(sd,AM_POTIONPITCHER)*10
+ pc->checkskill(sd,AM_LEARNINGPOTION)*5
+ pc->skillheal_bonus(sd, skill_id);
- potion_hp = potion_hp * (100+i)/100;
- potion_sp = potion_sp * (100+i)/100;
+ script->potion_hp = script->potion_hp * (100+i)/100;
+ script->potion_sp = script->potion_sp * (100+i)/100;
- if(potion_hp > 0 || potion_sp > 0) {
+ if(script->potion_hp > 0 || script->potion_sp > 0) {
i = skill->get_splash(skill_id, skill_lv);
- iMap->foreachinarea(skill->area_sub,
- src->m,x-i,y-i,x+i,y+i,BL_CHAR,
- src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1,
- skill->castend_nodamage_id);
+ map->foreachinarea(skill->area_sub,
+ src->m,x-i,y-i,x+i,y+i,BL_CHAR,
+ src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1,
+ skill->castend_nodamage_id);
}
} else {
int i = skill_lv%11 - 1;
struct item_data *item;
- i = skill_db[skill_id].itemid[i];
- item = itemdb_search(i);
- potion_flag = 1;
- potion_hp = 0;
- potion_sp = 0;
- run_script(item->script,0,src->id,0);
- potion_flag = 0;
+ i = skill->db[skill_id].itemid[i];
+ item = itemdb->search(i);
+ script->potion_flag = 1;
+ script->potion_hp = 0;
+ script->potion_sp = 0;
+ script->run(item->script,0,src->id,0);
+ script->potion_flag = 0;
i = skill->get_max(CR_SLIMPITCHER)*10;
- potion_hp = potion_hp * (100+i)/100;
- potion_sp = potion_sp * (100+i)/100;
+ script->potion_hp = script->potion_hp * (100+i)/100;
+ script->potion_sp = script->potion_sp * (100+i)/100;
- if(potion_hp > 0 || potion_sp > 0) {
+ if(script->potion_hp > 0 || script->potion_sp > 0) {
i = skill->get_splash(skill_id, skill_lv);
- iMap->foreachinarea(skill->area_sub,
- src->m,x-i,y-i,x+i,y+i,BL_CHAR,
- src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1,
- skill->castend_nodamage_id);
+ map->foreachinarea(skill->area_sub,
+ src->m,x-i,y-i,x+i,y+i,BL_CHAR,
+ src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1,
+ skill->castend_nodamage_id);
}
}
break;
@@ -9961,8 +10341,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
if (rnd()%100 < 80) {
int dummy = 1;
clif->skill_poseffect(src,skill_id,skill_lv,x,y,tick);
- i = skill->get_splash(skill_id, skill_lv);
- iMap->foreachinarea(skill->cell_overlap, src->m, x-i, y-i, x+i, y+i, BL_SKILL, HW_GANBANTEIN, &dummy, src);
+ r = skill->get_splash(skill_id, skill_lv);
+ map->foreachinarea(skill->cell_overlap, src->m, x-r, y-r, x+r, y+r, BL_SKILL, HW_GANBANTEIN, &dummy, src);
} else {
if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 1;
@@ -9971,15 +10351,14 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case HW_GRAVITATION:
if ((sg = skill->unitsetting(src,skill_id,skill_lv,x,y,0)))
- sc_start4(src,type,100,skill_lv,0,BCT_SELF,sg->group_id,skill->get_time(skill_id,skill_lv));
+ sc_start4(src,src,type,100,skill_lv,0,BCT_SELF,sg->group_id,skill->get_time(skill_id,skill_lv));
flag|=1;
break;
// Plant Cultivation [Celest]
case CR_CULTIVATION:
if (sd) {
- if( iMap->count_oncell(src->m,x,y,BL_CHAR) > 0 )
- {
+ if( map->count_oncell(src->m,x,y,BL_CHAR) > 0 ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 1;
}
@@ -9987,16 +10366,16 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
if (rnd()%100 < 50) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
} else {
- TBL_MOB* md = mob_once_spawn_sub(src, src->m, x, y, "--ja--",(skill_lv < 2 ? 1084+rnd()%2 : 1078+rnd()%6),"", SZ_SMALL, AI_NONE);
+ TBL_MOB* md = mob->once_spawn_sub(src, src->m, x, y, "--ja--",(skill_lv < 2 ? 1084+rnd()%2 : 1078+rnd()%6),"", SZ_MEDIUM, AI_NONE);
int i;
if (!md) break;
if ((i = skill->get_time(skill_id, skill_lv)) > 0)
{
if( md->deletetimer != INVALID_TIMER )
- iTimer->delete_timer(md->deletetimer, mob_timer_delete);
- md->deletetimer = iTimer->add_timer (tick + i, mob_timer_delete, md->bl.id, 0);
+ timer->delete(md->deletetimer, mob->timer_delete);
+ md->deletetimer = timer->add(tick + i, mob->timer_delete, md->bl.id, 0);
}
- mob_spawn (md);
+ mob->spawn (md);
}
}
break;
@@ -10006,32 +10385,30 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case SG_STAR_WARM:
skill->clear_unitgroup(src);
if ((sg = skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0)))
- sc_start4(src,type,100,skill_lv,0,0,sg->group_id,skill->get_time(skill_id,skill_lv));
+ sc_start4(src,src,type,100,skill_lv,0,0,sg->group_id,skill->get_time(skill_id,skill_lv));
flag|=1;
break;
case PA_GOSPEL:
- if (sce && sce->val4 == BCT_SELF)
- {
+ if (sce && sce->val4 == BCT_SELF) {
status_change_end(src, SC_GOSPEL, INVALID_TIMER);
return 0;
- }
- else
- {
+ } else {
sg = skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0);
if (!sg) break;
if (sce)
status_change_end(src, type, INVALID_TIMER); //Was under someone else's Gospel. [Skotlex]
- sc_start4(src,type,100,skill_lv,0,sg->group_id,BCT_SELF,skill->get_time(skill_id,skill_lv));
+ status->change_clear_buffs(src,3);
+ sc_start4(src,src,type,100,skill_lv,0,sg->group_id,BCT_SELF,skill->get_time(skill_id,skill_lv));
clif->skill_poseffect(src, skill_id, skill_lv, 0, 0, tick); // PA_GOSPEL music packet
}
break;
case NJ_TATAMIGAESHI:
if (skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0))
- sc_start(src,type,100,skill_lv,skill->get_time2(skill_id,skill_lv));
+ sc_start(src,src,type,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
- case AM_RESURRECTHOMUN: //[orn]
+ case AM_RESURRECTHOMUN: // [orn]
if (sd) {
if (!homun->ressurect(sd, 20*skill_lv, x, y)) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
@@ -10043,18 +10420,33 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case RK_WINDCUTTER:
clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
case NC_COLDSLOWER:
- case NC_ARMSCANNON:
case RK_DRAGONBREATH:
case RK_DRAGONBREATH_WATER:
- i = skill->get_splash(skill_id,skill_lv);
- iMap->foreachinarea(skill->area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),
- src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ r = skill->get_splash(skill_id,skill_lv);
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,splash_target(src),
+ src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ break;
+ case WM_GREAT_ECHO:
+ case WM_SOUND_OF_DESTRUCTION:
+ r = skill->get_splash(skill_id,skill_lv);
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
+ break;
+
+ case WM_LULLABY_DEEPSLEEP:
+ r = skill->get_splash(skill_id,skill_lv);
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,BL_CHAR,
+ src,skill_id,skill_lv,tick,flag|BCT_ALL|1,skill->castend_damage_id);
break;
+ case WM_VOICEOFSIREN:
+ r = skill->get_splash(skill_id,skill_lv);
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,BL_CHAR,
+ src,skill_id,skill_lv,tick,flag|BCT_ALL|1,skill->castend_damage_id);
+ break;
case SO_ARRULLO:
- i = skill->get_splash(skill_id,skill_lv);
- iMap->foreachinarea(skill->area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),
- src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
+ r = skill->get_splash(skill_id,skill_lv);
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,splash_target(src),
+ src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
break;
/**
* Guilotine Cross
@@ -10074,14 +10466,14 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
**/
case AB_EPICLESIS:
if( (sg = skill->unitsetting(src, skill_id, skill_lv, x, y, 0)) ) {
- i = sg->unit->range;
- iMap->foreachinarea(skill->area_sub, src->m, x - i, y - i, x + i, y + i, BL_CHAR, src, ALL_RESURRECTION, 1, tick, flag|BCT_NOENEMY|1,skill->castend_nodamage_id);
+ r = sg->unit->range;
+ map->foreachinarea(skill->area_sub, src->m, x - r, y - r, x + r, y + r, BL_CHAR, src, ALL_RESURRECTION, 1, tick, flag|BCT_NOENEMY|1,skill->castend_nodamage_id);
}
break;
case WL_EARTHSTRAIN:
{
- int i, wave = skill_lv + 4, dir = iMap->calc_dir(src,x,y);
+ int i, wave = skill_lv + 4, dir = map->calc_dir(src,x,y);
int sx = x = src->x, sy = y = src->y; // Store first caster's location to avoid glitch on unit setting
for( i = 1; i <= wave; i++ )
@@ -10092,7 +10484,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case 2: sx = x - i; break;
case 6: sx = x + i; break;
}
- skill->addtimerskill(src,iTimer->gettick() + (50 * i),0,sx,sy,skill_id,skill_lv,dir,flag&2);
+ skill->addtimerskill(src,timer->gettick() + (140 * i),0,sx,sy,skill_id,skill_lv,dir,flag&2);
}
}
break;
@@ -10100,8 +10492,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
* Ranger
**/
case RA_DETONATOR:
- i = skill->get_splash(skill_id, skill_lv);
- iMap->foreachinarea(skill->detonator, src->m, x-i, y-i, x+i, y+i, BL_SKILL, src);
+ r = skill->get_splash(skill_id, skill_lv);
+ map->foreachinarea(skill->detonator, src->m, x-r, y-r, x+r, y+r, BL_SKILL, src);
clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
break;
/**
@@ -10111,7 +10503,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case NC_STEALTHFIELD:
skill->clear_unitgroup(src); // To remove previous skills - cannot used combined
if( (sg = skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) != NULL ) {
- sc_start2(src,skill_id == NC_NEUTRALBARRIER ? SC_NEUTRALBARRIER_MASTER : SC_STEALTHFIELD_MASTER,100,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv));
+ sc_start2(src,src,skill_id == NC_NEUTRALBARRIER ? SC_NEUTRALBARRIER_MASTER : SC_STEALTHFIELD_MASTER,100,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv));
if( sd ) pc->overheat(sd,1);
}
break;
@@ -10121,15 +10513,14 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
int class_ = 2042;
struct mob_data *md;
- md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, AI_NONE);
- if( md )
- {
+ md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_MEDIUM, AI_NONE);
+ if( md ) {
md->master_id = src->id;
md->special_state.ai = AI_FLORA;
if( md->deletetimer != INVALID_TIMER )
- iTimer->delete_timer(md->deletetimer, mob_timer_delete);
- md->deletetimer = iTimer->add_timer (iTimer->gettick() + skill->get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0);
- mob_spawn( md );
+ timer->delete(md->deletetimer, mob->timer_delete);
+ md->deletetimer = timer->add(timer->gettick() + skill->get_time(skill_id, skill_lv), mob->timer_delete, md->bl.id, 0);
+ mob->spawn( md );
}
}
break;
@@ -10139,67 +10530,83 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
break;
case SC_FEINTBOMB:
- skill->unitsetting(src,skill_id,skill_lv,x,y,0); // Set bomb on current Position
- clif->skill_nodamage(src,src,skill_id,skill_lv,1);
- if( skill->blown(src,src,6,unit_getdir(src),0) )
- skill->castend_nodamage_id(src,src,TF_HIDING,1,tick,0x2);
+ skill->unitsetting(src, skill_id, skill_lv, x, y, 0); // Set bomb on current Position
+ clif->skill_nodamage(src, src, skill_id, skill_lv, 1);
+ if( skill->blown(src, src, 3 * skill_lv, unit->getdir(src), 0) && sc) {
+ sc_start(src, src, SC__FEINTBOMB_MASTER, 100, 0, skill->get_unit_interval(SC_FEINTBOMB));
+ }
+ break;
+
+ case SC_ESCAPE:
+ clif->skill_nodamage(src,src,skill_id,-1,1);
+ skill->unitsetting(src,HT_ANKLESNARE,skill_lv,x,y,2);
+ skill->addtimerskill(src,tick,src->id,0,0,skill_id,skill_lv,0,0);
break;
case LG_OVERBRAND:
- {
- int width;//according to data from irowiki it actually is a square
- for( width = 0; width < 7; width++ )
- for( i = 0; i < 7; i++ )
- iMap->foreachincell(skill->area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, LG_OVERBRAND_BRANDISH, skill_lv, tick, flag|BCT_ENEMY,skill->castend_damage_id);
- for( width = 0; width < 7; width++ )
- for( i = 0; i < 7; i++ )
- iMap->foreachincell(skill->area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY,skill->castend_damage_id);
- }
+ skill->area_temp[1] = 0;
+ map->foreachinpath(skill->attack_area,src->m,src->x,src->y,x,y,1,5,BL_CHAR,
+ skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
+ skill->addtimerskill(src,timer->gettick() + status_get_amotion(src), 0, x, y, LG_OVERBRAND_BRANDISH, skill_lv, 0, flag);
break;
case LG_BANDING:
if( sc && sc->data[SC_BANDING] )
status_change_end(src,SC_BANDING,INVALID_TIMER);
else if( (sg = skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) != NULL ) {
- sc_start4(src,SC_BANDING,100,skill_lv,0,0,sg->group_id,skill->get_time(skill_id,skill_lv));
+ sc_start4(src,src,SC_BANDING,100,skill_lv,0,0,sg->group_id,skill->get_time(skill_id,skill_lv));
if( sd ) pc->banding(sd,skill_lv);
}
clif->skill_nodamage(src,src,skill_id,skill_lv,1);
break;
case LG_RAYOFGENESIS:
- if( status_charge(src,status_get_max_hp(src)*3*skill_lv / 100,0) ) {
- i = skill->get_splash(skill_id,skill_lv);
- iMap->foreachinarea(skill->area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),
+ if( status->charge(src,status_get_max_hp(src)*3*skill_lv / 100,0) ) {
+ r = skill->get_splash(skill_id,skill_lv);
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,splash_target(src),
src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
} else if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
break;
case WM_DOMINION_IMPULSE:
- i = skill->get_splash(skill_id, skill_lv);
- iMap->foreachinarea( skill->activate_reverberation,
- src->m, x-i, y-i, x+i,y+i,BL_SKILL);
+ r = skill->get_splash(skill_id, skill_lv);
+ map->foreachinarea( skill->activate_reverberation,src->m, x-r, y-r, x+r,y+r,BL_SKILL);
break;
- case WM_GREAT_ECHO:
- flag|=1; // Should counsume 1 item per skill usage.
- iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->castend_damage_id);
- break;
- case GN_CRAZYWEED: {
- int area = skill->get_splash(GN_CRAZYWEED_ATK, skill_lv);
- short x1 = 0, y1 = 0;
+ case GN_CRAZYWEED:
+ {
+ int area = skill->get_splash(skill_id, skill_lv);
+ short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0;
- for( i = 0; i < 3 + (skill_lv/2); i++ ) {
- x1 = x - area + rnd()%(area * 2 + 1);
- y1 = y - area + rnd()%(area * 2 + 1);
- skill->addtimerskill(src,tick+i*150,0,x1,y1,GN_CRAZYWEED_ATK,skill_lv,-1,0);
+ for( r = 0; r < 3 + (skill_lv>>1); r++ ) {
+ // Creates a random Cell in the Splash Area
+ tmpx = x - area + rnd()%(area * 2 + 1);
+ tmpy = y - area + rnd()%(area * 2 + 1);
+
+ if( r > 0 )
+ skill->addtimerskill(src,tick+r*250,0,tmpx,tmpy,GN_CRAZYWEED,skill_lv,(x1<<16)|y1,flag);
+
+ x1 = tmpx;
+ y1 = tmpy;
}
+
+ skill->addtimerskill(src,tick+r*250,0,tmpx,tmpy,GN_CRAZYWEED,skill_lv,-1,flag);
+ }
+ break;
+
+ case GN_CRAZYWEED_ATK: {
+ int dummy = 1;
+ //Enable if any unique animation gets added to this skill ID in the future. [Rytech]
+ //clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
+ r = skill->get_splash(skill_id, skill_lv);
+ map->foreachinarea(skill->cell_overlap, src->m, x-r, y-r, x+r, y+r, BL_SKILL, skill_id, &dummy, src);
+ map->foreachinarea(skill->area_sub, src->m, x-r, y-r, x+r, y+r, BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
}
break;
case GN_FIRE_EXPANSION: {
int i;
- struct unit_data *ud = unit_bl2ud(src);
+ struct unit_data *ud = unit->bl2ud(src);
if( !ud ) break;
@@ -10216,10 +10623,10 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
clif->changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_TEAR_GAS);
break;
case 5:
- iMap->foreachinarea(skill->area_sub, src->m,
- ud->skillunit[i]->unit->bl.x - 3, ud->skillunit[i]->unit->bl.y - 3,
- ud->skillunit[i]->unit->bl.x + 3, ud->skillunit[i]->unit->bl.y + 3, BL_CHAR,
- src, CR_ACIDDEMONSTRATION, sd ? pc->checkskill(sd, CR_ACIDDEMONSTRATION) : skill_lv, tick, flag|BCT_ENEMY|1|SD_LEVEL, skill->castend_damage_id);
+ map->foreachinarea(skill->area_sub, src->m,
+ ud->skillunit[i]->unit->bl.x - 3, ud->skillunit[i]->unit->bl.y - 3,
+ ud->skillunit[i]->unit->bl.x + 3, ud->skillunit[i]->unit->bl.y + 3, BL_CHAR,
+ src, CR_ACIDDEMONSTRATION, sd ? pc->checkskill(sd, CR_ACIDDEMONSTRATION) : skill_lv, tick, flag|BCT_ENEMY|1|SD_LEVEL, skill->castend_damage_id);
skill->delunit(ud->skillunit[i]->unit);
break;
default:
@@ -10237,20 +10644,18 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
if( sc && sc->data[type] )
status_change_end(src,type,INVALID_TIMER);
clif->skill_nodamage(src, src ,skill_id, skill_lv,
- sc_start2(src, type, 100, skill_id, skill_lv, skill->get_time(skill_id, skill_lv)));
+ sc_start2(src,src, type, 100, skill_id, skill_lv, skill->get_time(skill_id, skill_lv)));
break;
- case SC_BLOODYLUST: //set in another group so instance will move if recasted
- flag |= 33;
- skill->unitsetting(src, skill_id, skill_lv, x, y, 0);
- break;
-
case KO_MAKIBISHI:
+ {
+ int i;
for( i = 0; i < (skill_lv+2); i++ ) {
x = src->x - 1 + rnd()%3;
y = src->y - 1 + rnd()%3;
skill->unitsetting(src,skill_id,skill_lv,x,y,0);
}
+ }
break;
default:
@@ -10262,7 +10667,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER);
if( sd ) {// ensure that the skill last-cast tick is recorded
- sd->canskill_tick = iTimer->gettick();
+ sd->canskill_tick = timer->gettick();
if( sd->state.arrow_atk && !(flag&1) ) {
// consume arrow if this is a ground skill
@@ -10294,7 +10699,7 @@ int skill_dance_overlap_sub(struct block_list* bl, va_list ap) {
else //Remove dissonance
target->val2 &= ~UF_ENSEMBLE;
- clif->skill_setunit(target); //Update look of affected cell.
+ clif->getareachar_skillunit(&target->bl,target,AREA); //Update look of affected cell.
return 1;
}
@@ -10302,32 +10707,38 @@ int skill_dance_overlap_sub(struct block_list* bl, va_list ap) {
//Does the song/dance overlapping -> dissonance check. [Skotlex]
//When flag is 0, this unit is about to be removed, cancel the dissonance effect
//When 1, this unit has been positioned, so start the cancel effect.
-int skill_dance_overlap(struct skill_unit* unit, int flag) {
- if (!unit || !unit->group || !(unit->group->state.song_dance&0x1))
+int skill_dance_overlap(struct skill_unit* su, int flag) {
+ if (!su || !su->group || !(su->group->state.song_dance&0x1))
return 0;
- if (!flag && !(unit->val2&UF_ENSEMBLE))
- return 0; //Nothing to remove, this unit is not overlapped.
-
- if (unit->val1 != unit->group->skill_id) {
+
+ if (su->val1 != su->group->skill_id) {
//Reset state
- unit->val1 = unit->group->skill_id;
- unit->val2 &= ~UF_ENSEMBLE;
+ su->val1 = su->group->skill_id;
+ su->val2 &= ~UF_ENSEMBLE;
}
-
- return iMap->foreachincell(skill->dance_overlap_sub, unit->bl.m,unit->bl.x,unit->bl.y,BL_SKILL, unit,flag);
+
+ return map->foreachincell(skill->dance_overlap_sub, su->bl.m,su->bl.x,su->bl.y,BL_SKILL, su,flag);
}
-/*==========================================
+/**
* Converts this group information so that it is handled as a Dissonance or Ugly Dance cell.
- * Flag: 0 - Convert, 1 - Revert.
- *------------------------------------------*/
-bool skill_dance_switch(struct skill_unit* unit, int flag) {
+ * This function is safe to call even when the unit or the group were freed by other function
+ * previously.
+ * @param su Skill unit data (from BA_DISSONANCE or DC_UGLYDANCE)
+ * @param flag 0 Convert
+ * @param flag 1 Revert
+ * @retval true success
+ **/
+bool skill_dance_switch(struct skill_unit* su, int flag) {
static int prevflag = 1; // by default the backup is empty
static struct skill_unit_group backup;
- struct skill_unit_group* group = unit->group;
+ struct skill_unit_group* group;
+
+ if( su == NULL || (group = su->group) == NULL )
+ return false;
// val2&UF_ENSEMBLE is a hack to indicate dissonance
- if ( !(group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE) )
+ if ( !(group->state.song_dance&0x1 && su->val2&UF_ENSEMBLE) )
return false;
if( flag == prevflag ) {
@@ -10340,7 +10751,7 @@ bool skill_dance_switch(struct skill_unit* unit, int flag) {
prevflag = flag;
if( !flag ) { //Transform
- uint16 skill_id = unit->val2&UF_SONG ? BA_DISSONANCE : DC_UGLYDANCE;
+ uint16 skill_id = su->val2&UF_SONG ? BA_DISSONANCE : DC_UGLYDANCE;
// backup
backup.skill_id = group->skill_id;
@@ -10377,14 +10788,14 @@ int skill_icewall_block(struct block_list *bl,va_list ap) {
nullpo_ret(bl);
nullpo_ret(md);
- if( !md->target_id || ( target = iMap->id2bl(md->target_id) ) == NULL )
+ if( !md->target_id || ( target = map->id2bl(md->target_id) ) == NULL )
return 0;
- if( path_search_long(NULL,bl->m,bl->x,bl->y,target->x,target->y,CELL_CHKICEWALL) )
+ if( path->search_long(NULL,bl->m,bl->x,bl->y,target->x,target->y,CELL_CHKICEWALL) )
return 0;
if( !check_distance_bl(bl, target, status_get_range(bl) ) ) {
- mob_unlocktarget(md,iTimer->gettick());
+ mob->unlocktarget(md,timer->gettick());
mob_stop_walking(md,1);
}
@@ -10394,14 +10805,13 @@ int skill_icewall_block(struct block_list *bl,va_list ap) {
* Initializes and sets a ground skill.
* flag&1 is used to determine when the skill 'morphs' (Warp portal becomes active, or Fire Pillar becomes active)
*------------------------------------------*/
-struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill_id, uint16 skill_lv, int16 x, int16 y, int flag)
-{
+struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_id, uint16 skill_lv, int16 x, int16 y, int flag) {
struct skill_unit_group *group;
int i,limit,val1=0,val2=0,val3=0;
int target,interval,range,unit_flag,req_item=0;
struct s_skill_unit_layout *layout;
struct map_session_data *sd;
- struct status_data *status;
+ struct status_data *st;
struct status_change *sc;
int active_flag=1;
int subunt=0;
@@ -10415,19 +10825,22 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
unit_flag = skill->get_unit_flag(skill_id);
layout = skill->get_unit_layout(skill_id,skill_lv,src,x,y);
- if( map[src->m].unit_count ) {
- ARR_FIND(0, map[src->m].unit_count, i, map[src->m].units[i]->skill_id == skill_id );
+ if( map->list[src->m].unit_count ) {
+ ARR_FIND(0, map->list[src->m].unit_count, i, map->list[src->m].units[i]->skill_id == skill_id );
- if( i < map[src->m].unit_count ) {
- limit = limit * map[src->m].units[i]->modifier / 100;
+ if( i < map->list[src->m].unit_count ) {
+ limit = limit * map->list[src->m].units[i]->modifier / 100;
}
}
sd = BL_CAST(BL_PC, src);
- status = status_get_status_data(src);
- sc = status_get_sc(src); // for traps, firewall and fogwall - celest
+ st = status->get_status_data(src);
+ sc = status->get_sc(src); // for traps, firewall and fogwall - celest
switch( skill_id ) {
+ case SO_ELEMENTAL_SHIELD:
+ val2 = 300 * skill_lv + 65 * (st->int_ + status->get_lv(src)) + st->max_sp;
+ break;
case MH_STEINWAND:
val2 = 4 + skill_lv; //nb of attack blocked
break;
@@ -10455,7 +10868,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
{ //Warp Portal morphing to active mode, extract relevant data from src. [Skotlex]
if( src->type != BL_SKILL ) return NULL;
group = ((TBL_SKILL*)src)->group;
- src = iMap->id2bl(group->src_id);
+ src = map->id2bl(group->src_id);
if( !src ) return NULL;
val2 = group->val2; //Copy the (x,y) position you warp to
val3 = group->val3; //as well as the mapindex to warp to.
@@ -10471,7 +10884,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
break;
case WZ_FIREPILLAR:
- if( iMap->getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
+ if( map->getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
return NULL;
if((flag&1)!=0)
limit=1000;
@@ -10480,10 +10893,15 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex]
case AM_DEMONSTRATION:
case GN_HELLS_PLANT:
+ if( skill_id == GN_HELLS_PLANT && map->getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
+ return NULL;
if (map_flag_vs(src->m) && battle_config.vs_traps_bctall
&& (src->type&battle_config.vs_traps_bctall))
target = BCT_ALL;
break;
+ case HT_ANKLESNARE:
+ if( flag&2 )
+ val3 = SC_ESCAPE;
case HT_SHOCKWAVE:
val1=skill_lv*15+10;
case HT_SANDMAN:
@@ -10493,7 +10911,6 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
case MA_SKIDTRAP:
case HT_LANDMINE:
case MA_LANDMINE:
- case HT_ANKLESNARE:
case HT_FLASHER:
case HT_FREEZINGTRAP:
case MA_FREEZINGTRAP:
@@ -10512,9 +10929,9 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
{
struct skill_condition req = skill->get_requirement(sd,skill_id,skill_lv);
ARR_FIND(0, MAX_SKILL_ITEM_REQUIRE, i, req.itemid[i] && (req.itemid[i] == ITEMID_TRAP || req.itemid[i] == ITEMID_TRAP_ALLOY));
- if( req.itemid[i] )
+ if( i != MAX_SKILL_ITEM_REQUIRE && req.itemid[i] )
req_item = req.itemid[i];
- if( map_flag_gvg(src->m) || map[src->m].flag.battleground )
+ if( map_flag_gvg2(src->m) || map->list[src->m].flag.battleground )
limit *= 4; // longer trap times in WOE [celest]
if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) )
target = BCT_ALL;
@@ -10536,7 +10953,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
old_sg->skill_id == SA_VIOLENTGALE
) && old_sg->limit > 0)
{ //Use the previous limit (minus the elapsed time) [Skotlex]
- limit = old_sg->limit - DIFF_TICK(iTimer->gettick(), old_sg->tick);
+ limit = old_sg->limit - DIFF_TICK32(timer->gettick(), old_sg->tick);
if (limit < 0) //This can happen...
limit = skill->get_time(skill_id,skill_lv);
}
@@ -10547,18 +10964,18 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
case BA_DISSONANCE:
case DC_UGLYDANCE:
- val1 = 10; //FIXME: This value is not used anywhere, what is it for? [Skotlex]
+ val1 = 10; //FIXME: This value is not used anywhere, what is it for? [Skotlex]
break;
case BA_WHISTLE:
- val1 = skill_lv +status->agi/10; // Flee increase
- val2 = ((skill_lv+1)/2)+status->luk/10; // Perfect dodge increase
+ val1 = skill_lv +st->agi/10; // Flee increase
+ val2 = ((skill_lv+1)/2)+st->luk/10; // Perfect dodge increase
if(sd){
val1 += pc->checkskill(sd,BA_MUSICALLESSON);
val2 += pc->checkskill(sd,BA_MUSICALLESSON);
}
break;
case DC_HUMMING:
- val1 = 2*skill_lv+status->dex/10; // Hit increase
+ val1 = 2*skill_lv+st->dex/10; // Hit increase
#ifdef RENEWAL
val1 *= 2;
#endif
@@ -10566,9 +10983,9 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
val1 += pc->checkskill(sd,DC_DANCINGLESSON);
break;
case BA_POEMBRAGI:
- val1 = 3*skill_lv+status->dex/10; // Casting time reduction
+ val1 = 3*skill_lv+st->dex/10; // Casting time reduction
//For some reason at level 10 the base delay reduction is 50%.
- val2 = (skill_lv<10?3*skill_lv:50)+status->int_/5; // After-cast delay reduction
+ val2 = (skill_lv<10?3*skill_lv:50)+st->int_/5; // After-cast delay reduction
if(sd){
val1 += 2*pc->checkskill(sd,BA_MUSICALLESSON);
val2 += 2*pc->checkskill(sd,BA_MUSICALLESSON);
@@ -10576,11 +10993,11 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
break;
case DC_DONTFORGETME:
#ifdef RENEWAL
- val1 = status->dex/10 + 3*skill_lv; // ASPD decrease
- val2 = status->agi/10 + 2*skill_lv; // Movement speed adjustment.
+ val1 = st->dex/10 + 3*skill_lv; // ASPD decrease
+ val2 = st->agi/10 + 2*skill_lv; // Movement speed adjustment.
#else
- val1 = status->dex/10 + 3*skill_lv + 5; // ASPD decrease
- val2 = status->agi/10 + 3*skill_lv + 5; // Movement speed adjustment.
+ val1 = st->dex/10 + 3*skill_lv + 5; // ASPD decrease
+ val2 = st->agi/10 + 3*skill_lv + 5; // Movement speed adjustment.
#endif
if(sd){
val1 += pc->checkskill(sd,DC_DANCINGLESSON);
@@ -10588,13 +11005,13 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
}
break;
case BA_APPLEIDUN:
- val1 = 5+2*skill_lv+status->vit/10; // MaxHP percent increase
+ val1 = 5+2*skill_lv+st->vit/10; // MaxHP percent increase
if(sd)
val1 += pc->checkskill(sd,BA_MUSICALLESSON);
break;
case DC_SERVICEFORYOU:
- val1 = 15+skill_lv+(status->int_/10); // MaxSP percent increase TO-DO: this INT bonus value is guessed
- val2 = 20+3*skill_lv+(status->int_/10); // SP cost reduction
+ val1 = 15+skill_lv+(st->int_/10); // MaxSP percent increase TO-DO: this INT bonus value is guessed
+ val2 = 20+3*skill_lv+(st->int_/10); // SP cost reduction
if(sd){
val1 += pc->checkskill(sd,DC_DANCINGLESSON); //TO-DO This bonus value is guessed
val2 += pc->checkskill(sd,DC_DANCINGLESSON); //TO-DO Should be half this value
@@ -10602,17 +11019,17 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
break;
case BA_ASSASSINCROSS:
#ifdef RENEWAL
- val1 = 10 + skill_lv + (status->agi/10); // ASPD increase
+ val1 = 10 + skill_lv + (st->agi/10); // ASPD increase
if(sd)
val1 += 4*pc->checkskill(sd,BA_MUSICALLESSON);
#else
- val1 = 100+(10*skill_lv)+(status->agi/10); // ASPD increase
+ val1 = 100+(10*skill_lv)+(st->agi/10); // ASPD increase
if(sd)
val1 += 5*pc->checkskill(sd,BA_MUSICALLESSON);
#endif
break;
case DC_FORTUNEKISS:
- val1 = 10+skill_lv+(status->luk/10); // Critical increase
+ val1 = 10+skill_lv+(st->luk/10); // Critical increase
if(sd)
val1 += pc->checkskill(sd,DC_DANCINGLESSON);
val1*=10; //Because every 10 crit is an actual cri point.
@@ -10660,7 +11077,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
{
int element[5]={ELE_WIND,ELE_DARK,ELE_POISON,ELE_WATER,ELE_FIRE};
- val1 = status->rhw.ele;
+ val1 = st->rhw.ele;
if (!val1)
val1=element[rnd()%5];
@@ -10706,10 +11123,16 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
limit = -1;
break;
case WM_REVERBERATION:
- interval = limit;
+ if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) )
+ target = BCT_ALL;
+ val1 = skill_lv + 1;
val2 = 1;
- case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector.
- if( iMap->getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
+ case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector.
+ case SO_WATER_INSIGNIA:
+ case SO_FIRE_INSIGNIA:
+ case SO_WIND_INSIGNIA:
+ case SO_EARTH_INSIGNIA:
+ if( map->getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
return NULL;
break;
case SO_CLOUD_KILL:
@@ -10718,12 +11141,6 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
case SO_WARMER:
skill->clear_group(src, 8);
break;
- case SO_VACUUM_EXTREME:
- range++;
- break;
- case SC_BLOODYLUST:
- skill->clear_group(src, 32);
- break;
case GN_WALLOFTHORN:
if( flag&1 )
limit = 3000;
@@ -10754,7 +11171,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
group->state.guildaura = ( skill_id >= GD_LEADERSHIP && skill_id <= GD_HAWKEYES )?1:0;
group->item_id = req_item;
//if tick is greater than current, do not invoke onplace function just yet. [Skotlex]
- if (DIFF_TICK(group->tick, iTimer->gettick()) > SKILLUNITTIMER_INTERVAL)
+ if (DIFF_TICK(group->tick, timer->gettick()) > SKILLUNITTIMER_INTERVAL)
active_flag = 0;
if(skill_id==HT_TALKIEBOX || skill_id==RG_GRAFFITI){
@@ -10771,7 +11188,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
sd->skill_lv_dance = skill_lv;
}
if (
- sc_start4(src, SC_DANCING, 100, skill_id, group->group_id, skill_lv,
+ sc_start4(src,src, SC_DANCING, 100, skill_id, group->group_id, skill_lv,
(group->state.song_dance&2?BCT_SELF:0), limit+1000) &&
sd && group->state.song_dance&2 && skill_id != CG_HERMODE //Hermod is a encore with a warp!
)
@@ -10780,16 +11197,16 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
limit = group->limit;
for( i = 0; i < layout->count; i++ ) {
- struct skill_unit *unit;
+ struct skill_unit *su;
int ux = x + layout->dx[i];
int uy = y + layout->dy[i];
- int val1 = skill_lv;
- int val2 = 0;
int alive = 1;
+ val1 = skill_lv;
+ val2 = 0;
- if( !group->state.song_dance && !iMap->getcell(src->m,ux,uy,CELL_CHKREACH) )
+ if( !group->state.song_dance && !map->getcell(src->m,ux,uy,CELL_CHKREACH) )
continue; // don't place skill units on walls (except for songs/dances/encores)
- if( battle_config.skill_wall_check && skill->get_unit_flag(skill_id)&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) )
+ if( battle_config.skill_wall_check && skill->get_unit_flag(skill_id)&UF_PATHCHECK && !path->search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) )
continue; // no path between cell and center of casting.
switch( skill_id ) {
@@ -10799,7 +11216,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
break;
case WZ_ICEWALL:
val1 = (skill_lv <= 1) ? 500 : 200 + 200*skill_lv;
- val2 = iMap->getcell(src->m, ux, uy, CELL_GETTYPE);
+ val2 = map->getcell(src->m, ux, uy, CELL_GETTYPE);
break;
case HT_LANDMINE:
case MA_LANDMINE:
@@ -10837,11 +11254,9 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
if (val1 < 1) val1 = 1;
val2 = 0;
break;
- case WM_REVERBERATION:
- val1 = 1 + skill_lv;
- break;
case GN_WALLOFTHORN:
- val1 = 1000 * skill_lv; // Need official value. [LimitLine]
+ val1 = 2000 + 2000 * skill_lv;
+ val2 = src->id;
break;
default:
if (group->state.song_dance&0x1)
@@ -10852,26 +11267,27 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
val2 |= UF_RANGEDSINGLEUNIT; // center.
if( range <= 0 )
- iMap->foreachincell(skill->cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src);
+ map->foreachincell(skill->cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src);
if( !alive )
continue;
- nullpo_retr(NULL, unit=skill->initunit(group,i,ux,uy,val1,val2));
- unit->limit=limit;
- unit->range=range;
+ nullpo_retr(NULL, su=skill->initunit(group,i,ux,uy,val1,val2));
+ su->limit=limit;
+ su->range=range;
if (skill_id == PF_FOGWALL && alive == 2) {
//Double duration of cells on top of Deluge/Suiton
- unit->limit *= 2;
- group->limit = unit->limit;
+ su->limit *= 2;
+ group->limit = su->limit;
}
// execute on all targets standing on this cell
if (range==0 && active_flag)
- iMap->foreachincell(skill->unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,iTimer->gettick(),1);
+ map->foreachincell(skill->unit_effect,su->bl.m,su->bl.x,su->bl.y,group->bl_flag,&su->bl,timer->gettick(),1);
}
- if (!group->alive_count) { //No cells? Something that was blocked completely by Land Protector?
+ if (!group->alive_count) {
+ //No cells? Something that was blocked completely by Land Protector?
skill->del_unitgroup(group,ALC_MARK);
return NULL;
}
@@ -10879,7 +11295,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
//success, unit created.
switch( skill_id ) {
case WZ_ICEWALL:
- iMap->foreachinrange(skill->icewall_block, src, AREA_SIZE, BL_MOB);
+ map->foreachinrange(skill->icewall_block, src, AREA_SIZE, BL_MOB);
break;
case NJ_TATAMIGAESHI: //Store number of tiles.
group->val1 = group->alive_count;
@@ -10892,7 +11308,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
/*==========================================
*
*------------------------------------------*/
-int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned int tick) {
+int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick) {
struct skill_unit_group *sg;
struct block_list *ss;
struct status_change *sc;
@@ -10903,21 +11319,23 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned
nullpo_ret(src);
nullpo_ret(bl);
- if(bl->prev==NULL || !src->alive || status_isdead(bl))
+ if(bl->prev==NULL || !src->alive || status->isdead(bl))
return 0;
nullpo_ret(sg=src->group);
- nullpo_ret(ss=iMap->id2bl(sg->src_id));
+ nullpo_ret(ss=map->id2bl(sg->src_id));
- if( skill->get_type(sg->skill_id) == BF_MAGIC && iMap->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR )
+ if( skill->get_type(sg->skill_id) == BF_MAGIC && map->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR )
return 0; //AoE skills are ineffective. [Skotlex]
-
- sc = status_get_sc(bl);
+ sc = status->get_sc(bl);
if (sc && sc->option&OPTION_HIDE && sg->skill_id != WZ_HEAVENDRIVE && sg->skill_id != WL_EARTHSTRAIN )
return 0; //Hidden characters are immune to AoE skills except to these. [Skotlex]
- type = status_skill2sc(sg->skill_id);
+ if (sc && sc->data[SC_VACUUM_EXTREME] && map->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR))
+ status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER);
+
+ type = status->skill2sc(sg->skill_id);
sce = (sc && type != -1)?sc->data[type]:NULL;
skill_id = sg->skill_id; //In case the group is deleted, we need to return the correct skill id, still.
switch (sg->unit_id) {
@@ -10928,44 +11346,36 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned
break;
} else if( sc && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) {
int sec = skill->get_time2(sg->skill_id,sg->skill_lv);
- if( status_change_start(bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8) ) {
- const struct TimerData* td = sc->data[type]?iTimer->get_timer(sc->data[type]->timer):NULL;
+ if( status->change_start(ss, bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8) ) {
+ const struct TimerData* td = sc->data[type]?timer->get(sc->data[type]->timer):NULL;
if( td )
- sec = DIFF_TICK(td->tick, tick);
- iMap->moveblock(bl, src->bl.x, src->bl.y, tick);
+ sec = DIFF_TICK32(td->tick, tick);
+ map->moveblock(bl, src->bl.x, src->bl.y, tick);
clif->fixpos(bl);
sg->val2 = bl->id;
}
else
sec = 3000; //Couldn't trap it?
- sg->limit = DIFF_TICK(tick,sg->tick)+sec;
+ sg->limit = DIFF_TICK32(tick,sg->tick)+sec;
}
break;
case UNT_SAFETYWALL:
if (!sce)
- sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit);
+ sc_start4(ss,bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit);
+ break;
+ case UNT_BLOODYLUST:
+ if (sg->src_id == bl->id)
+ break; //Does not affect the caster.
+ if (bl->type == BL_MOB)
+ break; //Does not affect the caster.
+ if( !sce && sc_start4(ss,bl,type,100,sg->skill_lv,0,SC__BLOODYLUST,0,sg->limit) )
+ sc_start(ss,bl,SC__BLOODYLUST,100,sg->skill_lv,sg->limit);
break;
-
case UNT_PNEUMA:
case UNT_CHAOSPANIC:
case UNT_MAELSTROM:
if (!sce)
- sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit);
- break;
- case UNT_BLOODYLUST:
- if (sg->src_id == bl->id)
- break; //Does not affect the caster.
- if (!sce) {
- TBL_PC *sd = BL_CAST(BL_PC, bl); //prevent fullheal exploit
- if (sd && sd->bloodylust_tick && DIFF_TICK(iTimer->gettick(), sd->bloodylust_tick) < skill->get_time2(SC_BLOODYLUST, 1))
- clif->skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv,
- sc_start4(bl, type, 100, sg->skill_lv, 1, 0, 0, skill->get_time(LK_BERSERK, sg->skill_lv)));
- else {
- if (sd) sd->bloodylust_tick = iTimer->gettick();
- clif->skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv,
- sc_start4(bl, type, 100, sg->skill_lv, 0, 0, 0, skill->get_time(LK_BERSERK, sg->skill_lv)));
- }
- }
+ sc_start4(ss,bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit);
break;
case UNT_WARP_WAITING: {
@@ -10984,7 +11394,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned
if( --count <= 0 )
skill->del_unitgroup(sg,ALC_MARK);
- if ( iMap->mapindex2mapid(sg->val3) == sd->bl.m && x == sd->bl.x && y == sd->bl.y )
+ if ( map->mapindex2mapid(sg->val3) == sd->bl.m && x == sd->bl.x && y == sd->bl.y )
working = 1;/* we break it because officials break it, lovely stuff. */
sg->val1 = (count<<16)|working;
@@ -10992,35 +11402,35 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned
pc->setpos(sd,m,x,y,CLR_TELEPORT);
}
} else if(bl->type == BL_MOB && battle_config.mob_warp&2) {
- int16 m = iMap->mapindex2mapid(sg->val3);
+ int16 m = map->mapindex2mapid(sg->val3);
if (m < 0) break; //Map not available on this map-server.
- unit_warp(bl,m,sg->val2>>16,sg->val2&0xffff,CLR_TELEPORT);
+ unit->warp(bl,m,sg->val2>>16,sg->val2&0xffff,CLR_TELEPORT);
}
}
break;
case UNT_QUAGMIRE:
if( !sce && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 )
- sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit);
+ sc_start4(ss,bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit);
break;
case UNT_VOLCANO:
case UNT_DELUGE:
case UNT_VIOLENTGALE:
if(!sce)
- sc_start(bl,type,100,sg->skill_lv,sg->limit);
+ sc_start(ss,bl,type,100,sg->skill_lv,sg->limit);
break;
case UNT_SUITON:
if(!sce)
- sc_start4(bl,type,100,sg->skill_lv,
+ sc_start4(ss,bl,type,100,sg->skill_lv,
map_flag_vs(bl->m) || battle->check_target(&src->bl,bl,BCT_ENEMY)>0?1:0, //Send val3 =1 to reduce agi.
0,0,sg->limit);
break;
case UNT_HERMODE:
if (sg->src_id!=bl->id && battle->check_target(&src->bl,bl,BCT_PARTY|BCT_GUILD) > 0)
- status_change_clear_buffs(bl,1); //Should dispell only allies.
+ status->change_clear_buffs(bl,1); //Should dispell only allies.
case UNT_RICHMANKIM:
case UNT_ETERNALCHAOS:
case UNT_DRUMBATTLEFIELD:
@@ -11032,7 +11442,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned
if (sg->src_id==bl->id && !(sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER))
return skill_id;
if (!sce)
- sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit);
+ sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit);
break;
case UNT_WHISTLE:
case UNT_ASSASSINCROSS:
@@ -11047,19 +11457,19 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned
if (!sc) return 0;
if (!sce)
- sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit);
+ sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit);
else if (sce->val4 == 1) {
//Readjust timers since the effect will not last long.
sce->val4 = 0;
- iTimer->delete_timer(sce->timer, status_change_timer);
- sce->timer = iTimer->add_timer(tick+sg->limit, status_change_timer, bl->id, type);
+ timer->delete(sce->timer, status->change_timer);
+ sce->timer = timer->add(tick+sg->limit, status->change_timer, bl->id, type);
}
break;
case UNT_FOGWALL:
if (!sce)
{
- sc_start4(bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit);
+ sc_start4(ss, bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit);
if (battle->check_target(&src->bl,bl,BCT_ENEMY)>0)
skill->additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, ATK_DEF, tick);
}
@@ -11067,14 +11477,14 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned
case UNT_GRAVITATION:
if (!sce)
- sc_start4(bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit);
+ sc_start4(ss,bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit);
break;
// officially, icewall has no problems existing on occupied cells [ultramage]
// case UNT_ICEWALL: //Destroy the cell. [Skotlex]
// src->val1 = 0;
// if(src->limit + sg->tick > tick + 700)
- // src->limit = DIFF_TICK(tick+700,sg->tick);
+ // src->limit = DIFF_TICK32(tick+700,sg->tick);
// break;
case UNT_MOONLIT:
@@ -11083,7 +11493,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned
break;
if (ss == bl) //Also needed to prevent infinite loop crash.
break;
- skill->blown(ss,bl,skill->get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0);
+ skill->blown(ss,bl,skill->get_blewcount(sg->skill_id,sg->skill_lv),unit->getdir(bl),0);
break;
case UNT_WALLOFTHORN:
@@ -11093,17 +11503,26 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned
skill->attack(skill->get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
break;
+ case UNT_REVERBERATION:
+ if (sg->src_id == bl->id)
+ break; //Does not affect the caster.
+ clif->changetraplook(&src->bl,UNT_USED_TRAPS);
+ map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
+ sg->unit_id = UNT_USED_TRAPS;
+ sg->limit = DIFF_TICK32(tick,sg->tick) + 1500;
+ break;
+
case UNT_VOLCANIC_ASH:
if (!sce)
- sc_start(bl, SC_VOLCANIC_ASH, 100, sg->skill_lv, skill->get_time(MH_VOLCANIC_ASH, sg->skill_lv));
+ sc_start(ss, bl, SC_VOLCANIC_ASH, 100, sg->skill_lv, skill->get_time(MH_VOLCANIC_ASH, sg->skill_lv));
break;
case UNT_GD_LEADERSHIP:
case UNT_GD_GLORYWOUNDS:
case UNT_GD_SOULCOLD:
case UNT_GD_HAWKEYES:
- if ( !sce )
- sc_start4(bl,type,100,sg->skill_lv,0,0,0,1000);
+ if ( !sce && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 )
+ sc_start4(ss,bl,type,100,sg->skill_lv,0,0,0,1000);
break;
}
return skill_id;
@@ -11112,12 +11531,12 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned
/*==========================================
*
*------------------------------------------*/
-int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, unsigned int tick) {
+int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int64 tick) {
struct skill_unit_group *sg;
struct block_list *ss;
TBL_PC* tsd;
struct status_data *tstatus;
- struct status_change *tsc;
+ struct status_change *tsc, *ssc;
struct skill_unit_group_tickset *ts;
enum sc_type type;
uint16 skill_id;
@@ -11126,19 +11545,24 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
nullpo_ret(src);
nullpo_ret(bl);
- if (bl->prev==NULL || !src->alive || status_isdead(bl))
+ if (bl->prev==NULL || !src->alive || status->isdead(bl))
return 0;
nullpo_ret(sg=src->group);
- nullpo_ret(ss=iMap->id2bl(sg->src_id));
+ nullpo_ret(ss=map->id2bl(sg->src_id));
tsd = BL_CAST(BL_PC, bl);
- tsc = status_get_sc(bl);
+ tsc = status->get_sc(bl);
+ ssc = status->get_sc(ss); // Status Effects for Unit caster.
if ( tsc && tsc->data[SC_HOVERING] )
return 0; //Under hovering characters are immune to trap and ground target skills.
- tstatus = status_get_status_data(bl);
- type = status_skill2sc(sg->skill_id);
+ // Maestro or Wanderer is unaffected by traps of trappers he or she charmed [SuperHulk]
+ if ( ssc && ssc->data[SC_SIREN] && ssc->data[SC_SIREN]->val2 == bl->id && (skill->get_inf2(sg->skill_id)&INF2_TRAP) )
+ return 0;
+
+ tstatus = status->get_status_data(bl);
+ type = status->skill2sc(sg->skill_id);
skill_id = sg->skill_id;
if (sg->interval == -1) {
@@ -11156,13 +11580,13 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
if ((ts = skill->unitgrouptickset_search(bl,sg,tick))) {
//Not all have it, eg: Traps don't have it even though they can be hit by Heaven's Drive [Skotlex]
- diff = DIFF_TICK(tick,ts->tick);
+ diff = DIFF_TICK32(tick,ts->tick);
if (diff < 0)
return 0;
ts->tick = tick+sg->interval;
if ((skill_id==CR_GRANDCROSS || skill_id==NPC_GRANDDARKNESS) && !battle_config.gx_allhit)
- ts->tick += sg->interval*(iMap->count_oncell(bl->m,bl->x,bl->y,BL_CHAR)-1);
+ ts->tick += sg->interval*(map->count_oncell(bl->m,bl->x,bl->y,BL_CHAR)-1);
}
switch (sg->unit_id) {
@@ -11177,8 +11601,8 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
//Take into account these hit more times than the timer interval can handle.
do
skill->attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0);
- while(--src->val2 && x == bl->x && y == bl->y &&
- ++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl));
+ while(--src->val2 && x == bl->x && y == bl->y
+ && ++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status->isdead(bl));
if (src->val2<=0)
skill->delunit(src);
@@ -11201,12 +11625,12 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
break;
if( tstatus->hp >= tstatus->max_hp )
break;
- if( status_isimmune(bl) )
+ if( status->isimmune(bl) )
heal = 0;
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
if( tsc && tsc->data[SC_AKAITSUKI] && heal )
heal = ~heal + 1;
- status_heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, 0);
if( diff >= 500 )
sg->val1--;
}
@@ -11216,18 +11640,18 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
case UNT_EVILLAND:
//Will heal demon and undead element monsters, but not players.
- if ((bl->type == BL_PC) || (!battle->check_undead(tstatus->race, tstatus->def_ele) && tstatus->race!=RC_DEMON))
- { //Damage enemies
+ if ((bl->type == BL_PC) || (!battle->check_undead(tstatus->race, tstatus->def_ele) && tstatus->race!=RC_DEMON)) {
+ //Damage enemies
if(battle->check_target(&src->bl,bl,BCT_ENEMY)>0)
skill->attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
} else {
int heal = skill->calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true);
if (tstatus->hp >= tstatus->max_hp)
break;
- if (status_isimmune(bl))
+ if (status->isimmune(bl))
heal = 0;
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
- status_heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, 0);
}
break;
@@ -11238,8 +11662,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
break;
case UNT_DUMMYSKILL:
- switch (sg->skill_id)
- {
+ switch (sg->skill_id) {
case SG_SUN_WARM: //SG skills [Komurka]
case SG_MOON_WARM:
case SG_STAR_WARM:
@@ -11247,24 +11670,23 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
int count = 0;
const int x = bl->x, y = bl->y;
+ map->freeblock_lock();
//If target isn't knocked back it should hit every "interval" ms [Playtester]
- do
- {
+ do {
if( bl->type == BL_PC )
status_zap(bl, 0, 15); // sp damage to players
- else // mobs
- if( status_charge(ss, 0, 2) ) // costs 2 SP per hit
- {
+ else if( status->charge(ss, 0, 2) ) { // mobs
+ // costs 2 SP per hit
if( !skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0) )
- status_charge(ss, 0, 8); //costs additional 8 SP if miss
- }
- else
- { //should end when out of sp.
- sg->limit = DIFF_TICK(tick,sg->tick);
+ status->charge(ss, 0, 8); //costs additional 8 SP if miss
+ } else { // mobs
+ //should end when out of sp.
+ sg->limit = DIFF_TICK32(tick,sg->tick);
break;
}
- } while( x == bl->x && y == bl->y &&
- ++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl) );
+ } while( x == bl->x && y == bl->y && sg->alive_count
+ && ++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status->isdead(bl) );
+ map->freeblock_unlock();
}
break;
/**
@@ -11282,12 +11704,6 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
if (rnd()%100 < src->val1)
skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
- case GN_CRAZYWEED_ATK:
- if( bl->type == BL_SKILL ){
- struct skill_unit *su = (struct skill_unit *)bl;
- if( su && !(skill->get_inf2(su->group->skill_id)&INF2_TRAP) )
- break;
- }
default:
skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
}
@@ -11300,10 +11716,10 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
case UNT_SKIDTRAP:
{
- skill->blown(&src->bl,bl,skill->get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0);
+ skill->blown(&src->bl,bl,skill->get_blewcount(sg->skill_id,sg->skill_lv),unit->getdir(bl),0);
sg->unit_id = UNT_USED_TRAPS;
clif->changetraplook(&src->bl, UNT_USED_TRAPS);
- sg->limit=DIFF_TICK(tick,sg->tick)+1500;
+ sg->limit=DIFF_TICK32(tick,sg->tick)+1500;
}
break;
@@ -11311,12 +11727,12 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
case UNT_MANHOLE:
if( sg->val2 == 0 && tsc && (sg->unit_id == UNT_ANKLESNARE || bl->id != sg->src_id) ) {
int sec = skill->get_time2(sg->skill_id,sg->skill_lv);
- if( status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 8) ) {
- const struct TimerData* td = tsc->data[type]?iTimer->get_timer(tsc->data[type]->timer):NULL;
+ if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 8) ) {
+ const struct TimerData* td = tsc->data[type]?timer->get(tsc->data[type]->timer):NULL;
if( td )
- sec = DIFF_TICK(td->tick, tick);
- if( sg->unit_id == UNT_MANHOLE || battle_config.skill_trap_type || !map_flag_gvg(src->bl.m) ) {
- unit_movepos(bl, src->bl.x, src->bl.y, 0, 0);
+ sec = DIFF_TICK32(td->tick, tick);
+ if( sg->unit_id == UNT_MANHOLE || battle_config.skill_trap_type || !map_flag_gvg2(src->bl.m) ) {
+ unit->movepos(bl, src->bl.x, src->bl.y, 0, 0);
clif->fixpos(bl);
}
sg->val2 = bl->id;
@@ -11331,7 +11747,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
**/
clif->changetraplook(&src->bl, UNT_ANKLESNARE);
}
- sg->limit = DIFF_TICK(tick,sg->tick)+sec;
+ sg->limit = DIFF_TICK32(tick,sg->tick)+sec;
sg->interval = -1;
src->range = 0;
}
@@ -11341,21 +11757,20 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
if( bl->id != ss->id ) {
if( status_get_mode(bl)&MD_BOSS )
break;
- if( status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id, sg->skill_lv), 8) ) {
-
- iMap->moveblock(bl, src->bl.x, src->bl.y, tick);
+ if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id, sg->skill_lv), 8) ) {
+ map->moveblock(bl, src->bl.x, src->bl.y, tick);
clif->fixpos(bl);
}
- iMap->foreachinrange(skill->trap_splash, &src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl, tick);
+ map->foreachinrange(skill->trap_splash, &src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl, tick);
sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again.
}
break;
case UNT_VENOMDUST:
if(tsc && !tsc->data[type])
- status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),0);
+ status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),0);
break;
@@ -11371,17 +11786,20 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
if( bl->id == ss->id )// it won't trigger on caster
break;
case UNT_LANDMINE:
- case UNT_CLAYMORETRAP:
case UNT_BLASTMINE:
case UNT_SHOCKWAVE:
case UNT_SANDMAN:
case UNT_FLASHER:
case UNT_FREEZINGTRAP:
case UNT_FIREPILLAR_ACTIVE:
- iMap->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
+ case UNT_CLAYMORETRAP:
+ if( sg->unit_id == UNT_FIRINGTRAP || sg->unit_id == UNT_ICEBOUNDTRAP || sg->unit_id == UNT_CLAYMORETRAP )
+ map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &src->bl,tick);
+ else
+ map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
if (sg->unit_id != UNT_FIREPILLAR_ACTIVE)
clif->changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS);
- sg->limit=DIFF_TICK(tick,sg->tick)+1500 +
+ sg->limit=DIFF_TICK32(tick,sg->tick)+1500 +
(sg->unit_id== UNT_CLUSTERBOMB || sg->unit_id== UNT_ICEBOUNDTRAP?1000:0);// Cluster Bomb/Icebound has 1s to disappear once activated.
sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again.
break;
@@ -11393,7 +11811,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
clif->talkiebox(&src->bl, sg->valstr);
sg->unit_id = UNT_USED_TRAPS;
clif->changetraplook(&src->bl, UNT_USED_TRAPS);
- sg->limit = DIFF_TICK(tick, sg->tick) + 5000;
+ sg->limit = DIFF_TICK32(tick, sg->tick) + 5000;
sg->val2 = -1;
}
break;
@@ -11427,7 +11845,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
if( tsc->data[SC_AKAITSUKI] && heal )
heal = ~heal + 1;
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
- status_heal(bl, heal, 0, 0);
+ status->heal(bl, heal, 0, 0);
break;
}
@@ -11444,58 +11862,57 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
int heal;
int i = rnd()%13; // Positive buff count
int time = skill->get_time2(sg->skill_id, sg->skill_lv); //Duration
- switch (i)
- {
+ switch (i) {
case 0: // Heal 1~9999 HP
heal = rnd() %9999+1;
clif->skill_nodamage(ss,bl,AL_HEAL,heal,1);
- status_heal(bl,heal,0,0);
+ status->heal(bl,heal,0,0);
break;
case 1: // End all negative status
- status_change_clear_buffs(bl,2);
+ status->change_clear_buffs(bl,2);
if (tsd) clif->gospel_info(tsd, 0x15);
break;
case 2: // Immunity to all status
- sc_start(bl,SC_SCRESIST,100,100,time);
+ sc_start(ss,bl,SC_SCRESIST,100,100,time);
if (tsd) clif->gospel_info(tsd, 0x16);
break;
case 3: // MaxHP +100%
- sc_start(bl,SC_INCMHPRATE,100,100,time);
+ sc_start(ss,bl,SC_INCMHPRATE,100,100,time);
if (tsd) clif->gospel_info(tsd, 0x17);
break;
case 4: // MaxSP +100%
- sc_start(bl,SC_INCMSPRATE,100,100,time);
+ sc_start(ss,bl,SC_INCMSPRATE,100,100,time);
if (tsd) clif->gospel_info(tsd, 0x18);
break;
case 5: // All stats +20
- sc_start(bl,SC_INCALLSTATUS,100,20,time);
+ sc_start(ss,bl,SC_INCALLSTATUS,100,20,time);
if (tsd) clif->gospel_info(tsd, 0x19);
break;
case 6: // Level 10 Blessing
- sc_start(bl,SC_BLESSING,100,10,time);
+ sc_start(ss,bl,SC_BLESSING,100,10,time);
break;
case 7: // Level 10 Increase AGI
- sc_start(bl,SC_INC_AGI,100,10,time);
+ sc_start(ss,bl,SC_INC_AGI,100,10,time);
break;
case 8: // Enchant weapon with Holy element
- sc_start(bl,SC_ASPERSIO,100,1,time);
+ sc_start(ss,bl,SC_ASPERSIO,100,1,time);
if (tsd) clif->gospel_info(tsd, 0x1c);
break;
case 9: // Enchant armor with Holy element
- sc_start(bl,SC_BENEDICTIO,100,1,time);
+ sc_start(ss,bl,SC_BENEDICTIO,100,1,time);
if (tsd) clif->gospel_info(tsd, 0x1d);
break;
case 10: // DEF +25%
- sc_start(bl,SC_INCDEFRATE,100,25,time);
+ sc_start(ss,bl,SC_INCDEFRATE,100,25,time);
if (tsd) clif->gospel_info(tsd, 0x1e);
break;
case 11: // ATK +100%
- sc_start(bl,SC_INCATKRATE,100,100,time);
+ sc_start(ss,bl,SC_INCATKRATE,100,100,time);
if (tsd) clif->gospel_info(tsd, 0x1f);
break;
case 12: // HIT/Flee +50
- sc_start(bl,SC_INCHIT,100,50,time);
- sc_start(bl,SC_INCFLEE,100,50,time);
+ sc_start(ss,bl,SC_INCHIT,100,50,time);
+ sc_start(ss,bl,SC_INCFLEE,100,50,time);
if (tsd) clif->gospel_info(tsd, 0x20);
break;
}
@@ -11510,28 +11927,28 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
skill->attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
case 1: // Curse
- sc_start(bl,SC_CURSE,100,1,time);
+ sc_start(ss,bl,SC_CURSE,100,1,time);
break;
case 2: // Blind
- sc_start(bl,SC_BLIND,100,1,time);
+ sc_start(ss,bl,SC_BLIND,100,1,time);
break;
case 3: // Poison
- sc_start(bl,SC_POISON,100,1,time);
+ sc_start(ss,bl,SC_POISON,100,1,time);
break;
case 4: // Level 10 Provoke
- sc_start(bl,SC_PROVOKE,100,10,time);
+ sc_start(ss,bl,SC_PROVOKE,100,10,time);
break;
case 5: // DEF -100%
- sc_start(bl,SC_INCDEFRATE,100,-100,time);
+ sc_start(ss,bl,SC_INCDEFRATE,100,-100,time);
break;
case 6: // ATK -100%
- sc_start(bl,SC_INCATKRATE,100,-100,time);
+ sc_start(ss,bl,SC_INCATKRATE,100,-100,time);
break;
case 7: // Flee -100%
- sc_start(bl,SC_INCFLEERATE,100,-100,time);
+ sc_start(ss,bl,SC_INCFLEERATE,100,-100,time);
break;
case 8: // Speed/ASPD -25%
- sc_start4(bl,SC_GOSPEL,100,1,0,0,BCT_ENEMY,time);
+ sc_start4(ss,bl,SC_GOSPEL,100,1,0,0,BCT_ENEMY,time);
break;
}
}
@@ -11542,12 +11959,12 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
int i = battle->check_target(&src->bl, bl, BCT_ENEMY);
if( i > 0 && !(status_get_mode(bl)&MD_BOSS) )
{ // knock-back any enemy except Boss
- skill->blown(&src->bl, bl, 2, unit_getdir(bl), 0);
+ skill->blown(&src->bl, bl, 2, unit->getdir(bl), 0);
clif->fixpos(bl);
}
if( sg->src_id != bl->id && i <= 0 )
- sc_start4(bl, type, 100, 0, 0, 0, src->bl.id, sg->interval + 100);
+ sc_start4(ss, bl, type, 100, 0, 0, 0, src->bl.id, sg->interval + 100);
}
break;
@@ -11566,19 +11983,23 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
case UNT_GROUNDDRIFT_POISON:
case UNT_GROUNDDRIFT_WATER:
case UNT_GROUNDDRIFT_FIRE:
- iMap->foreachinrange(skill->trap_splash,&src->bl,
- skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag,
- &src->bl,tick);
+ map->foreachinrange(skill->trap_splash,&src->bl,
+ skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag,
+ &src->bl,tick);
sg->unit_id = UNT_USED_TRAPS;
//clif->changetraplook(&src->bl, UNT_FIREPILLAR_ACTIVE);
- sg->limit=DIFF_TICK(tick,sg->tick)+1500;
+ sg->limit=DIFF_TICK32(tick,sg->tick)+1500;
break;
/**
* 3rd stuff
**/
case UNT_POISONSMOKE:
- if( battle->check_target(ss,bl,BCT_ENEMY) > 0 && !(tsc && tsc->data[sg->val2]) && rnd()%100 < 20 )
- sc_start(bl,sg->val2,100,sg->val3,skill->get_time2(GC_POISONINGWEAPON, 1));
+ if( battle->check_target(ss,bl,BCT_ENEMY) > 0 && !(tsc && tsc->data[sg->val2]) && rnd()%100 < 50 ) {
+ short rate = 100;
+ if ( sg->val1 == 9 )//Oblivion Curse gives a 2nd success chance after the 1st one passes which is reducible. [Rytech]
+ rate = 100 - tstatus->int_ * 4 / 5 ;
+ sc_start(ss,bl,sg->val2,rate,sg->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000);
+ }
break;
case UNT_EPICLESIS:
@@ -11592,14 +12013,15 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
}
hp = tstatus->max_hp * hp / 100;
sp = tstatus->max_sp * sp / 100;
- status_heal(bl, hp, sp, 2);
- sc_start(bl, type, 100, sg->skill_lv, (sg->interval * 3) + 100);
+ status->heal(bl, hp, sp, 2);
+ sc_start(ss, bl, type, 100, sg->skill_lv, (sg->interval * 3) + 100);
}
// Reveal hidden players every 5 seconds.
if( sg->val2 % 5 == 0 ) {
// TODO: check if other hidden status can be removed.
status_change_end(bl,SC_HIDING,INVALID_TIMER);
status_change_end(bl,SC_CLOAKING,INVALID_TIMER);
+ status_change_end(bl,SC_CLOAKINGEXCEED,INVALID_TIMER);
}
}
/* Enable this if kRO fix the current skill. Currently no damage on undead and demon monster. [Jobbie]
@@ -11609,35 +12031,33 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
case UNT_STEALTHFIELD:
if( bl->id == sg->src_id )
- break; // Dont work on Self (video shows that)
+ break; // Don't work on Self (video shows that)
case UNT_NEUTRALBARRIER:
- sc_start(bl,type,100,sg->skill_lv,sg->interval + 100);
+ sc_start(ss,bl,type,100,sg->skill_lv,sg->interval + 100);
break;
case UNT_DIMENSIONDOOR:
- if( tsd && !map[bl->m].flag.noteleport )
+ if( tsd && !map->list[bl->m].flag.noteleport )
pc->randomwarp(tsd,3);
else if( bl->type == BL_MOB && battle_config.mob_warp&8 )
- unit_warp(bl,-1,-1,-1,3);
+ unit->warp(bl,-1,-1,-1,3);
break;
case UNT_REVERBERATION:
clif->changetraplook(&src->bl,UNT_USED_TRAPS);
- iMap->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
- sg->limit = DIFF_TICK(tick,sg->tick)+1000;
+ map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick);
+ sg->limit = DIFF_TICK32(tick,sg->tick)+1500;
sg->unit_id = UNT_USED_TRAPS;
break;
case UNT_SEVERE_RAINSTORM:
- if( battle->check_target(&src->bl, bl, BCT_ENEMY) > 0 )
+ if( battle->check_target(&src->bl, bl, BCT_ENEMY))
skill->attack(BF_WEAPON,ss,&src->bl,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0);
break;
case UNT_NETHERWORLD:
- if( !(status_get_mode(bl)&MD_BOSS) && ss != bl && battle->check_target(&src->bl, bl, BCT_PARTY) > 0 ) {
+ if( !(status_get_mode(bl)&MD_BOSS)) {
if( !(tsc && tsc->data[type]) ){
- sc_start(bl, type, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv));
- sg->limit = DIFF_TICK(tick,sg->tick);
- sg->unit_id = UNT_USED_TRAPS;
+ sc_start(ss, bl, type, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv));
}
}
break;
@@ -11645,16 +12065,16 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
if( tsc ) {
if( !sg->val2 ) {
int sec = skill->get_time2(sg->skill_id, sg->skill_lv);
- if( sc_start(bl, type, 100, sg->skill_lv, sec) ) {
- const struct TimerData* td = tsc->data[type]?iTimer->get_timer(tsc->data[type]->timer):NULL;
+ if( sc_start(ss, bl, type, 100, sg->skill_lv, sec) ) {
+ const struct TimerData* td = tsc->data[type]?timer->get(tsc->data[type]->timer):NULL;
if( td )
- sec = DIFF_TICK(td->tick, tick);
- ///iMap->moveblock(bl, src->bl.x, src->bl.y, tick); // in official server it doesn't behave like this. [malufett]
+ sec = DIFF_TICK32(td->tick, tick);
+ ///map->moveblock(bl, src->bl.x, src->bl.y, tick); // in official server it doesn't behave like this. [malufett]
clif->fixpos(bl);
sg->val2 = bl->id;
} else
sec = 3000; // Couldn't trap it?
- sg->limit = DIFF_TICK(tick, sg->tick) + sec;
+ sg->limit = DIFF_TICK32(tick, sg->tick) + sec;
} else if( tsc->data[SC_THORNS_TRAP] && bl->id == sg->val2 )
skill->attack(skill->get_type(GN_THORNS_TRAP), ss, ss, bl, sg->skill_id, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION);
}
@@ -11666,7 +12086,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
case 1:
case 2:
default:
- sc_start4(bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, 0, ss->id, 0,
+ sc_start4(ss, bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, 0, ss->id, 0,
skill->get_time2(sg->skill_id, sg->skill_lv));
skill->attack(skill->get_type(sg->skill_id), ss, &src->bl, bl,
sg->skill_id, sg->skill_lv + 10 * sg->val2, tick, 0);
@@ -11681,38 +12101,40 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
break;
case UNT_FIRE_EXPANSION_SMOKE_POWDER:
- sc_start(bl, status_skill2sc(GN_FIRE_EXPANSION_SMOKE_POWDER), 100, sg->skill_lv, 1000);
+ sc_start(ss, bl, status->skill2sc(GN_FIRE_EXPANSION_SMOKE_POWDER), 100, sg->skill_lv, 1000);
break;
case UNT_FIRE_EXPANSION_TEAR_GAS:
- sc_start(bl, status_skill2sc(GN_FIRE_EXPANSION_TEAR_GAS), 100, sg->skill_lv, 1000);
+ sc_start(ss, bl, status->skill2sc(GN_FIRE_EXPANSION_TEAR_GAS), 100, sg->skill_lv, 1000);
break;
case UNT_HELLS_PLANT:
if( battle->check_target(&src->bl,bl,BCT_ENEMY) > 0 )
skill->attack(skill->get_type(GN_HELLS_PLANT_ATK), ss, &src->bl, bl, GN_HELLS_PLANT_ATK, sg->skill_lv, tick, 0);
if( ss != bl) //The caster is the only one who can step on the Plants, without destroying them
- sg->limit = DIFF_TICK(tick, sg->tick) + 100;
+ sg->limit = DIFF_TICK32(tick, sg->tick) + 100;
break;
case UNT_CLOUD_KILL:
if(tsc && !tsc->data[type])
- status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),8);
+ status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),8);
skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
case UNT_WARMER:
if( bl->type == BL_PC && !battle->check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON ) {
- int hp = 125 * sg->skill_lv; // Officially is 125 * skill_lv.
- struct status_change *ssc = status_get_sc(ss);
+ int hp = 0;
if( ssc && ssc->data[SC_HEATER_OPTION] )
- hp += hp * ssc->data[SC_HEATER_OPTION]->val3 / 100;
+ hp = tstatus->max_hp * 3 * sg->skill_lv / 100;
+ else
+ hp = tstatus->max_hp * sg->skill_lv / 100;
+ status->heal(bl, hp, 0, 0);
if( tstatus->hp != tstatus->max_hp )
clif->skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0);
if( tsc && tsc->data[SC_AKAITSUKI] && hp )
hp = ~hp + 1;
- status_heal(bl, hp, 0, 0);
- sc_start(bl, SC_WARMER, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv));
+ status->heal(bl, hp, 0, 0);
+ sc_start(ss, bl, SC_WARMER, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv));
}
break;
@@ -11721,18 +12143,18 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
case UNT_WIND_INSIGNIA:
case UNT_EARTH_INSIGNIA:
case UNT_ZEPHYR:
- sc_start(bl,type, 100, sg->skill_lv, sg->interval);
+ sc_start(ss, bl,type, 100, sg->skill_lv, sg->interval);
if (sg->unit_id != UNT_ZEPHYR && !battle->check_undead(tstatus->race, tstatus->def_ele)) {
int hp = tstatus->max_hp / 100; //+1% each 5s
if ((sg->val3) % 5) { //each 5s
- if (tstatus->def_ele == skill->get_ele(sg->skill_id,sg->skill_lv)){
- status_heal(bl, hp, 0, 2);
- } else if((sg->unit_id == UNT_FIRE_INSIGNIA && tstatus->def_ele == ELE_EARTH)
- ||(sg->unit_id == UNT_WATER_INSIGNIA && tstatus->def_ele == ELE_FIRE)
- ||(sg->unit_id == UNT_WIND_INSIGNIA && tstatus->def_ele == ELE_WATER)
- ||(sg->unit_id == UNT_EARTH_INSIGNIA && tstatus->def_ele == ELE_WIND)
- ){
- status_heal(bl, -hp, 0, 0);
+ if (tstatus->def_ele == skill->get_ele(sg->skill_id,sg->skill_lv)) {
+ status->heal(bl, hp, 0, 2);
+ } else if( (sg->unit_id == UNT_FIRE_INSIGNIA && tstatus->def_ele == ELE_EARTH)
+ || (sg->unit_id == UNT_WATER_INSIGNIA && tstatus->def_ele == ELE_FIRE)
+ || (sg->unit_id == UNT_WIND_INSIGNIA && tstatus->def_ele == ELE_WATER)
+ || (sg->unit_id == UNT_EARTH_INSIGNIA && tstatus->def_ele == ELE_WIND)
+ ) {
+ status->heal(bl, -hp, 0, 0);
}
}
sg->val3++; //timer
@@ -11741,31 +12163,11 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
break;
case UNT_VACUUM_EXTREME:
- {// TODO: official behavior in gvg area. [malufett]
- int sec = sg->limit - DIFF_TICK(tick, sg->tick);
- int range = skill->get_unit_range(sg->skill_id, sg->skill_lv);
-
- if( tsc && !tsc->data[type] &&
- distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) <= range)// don't consider outer bounderies
- sc_start(bl, type, 100, sg->skill_lv, sec);
-
- if( unit_is_walking(bl) && // wait until target stop walking
- ( tsc && tsc->data[type] && tsc->data[type]->val4 >= tsc->data[type]->val3-range ))
- break;
-
- if( tsc && ( !tsc->data[type] || (tsc->data[type] && tsc->data[type]->val4 < 1 ) ) )
- break;
-
- if( unit_is_walking(bl) &&
- distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) > range )// going outside of boundaries? then force it to stop
- unit_stop_walking(bl,1);
-
- if( !unit_is_walking(bl) &&
- distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) <= range && // only snap if the target is inside the range or
- src->bl.x != bl->x && src->bl.y != bl->y){// diagonal position parallel to VE's center
- unit_movepos(bl, src->bl.x, src->bl.y, 0, 0);
- clif->fixpos(bl);
- }
+ if ( tsc && tsc->data[SC_HALLUCINATIONWALK] ) {
+ return 0;
+ } else {
+ sg->limit -= 100 * tstatus->str/20;
+ sc_start(ss, bl, SC_VACUUM_EXTREME, 100, sg->skill_lv, sg->limit);
}
break;
@@ -11781,48 +12183,48 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
if( battle->check_target(&src->bl,bl,BCT_ENEMY) > 0 ){
switch( sg->unit_id ){
case UNT_ZENKAI_WATER:
- sc_start(bl, SC_CRYSTALIZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
- sc_start(bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
- sc_start(bl, SC_FROSTMISTY, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(ss, bl, SC_COLD, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(ss, bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(ss, bl, SC_FROSTMISTY, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
break;
case UNT_ZENKAI_LAND:
- sc_start(bl, SC_STONE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
- sc_start(bl, SC_POISON, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(ss, bl, SC_STONE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(ss, bl, SC_POISON, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
break;
case UNT_ZENKAI_FIRE:
- sc_start4(bl, SC_BURNING, sg->val1*5, sg->skill_lv, 0, ss->id, 0, skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start4(ss, bl, SC_BURNING, sg->val1*5, sg->skill_lv, 0, ss->id, 0, skill->get_time2(sg->skill_id, sg->skill_lv));
break;
case UNT_ZENKAI_WIND:
- sc_start(bl, SC_SILENCE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
- sc_start(bl, SC_SLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
- sc_start(bl, SC_DEEP_SLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(ss, bl, SC_SILENCE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(ss, bl, SC_SLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(ss, bl, SC_DEEP_SLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
break;
}
}else
- sc_start2(bl,type,100,sg->val1,sg->val2,skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start2(ss, bl,type,100,sg->val1,sg->val2,skill->get_time2(sg->skill_id, sg->skill_lv));
break;
case UNT_LAVA_SLIDE:
skill->attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
if(++sg->val1 > 4) //after 5 stop hit and destroy me
- sg->limit = DIFF_TICK(tick, sg->tick);
+ sg->limit = DIFF_TICK32(tick, sg->tick);
break;
case UNT_POISON_MIST:
skill->attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
- status_change_start(bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill->get_time2(sg->skill_id, sg->skill_lv), 2|8);
+ status->change_start(ss, bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill->get_time2(sg->skill_id, sg->skill_lv), 2|8);
break;
}
if (bl->type == BL_MOB && ss != bl)
- mobskill_event((TBL_MOB*)bl, ss, tick, MSC_SKILLUSED|(skill_id<<16));
+ mob->skill_event((TBL_MOB*)bl, ss, tick, MSC_SKILLUSED|(skill_id<<16));
return skill_id;
}
/*==========================================
* Triggered when a char steps out of a skill cell
*------------------------------------------*/
-int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned int tick) {
+int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick) {
struct skill_unit_group *sg;
struct status_change *sc;
struct status_change_entry *sce;
@@ -11831,12 +12233,13 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in
nullpo_ret(src);
nullpo_ret(bl);
nullpo_ret(sg=src->group);
- sc = status_get_sc(bl);
- type = status_skill2sc(sg->skill_id);
+ sc = status->get_sc(bl);
+ type = status->skill2sc(sg->skill_id);
sce = (sc && type != -1)?sc->data[type]:NULL;
- if( bl->prev==NULL ||
- (status_isdead(bl) && sg->unit_id != UNT_ANKLESNARE && sg->unit_id != UNT_SPIDERWEB) ) //Need to delete the trap if the source died.
+ if( bl->prev == NULL
+ || (status->isdead(bl) && sg->unit_id != UNT_ANKLESNARE && sg->unit_id != UNT_SPIDERWEB && sg->unit_id != UNT_THORNS_TRAP)
+ ) //Need to delete the trap if the source died.
return 0;
switch(sg->unit_id){
@@ -11845,6 +12248,7 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in
case UNT_EPICLESIS://Arch Bishop
case UNT_NEUTRALBARRIER:
case UNT_STEALTHFIELD:
+ case UNT_WARMER:
if (sce)
status_change_end(bl, type, INVALID_TIMER);
break;
@@ -11858,16 +12262,17 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in
status_change_end(bl, type, INVALID_TIMER);
break;
- case UNT_SPIDERWEB: {
- struct block_list *target = iMap->id2bl(sg->val2);
- if (target && target==bl)
- {
- if (sce && sce->val3 == sg->group_id)
- status_change_end(bl, type, INVALID_TIMER);
- sg->limit = DIFF_TICK(tick,sg->tick)+1000;
- }
- break;
+ case UNT_THORNS_TRAP:
+ case UNT_SPIDERWEB:
+ {
+ struct block_list *target = map->id2bl(sg->val2);
+ if (target && target==bl) {
+ if (sce && sce->val3 == sg->group_id)
+ status_change_end(bl, type, INVALID_TIMER);
+ sg->limit = DIFF_TICK32(tick,sg->tick)+1000;
}
+ }
+ break;
}
return sg->skill_id;
}
@@ -11875,17 +12280,16 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in
/*==========================================
* Triggered when a char steps out of a skill group (entirely) [Skotlex]
*------------------------------------------*/
-static int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned int tick)
-{
+int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) {
struct status_change *sc;
struct status_change_entry *sce;
enum sc_type type;
- sc = status_get_sc(bl);
+ sc = status->get_sc(bl);
if (sc && !sc->count)
sc = NULL;
- type = status_skill2sc(skill_id);
+ type = status->skill2sc(skill_id);
sce = (sc && type != -1)?sc->data[type]:NULL;
switch (skill_id) {
@@ -11909,8 +12313,8 @@ static int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned i
//We don't check for SC_LONGING because someone could always have knocked you back and out of the song/dance.
//FIXME: This code is not perfect, it doesn't checks for the real ensemble's owner,
//it only checks if you are doing the same ensemble. So if there's two chars doing an ensemble
- //which overlaps, by stepping outside of the other parther's ensemble will cause you to cancel
- //your own. Let's pray that scenario is pretty unlikely and noone will complain too much about it.
+ //which overlaps, by stepping outside of the other partner's ensemble will cause you to cancel
+ //your own. Let's pray that scenario is pretty unlikely and none will complain too much about it.
status_change_end(bl, SC_DANCING, INVALID_TIMER);
}
case MH_STEINWAND:
@@ -11926,20 +12330,18 @@ static int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned i
case EL_WATER_BARRIER:
case EL_ZEPHYR:
case EL_POWER_OF_GAIA:
+ case SO_ELEMENTAL_SHIELD:
+ case SC_BLOODYLUST:
+ if (sce)
+ status_change_end(bl, type, INVALID_TIMER);
+ break;
case SO_FIRE_INSIGNIA:
case SO_WATER_INSIGNIA:
case SO_WIND_INSIGNIA:
case SO_EARTH_INSIGNIA:
- if (sce)
- status_change_end(bl, type, INVALID_TIMER);
- break;
- case SC_BLOODYLUST:
- if (sce) {
+ if (sce && bl->type != BL_ELEM)
status_change_end(bl, type, INVALID_TIMER);
- status_set_sp(bl, 0, 0); //set sp to 0 when quitting zone
- }
break;
-
case BA_POEMBRAGI:
case BA_WHISTLE:
case BA_ASSASSINCROSS:
@@ -11949,22 +12351,22 @@ static int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned i
case DC_FORTUNEKISS:
case DC_SERVICEFORYOU:
if (sce) {
- iTimer->delete_timer(sce->timer, status_change_timer);
+ timer->delete(sce->timer, status->change_timer);
//NOTE: It'd be nice if we could get the skill_lv for a more accurate extra time, but alas...
//not possible on our current implementation.
sce->val4 = 1; //Store the fact that this is a "reduced" duration effect.
- sce->timer = iTimer->add_timer(tick+skill->get_time2(skill_id,1), status_change_timer, bl->id, type);
+ sce->timer = timer->add(tick+skill->get_time2(skill_id,1), status->change_timer, bl->id, type);
}
break;
case PF_FOGWALL:
if (sce) {
status_change_end(bl, type, INVALID_TIMER);
if ((sce=sc->data[SC_BLIND])) {
- if (bl->type == BL_PC) //Players get blind ended inmediately, others have it still for 30 secs. [Skotlex]
+ if (bl->type == BL_PC) //Players get blind ended immediately, others have it still for 30 secs. [Skotlex]
status_change_end(bl, SC_BLIND, INVALID_TIMER);
else {
- iTimer->delete_timer(sce->timer, status_change_timer);
- sce->timer = iTimer->add_timer(30000+tick, status_change_timer, bl->id, SC_BLIND);
+ timer->delete(sce->timer, status->change_timer);
+ sce->timer = timer->add(30000+tick, status->change_timer, bl->id, SC_BLIND);
}
}
}
@@ -11987,38 +12389,38 @@ static int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned i
* flag&1: Invoke onplace function (otherwise invoke onout)
* flag&4: Invoke a onleft call (the unit might be scheduled for deletion)
*------------------------------------------*/
-int skill_unit_effect (struct block_list* bl, va_list ap) {
- struct skill_unit* unit = va_arg(ap,struct skill_unit*);
- struct skill_unit_group* group = unit->group;
- unsigned int tick = va_arg(ap,unsigned int);
+int skill_unit_effect(struct block_list* bl, va_list ap) {
+ struct skill_unit* su = va_arg(ap,struct skill_unit*);
+ struct skill_unit_group* group = su->group;
+ int64 tick = va_arg(ap,int64);
unsigned int flag = va_arg(ap,unsigned int);
uint16 skill_id;
bool dissonance;
- if( (!unit->alive && !(flag&4)) || bl->prev == NULL )
+ if( (!su->alive && !(flag&4)) || bl->prev == NULL )
return 0;
nullpo_ret(group);
- dissonance = skill->dance_switch(unit, 0);
+ dissonance = skill->dance_switch(su, 0);
//Necessary in case the group is deleted after calling on_place/on_out [Skotlex]
skill_id = group->skill_id;
//Target-type check.
- if( !(group->bl_flag&bl->type && battle->check_target(&unit->bl,bl,group->target_flag)>0) && (flag&4) ) {
- if( group->state.song_dance&0x1 || (group->src_id == bl->id && group->state.song_dance&0x2) )
+ if( !(group->bl_flag&bl->type && battle->check_target(&su->bl,bl,group->target_flag)>0) ) {
+ if( (flag&4) && ( group->state.song_dance&0x1 || (group->src_id == bl->id && group->state.song_dance&0x2) ) )
skill->unit_onleft(skill_id, bl, tick);//Ensemble check to terminate it.
} else {
if( flag&1 )
- skill->unit_onplace(unit,bl,tick);
+ skill->unit_onplace(su,bl,tick);
else
- skill->unit_onout(unit,bl,tick);
+ skill->unit_onout(su,bl,tick);
if( flag&4 )
skill->unit_onleft(skill_id, bl, tick);
}
- if( dissonance ) skill->dance_switch(unit, 1);
+ if( dissonance ) skill->dance_switch(su, 1);
return 0;
}
@@ -12026,8 +12428,7 @@ int skill_unit_effect (struct block_list* bl, va_list ap) {
/*==========================================
*
*------------------------------------------*/
-int skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl, int damage, unsigned int tick)
-{
+int skill_unit_ondamaged(struct skill_unit *src, struct block_list *bl, int64 damage, int64 tick) {
struct skill_unit_group *sg;
nullpo_ret(src);
@@ -12045,15 +12446,17 @@ int skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl, int dam
case UNT_TALKIEBOX:
case UNT_ANKLESNARE:
case UNT_ICEWALL:
- case UNT_REVERBERATION:
case UNT_WALLOFTHORN:
- src->val1-=damage;
+ src->val1 -= (int)cap_value(damage,INT_MIN,INT_MAX);
+ break;
+ case UNT_REVERBERATION:
+ src->val1--;
break;
default:
damage = 0;
break;
}
- return damage;
+ return (int)cap_value(damage,INT_MIN,INT_MAX);
}
/*==========================================
@@ -12095,8 +12498,8 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap) {
switch(skill_id) {
case PR_BENEDICTIO: {
- uint8 dir = iMap->calc_dir(&sd->bl,tsd->bl.x,tsd->bl.y);
- dir = (unit_getdir(&sd->bl) + dir)%8; //This adjusts dir to account for the direction the sd is facing.
+ uint8 dir = map->calc_dir(&sd->bl,tsd->bl.x,tsd->bl.y);
+ dir = (unit->getdir(&sd->bl) + dir)%8; //This adjusts dir to account for the direction the sd is facing.
if ((tsd->class_&MAPID_BASEMASK) == MAPID_ACOLYTE && (dir == 2 || dir == 6) //Must be standing to the left/right of Priest.
&& sd->status.sp >= 10)
p_sd[(*c)++]=tsd->bl.id;
@@ -12120,7 +12523,7 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap) {
default: //Warning: Assuming Ensemble Dance/Songs for code speed. [Skotlex]
{
uint16 skill_lv;
- if(pc_issit(tsd) || !unit_can_move(&tsd->bl))
+ if(pc_issit(tsd) || !unit->can_move(&tsd->bl))
return 0;
if (sd->status.sex != tsd->status.sex &&
(tsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER &&
@@ -12146,7 +12549,7 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap) {
/*==========================================
* Checks and stores partners for ensemble skills [Skotlex]
*------------------------------------------*/
-int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, short* skill_lv, int range, int cast_flag) {
+int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, uint16* skill_lv, int range, int cast_flag) {
static int c=0;
static int p_sd[2] = { 0, 0 };
int i;
@@ -12160,28 +12563,22 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, short*
switch (skill_id) {
case PR_BENEDICTIO:
for (i = 0; i < c; i++) {
- if ((tsd = iMap->id2sd(p_sd[i])) != NULL)
- status_charge(&tsd->bl, 0, 10);
+ if ((tsd = map->id2sd(p_sd[i])) != NULL)
+ status->charge(&tsd->bl, 0, 10);
}
return c;
case AB_ADORAMUS:
- if( c > 0 && (tsd = iMap->id2sd(p_sd[0])) != NULL ) {
+ if( c > 0 && (tsd = map->id2sd(p_sd[0])) != NULL ) {
i = 2 * (*skill_lv);
- status_charge(&tsd->bl, 0, i);
+ status->charge(&tsd->bl, 0, i);
}
break;
- case WM_GREAT_ECHO:
- for( i = 0; i < c; i++ ) {
- if( (tsd = iMap->id2sd(p_sd[i])) != NULL )
- status_zap(&tsd->bl,0,skill->get_sp(skill_id,*skill_lv)/c);
- }
- break;
default: //Warning: Assuming Ensemble skills here (for speed)
if( is_chorus )
break;//Chorus skills are not to be parsed as ensambles
- if (c > 0 && sd->sc.data[SC_DANCING] && (tsd = iMap->id2sd(p_sd[0])) != NULL) {
+ if (c > 0 && sd->sc.data[SC_DANCING] && (tsd = map->id2sd(p_sd[0])) != NULL) {
sd->sc.data[SC_DANCING]->val4 = tsd->bl.id;
- sc_start4(&tsd->bl,SC_DANCING,100,skill_id,sd->sc.data[SC_DANCING]->val2,*skill_lv,sd->bl.id,skill->get_time(skill_id,*skill_lv)+1000);
+ sc_start4(&tsd->bl,&tsd->bl,SC_DANCING,100,skill_id,sd->sc.data[SC_DANCING]->val2,*skill_lv,sd->bl.id,skill->get_time(skill_id,*skill_lv)+1000);
clif->skill_nodamage(&tsd->bl, &sd->bl, skill_id, *skill_lv, 1);
tsd->skill_id_dance = skill_id;
tsd->skill_lv_dance = *skill_lv;
@@ -12194,9 +12591,9 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, short*
c = 0;
memset (p_sd, 0, sizeof(p_sd));
if( is_chorus )
- i = party_foreachsamemap(skill->check_condition_char_sub,sd,AREA_SIZE,&sd->bl, &c, &p_sd, skill_id, *skill_lv);
+ i = party->foreachsamemap(skill->check_condition_char_sub,sd,AREA_SIZE,&sd->bl, &c, &p_sd, skill_id, *skill_lv);
else
- i = iMap->foreachinrange(skill->check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id);
+ i = map->foreachinrange(skill->check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id);
if ( skill_id != PR_BENEDICTIO && skill_id != AB_ADORAMUS && skill_id != WL_COMET ) //Apply the average lv to encore skills.
*skill_lv = (i+(*skill_lv))/(c+1); //I know c should be one, but this shows how it could be used for the average of n partners.
@@ -12207,15 +12604,15 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, short*
*
*------------------------------------------*/
int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap) {
- int *c,src_id,mob_class,skill;
+ int *c,src_id,mob_class,skill_id;
struct mob_data *md;
md=(struct mob_data*)bl;
src_id=va_arg(ap,int);
mob_class=va_arg(ap,int);
- skill=va_arg(ap,int);
+ skill_id=va_arg(ap,int);
c=va_arg(ap,int *);
- if( md->master_id != src_id || md->special_state.ai != (unsigned)(skill == AM_SPHEREMINE?2:skill == KO_ZANZOU?4:skill == MH_SUMMON_LEGION?1:3) )
+ if( md->master_id != src_id || md->special_state.ai != (unsigned)(skill_id == AM_SPHEREMINE?2:skill_id == KO_ZANZOU?4:skill_id == MH_SUMMON_LEGION?1:3) )
return 0; //Non alchemist summoned mobs have nothing to do here.
if(md->class_==mob_class)
(*c)++;
@@ -12239,11 +12636,39 @@ int skill_isammotype (struct map_session_data *sd, int skill_id)
);
}
+/**
+ * Checks whether a skill can be used in combos or not
+ **/
+bool skill_is_combo( int skill_id )
+{
+ switch( skill_id )
+ {
+ case MO_CHAINCOMBO:
+ case MO_COMBOFINISH:
+ case CH_TIGERFIST:
+ case CH_CHAINCRUSH:
+ case MO_EXTREMITYFIST:
+ case TK_TURNKICK:
+ case TK_STORMKICK:
+ case TK_DOWNKICK:
+ case TK_COUNTER:
+ case TK_JUMPKICK:
+ case HT_POWER:
+ case GC_COUNTERSLASH:
+ case GC_WEAPONCRUSH:
+ case SR_FALLENEMPIRE:
+ case SR_DRAGONCOMBO:
+ case SR_TIGERCANNON:
+ case SR_GATEOFHELL:
+ return true;
+ }
+ return false;
+}
+
int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) {
- struct status_data *status;
+ struct status_data *st;
struct status_change *sc;
struct skill_condition require;
- int i;
nullpo_ret(sd);
@@ -12276,7 +12701,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
break;
}
- status = &sd->battle_status;
+ st = &sd->battle_status;
sc = &sd->sc;
if( !sc->count )
sc = NULL;
@@ -12285,6 +12710,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if( sd->state.abra_flag ) // Hocus-Pocus was used. [Inkfish]
sd->state.abra_flag = 0;
else {
+ int i;
// When a target was selected, consume items that were skipped in pc_use_item [Skotlex]
if( (i = sd->itemindex) == -1 ||
sd->status.inventory[i].nameid != sd->itemid ||
@@ -12315,45 +12741,76 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
switch( skill_id ) { // Turn off check.
- case BS_MAXIMIZE: case NV_TRICKDEAD: case TF_HIDING: case AS_CLOAKING: case CR_AUTOGUARD:
- case ML_AUTOGUARD: case CR_DEFENDER: case ML_DEFENDER: case ST_CHASEWALK: case PA_GOSPEL:
- case CR_SHRINK: case TK_RUN: case GS_GATLINGFEVER: case TK_READYCOUNTER: case TK_READYDOWN:
- case TK_READYSTORM: case TK_READYTURN: case SG_FUSION: case RA_WUGDASH: case KO_YAMIKUMO:
- if( sc && sc->data[status_skill2sc(skill_id)] )
+ case BS_MAXIMIZE:
+ case NV_TRICKDEAD:
+ case TF_HIDING:
+ case AS_CLOAKING:
+ case CR_AUTOGUARD:
+ case ML_AUTOGUARD:
+ case CR_DEFENDER:
+ case ML_DEFENDER:
+ case ST_CHASEWALK:
+ case PA_GOSPEL:
+ case CR_SHRINK:
+ case TK_RUN:
+ case GS_GATLINGFEVER:
+ case TK_READYCOUNTER:
+ case TK_READYDOWN:
+ case TK_READYSTORM:
+ case TK_READYTURN:
+ case SG_FUSION:
+ case RA_WUGDASH:
+ case KO_YAMIKUMO:
+ if( sc && sc->data[status->skill2sc(skill_id)] )
return 1;
}
// Check the skills that can be used while mounted on a warg
if( pc_isridingwug(sd) ) {
switch( skill_id ) {
- case HT_SKIDTRAP: case HT_LANDMINE: case HT_ANKLESNARE: case HT_SHOCKWAVE:
- case HT_SANDMAN: case HT_FLASHER: case HT_FREEZINGTRAP: case HT_BLASTMINE:
- case HT_CLAYMORETRAP: case HT_SPRINGTRAP: case RA_DETONATOR: case RA_CLUSTERBOMB:
- case HT_TALKIEBOX: case RA_FIRINGTRAP: case RA_ICEBOUNDTRAP:
- case RA_WUGDASH: case RA_WUGRIDER: case RA_WUGSTRIKE:
+ // Hunter skills
+ case HT_SKIDTRAP:
+ case HT_LANDMINE:
+ case HT_ANKLESNARE:
+ case HT_SHOCKWAVE:
+ case HT_SANDMAN:
+ case HT_FLASHER:
+ case HT_FREEZINGTRAP:
+ case HT_BLASTMINE:
+ case HT_CLAYMORETRAP:
+ case HT_TALKIEBOX:
+ // Ranger skills
+ case RA_DETONATOR:
+ case RA_ELECTRICSHOCKER:
+ case RA_CLUSTERBOMB:
+ case RA_MAGENTATRAP:
+ case RA_COBALTTRAP:
+ case RA_MAIZETRAP:
+ case RA_VERDURETRAP:
+ case RA_FIRINGTRAP:
+ case RA_ICEBOUNDTRAP:
+ case RA_WUGDASH:
+ case RA_WUGRIDER:
+ case RA_WUGSTRIKE:
+ // Other
+ case BS_GREED:
break;
default: // in official there is no message.
return 0;
}
}
+
+ // Check the skills that can be used whiled using mado
if( pc_ismadogear(sd) ) {
- switch( skill_id ) { //None Mado skills are unusable when Mado is equipped. [Jobbie]
- case BS_REPAIRWEAPON: case WS_MELTDOWN:
- case BS_HAMMERFALL: case WS_CARTBOOST:
- case BS_ADRENALINE: case WS_WEAPONREFINE:
- case BS_WEAPONPERFECT: case WS_CARTTERMINATION:
- case BS_OVERTHRUST: case WS_OVERTHRUSTMAX:
- case BS_MAXIMIZE:
- case BS_ADRENALINE2:
- case BS_UNFAIRLYTRICK:
- case BS_GREED:
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR,0);
- return 0;
- default: //Only Mechanic exlcusive skill can be used.
- break;
+ if( !(skill_id > NC_MADOLICENCE && skill_id <= NC_DISJOINT)
+ && skill_id != NC_MAGMA_ERUPTION
+ && skill_id != BS_GREED ) {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR,0);
+ return 0;
}
}
+
if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL )
return 0;
@@ -12404,34 +12861,38 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
if(sc->data[SC_BLADESTOP])
break;
- if( (i=(sc && sc->data[SC_COMBOATTACK])) && sc->data[SC_COMBOATTACK]->val1 == MO_TRIPLEATTACK )
- break;
- if( i )
+ if( sc && sc->data[SC_COMBOATTACK] ) {
+ if( sc->data[SC_COMBOATTACK]->val1 == MO_TRIPLEATTACK )
+ break;
clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_TRIPLEATTACK);
+ }
return 0;
case MO_COMBOFINISH:
if(!sc)
return 0;
- if( (i=(sc && sc->data[SC_COMBOATTACK])) && sc->data[SC_COMBOATTACK]->val1 == MO_CHAINCOMBO )
- break;
- if( i )
+ if( sc && sc->data[SC_COMBOATTACK] ) {
+ if ( sc->data[SC_COMBOATTACK]->val1 == MO_CHAINCOMBO )
+ break;
clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_CHAINCOMBO);
+ }
return 0;
case CH_TIGERFIST:
if(!sc)
return 0;
- if( (i=(sc && sc->data[SC_COMBOATTACK])) && sc->data[SC_COMBOATTACK]->val1 == MO_COMBOFINISH )
- break;
- if( i )
+ if( sc && sc->data[SC_COMBOATTACK] ) {
+ if ( sc->data[SC_COMBOATTACK]->val1 == MO_COMBOFINISH )
+ break;
clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_COMBOFINISH);
+ }
return 0;
case CH_CHAINCRUSH:
if(!sc)
return 0;
- if( (i=(sc && sc->data[SC_COMBOATTACK])) && sc->data[SC_COMBOATTACK]->val1 == CH_TIGERFIST )
- break;
- if( i )
+ if( sc && sc->data[SC_COMBOATTACK] ) {
+ if( sc->data[SC_COMBOATTACK]->val1 == CH_TIGERFIST )
+ break;
clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, CH_TIGERFIST);
+ }
return 0;
case MO_EXTREMITYFIST:
// if(sc && sc->data[SC_EXTREMITYFIST]) //To disable Asura during the 5 min skill block uncomment this...
@@ -12449,7 +12910,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
}
- else if( !unit_can_move(&sd->bl) )
+ else if( !unit->can_move(&sd->bl) )
{ //Placed here as ST_MOVE_ENABLE should not apply if rooted or on a combo. [Skotlex]
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
@@ -12493,7 +12954,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
if(sc->data[SC_COMBOATTACK]->val1 != skill_id && !( sd && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )) { //Cancel combo wait.
- unit_cancel_combo(&sd->bl);
+ unit->cancel_combo(&sd->bl);
return 0;
}
break; //Combo ready.
@@ -12536,7 +12997,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
break;
case CG_HERMODE:
- if(!npc_check_areanpc(1,sd->bl.m,sd->bl.x,sd->bl.y,skill->get_splash(skill_id, skill_lv)))
+ if(!npc->check_areanpc(1,sd->bl.m,sd->bl.x,sd->bl.y,skill->get_splash(skill_id, skill_lv)))
{
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
@@ -12549,7 +13010,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
for (i=0;i<size*size;i++) {
x = sd->bl.x+(i%size-range);
y = sd->bl.y+(i/size-range);
- if (iMap->getcell(sd->bl.m,x,y,CELL_CHKWALL)) {
+ if (map->getcell(sd->bl.m,x,y,CELL_CHKWALL)) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
@@ -12579,8 +13040,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case SG_STAR_WARM:
if (sc && sc->data[SC_MIRACLE])
break;
- i = skill_id-SG_SUN_WARM;
- if (sd->bl.m == sd->feel_map[i].m)
+ if (sd->bl.m == sd->feel_map[skill_id-SG_SUN_WARM].m)
break;
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
@@ -12590,9 +13050,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case SG_STAR_COMFORT:
if (sc && sc->data[SC_MIRACLE])
break;
- i = skill_id-SG_SUN_COMFORT;
- if (sd->bl.m == sd->feel_map[i].m &&
- (battle_config.allow_skill_without_day || sg_info[i].day_func()))
+ if (sd->bl.m == sd->feel_map[skill_id-SG_SUN_COMFORT].m &&
+ (battle_config.allow_skill_without_day || pc->sg_info[skill_id-SG_SUN_COMFORT].day_func()))
break;
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
@@ -12601,9 +13060,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
break;
//Auron insists we should implement SP consumption when you are not Soul Linked. [Skotlex]
//Only invoke on skill begin cast (instant cast skill). [Kevin]
- if( require.sp > 0 )
- {
- if (status->sp < (unsigned int)require.sp)
+ if( require.sp > 0 ) {
+ if (st->sp < (unsigned int)require.sp)
clif->skill_fail(sd,skill_id,USESKILL_FAIL_SP_INSUFFICIENT,0);
else
status_zap(&sd->bl, 0, require.sp);
@@ -12631,9 +13089,9 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case NJ_ISSEN:
#ifdef RENEWAL
- if (status->hp < (status->hp/100)) {
+ if (st->hp < (st->hp/100)) {
#else
- if (status->hp < 2) {
+ if (st->hp < 2) {
#endif
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
@@ -12653,7 +13111,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
}
break;
case PF_HPCONVERSION:
- if (status->sp == status->max_sp)
+ if (st->sp == st->max_sp)
return 0; //Unusable when at full SP.
break;
case AM_CALLHOMUN: //Can't summon if a hom is already out
@@ -12662,7 +13120,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
break;
- case AM_REST: //Can't vapo homun if you don't have an active homunc or it's hp is < 80%
+ case AM_REST: //Can't vapo homun if you don't have an active homun or it's hp is < 80%
if (!homun_alive(sd->hd) || sd->hd->battle_status.hp < (sd->hd->battle_status.max_hp*80/100))
{
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
@@ -12674,7 +13132,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
**/
case AB_ANCILLA:
{
- int count = 0;
+ int count = 0, i;
for( i = 0; i < MAX_INVENTORY; i ++ )
if( sd->status.inventory[i].nameid == ITEMID_ANCILLA )
count += sd->status.inventory[i].amount;
@@ -12701,13 +13159,21 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
* Warlock
**/
case WL_COMET:
- if( skill->check_pc_partner(sd,skill_id,&skill_lv,1,0) <= 0 && ((i = pc->search_inventory(sd,require.itemid[0])) < 0 || sd->status.inventory[i].amount < require.amount[0]) )
- {
+ {
+ int idx;
+
+ if( !require.itemid[0] ) // issue: 7935
+ break;
+ if (skill->check_pc_partner(sd,skill_id,&skill_lv,1,0) <= 0
+ && ((idx = pc->search_inventory(sd,require.itemid[0])) == INDEX_NOT_FOUND
+ || sd->status.inventory[idx].amount < require.amount[0])
+ ) {
//clif->skill_fail(sd,skill_id,USESKILL_FAIL_NEED_ITEM,require.amount[0],require.itemid[0]);
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
break;
+ }
case WL_SUMMONFB:
case WL_SUMMONBL:
case WL_SUMMONWB:
@@ -12715,10 +13181,9 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case WL_TETRAVORTEX:
case WL_RELEASE:
{
- int x = SC_SUMMON1;
- i = 0;
- for(; x <= SC_SUMMON5; x++)
- if( sc && sc->data[x] )
+ int j, i = 0;
+ for(j = SC_SUMMON1; j <= SC_SUMMON5; j++)
+ if( sc && sc->data[j] )
i++;
switch(skill_id){
@@ -12729,8 +13194,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
}
break;
case WL_RELEASE:
- for(x = SC_SPELLBOOK7; x >= SC_SPELLBOOK1; x--)
- if( sc && sc->data[x] )
+ for(j = SC_SPELLBOOK7; j >= SC_SPELLBOOK1; j--)
+ if( sc && sc->data[j] )
i++;
if( i == 0 ){
clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON_NONE,0);
@@ -12803,13 +13268,6 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
break;
- case LG_RAGEBURST:
- if( sd->spiritball == 0 ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_SKILLINTERVAL,0);
- return 0;
- }
- sd->spiritball_old = require.spiritball = sd->spiritball;
- break;
case LG_RAYOFGENESIS:
if( sc && sc->data[SC_INSPIRATION] )
return 1; // Don't check for partner.
@@ -12826,12 +13284,11 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
}
break;
case SR_FALLENEMPIRE:
- if( !sc )
- return 0;
- if( (i=(sc && sc->data[SC_COMBOATTACK])) && sc->data[SC_COMBOATTACK]->val1 == SR_DRAGONCOMBO )
- break;
- if( i )
+ if( sc && sc->data[SC_COMBOATTACK] ) {
+ if( sc->data[SC_COMBOATTACK]->val1 == SR_DRAGONCOMBO )
+ break;
clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, SR_DRAGONCOMBO);
+ }
return 0;
case SR_CRESCENTELBOW:
if( sc && sc->data[SC_CRESCENTELBOW] ) {
@@ -12840,19 +13297,19 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
}
break;
case SR_CURSEDCIRCLE:
- if (map_flag_gvg(sd->bl.m)) {
- if (iMap->foreachinrange(mob_count_sub, &sd->bl, skill->get_splash(skill_id, skill_lv), BL_MOB,
- MOBID_EMPERIUM, MOBID_GUARIDAN_STONE1, MOBID_GUARIDAN_STONE2)) {
- char output[128];
- sprintf(output, "You're too close to a stone or emperium to do this skill");
- clif->colormes(sd->fd, COLOR_RED, output);
- return 0;
- }
+ if (map_flag_gvg2(sd->bl.m)) {
+ if (map->foreachinrange(mob->count_sub, &sd->bl, skill->get_splash(skill_id, skill_lv), BL_MOB,
+ MOBID_EMPERIUM, MOBID_GUARIDAN_STONE1, MOBID_GUARIDAN_STONE2)) {
+ char output[128];
+ sprintf(output, "You're too close to a stone or emperium to do this skill"); /* TODO official response? or message.conf it */
+ clif->colormes(sd->fd, COLOR_RED, output);
+ return 0;
+ }
}
if( sd->spiritball > 0 )
sd->spiritball_old = require.spiritball = sd->spiritball;
else {
- clif->skill_fail(sd,skill_id,0,0);
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
break;
@@ -12863,7 +13320,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case SC_MANHOLE:
case SC_DIMENSIONDOOR:
if( sc && sc->data[SC_MAGNETICFIELD] ) {
- clif->skill_fail(sd,skill_id,0,0);
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
break;
@@ -12877,11 +13334,17 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
require.sp -= require.sp * 20 * count / 100; // -20% each W/M in the party.
}
break;
+ case NC_PILEBUNKER:
+ if ( sd->equip_index[EQI_HAND_R] < 0 || sd->status.inventory[sd->equip_index[EQI_HAND_R]].nameid != ITEMID_PILEBUNCKER ) {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ return 0;
+ }
+ break;
case SO_FIREWALK:
case SO_ELECTRICWALK: // Can't be casted until you've walked all cells.
if( sc && sc->data[SC_PROPERTYWALK] &&
sc->data[SC_PROPERTYWALK]->val3 < skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) {
- clif->skill_fail(sd,skill_id,0x0,0);
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
break;
@@ -12897,9 +13360,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
break;
- case LG_REFLECTDAMAGE:
case CR_REFLECTSHIELD:
- if( sc && sc->data[SC_KYOMU] && rand()%100 < 5 * sc->data[SC_KYOMU]->val1 ){
+ if( sc && sc->data[SC_KYOMU] && rnd()%100 < 5 * sc->data[SC_KYOMU]->val1 ){
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
@@ -12918,11 +13380,14 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
break;
case KO_KAIHOU:
case KO_ZENKAI:
- ARR_FIND(1, 6, i, sd->charm[i] > 0);
+ {
+ int i;
+ ARR_FIND(1, 6, i, sd->charm[i] > 0); // FIXME: 4 or 6?
if( i > 4 ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0);
return 0;
}
+ }
break;
}
@@ -12994,9 +13459,9 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
break;
case ST_MOVE_ENABLE:
if (sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == skill_id)
- sd->ud.canmove_tick = iTimer->gettick(); //When using a combo, cancel the can't move delay to enable the skill. [Skotlex]
+ sd->ud.canmove_tick = timer->gettick(); //When using a combo, cancel the can't move delay to enable the skill. [Skotlex]
- if (!unit_can_move(&sd->bl)) {
+ if (!unit->can_move(&sd->bl)) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
@@ -13004,7 +13469,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case ST_WATER:
if (sc && (sc->data[SC_DELUGE] || sc->data[SC_NJ_SUITON]))
break;
- if (iMap->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER))
+ if (map->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER))
break;
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
@@ -13068,7 +13533,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
break;
}
- if(require.mhp > 0 && get_percentage(status->hp, status->max_hp) > require.mhp) {
+ if(require.mhp > 0 && get_percentage(st->hp, st->max_hp) > require.mhp) {
//mhp is the max-hp-requirement, that is,
//you must have this % or less of HP to cast it.
clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0);
@@ -13080,7 +13545,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
- if( require.sp > 0 && status->sp < (unsigned int)require.sp) {
+ if( require.sp > 0 && st->sp < (unsigned int)require.sp) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_SP_INSUFFICIENT,0);
return 0;
}
@@ -13095,37 +13560,18 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
- if( sd->sc.data[SC_COMBOATTACK] ) {
- switch( skill_id ) {
- case MO_CHAINCOMBO:
- case MO_COMBOFINISH:
- case CH_TIGERFIST:
- case CH_CHAINCRUSH:
- case MO_EXTREMITYFIST:
- case TK_TURNKICK:
- case TK_STORMKICK:
- case TK_DOWNKICK:
- case TK_COUNTER:
- case TK_JUMPKICK:
- case HT_POWER:
- case GC_COUNTERSLASH:
- case GC_WEAPONCRUSH:
- case SR_FALLENEMPIRE:
- case SR_DRAGONCOMBO:
- case SR_TIGERCANNON:
- case SR_GATEOFHELL:
- break;
- default: return 0;
- }
- }
+ // There's no need to check if the skill is part of a combo if it's
+ // already been checked before, see unit_skilluse_id2 [Panikon]
+ // Note that if this check is read part of issue:8047 will reappear!
+ //if( sd->sc.data[SC_COMBOATTACK] && !skill->is_combo(skill_id ) )
+ // return 0;
return 1;
}
-int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv)
-{
+int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) {
struct skill_condition require;
- struct status_data *status;
+ struct status_data *st;
int i;
int index[MAX_SKILL_ITEM_REQUIRE];
@@ -13186,10 +13632,11 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
int maxcount = (skill_id==AM_CANNIBALIZE)? 6-skill_lv : skill->get_maxcount(skill_id,skill_lv);
int mob_class = (skill_id==AM_CANNIBALIZE)? summons[skill_lv-1] :1142;
if(battle_config.land_skill_limit && maxcount>0 && (battle_config.land_skill_limit&BL_PC)) {
- i = iMap->foreachinmap(skill->check_condition_mob_master_sub ,sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill_id, &c);
- if(c >= maxcount ||
- (skill_id==AM_CANNIBALIZE && c != i && battle_config.summon_flora&2))
- { //Fails when: exceed max limit. There are other plant types already out.
+ i = map->foreachinmap(skill->check_condition_mob_master_sub ,sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill_id, &c);
+ if( c >= maxcount
+ || (skill_id==AM_CANNIBALIZE && c != i && battle_config.summon_flora&2)
+ ) {
+ //Fails when: exceed max limit. There are other plant types already out.
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
@@ -13207,9 +13654,9 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
if( battle_config.land_skill_limit && maxcount > 0 && ( battle_config.land_skill_limit&BL_PC ) ) {
if( skill_id == NC_MAGICDECOY ) {
for( j = mob_class; j <= 2046; j++ )
- iMap->foreachinmap(skill->check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, j, skill_id, &c);
+ map->foreachinmap(skill->check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, j, skill_id, &c);
} else
- iMap->foreachinmap(skill->check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill_id, &c);
+ map->foreachinmap(skill->check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill_id, &c);
if( c >= maxcount ) {
clif->skill_fail(sd , skill_id, USESKILL_FAIL_LEVEL, 0);
return 0;
@@ -13219,7 +13666,7 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
break;
case KO_ZANZOU: {
int c = 0;
- i = iMap->foreachinmap(skill->check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, 2308, skill_id, &c);
+ i = map->foreachinmap(skill->check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, 2308, skill_id, &c);
if( c >= skill->get_maxcount(skill_id,skill_lv) || c != i) {
clif->skill_fail(sd , skill_id, USESKILL_FAIL_LEVEL, 0);
return 0;
@@ -13228,11 +13675,11 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
break;
}
- status = &sd->battle_status;
+ st = &sd->battle_status;
require = skill->get_requirement(sd,skill_id,skill_lv);
- if( require.hp > 0 && status->hp <= (unsigned int)require.hp) {
+ if( require.hp > 0 && st->hp <= (unsigned int)require.hp) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0);
return 0;
}
@@ -13270,7 +13717,7 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
if( !require.itemid[i] )
continue;
index[i] = pc->search_inventory(sd,require.itemid[i]);
- if( index[i] < 0 || sd->status.inventory[index[i]].amount < require.amount[i] ) {
+ if (index[i] == INDEX_NOT_FOUND || sd->status.inventory[index[i]].amount < require.amount[i]) {
useskill_fail_cause cause = USESKILL_FAIL_NEED_ITEM;
switch( skill_id ){
case NC_SILVERSNIPER:
@@ -13363,7 +13810,7 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin
continue;
if( itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_WIZARD )
- continue; //Gemstones are checked, but not substracted from inventory.
+ continue; //Gemstones are checked, but not subtracted from inventory.
switch( skill_id ){
case SA_SEISMICWEAPON:
@@ -13387,7 +13834,7 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin
break;
}
- if( (n = pc->search_inventory(sd,req.itemid[i])) >= 0 )
+ if ((n = pc->search_inventory(sd,req.itemid[i])) != INDEX_NOT_FOUND)
pc->delitem(sd,n,req.amount[i],0,1,LOG_TYPE_CONSUME);
}
}
@@ -13395,10 +13842,9 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin
return 1;
}
-struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv)
-{
+struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) {
struct skill_condition req;
- struct status_data *status;
+ struct status_data *st;
struct status_change *sc;
int i,hp_rate,sp_rate, sp_skill_rate_bonus = 100;
uint16 idx;
@@ -13407,12 +13853,11 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
if( !sd )
return req;
- /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */
-#if 0
+#if 0 /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */
if( sd->state.abra_flag )
-#else
+#else // not 0
if( sd->skillitem == skill_id )
-#endif
+#endif // 0
return req; // Hocus-Pocus don't have requirements.
sc = &sd->sc;
@@ -13420,11 +13865,26 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
sc = NULL;
switch( skill_id ) { // Turn off check.
- case BS_MAXIMIZE: case NV_TRICKDEAD: case TF_HIDING: case AS_CLOAKING: case CR_AUTOGUARD:
- case ML_AUTOGUARD: case CR_DEFENDER: case ML_DEFENDER: case ST_CHASEWALK: case PA_GOSPEL:
- case CR_SHRINK: case TK_RUN: case GS_GATLINGFEVER: case TK_READYCOUNTER: case TK_READYDOWN:
- case TK_READYSTORM: case TK_READYTURN: case SG_FUSION: case KO_YAMIKUMO:
- if( sc && sc->data[status_skill2sc(skill_id)] )
+ case BS_MAXIMIZE:
+ case NV_TRICKDEAD:
+ case TF_HIDING:
+ case AS_CLOAKING:
+ case CR_AUTOGUARD:
+ case ML_AUTOGUARD:
+ case CR_DEFENDER:
+ case ML_DEFENDER:
+ case ST_CHASEWALK:
+ case PA_GOSPEL:
+ case CR_SHRINK:
+ case TK_RUN:
+ case GS_GATLINGFEVER:
+ case TK_READYCOUNTER:
+ case TK_READYDOWN:
+ case TK_READYSTORM:
+ case TK_READYTURN:
+ case SG_FUSION:
+ case KO_YAMIKUMO:
+ if( sc && sc->data[status->skill2sc(skill_id)] )
return req;
}
@@ -13434,23 +13894,23 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL )
return req;
- status = &sd->battle_status;
+ st = &sd->battle_status;
- req.hp = skill_db[idx].hp[skill_lv-1];
- hp_rate = skill_db[idx].hp_rate[skill_lv-1];
+ req.hp = skill->db[idx].hp[skill_lv-1];
+ hp_rate = skill->db[idx].hp_rate[skill_lv-1];
if(hp_rate > 0)
- req.hp += (status->hp * hp_rate)/100;
+ req.hp += (st->hp * hp_rate)/100;
else
- req.hp += (status->max_hp * (-hp_rate))/100;
+ req.hp += (st->max_hp * (-hp_rate))/100;
- req.sp = skill_db[idx].sp[skill_lv-1];
+ req.sp = skill->db[idx].sp[skill_lv-1];
if((sd->skill_id_old == BD_ENCORE) && skill_id == sd->skill_id_dance)
req.sp /= 2;
- sp_rate = skill_db[idx].sp_rate[skill_lv-1];
+ sp_rate = skill->db[idx].sp_rate[skill_lv-1];
if(sp_rate > 0)
- req.sp += (status->sp * sp_rate)/100;
+ req.sp += (st->sp * sp_rate)/100;
else
- req.sp += (status->max_sp * (-sp_rate))/100;
+ req.sp += (st->max_sp * (-sp_rate))/100;
if( sd->dsprate != 100 )
req.sp = req.sp * sd->dsprate / 100;
@@ -13467,29 +13927,29 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
if( sc->data[SC__LAZINESS] )
req.sp += req.sp + sc->data[SC__LAZINESS]->val1 * 10;
if( sc->data[SC_UNLIMITED_HUMMING_VOICE] )
- req.sp += req.sp * sc->data[SC_UNLIMITED_HUMMING_VOICE]->val2 / 100;
+ req.sp += req.sp * sc->data[SC_UNLIMITED_HUMMING_VOICE]->val3 / 100;
if( sc->data[SC_RECOGNIZEDSPELL] )
req.sp += req.sp / 4;
if( sc->data[SC_TELEKINESIS_INTENSE] && skill->get_ele(skill_id, skill_lv) == ELE_GHOST)
req.sp -= req.sp * sc->data[SC_TELEKINESIS_INTENSE]->val2 / 100;
}
- req.zeny = skill_db[idx].zeny[skill_lv-1];
+ req.zeny = skill->db[idx].zeny[skill_lv-1];
if( sc && sc->data[SC__UNLUCKY] )
req.zeny += sc->data[SC__UNLUCKY]->val1 * 500;
- req.spiritball = skill_db[idx].spiritball[skill_lv-1];
+ req.spiritball = skill->db[idx].spiritball[skill_lv-1];
- req.state = skill_db[idx].state;
+ req.state = skill->db[idx].state;
- req.mhp = skill_db[idx].mhp[skill_lv-1];
+ req.mhp = skill->db[idx].mhp[skill_lv-1];
- req.weapon = skill_db[idx].weapon;
+ req.weapon = skill->db[idx].weapon;
- req.ammo_qty = skill_db[idx].ammo_qty[skill_lv-1];
+ req.ammo_qty = skill->db[idx].ammo_qty[skill_lv-1];
if (req.ammo_qty)
- req.ammo = skill_db[idx].ammo;
+ req.ammo = skill->db[idx].ammo;
if (!req.ammo && skill_id && skill->isammotype(sd, skill_id)) {
//Assume this skill is using the weapon, therefore it requires arrows.
@@ -13515,11 +13975,11 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
continue;
break;
case AB_ADORAMUS:
- if( itemid_isgemstone(skill_db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 2) )
+ if( itemid_isgemstone(skill->db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 2) )
continue;
break;
case WL_COMET:
- if( itemid_isgemstone(skill_db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 0) )
+ if( itemid_isgemstone(skill->db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 0) )
continue;
break;
case GN_FIRE_EXPANSION:
@@ -13539,27 +13999,31 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
break;
}
- req.itemid[i] = skill_db[idx].itemid[i];
- req.amount[i] = skill_db[idx].amount[i];
+ req.itemid[i] = skill->db[idx].itemid[i];
+ req.amount[i] = skill->db[idx].amount[i];
if( itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN )
{
if( sd->special_state.no_gemstone )
- { //Make it substract 1 gem rather than skipping the cost.
- if( --req.amount[i] < 1 )
- req.itemid[i] = 0;
+ { // All gem skills except Hocus Pocus and Ganbantein can cast for free with Mistress card [helvetica]
+ if( skill_id != SA_ABRACADABRA )
+ req.itemid[i] = req.amount[i] = 0;
+ else if( --req.amount[i] < 1 )
+ req.amount[i] = 1; // Hocus Pocus always use at least 1 gem
}
if(sc && sc->data[SC_INTOABYSS])
{
if( skill_id != SA_ABRACADABRA )
req.itemid[i] = req.amount[i] = 0;
else if( --req.amount[i] < 1 )
- req.amount[i] = 1; // Hocus Pocus allways use at least 1 gem
+ req.amount[i] = 1; // Hocus Pocus always use at least 1 gem
}
}
if( skill_id >= HT_SKIDTRAP && skill_id <= HT_TALKIEBOX && pc->checkskill(sd, RA_RESEARCHTRAP) > 0){
- int16 itIndex;
- if( (itIndex = pc->search_inventory(sd,req.itemid[i])) < 0 || ( itIndex >= 0 && sd->status.inventory[itIndex].amount < req.amount[i] ) ){
+ int16 item_index;
+ if ((item_index = pc->search_inventory(sd,req.itemid[i])) == INDEX_NOT_FOUND
+ || sd->status.inventory[item_index].amount < req.amount[i]
+ ) {
req.itemid[i] = ITEMID_TRAP_ALLOY;
req.amount[i] = 1;
}
@@ -13579,10 +14043,26 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
case SO_FIRE_INSIGNIA:
case SO_WIND_INSIGNIA:
case SO_EARTH_INSIGNIA:
- req.itemid[skill_lv-1] = skill_db[idx].itemid[skill_lv-1];
- req.amount[skill_lv-1] = skill_db[idx].amount[skill_lv-1];
+ req.itemid[skill_lv-1] = skill->db[idx].itemid[skill_lv-1];
+ req.amount[skill_lv-1] = skill->db[idx].amount[skill_lv-1];
break;
}
+ if (skill_id == NC_REPAIR) {
+ switch(skill_lv) {
+ case 1:
+ case 2:
+ req.itemid[1] = ITEMID_REPAIR_A;
+ break;
+ case 3:
+ case 4:
+ req.itemid[1] = ITEMID_REPAIR_B;
+ break;
+ case 5:
+ req.itemid[1] = ITEMID_REPAIR_C;
+ break;
+ }
+ req.amount[1] = 1;
+ }
// Check for cost reductions due to skills & SCs
switch(skill_id) {
@@ -13656,10 +14136,14 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
case SO_SUMMON_AQUA:
case SO_SUMMON_VENTUS:
case SO_SUMMON_TERA:
- req.sp -= req.sp * (5 + 5 * pc->checkskill(sd,SO_EL_SYMPATHY)) / 100;
+ {
+ int spirit_sympathy = pc->checkskill(sd,SO_EL_SYMPATHY);
+ if (spirit_sympathy)
+ req.sp -= req.sp * (5 + 5 * spirit_sympathy) / 100;
+ }
break;
case SO_PSYCHIC_WAVE:
- if( sc && sc->data[SC_BLAST_OPTION] )
+ if( sc && (sc->data[SC_HEATER_OPTION] || sc->data[SC_COOLER_OPTION] || sc->data[SC_BLAST_OPTION] || sc->data[SC_CURSED_SOIL_OPTION] ))
req.sp += req.sp * 150 / 100;
break;
}
@@ -13720,9 +14204,8 @@ int skill_castfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
/*==========================================
* Does cast-time reductions based on sc data.
*------------------------------------------*/
-int skill_castfix_sc (struct block_list *bl, int time)
-{
- struct status_change *sc = status_get_sc(bl);
+int skill_castfix_sc (struct block_list *bl, int time) {
+ struct status_change *sc = status->get_sc(bl);
if( time < 0 )
return 0;
@@ -13733,8 +14216,8 @@ int skill_castfix_sc (struct block_list *bl, int time)
if (sc && sc->count) {
if (sc->data[SC_SLOWCAST])
time += time * sc->data[SC_SLOWCAST]->val2 / 100;
- if (sc->data[SC_NEEDLE_OF_PARALYZE])
- time += sc->data[SC_NEEDLE_OF_PARALYZE]->val3;
+ if (sc->data[SC_NEEDLE_OF_PARALYZE])
+ time += sc->data[SC_NEEDLE_OF_PARALYZE]->val3;
if (sc->data[SC_SUFFRAGIUM]) {
time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100;
status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER);
@@ -13749,15 +14232,14 @@ int skill_castfix_sc (struct block_list *bl, int time)
if (sc->data[SC_IZAYOI])
time -= time * 50 / 100;
}
- time = max(time, 0);
+ time = max(time, 0);
-// ShowInfo("Castime castfix_sc = %d\n",time);
+ //ShowInfo("Castime castfix_sc = %d\n",time);
return time;
}
+int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv) {
#ifdef RENEWAL_CAST
-int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv)
-{
- struct status_change *sc = status_get_sc(bl);
+ struct status_change *sc = status->get_sc(bl);
struct map_session_data *sd = BL_CAST(BL_PC,bl);
int fixed = skill->get_fixed_cast(skill_id, skill_lv), fixcast_r = 0, varcast_r = 0, i = 0;
@@ -13777,9 +14259,9 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16
if( sd->bonus.varcastrate < 0 )
VARCAST_REDUCTION(sd->bonus.varcastrate);
if( sd->bonus.add_varcast != 0 ) // bonus bVariableCast
- time += sd->bonus.add_varcast;
+ time += sd->bonus.add_varcast;
if( sd->bonus.add_fixcast != 0 ) // bonus bFixedCast
- fixed += sd->bonus.add_fixcast;
+ fixed += sd->bonus.add_fixcast;
for (i = 0; i < ARRAYLENGTH(sd->skillfixcast) && sd->skillfixcast[i].id; i++)
if (sd->skillfixcast[i].id == skill_id){ // bonus2 bSkillFixedCast
fixed += sd->skillfixcast[i].val;
@@ -13806,8 +14288,6 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16
if (sc && sc->count && !(skill->get_castnodex(skill_id, skill_lv)&2) ) {
// All variable cast additive bonuses must come first
- if (sc->data[SC_MAGICPOWER] )
- time += 700;
if (sc->data[SC_SLOWCAST])
VARCAST_REDUCTION(-sc->data[SC_SLOWCAST]->val2);
if (sc->data[SC_FROSTMISTY])
@@ -13848,13 +14328,15 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16
// Fixed cast reduction bonuses
if( sc->data[SC__LAZINESS] )
fixcast_r = max(fixcast_r, sc->data[SC__LAZINESS]->val2);
+ if( sc->data[SC_DANCE_WITH_WUG])
+ fixcast_r = max(fixcast_r, sc->data[SC_DANCE_WITH_WUG]->val4);
if( sc->data[SC_SECRAMENT] )
fixcast_r = max(fixcast_r, sc->data[SC_SECRAMENT]->val2);
- if( sd && ( skill_lv = pc->checkskill(sd, WL_RADIUS) ) && (skill_id >= WL_WHITEIMPRISON && skill_id < WL_FREEZE_SP) )
- fixcast_r = max(fixcast_r, (status_get_int(bl) + status_get_lv(bl)) / 15 + skill_lv * 5); // [{(Caster?s INT / 15) + (Caster?s Base Level / 15) + (Radius Skill Level x 5)}] %
+ if( sd && ( skill_lv = pc->checkskill(sd, WL_RADIUS) ) && (skill_id >= WL_WHITEIMPRISON && skill_id < WL_FREEZE_SP) )
+ fixcast_r = max(fixcast_r, (status_get_int(bl) + status->get_lv(bl)) / 15 + skill_lv * 5); // [{(Caster?s INT / 15) + (Caster?s Base Level / 15) + (Radius Skill Level x 5)}] %
// Fixed cast non percentage bonuses
if( sc->data[SC_MANDRAGORA] )
- fixed += sc->data[SC_MANDRAGORA]->val1 * 1000 / 2;
+ fixed += sc->data[SC_MANDRAGORA]->val1 * 500;
if( sc->data[SC_IZAYOI] )
fixed = 0;
if( sc->data[SC_GUST_OPTION] || sc->data[SC_BLAST_OPTION] || sc->data[SC_WILD_STORM_OPTION] )
@@ -13864,6 +14346,12 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16
if( sd && !(skill->get_castnodex(skill_id, skill_lv)&4) ){
VARCAST_REDUCTION( max(sd->bonus.varcastrate, 0) + max(i, 0) );
fixcast_r = max(fixcast_r, sd->bonus.fixcastrate) + min(sd->bonus.fixcastrate,0);
+ for( i = 0; i < ARRAYLENGTH(sd->skillcast) && sd->skillcast[i].id; i++ )
+ if( sd->skillcast[i].id == skill_id ){ // bonus2 bVariableCastrate
+ if( (i=sd->skillcast[i].val) > 0)
+ VARCAST_REDUCTION(i);
+ break;
+ }
}
if( varcast_r < 0 ) // now compute overall factors
@@ -13872,20 +14360,18 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16
time = (1 - sqrt( ((float)(status_get_dex(bl)*2 + status_get_int(bl)) / battle_config.vcast_stat_scale) )) * time;
// underflow checking/capping
time = max(time, 0) + (1 - (float)min(fixcast_r, 100) / 100) * max(fixed,0);
-
+#endif
return (int)time;
}
-#endif
/*==========================================
* Does delay reductions based on dex/agi, sc data, item bonuses, ...
*------------------------------------------*/
-int skill_delay_fix (struct block_list *bl, uint16 skill_id, uint16 skill_lv)
-{
+int skill_delay_fix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
int delaynodex = skill->get_delaynodex(skill_id, skill_lv);
int time = skill->get_delay(skill_id, skill_lv);
struct map_session_data *sd;
- struct status_change *sc = status_get_sc(bl);
+ struct status_change *sc = status->get_sc(bl);
nullpo_ret(bl);
sd = BL_CAST(BL_PC, bl);
@@ -13940,7 +14426,7 @@ int skill_delay_fix (struct block_list *bl, uint16 skill_id, uint16 skill_lv)
time /= 2;
break;
case AS_SONICBLOW:
- if (!map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && sc->data[SC_SOULLINK]->val2 == SL_ASSASIN)
+ if (!map_flag_gvg2(bl->m) && !map->list[bl->m].flag.battleground && sc->data[SC_SOULLINK]->val2 == SL_ASSASIN)
time /= 2;
break;
}
@@ -14092,22 +14578,21 @@ void skill_brandishspear_dir (struct square* tc, uint8 dir, int are) {
}
}
-void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag)
-{
+void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
int c,n=4;
- uint8 dir = iMap->calc_dir(src,bl->x,bl->y);
+ uint8 dir = map->calc_dir(src,bl->x,bl->y);
struct square tc;
int x=bl->x,y=bl->y;
skill->brandishspear_first(&tc,dir,x,y);
skill->brandishspear_dir(&tc,dir,4);
- skill_area_temp[1] = bl->id;
+ skill->area_temp[1] = bl->id;
if(skill_lv > 9){
for(c=1;c<4;c++){
- iMap->foreachincell(skill->area_sub,
- bl->m,tc.val1[c],tc.val2[c],BL_CHAR,
- src,skill_id,skill_lv,tick, flag|BCT_ENEMY|n,
- skill->castend_damage_id);
+ map->foreachincell(skill->area_sub,
+ bl->m,tc.val1[c],tc.val2[c],BL_CHAR,
+ src,skill_id,skill_lv,tick, flag|BCT_ENEMY|n,
+ skill->castend_damage_id);
}
}
if(skill_lv > 6){
@@ -14120,19 +14605,19 @@ void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 s
if(skill_lv > 3){
for(c=0;c<5;c++){
- iMap->foreachincell(skill->area_sub,
- bl->m,tc.val1[c],tc.val2[c],BL_CHAR,
- src,skill_id,skill_lv,tick, flag|BCT_ENEMY|n,
- skill->castend_damage_id);
- if(skill_lv > 6 && n==3 && c==4){
- skill_brandishspear_dir(&tc,dir,-1);
+ map->foreachincell(skill->area_sub,
+ bl->m,tc.val1[c],tc.val2[c],BL_CHAR,
+ src,skill_id,skill_lv,tick, flag|BCT_ENEMY|n,
+ skill->castend_damage_id);
+ if(skill_lv > 6 && n==3 && c==4) {
+ skill->brandishspear_dir(&tc,dir,-1);
n--;c=-1;
}
}
}
for(c=0;c<10;c++){
if(c==0||c==5) skill->brandishspear_dir(&tc,dir,-1);
- iMap->foreachincell(skill->area_sub,
+ map->foreachincell(skill->area_sub,
bl->m,tc.val1[c%5],tc.val2[c%5],BL_CHAR,
src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
skill->castend_damage_id);
@@ -14144,13 +14629,18 @@ void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 s
*------------------------------------------*/
void skill_repairweapon (struct map_session_data *sd, int idx) {
int material;
- int materials[4] = { 1002, 998, 999, 756 };
+ int materials[4] = {
+ ITEMID_IRON_ORE,
+ ITEMID_IRON,
+ ITEMID_STEEL,
+ ITEMID_ORIDECON_STONE,
+ };
struct item *item;
struct map_session_data *target_sd;
nullpo_retv(sd);
- if ( !( target_sd = iMap->id2sd(sd->menuskill_val) ) ) //Failed....
+ if ( !( target_sd = map->id2sd(sd->menuskill_val) ) ) //Failed....
return;
if( idx == 0xFFFF ) // No item selected ('Cancel' clicked)
@@ -14168,10 +14658,10 @@ void skill_repairweapon (struct map_session_data *sd, int idx) {
}
if ( target_sd->inventory_data[idx]->type == IT_WEAPON )
- material = materials [ target_sd->inventory_data[idx]->wlv - 1 ]; // Lv1/2/3/4 weapons consume 1 Iron Ore/Iron/Steel/Rough Oridecon
+ material = materials[ target_sd->inventory_data[idx]->wlv - 1 ]; // Lv1/2/3/4 weapons consume 1 Iron Ore/Iron/Steel/Rough Oridecon
else
- material = materials [2]; // Armors consume 1 Steel
- if ( pc->search_inventory(sd,material) < 0 ) {
+ material = materials[2]; // Armors consume 1 Steel
+ if (pc->search_inventory(sd,material) == INDEX_NOT_FOUND) {
clif->skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0);
return;
}
@@ -14218,7 +14708,13 @@ void skill_weaponrefine (struct map_session_data *sd, int idx)
if (idx >= 0 && idx < MAX_INVENTORY)
{
int i = 0, ep = 0, per;
- int material[5] = { 0, 1010, 1011, 984, 984 };
+ int material[5] = {
+ 0,
+ ITEMID_PHRACON,
+ ITEMID_EMVERETARCON,
+ ITEMID_ORIDECON,
+ ITEMID_ORIDECON,
+ };
struct item *item;
struct item_data *ditem = sd->inventory_data[idx];
item = &sd->status.inventory[idx];
@@ -14233,12 +14729,12 @@ void skill_weaponrefine (struct map_session_data *sd, int idx)
clif->upgrademessage(sd->fd, 2, item->nameid);
return;
}
- if( (i = pc->search_inventory(sd, material [ditem->wlv])) < 0 ){
- clif->upgrademessage(sd->fd, 3, material [ditem->wlv]);
+ if ((i = pc->search_inventory(sd, material[ditem->wlv])) == INDEX_NOT_FOUND) {
+ clif->upgrademessage(sd->fd, 3, material[ditem->wlv]);
return;
}
- per = status_get_refine_chance(ditem->wlv, (int)item->refine) * 10;
+ per = status->get_refine_chance(ditem->wlv, (int)item->refine) * 10;
// Aegis leaked formula. [malufett]
if( sd->status.class_ == JOB_MECHANIC_T )
@@ -14329,7 +14825,7 @@ int skill_autospell (struct map_session_data *sd, uint16 skill_id)
if(maxlv > lv)
maxlv = lv;
- sc_start4(&sd->bl,SC_AUTOSPELL,100,skill_lv,skill_id,maxlv,0,
+ sc_start4(&sd->bl,&sd->bl,SC_AUTOSPELL,100,skill_lv,skill_id,maxlv,0,
skill->get_time(SA_AUTOSPELL,skill_lv));
return 0;
}
@@ -14368,8 +14864,8 @@ int skill_sit_in (struct block_list *bl, va_list ap) {
if(type&2 && (pc->checkskill(sd,TK_HPTIME) > 0 || pc->checkskill(sd,TK_SPTIME) > 0 )) {
sd->state.rest=1;
- status_calc_regen(bl, &sd->battle_status, &sd->regen);
- status_calc_regen_rate(bl, &sd->regen, &sd->sc);
+ status->calc_regen(bl, &sd->battle_status, &sd->regen);
+ status->calc_regen_rate(bl, &sd->regen, &sd->sc);
}
return 0;
@@ -14383,8 +14879,8 @@ int skill_sit_out (struct block_list *bl, va_list ap) {
sd->state.gangsterparadise=0;
if(sd->state.rest && type&2) {
sd->state.rest=0;
- status_calc_regen(bl, &sd->battle_status, &sd->regen);
- status_calc_regen_rate(bl, &sd->regen, &sd->sc);
+ status->calc_regen(bl, &sd->battle_status, &sd->regen);
+ status->calc_regen_rate(bl, &sd->regen, &sd->sc);
}
return 0;
}
@@ -14418,11 +14914,11 @@ int skill_sit (struct map_session_data *sd, int type)
if (!flag) return 0;
if(type) {
- if (iMap->foreachinrange(skill->sit_count,&sd->bl, range, BL_PC, flag) > 1)
- iMap->foreachinrange(skill->sit_in,&sd->bl, range, BL_PC, flag);
+ if (map->foreachinrange(skill->sit_count,&sd->bl, range, BL_PC, flag) > 1)
+ map->foreachinrange(skill->sit_in,&sd->bl, range, BL_PC, flag);
} else {
- if (iMap->foreachinrange(skill->sit_count,&sd->bl, range, BL_PC, flag) < 2)
- iMap->foreachinrange(skill->sit_out,&sd->bl, range, BL_PC, flag);
+ if (map->foreachinrange(skill->sit_count,&sd->bl, range, BL_PC, flag) < 2)
+ map->foreachinrange(skill->sit_out,&sd->bl, range, BL_PC, flag);
}
return 0;
}
@@ -14430,10 +14926,10 @@ int skill_sit (struct map_session_data *sd, int type)
/*==========================================
*
*------------------------------------------*/
-int skill_frostjoke_scream (struct block_list *bl, va_list ap) {
+int skill_frostjoke_scream(struct block_list *bl, va_list ap) {
struct block_list *src;
uint16 skill_id,skill_lv;
- unsigned int tick;
+ int64 tick;
nullpo_ret(bl);
nullpo_ret(src=va_arg(ap,struct block_list*));
@@ -14441,9 +14937,9 @@ int skill_frostjoke_scream (struct block_list *bl, va_list ap) {
skill_id=va_arg(ap,int);
skill_lv=va_arg(ap,int);
if(!skill_lv) return 0;
- tick=va_arg(ap,unsigned int);
+ tick=va_arg(ap,int64);
- if (src == bl || status_isdead(bl))
+ if (src == bl || status->isdead(bl))
return 0;
if (bl->type == BL_PC) {
struct map_session_data *sd = (struct map_session_data *)bl;
@@ -14468,36 +14964,35 @@ void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint16 skill
for( y = src->bl.y - range; y <= src->bl.y + range; ++y )
for( x = src->bl.x - range; x <= src->bl.x + range; ++x )
- map[src->bl.m].setcell(src->bl.m, x, y, cell, flag);
+ map->list[src->bl.m].setcell(src->bl.m, x, y, cell, flag);
}
/*==========================================
*
*------------------------------------------*/
-int skill_attack_area (struct block_list *bl, va_list ap)
-{
+int skill_attack_area(struct block_list *bl, va_list ap) {
struct block_list *src,*dsrc;
int atk_type,skill_id,skill_lv,flag,type;
- unsigned int tick;
+ int64 tick;
- if(status_isdead(bl))
+ if(status->isdead(bl))
return 0;
atk_type = va_arg(ap,int);
- src=va_arg(ap,struct block_list*);
- dsrc=va_arg(ap,struct block_list*);
- skill_id=va_arg(ap,int);
- skill_lv=va_arg(ap,int);
- tick=va_arg(ap,unsigned int);
- flag=va_arg(ap,int);
- type=va_arg(ap,int);
+ src = va_arg(ap,struct block_list*);
+ dsrc = va_arg(ap,struct block_list*);
+ skill_id = va_arg(ap,int);
+ skill_lv = va_arg(ap,int);
+ tick = va_arg(ap,int64);
+ flag = va_arg(ap,int);
+ type = va_arg(ap,int);
- if (skill_area_temp[1] == bl->id) //This is the target of the skill, do a full attack and skip target checks.
+ if (skill->area_temp[1] == bl->id) //This is the target of the skill, do a full attack and skip target checks.
return skill->attack(atk_type,src,dsrc,bl,skill_id,skill_lv,tick,flag);
- if(battle->check_target(dsrc,bl,type) <= 0 ||
- !status_check_skilluse(NULL, bl, skill_id, 2))
+ if( battle->check_target(dsrc,bl,type) <= 0
+ || !status->check_skilluse(NULL, bl, skill_id, 2))
return 0;
@@ -14519,7 +15014,7 @@ int skill_attack_area (struct block_list *bl, va_list ap)
*------------------------------------------*/
int skill_clear_group (struct block_list *bl, int flag)
{
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
struct skill_unit_group *group[MAX_SKILLUNITGROUP];
int i, count=0;
@@ -14538,14 +15033,14 @@ int skill_clear_group (struct block_list *bl, int flag)
if (flag&1)
group[count++]= ud->skillunit[i];
break;
+ case SO_CLOUD_KILL:
+ if( flag&4 )
+ group[count++]= ud->skillunit[i];
+ break;
case SO_WARMER:
if( flag&8 )
group[count++]= ud->skillunit[i];
break;
- case SC_BLOODYLUST:
- if (flag & 32)
- group[count++] = ud->skillunit[i];
- break;
default:
if (flag&2 && skill->get_inf2(ud->skillunit[i]->skill_id)&INF2_TRAP)
group[count++]= ud->skillunit[i];
@@ -14562,7 +15057,7 @@ int skill_clear_group (struct block_list *bl, int flag)
* Returns the first element field found [Skotlex]
*------------------------------------------*/
struct skill_unit_group *skill_locate_element_field(struct block_list *bl) {
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
int i;
nullpo_ret(bl);
if (!ud) return NULL;
@@ -14574,8 +15069,8 @@ struct skill_unit_group *skill_locate_element_field(struct block_list *bl) {
case SA_VIOLENTGALE:
case SA_LANDPROTECTOR:
case NJ_SUITON:
+ case SO_CLOUD_KILL:
case SO_WARMER:
- case SC_BLOODYLUST:
return ud->skillunit[i];
}
}
@@ -14584,16 +15079,16 @@ struct skill_unit_group *skill_locate_element_field(struct block_list *bl) {
// for graffiti cleaner [Valaris]
int skill_graffitiremover (struct block_list *bl, va_list ap) {
- struct skill_unit *unit=NULL;
+ struct skill_unit *su=NULL;
nullpo_ret(bl);
nullpo_ret(ap);
- if(bl->type!=BL_SKILL || (unit=(struct skill_unit *)bl) == NULL)
+ if(bl->type!=BL_SKILL || (su=(struct skill_unit *)bl) == NULL)
return 0;
- if((unit->group) && (unit->group->unit_id == UNT_GRAFFITI))
- skill->delunit(unit);
+ if((su->group) && (su->group->unit_id == UNT_GRAFFITI))
+ skill->delunit(su);
return 0;
}
@@ -14612,9 +15107,8 @@ int skill_greed (struct block_list *bl, va_list ap) {
return 0;
}
//For Ranger's Detonator [Jobbie/3CeAM]
-int skill_detonator(struct block_list *bl, va_list ap)
-{
- struct skill_unit *unit=NULL;
+int skill_detonator(struct block_list *bl, va_list ap) {
+ struct skill_unit *su=NULL;
struct block_list *src;
int unit_id;
@@ -14622,14 +15116,14 @@ int skill_detonator(struct block_list *bl, va_list ap)
nullpo_ret(ap);
src = va_arg(ap,struct block_list *);
- if( bl->type != BL_SKILL || (unit = (struct skill_unit *)bl) == NULL || !unit->group )
+ if( bl->type != BL_SKILL || (su = (struct skill_unit *)bl) == NULL || !su->group )
return 0;
- if( unit->group->src_id != src->id )
+ if( su->group->src_id != src->id )
return 0;
- unit_id = unit->group->unit_id;
- switch( unit_id )
- { //List of Hunter and Ranger Traps that can be detonate.
+ unit_id = su->group->unit_id;
+ switch( unit_id ) {
+ //List of Hunter and Ranger Traps that can be detonate.
case UNT_BLASTMINE:
case UNT_SANDMAN:
case UNT_CLAYMORETRAP:
@@ -14637,16 +15131,23 @@ int skill_detonator(struct block_list *bl, va_list ap)
case UNT_CLUSTERBOMB:
case UNT_FIRINGTRAP:
case UNT_ICEBOUNDTRAP:
- if( unit_id == UNT_TALKIEBOX ) {
- clif->talkiebox(bl,unit->group->valstr);
- unit->group->val2 = -1;
- } else
- iMap->foreachinrange(skill->trap_splash,bl,skill->get_splash(unit->group->skill_id,unit->group->skill_lv),unit->group->bl_flag,bl,unit->group->tick);
-
- clif->changetraplook(bl,unit_id == UNT_FIRINGTRAP ? UNT_DUMMYSKILL : UNT_USED_TRAPS);
- unit->group->unit_id = UNT_USED_TRAPS;
- unit->group->limit = DIFF_TICK(iTimer->gettick(),unit->group->tick) +
- (unit_id == UNT_TALKIEBOX ? 5000 : (unit_id == UNT_CLUSTERBOMB || unit_id == UNT_ICEBOUNDTRAP? 2500 : 1500) );
+ switch(unit_id) {
+ case UNT_TALKIEBOX:
+ clif->talkiebox(bl,su->group->valstr);
+ su->group->val2 = -1;
+ break;
+ case UNT_CLAYMORETRAP:
+ case UNT_FIRINGTRAP:
+ case UNT_ICEBOUNDTRAP:
+ map->foreachinrange(skill->trap_splash,bl,skill->get_splash(su->group->skill_id,su->group->skill_lv),su->group->bl_flag|BL_SKILL|~BCT_SELF,bl,su->group->tick);
+ break;
+ default:
+ map->foreachinrange(skill->trap_splash,bl,skill->get_splash(su->group->skill_id,su->group->skill_lv),su->group->bl_flag,bl,su->group->tick);
+ }
+ clif->changetraplook(bl, UNT_USED_TRAPS);
+ su->group->limit = DIFF_TICK32(timer->gettick(),su->group->tick) +
+ (unit_id == UNT_TALKIEBOX ? 5000 : (unit_id == UNT_CLUSTERBOMB || unit_id == UNT_ICEBOUNDTRAP? 2500 : (unit_id == UNT_FIRINGTRAP ? 0 : 1500)) );
+ su->group->unit_id = UNT_USED_TRAPS;
break;
}
return 0;
@@ -14658,31 +15159,35 @@ int skill_detonator(struct block_list *bl, va_list ap)
int skill_cell_overlap(struct block_list *bl, va_list ap) {
uint16 skill_id;
int *alive;
- struct skill_unit *unit;
+ struct skill_unit *su;
skill_id = va_arg(ap,int);
alive = va_arg(ap,int *);
- unit = (struct skill_unit *)bl;
+ su = (struct skill_unit *)bl;
- if (unit == NULL || unit->group == NULL || (*alive) == 0)
+ if( su == NULL || su->group == NULL || (*alive) == 0 )
return 0;
-
+
+ if( su->group->state.guildaura ) /* guild auras are not canceled! */
+ return 0;
+
switch (skill_id) {
case SA_LANDPROTECTOR:
- if( unit->group->skill_id == SA_LANDPROTECTOR ) {//Check for offensive Land Protector to delete both. [Skotlex]
+ if( su->group->skill_id == SA_LANDPROTECTOR ) {//Check for offensive Land Protector to delete both. [Skotlex]
(*alive) = 0;
- skill->delunit(unit);
+ skill->delunit(su);
return 1;
}
- if( !(skill->get_inf2(unit->group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) || unit->group->skill_id == WZ_FIREPILLAR ) { //It deletes everything except songs/dances and traps
- skill->delunit(unit);
+ if( !(skill->get_inf2(su->group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) || su->group->skill_id == WZ_FIREPILLAR || su->group->skill_id == GN_HELLS_PLANT) { //It deletes everything except songs/dances and traps
+ skill->delunit(su);
return 1;
}
break;
case HW_GANBANTEIN:
case LG_EARTHDRIVE:
- if( !(unit->group->state.song_dance&0x1) ) {// Don't touch song/dance.
- skill->delunit(unit);
+ case GN_CRAZYWEED_ATK:
+ if( !(su->group->state.song_dance&0x1) ) {// Don't touch song/dance.
+ skill->delunit(su);
return 1;
}
break;
@@ -14692,14 +15197,13 @@ int skill_cell_overlap(struct block_list *bl, va_list ap) {
// The official implementation makes them fail to appear when casted on top of ANYTHING
// but I wonder if they didn't actually meant to fail when casted on top of each other?
// hence, I leave the alternate implementation here, commented. [Skotlex]
- if (unit->range <= 0)
- {
+ if (su->range <= 0) {
(*alive) = 0;
return 1;
}
/*
- switch (unit->group->skill_id)
- { //These cannot override each other.
+ switch (su->group->skill_id) {
+ //These cannot override each other.
case SA_VOLCANO:
case SA_DELUGE:
case SA_VIOLENTGALE:
@@ -14709,7 +15213,7 @@ int skill_cell_overlap(struct block_list *bl, va_list ap) {
*/
break;
case PF_FOGWALL:
- switch(unit->group->skill_id) {
+ switch(su->group->skill_id) {
case SA_VOLCANO: //Can't be placed on top of these
case SA_VIOLENTGALE:
(*alive) = 0;
@@ -14722,33 +15226,16 @@ int skill_cell_overlap(struct block_list *bl, va_list ap) {
}
break;
case HP_BASILICA:
- if (unit->group->skill_id == HP_BASILICA)
- { //Basilica can't be placed on top of itself to avoid map-cell stacking problems. [Skotlex]
+ if (su->group->skill_id == HP_BASILICA) {
+ //Basilica can't be placed on top of itself to avoid map-cell stacking problems. [Skotlex]
(*alive) = 0;
return 1;
}
break;
- case GN_CRAZYWEED_ATK:
- switch(unit->group->unit_id){ //TODO: look for other ground skills that are affected.
- case UNT_WALLOFTHORN:
- case UNT_THORNS_TRAP:
- case UNT_BLOODYLUST:
- case UNT_CHAOSPANIC:
- case UNT_MAELSTROM:
- case UNT_FIREPILLAR_ACTIVE:
- case UNT_LANDPROTECTOR:
- case UNT_VOLCANO:
- case UNT_DELUGE:
- case UNT_VIOLENTGALE:
- case UNT_SAFETYWALL:
- case UNT_PNEUMA:
- skill->delunit(unit);
- return 1;
- }
- break;
}
- if (unit->group->skill_id == SA_LANDPROTECTOR && !(skill->get_inf2(skill_id)&(INF2_SONG_DANCE|INF2_TRAP))) { //It deletes everything except songs/dances/traps
+ if (su->group->skill_id == SA_LANDPROTECTOR && !(skill->get_inf2(skill_id)&(INF2_SONG_DANCE|INF2_TRAP))) {
+ //It deletes everything except songs/dances/traps
(*alive) = 0;
return 1;
}
@@ -14762,7 +15249,7 @@ int skill_cell_overlap(struct block_list *bl, va_list ap) {
int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap)
{
struct mob_data* md;
- struct unit_data*ud = unit_bl2ud(bl);
+ struct unit_data*ud = unit->bl2ud(bl);
struct block_list *from_bl;
struct block_list *to_bl;
md = (struct mob_data*)bl;
@@ -14780,21 +15267,21 @@ int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap)
/*==========================================
*
*------------------------------------------*/
-int skill_trap_splash (struct block_list *bl, va_list ap) {
+int skill_trap_splash(struct block_list *bl, va_list ap) {
struct block_list *src;
- int tick;
- struct skill_unit *unit;
+ int64 tick;
+ struct skill_unit *src_su;
struct skill_unit_group *sg;
struct block_list *ss;
src = va_arg(ap,struct block_list *);
- unit = (struct skill_unit *)src;
- tick = va_arg(ap,int);
+ src_su = (struct skill_unit *)src;
+ tick = va_arg(ap,int64);
- if( !unit->alive || bl->prev == NULL )
+ if( !src_su->alive || bl->prev == NULL )
return 0;
- nullpo_ret(sg = unit->group);
- nullpo_ret(ss = iMap->id2bl(sg->src_id));
+ nullpo_ret(sg = src_su->group);
+ nullpo_ret(ss = map->id2bl(sg->src_id));
if(battle->check_target(src,bl,sg->target_flag) <= 0)
return 0;
@@ -14807,19 +15294,19 @@ int skill_trap_splash (struct block_list *bl, va_list ap) {
break;
case UNT_GROUNDDRIFT_WIND:
if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1))
- sc_start(bl,SC_STUN,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(src,bl,SC_STUN,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv));
break;
case UNT_GROUNDDRIFT_DARK:
if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1))
- sc_start(bl,SC_BLIND,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(src,bl,SC_BLIND,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv));
break;
case UNT_GROUNDDRIFT_POISON:
if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1))
- sc_start(bl,SC_POISON,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(src,bl,SC_POISON,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv));
break;
case UNT_GROUNDDRIFT_WATER:
if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1))
- sc_start(bl,SC_FREEZE,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(src,bl,SC_FREEZE,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv));
break;
case UNT_GROUNDDRIFT_FIRE:
if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1))
@@ -14828,23 +15315,51 @@ int skill_trap_splash (struct block_list *bl, va_list ap) {
case UNT_ELECTRICSHOCKER:
clif->skill_damage(src,bl,tick,0,0,-30000,1,sg->skill_id,sg->skill_lv,5);
break;
- case UNT_FIRINGTRAP:
- case UNT_ICEBOUNDTRAP:
- case UNT_CLUSTERBOMB:
- if( ss != bl )
- skill->attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1|SD_LEVEL);
- break;
case UNT_MAGENTATRAP:
case UNT_COBALTTRAP:
case UNT_MAIZETRAP:
case UNT_VERDURETRAP:
if( bl->type != BL_PC && !is_boss(bl) )
- sc_start2(bl,SC_ARMOR_PROPERTY,100,sg->skill_lv,skill->get_ele(sg->skill_id,sg->skill_lv),skill->get_time2(sg->skill_id,sg->skill_lv));
+ sc_start2(ss,bl,SC_ARMOR_PROPERTY,100,sg->skill_lv,skill->get_ele(sg->skill_id,sg->skill_lv),skill->get_time2(sg->skill_id,sg->skill_lv));
break;
case UNT_REVERBERATION:
- skill->addtimerskill(ss,tick+50,bl->id,0,0,WM_REVERBERATION_MELEE,sg->skill_lv,BF_WEAPON,0); // for proper skill delay animation when use with Dominion Impulse
- skill->addtimerskill(ss,tick+250,bl->id,0,0,WM_REVERBERATION_MAGIC,sg->skill_lv,BF_MAGIC,0);
+ if( battle->check_target(src,bl,BCT_ENEMY) > 0 ) {
+ skill->attack(BF_WEAPON,ss,src,bl,WM_REVERBERATION_MELEE,sg->skill_lv,tick,0);
+ skill->addtimerskill(ss,tick+200,bl->id,0,0,WM_REVERBERATION_MAGIC,sg->skill_lv,BF_MAGIC,SD_LEVEL);
+ }
break;
+ case UNT_FIRINGTRAP:
+ case UNT_ICEBOUNDTRAP:
+ if( src->id == bl->id ) break;
+ if( bl->type == BL_SKILL ){
+ struct skill_unit *su = (struct skill_unit *)bl;
+ if( su->group->unit_id == UNT_USED_TRAPS )
+ break;
+ }
+ case UNT_CLUSTERBOMB:
+ if( ss != bl )
+ skill->attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1|SD_LEVEL);
+ break;
+ case UNT_CLAYMORETRAP:
+ if( src->id == bl->id ) break;
+ if( bl->type == BL_SKILL ){
+ struct skill_unit *su = (struct skill_unit *)bl;
+ switch( su->group->unit_id ){
+ case UNT_CLAYMORETRAP:
+ case UNT_LANDMINE:
+ case UNT_BLASTMINE:
+ case UNT_SHOCKWAVE:
+ case UNT_SANDMAN:
+ case UNT_FLASHER:
+ case UNT_FREEZINGTRAP:
+ case UNT_FIRINGTRAP:
+ case UNT_ICEBOUNDTRAP:
+ clif->changetraplook(bl, UNT_USED_TRAPS);
+ su->group->limit = DIFF_TICK32(timer->gettick(),su->group->tick) + 1500;
+ su->group->unit_id = UNT_USED_TRAPS;
+ }
+ break;
+ }
default:
skill->attack(skill->get_type(sg->skill_id),ss,src,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
@@ -14855,13 +15370,12 @@ int skill_trap_splash (struct block_list *bl, va_list ap) {
/*==========================================
*
*------------------------------------------*/
-int skill_enchant_elemental_end (struct block_list *bl, int type)
-{
+int skill_enchant_elemental_end (struct block_list *bl, int type) {
struct status_change *sc;
- const enum sc_type scs[] = { SC_ENCHANTPOISON, SC_ASPERSIO, SC_PROPERTYFIRE, SC_PROPERTYWATER, SC_PROPERTYWIND, SC_PROPERTYGROUND, SC_PROPERTYDARK, SC_PROPERTYTELEKINESIS, SC_ENCHANTARMS, SC_EXEEDBREAK };
+ const enum sc_type scs[] = { SC_ENCHANTPOISON, SC_ASPERSIO, SC_PROPERTYFIRE, SC_PROPERTYWATER, SC_PROPERTYWIND, SC_PROPERTYGROUND, SC_PROPERTYDARK, SC_PROPERTYTELEKINESIS, SC_ENCHANTARMS };
int i;
nullpo_ret(bl);
- nullpo_ret(sc= status_get_sc(bl));
+ nullpo_ret(sc = status->get_sc(bl));
if (!sc->count) return 0;
@@ -14879,10 +15393,11 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce
bool wall = true;
if( (bl->type == BL_PC && battle_config.pc_cloak_check_type&1)
- || (bl->type != BL_PC && battle_config.monster_cloak_check_type&1) )
- { //Check for walls.
+ || (bl->type != BL_PC && battle_config.monster_cloak_check_type&1)
+ ) {
+ //Check for walls.
int i;
- ARR_FIND( 0, 8, i, iMap->getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 );
+ ARR_FIND( 0, 8, i, map->getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 );
if( i == 8 )
wall = false;
}
@@ -14905,6 +15420,36 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce
return wall;
}
+
+/**
+ * Verifies if an user can use SC_CLOAKING
+ **/
+bool skill_can_cloak(struct map_session_data *sd) {
+ nullpo_retr(false, sd);
+
+ //Avoid cloaking with no wall and low skill level. [Skotlex]
+ //Due to the cloaking card, we have to check the wall versus to known
+ //skill level rather than the used one. [Skotlex]
+ //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL))
+ if (pc->checkskill(sd, AS_CLOAKING) < 3 && !skill->check_cloaking(&sd->bl,NULL))
+ return false;
+
+ return true;
+}
+
+/**
+ * Verifies if an user can still be cloaked (AS_CLOAKING)
+ * Is called via map->foreachinrange when any kind of wall disapears
+ **/
+int skill_check_cloaking_end(struct block_list *bl, va_list ap) {
+ TBL_PC *sd = BL_CAST(BL_PC, bl);
+
+ if (sd && sd->sc.data[SC_CLOAKING] && !skill->can_cloak(sd))
+ status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
+
+ return 0;
+}
+
bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *sce)
{
static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1};
@@ -14913,7 +15458,7 @@ bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *s
if( bl->type == BL_PC ) { //Check for walls.
int i;
- ARR_FIND( 0, 8, i, iMap->getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 );
+ ARR_FIND( 0, 8, i, map->getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 );
if( i == 8 )
wall = false;
}
@@ -14932,126 +15477,162 @@ bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *s
return wall;
}
+bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit){
+ struct status_change *sc;
+ struct block_list *src;
+
+ nullpo_retr(false, bl);
+
+ sc = status->get_sc(bl);
+
+ if( sc && sc->data[SC__SHADOWFORM] && damage ) {
+ src = map->id2bl(sc->data[SC__SHADOWFORM]->val2);
+
+ if( !src || src->m != bl->m ) {
+ status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
+ return false;
+ }
+
+ if( src && (status->isdead(src) || !battle->check_target(bl,src,BCT_ENEMY)) ){
+ if( src->type == BL_PC )
+ ((TBL_PC*)src)->shadowform_id = 0;
+ status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
+ return false;
+ }
+
+ status->damage(bl, src, damage, 0, clif->damage(src, src, 500, 500, damage, hit, (hit > 1 ? 8 : 0), 0), 0);
+
+ /* because damage can cancel it */
+ if( sc->data[SC__SHADOWFORM] && (--sc->data[SC__SHADOWFORM]->val3) <= 0 ) {
+ status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
+ if( src->type == BL_PC )
+ ((TBL_PC*)src)->shadowform_id = 0;
+ }
+ return true;
+ }
+ return false;
+}
/*==========================================
*
*------------------------------------------*/
-struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2)
-{
- struct skill_unit *unit;
+struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2) {
+ struct skill_unit *su;
nullpo_retr(NULL, group);
nullpo_retr(NULL, group->unit); // crash-protection against poor coding
- nullpo_retr(NULL, unit=&group->unit[idx]);
+ nullpo_retr(NULL, su=&group->unit[idx]);
- if(!unit->alive)
+ if(!su->alive)
group->alive_count++;
- unit->bl.id=iMap->get_new_object_id();
- unit->bl.type=BL_SKILL;
- unit->bl.m=group->map;
- unit->bl.x=x;
- unit->bl.y=y;
- unit->group=group;
- unit->alive=1;
- unit->val1=val1;
- unit->val2=val2;
+ su->bl.id=map->get_new_object_id();
+ su->bl.type=BL_SKILL;
+ su->bl.m=group->map;
+ su->bl.x=x;
+ su->bl.y=y;
+ su->group=group;
+ su->alive=1;
+ su->val1=val1;
+ su->val2=val2;
- idb_put(skillunit_db, unit->bl.id, unit);
- iMap->addiddb(&unit->bl);
- iMap->addblock(&unit->bl);
+ idb_put(skill->unit_db, su->bl.id, su);
+ map->addiddb(&su->bl);
+ map->addblock(&su->bl);
// perform oninit actions
switch (group->skill_id) {
case WZ_ICEWALL:
- iMap->setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,5);
- clif->changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,5,AREA);
- skill->unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,true);
- map[unit->bl.m].icewall_num++;
+ map->setgatcell(su->bl.m,su->bl.x,su->bl.y,5);
+ clif->changemapcell(0,su->bl.m,su->bl.x,su->bl.y,5,AREA);
+ skill->unitsetmapcell(su,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,true);
+ map->list[su->bl.m].icewall_num++;
break;
case SA_LANDPROTECTOR:
- skill->unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,true);
+ skill->unitsetmapcell(su,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,true);
break;
case HP_BASILICA:
- skill->unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,true);
- break;
- case SC_MAELSTROM:
- skill->unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,true);
+ skill->unitsetmapcell(su,HP_BASILICA,group->skill_lv,CELL_BASILICA,true);
break;
default:
if (group->state.song_dance&0x1) //Check for dissonance.
- skill->dance_overlap(unit, 1);
+ skill->dance_overlap(su, 1);
break;
}
- clif->skill_setunit(unit);
+ clif->getareachar_skillunit(&su->bl,su,AREA);
- return unit;
+ return su;
}
/*==========================================
*
*------------------------------------------*/
-int skill_delunit (struct skill_unit* unit) {
+int skill_delunit (struct skill_unit* su) {
struct skill_unit_group *group;
- nullpo_ret(unit);
- if( !unit->alive )
+ nullpo_ret(su);
+ if( !su->alive )
return 0;
- unit->alive=0;
+ su->alive=0;
- nullpo_ret(group=unit->group);
+ nullpo_ret(group=su->group);
if( group->state.song_dance&0x1 ) //Cancel dissonance effect.
- skill->dance_overlap(unit, 0);
+ skill->dance_overlap(su, 0);
// invoke onout event
- if( !unit->range )
- iMap->foreachincell(skill->unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,iTimer->gettick(),4);
+ if( !su->range )
+ map->foreachincell(skill->unit_effect,su->bl.m,su->bl.x,su->bl.y,group->bl_flag,&su->bl,timer->gettick(),4);
// perform ondelete actions
switch (group->skill_id) {
- case HT_ANKLESNARE: {
- struct block_list* target = iMap->id2bl(group->val2);
- if( target )
- status_change_end(target, SC_ANKLESNARE, INVALID_TIMER);
- }
+ case HT_ANKLESNARE:
+ {
+ struct block_list* target = map->id2bl(group->val2);
+ if( target )
+ status_change_end(target, SC_ANKLESNARE, INVALID_TIMER);
+ }
break;
case WZ_ICEWALL:
- iMap->setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,unit->val2);
- clif->changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,ALL_SAMEMAP); // hack to avoid clientside cell bug
- skill->unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,false);
- map[unit->bl.m].icewall_num--;
+ map->setgatcell(su->bl.m,su->bl.x,su->bl.y,su->val2);
+ clif->changemapcell(0,su->bl.m,su->bl.x,su->bl.y,su->val2,ALL_SAMEMAP); // hack to avoid clientside cell bug
+ skill->unitsetmapcell(su,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,false);
+ map->list[su->bl.m].icewall_num--;
+ // AS_CLOAKING in low levels requires a wall to be cast, thus it needs to be
+ // checked again when a wall disapears! issue:8182 [Panikon]
+ map->foreachinarea(skill->check_cloaking_end, su->bl.m,
+ // Use 3x3 area to check for users near cell
+ su->bl.x - 1, su->bl.y - 1,
+ su->bl.x + 1, su->bl.x + 1,
+ BL_PC);
break;
case SA_LANDPROTECTOR:
- skill->unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,false);
+ skill->unitsetmapcell(su,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,false);
break;
case HP_BASILICA:
- skill->unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,false);
+ skill->unitsetmapcell(su,HP_BASILICA,group->skill_lv,CELL_BASILICA,false);
break;
case RA_ELECTRICSHOCKER: {
- struct block_list* target = iMap->id2bl(group->val2);
+ struct block_list* target = map->id2bl(group->val2);
if( target )
status_change_end(target, SC_ELECTRICSHOCKER, INVALID_TIMER);
}
break;
- case SC_MAELSTROM:
- skill->unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,false);
- break;
case SC_MANHOLE: // Note : Removing the unit don't remove the status (official info)
- if( group->val2 ) { // Someone Traped
- struct status_change *tsc = status_get_sc( iMap->id2bl(group->val2));
+ if( group->val2 ) { // Someone Trapped
+ struct status_change *tsc = status->get_sc(map->id2bl(group->val2));
if( tsc && tsc->data[SC__MANHOLE] )
tsc->data[SC__MANHOLE]->val4 = 0; // Remove the Unit ID
}
break;
}
- clif->skill_delunit(unit);
+ clif->skill_delunit(su);
- unit->group=NULL;
- iMap->delblock(&unit->bl); // don't free yet
- iMap->deliddb(&unit->bl);
- idb_remove(skillunit_db, unit->bl.id);
+ su->group=NULL;
+ map->delblock(&su->bl); // don't free yet
+ map->deliddb(&su->bl);
+ idb_remove(skill->unit_db, su->bl.id);
if(--group->alive_count==0)
skill->del_unitgroup(group,ALC_MARK);
@@ -15060,31 +15641,26 @@ int skill_delunit (struct skill_unit* unit) {
/*==========================================
*
*------------------------------------------*/
-static DBMap* group_db = NULL;// int group_id -> struct skill_unit_group*
-
/// Returns the target skill_unit_group or NULL if not found.
struct skill_unit_group* skill_id2group(int group_id)
{
- return (struct skill_unit_group*)idb_get(group_db, group_id);
+ return (struct skill_unit_group*)idb_get(skill->group_db, group_id);
}
-
-static int skill_unit_group_newid = MAX_SKILL_DB;
-
-/// Returns a new group_id that isn't being used in group_db.
+/// Returns a new group_id that isn't being used in skill->group_db.
/// Fatal error if nothing is available.
-static int skill_get_new_group_id(void)
+int skill_get_new_group_id(void)
{
- if( skill_unit_group_newid >= MAX_SKILL_DB && skill->id2group(skill_unit_group_newid) == NULL )
- return skill_unit_group_newid++;// available
+ if( skill->unit_group_newid >= MAX_SKILL_DB && skill->id2group(skill->unit_group_newid) == NULL )
+ return skill->unit_group_newid++;// available
{// find next id
- int base_id = skill_unit_group_newid;
- while( base_id != ++skill_unit_group_newid )
+ int base_id = skill->unit_group_newid;
+ while( base_id != ++skill->unit_group_newid )
{
- if( skill_unit_group_newid < MAX_SKILL_DB )
- skill_unit_group_newid = MAX_SKILL_DB;
- if( skill->id2group(skill_unit_group_newid) == NULL )
- return skill_unit_group_newid++;// available
+ if( skill->unit_group_newid < MAX_SKILL_DB )
+ skill->unit_group_newid = MAX_SKILL_DB;
+ if( skill->id2group(skill->unit_group_newid) == NULL )
+ return skill->unit_group_newid++;// available
}
// full loop, nothing available
ShowFatalError("skill_get_new_group_id: All ids are taken. Exiting...");
@@ -15094,7 +15670,7 @@ static int skill_get_new_group_id(void)
struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval)
{
- struct unit_data* ud = unit_bl2ud( src );
+ struct unit_data* ud = unit->bl2ud( src );
struct skill_unit_group* group;
int i;
@@ -15108,70 +15684,68 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count,
if(i == MAX_SKILLUNITGROUP) {
// array is full, make room by discarding oldest group
int j=0;
- unsigned maxdiff=0,x,tick=iTimer->gettick();
+ int64 maxdiff = 0, x, tick = timer->gettick();
for(i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++)
- if((x=DIFF_TICK(tick,ud->skillunit[i]->tick))>maxdiff){
- maxdiff=x;
- j=i;
+ if( (x=DIFF_TICK(tick,ud->skillunit[i]->tick)) > maxdiff ) {
+ maxdiff = x;
+ j = i;
}
skill->del_unitgroup(ud->skillunit[j],ALC_MARK);
//Since elements must have shifted, we use the last slot.
i = MAX_SKILLUNITGROUP-1;
}
- group = ers_alloc(skill_unit_ers, struct skill_unit_group);
- group->src_id = src->id;
- group->party_id = status_get_party_id(src);
- group->guild_id = status_get_guild_id(src);
- group->bg_id = bg_team_get_id(src);
- group->group_id = skill_get_new_group_id();
- group->unit = (struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
- group->unit_count = count;
+ group = ers_alloc(skill->unit_ers, struct skill_unit_group);
+ group->src_id = src->id;
+ group->party_id = status->get_party_id(src);
+ group->guild_id = status->get_guild_id(src);
+ group->bg_id = bg->team_get_id(src);
+ group->group_id = skill->get_new_group_id();
+ group->unit = (struct skill_unit *)aCalloc(count,sizeof(struct skill_unit));
+ group->unit_count = count;
group->alive_count = 0;
- group->val1 = 0;
- group->val2 = 0;
- group->val3 = 0;
- group->skill_id = skill_id;
- group->skill_lv = skill_lv;
- group->unit_id = unit_id;
- group->map = src->m;
- group->limit = limit;
- group->interval = interval;
- group->tick = iTimer->gettick();
- group->valstr = NULL;
+ group->val1 = 0;
+ group->val2 = 0;
+ group->val3 = 0;
+ group->skill_id = skill_id;
+ group->skill_lv = skill_lv;
+ group->unit_id = unit_id;
+ group->map = src->m;
+ group->limit = limit;
+ group->interval = interval;
+ group->tick = timer->gettick();
+ group->valstr = NULL;
ud->skillunit[i] = group;
if (skill_id == PR_SANCTUARY) //Sanctuary starts healing +1500ms after casted. [Skotlex]
group->tick += 1500;
- idb_put(group_db, group->group_id, group);
+ idb_put(skill->group_db, group->group_id, group);
return group;
}
/*==========================================
*
*------------------------------------------*/
-int skill_delunitgroup(struct skill_unit_group *group, const char* file, int line, const char* func)
-{
+int skill_delunitgroup(struct skill_unit_group *group, const char* file, int line, const char* func) {
struct block_list* src;
struct unit_data *ud;
int i,j;
- if( group == NULL )
- {
+ if( group == NULL ) {
ShowDebug("skill_delunitgroup: group is NULL (source=%s:%d, %s)! Please report this! (#3504)\n", file, line, func);
return 0;
}
- src=iMap->id2bl(group->src_id);
- ud = unit_bl2ud(src);
+ src=map->id2bl(group->src_id);
+ ud = unit->bl2ud(src);
if(!src || !ud) {
ShowError("skill_delunitgroup: Group's source not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id);
return 0;
}
- if( !status_isdead(src) && ((TBL_PC*)src)->state.warping && !((TBL_PC*)src)->state.changemap ) {
+ if( !status->isdead(src) && ((TBL_PC*)src)->state.warping && !((TBL_PC*)src)->state.changemap ) {
switch( group->skill_id ) {
case BA_DISSONANCE:
case BA_POEMBRAGI:
@@ -15188,12 +15762,11 @@ int skill_delunitgroup(struct skill_unit_group *group, const char* file, int lin
}
}
- if (skill->get_unit_flag(group->skill_id)&(UF_DANCE|UF_SONG|UF_ENSEMBLE))
- {
- struct status_change* sc = status_get_sc(src);
+ if (skill->get_unit_flag(group->skill_id)&(UF_DANCE|UF_SONG|UF_ENSEMBLE)) {
+ struct status_change* sc = status->get_sc(src);
if (sc && sc->data[SC_DANCING])
{
- sc->data[SC_DANCING]->val2 = 0 ; //This prevents status_change_end attempting to redelete the group. [Skotlex]
+ sc->data[SC_DANCING]->val2 = 0 ; //This prevents status_change_end attempting to re-delete the group. [Skotlex]
status_change_end(src, SC_DANCING, INVALID_TIMER);
}
}
@@ -15201,7 +15774,7 @@ int skill_delunitgroup(struct skill_unit_group *group, const char* file, int lin
// end Gospel's status change on 'src'
// (needs to be done when the group is deleted by other means than skill deactivation)
if (group->unit_id == UNT_GOSPEL) {
- struct status_change *sc = status_get_sc(src);
+ struct status_change *sc = status->get_sc(src);
if(sc && sc->data[SC_GOSPEL]) {
sc->data[SC_GOSPEL]->val3 = 0; //Remove reference to this group. [Skotlex]
status_change_end(src, SC_GOSPEL, INVALID_TIMER);
@@ -15212,40 +15785,40 @@ int skill_delunitgroup(struct skill_unit_group *group, const char* file, int lin
case SG_SUN_WARM:
case SG_MOON_WARM:
case SG_STAR_WARM:
- {
- struct status_change *sc = NULL;
- if( (sc = status_get_sc(src)) != NULL && sc->data[SC_WARM] ) {
- sc->data[SC_WARM]->val4 = 0;
- status_change_end(src, SC_WARM, INVALID_TIMER);
- }
+ {
+ struct status_change *sc = NULL;
+ if( (sc = status->get_sc(src)) != NULL && sc->data[SC_WARM] ) {
+ sc->data[SC_WARM]->val4 = 0;
+ status_change_end(src, SC_WARM, INVALID_TIMER);
}
+ }
break;
case NC_NEUTRALBARRIER:
- {
- struct status_change *sc = NULL;
- if( (sc = status_get_sc(src)) != NULL && sc->data[SC_NEUTRALBARRIER_MASTER] ) {
- sc->data[SC_NEUTRALBARRIER_MASTER]->val2 = 0;
- status_change_end(src,SC_NEUTRALBARRIER_MASTER,INVALID_TIMER);
- }
+ {
+ struct status_change *sc = NULL;
+ if( (sc = status->get_sc(src)) != NULL && sc->data[SC_NEUTRALBARRIER_MASTER] ) {
+ sc->data[SC_NEUTRALBARRIER_MASTER]->val2 = 0;
+ status_change_end(src,SC_NEUTRALBARRIER_MASTER,INVALID_TIMER);
}
+ }
break;
case NC_STEALTHFIELD:
- {
- struct status_change *sc = NULL;
- if( (sc = status_get_sc(src)) != NULL && sc->data[SC_STEALTHFIELD_MASTER] ) {
- sc->data[SC_STEALTHFIELD_MASTER]->val2 = 0;
- status_change_end(src,SC_STEALTHFIELD_MASTER,INVALID_TIMER);
- }
+ {
+ struct status_change *sc = NULL;
+ if( (sc = status->get_sc(src)) != NULL && sc->data[SC_STEALTHFIELD_MASTER] ) {
+ sc->data[SC_STEALTHFIELD_MASTER]->val2 = 0;
+ status_change_end(src,SC_STEALTHFIELD_MASTER,INVALID_TIMER);
}
+ }
break;
case LG_BANDING:
- {
- struct status_change *sc = NULL;
- if( (sc = status_get_sc(src)) && sc->data[SC_BANDING] ) {
- sc->data[SC_BANDING]->val4 = 0;
- status_change_end(src,SC_BANDING,INVALID_TIMER);
- }
+ {
+ struct status_change *sc = NULL;
+ if( (sc = status->get_sc(src)) && sc->data[SC_BANDING] ) {
+ sc->data[SC_BANDING]->val4 = 0;
+ status_change_end(src,SC_BANDING,INVALID_TIMER);
}
+ }
break;
}
@@ -15265,8 +15838,8 @@ int skill_delunitgroup(struct skill_unit_group *group, const char* file, int lin
group->valstr = NULL;
}
- idb_remove(group_db, group->group_id);
- iMap->freeblock(&group->unit->bl); // schedules deallocation of whole array (HACK)
+ idb_remove(skill->group_db, group->group_id);
+ map->freeblock(&group->unit->bl); // schedules deallocation of whole array (HACK)
group->unit=NULL;
group->group_id=0;
group->unit_count=0;
@@ -15277,7 +15850,7 @@ int skill_delunitgroup(struct skill_unit_group *group, const char* file, int lin
if( i < MAX_SKILLUNITGROUP ) {
ud->skillunit[i] = ud->skillunit[j];
ud->skillunit[j] = NULL;
- ers_free(skill_unit_ers, group);
+ ers_free(skill->unit_ers, group);
} else
ShowError("skill_delunitgroup: Group not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id);
@@ -15289,7 +15862,7 @@ int skill_delunitgroup(struct skill_unit_group *group, const char* file, int lin
*------------------------------------------*/
int skill_clear_unitgroup (struct block_list *src)
{
- struct unit_data *ud = unit_bl2ud(src);
+ struct unit_data *ud = unit->bl2ud(src);
nullpo_ret(ud);
@@ -15302,7 +15875,7 @@ int skill_clear_unitgroup (struct block_list *src)
/*==========================================
*
*------------------------------------------*/
-struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_list *bl, struct skill_unit_group *group, int tick) {
+struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl, struct skill_unit_group *group, int64 tick) {
int i,j=-1,k,s,id;
struct unit_data *ud;
struct skill_unit_group_tickset *set;
@@ -15311,7 +15884,7 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_lis
if (group->interval==-1)
return NULL;
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
if (!ud) return NULL;
set = ud->skillunittick;
@@ -15342,23 +15915,23 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_lis
/*==========================================
*
*------------------------------------------*/
-int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) {
- struct skill_unit* unit = va_arg(ap,struct skill_unit *);
- struct skill_unit_group* group = unit->group;
- unsigned int tick = va_arg(ap,unsigned int);
+int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap) {
+ struct skill_unit* su = va_arg(ap,struct skill_unit *);
+ struct skill_unit_group* group = su->group;
+ int64 tick = va_arg(ap,int64);
- if( !unit->alive || bl->prev == NULL )
+ if( !su->alive || bl->prev == NULL )
return 0;
nullpo_ret(group);
- if( !(skill->get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && iMap->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) )
+ if( !(skill->get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) )
return 0; //AoE skills are ineffective. [Skotlex]
- if( battle->check_target(&unit->bl,bl,group->target_flag) <= 0 )
+ if( battle->check_target(&su->bl,bl,group->target_flag) <= 0 )
return 0;
- skill->unit_onplace_timer(unit,bl,tick);
+ skill->unit_onplace_timer(su,bl,tick);
return 1;
}
@@ -15367,22 +15940,21 @@ int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) {
* @see DBApply
*/
int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) {
- struct skill_unit* unit = DB->data2ptr(data);
- struct skill_unit_group* group = unit->group;
- unsigned int tick = va_arg(ap,unsigned int);
+ struct skill_unit* su = DB->data2ptr(data);
+ struct skill_unit_group* group = su->group;
+ int64 tick = va_arg(ap,int64);
bool dissonance;
- struct block_list* bl = &unit->bl;
+ struct block_list* bl = &su->bl;
- if( !unit->alive )
+ if( !su->alive )
return 0;
nullpo_ret(group);
// check for expiration
- if( !group->state.guildaura && (DIFF_TICK(tick,group->tick) >= group->limit || DIFF_TICK(tick,group->tick) >= unit->limit) )
- {// skill unit expired (inlined from skill_unit_onlimit())
- switch( group->unit_id )
- {
+ if( !group->state.guildaura && (DIFF_TICK(tick,group->tick) >= group->limit || DIFF_TICK(tick,group->tick) >= su->limit) ) {
+ // skill unit expired (inlined from skill_unit_onlimit())
+ switch( group->unit_id ) {
case UNT_BLASTMINE:
#ifdef RENEWAL
case UNT_CLAYMORETRAP:
@@ -15394,15 +15966,15 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) {
case UNT_GROUNDDRIFT_FIRE:
group->unit_id = UNT_USED_TRAPS;
//clif->changetraplook(bl, UNT_FIREPILLAR_ACTIVE);
- group->limit=DIFF_TICK(tick+1500,group->tick);
- unit->limit=DIFF_TICK(tick+1500,group->tick);
+ group->limit=DIFF_TICK32(tick+1500,group->tick);
+ su->limit=DIFF_TICK32(tick+1500,group->tick);
break;
case UNT_ANKLESNARE:
case UNT_ELECTRICSHOCKER:
- if( group->val2 > 0 ) {
+ if( group->val2 > 0 || group->val3 == SC_ESCAPE ) {
// Used Trap don't returns back to item
- skill->delunit(unit);
+ skill->delunit(su);
break;
}
case UNT_SKIDTRAP:
@@ -15425,93 +15997,94 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) {
{
struct block_list* src;
- if( unit->val1 > 0 && (src = iMap->id2bl(group->src_id)) != NULL && src->type == BL_PC )
- { // revert unit back into a trap
+ if( su->val1 > 0 && (src = map->id2bl(group->src_id)) != NULL && src->type == BL_PC ) {
+ // revert unit back into a trap
struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = group->item_id?group->item_id:ITEMID_TRAP;
item_tmp.identify = 1;
- iMap->addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0);
+ map->addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0);
}
- skill->delunit(unit);
+ skill->delunit(su);
}
break;
case UNT_WARP_ACTIVE:
// warp portal opens (morph to a UNT_WARP_WAITING cell)
group->unit_id = skill->get_unit_id(group->skill_id, 1); // UNT_WARP_WAITING
- clif->changelook(&unit->bl, LOOK_BASE, group->unit_id);
+ clif->changelook(&su->bl, LOOK_BASE, group->unit_id);
// restart timers
group->limit = skill->get_time(group->skill_id,group->skill_lv);
- unit->limit = skill->get_time(group->skill_id,group->skill_lv);
+ su->limit = skill->get_time(group->skill_id,group->skill_lv);
// apply effect to all units standing on it
- iMap->foreachincell(skill->unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,iTimer->gettick(),1);
+ map->foreachincell(skill->unit_effect,su->bl.m,su->bl.x,su->bl.y,group->bl_flag,&su->bl,timer->gettick(),1);
break;
case UNT_CALLFAMILY:
{
struct map_session_data *sd = NULL;
if(group->val1) {
- sd = iMap->charid2sd(group->val1);
+ sd = map->charid2sd(group->val1);
group->val1 = 0;
- if (sd && !map[sd->bl.m].flag.nowarp)
- pc->setpos(sd,map_id2index(unit->bl.m),unit->bl.x,unit->bl.y,CLR_TELEPORT);
+ if (sd && !map->list[sd->bl.m].flag.nowarp)
+ pc->setpos(sd,map_id2index(su->bl.m),su->bl.x,su->bl.y,CLR_TELEPORT);
}
if(group->val2) {
- sd = iMap->charid2sd(group->val2);
+ sd = map->charid2sd(group->val2);
group->val2 = 0;
- if (sd && !map[sd->bl.m].flag.nowarp)
- pc->setpos(sd,map_id2index(unit->bl.m),unit->bl.x,unit->bl.y,CLR_TELEPORT);
+ if (sd && !map->list[sd->bl.m].flag.nowarp)
+ pc->setpos(sd,map_id2index(su->bl.m),su->bl.x,su->bl.y,CLR_TELEPORT);
}
- skill->delunit(unit);
+ skill->delunit(su);
}
break;
case UNT_REVERBERATION:
- if( unit->val1 <= 0 ) { // If it was deactivated.
- skill->delunit(unit);
+ if( su->val1 <= 0 ) { // If it was deactivated.
+ skill->delunit(su);
break;
}
clif->changetraplook(bl,UNT_USED_TRAPS);
- iMap->foreachinrange(skill->trap_splash, bl, skill->get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick);
- group->limit = DIFF_TICK(tick,group->tick)+1000;
- unit->limit = DIFF_TICK(tick,group->tick)+1000;
+ map->foreachinrange(skill->trap_splash, bl, skill->get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick);
+ group->limit = DIFF_TICK32(tick,group->tick)+1500;
+ su->limit = DIFF_TICK32(tick,group->tick)+1500;
group->unit_id = UNT_USED_TRAPS;
break;
case UNT_FEINTBOMB: {
- struct block_list *src = iMap->id2bl(group->src_id);
- if( src )
- iMap->foreachinrange(skill->area_sub, &group->unit->bl, unit->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill->castend_damage_id);
- skill->delunit(unit);
+ struct block_list *src = map->id2bl(group->src_id);
+ if( src ) {
+ map->foreachinrange(skill->area_sub, &group->unit->bl, su->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill->castend_damage_id);
+ status_change_end(src, SC__FEINTBOMB_MASTER, INVALID_TIMER);
+ }
+ skill->delunit(su);
break;
}
case UNT_BANDING:
{
- struct block_list *src = iMap->id2bl(group->src_id);
+ struct block_list *src = map->id2bl(group->src_id);
struct status_change *sc;
- if( !src || (sc = status_get_sc(src)) == NULL || !sc->data[SC_BANDING] )
- {
- skill->delunit(unit);
+ if( !src || (sc = status->get_sc(src)) == NULL || !sc->data[SC_BANDING] ) {
+ skill->delunit(su);
break;
}
// This unit isn't removed while SC_BANDING is active.
- group->limit = DIFF_TICK(tick+group->interval,group->tick);
- unit->limit = DIFF_TICK(tick+group->interval,group->tick);
+ group->limit = DIFF_TICK32(tick+group->interval,group->tick);
+ su->limit = DIFF_TICK32(tick+group->interval,group->tick);
}
break;
default:
- skill->delunit(unit);
+ skill->delunit(su);
}
} else {// skill unit is still active
switch( group->unit_id ) {
case UNT_ICEWALL:
// icewall loses 50 hp every second
- unit->val1 -= SKILLUNITTIMER_INTERVAL/20; // trap's hp
- if( unit->val1 <= 0 && unit->limit + group->tick > tick + 700 )
- unit->limit = DIFF_TICK(tick+700,group->tick);
+ su->val1 -= SKILLUNITTIMER_INTERVAL/20; // trap's hp
+ if( su->val1 <= 0 && su->limit + group->tick > tick + 700 )
+ su->limit = DIFF_TICK32(tick+700,group->tick);
break;
case UNT_BLASTMINE:
case UNT_SKIDTRAP:
@@ -15523,51 +16096,45 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) {
case UNT_FREEZINGTRAP:
case UNT_TALKIEBOX:
case UNT_ANKLESNARE:
- if( unit->val1 <= 0 ) {
+ if( su->val1 <= 0 ) {
if( group->unit_id == UNT_ANKLESNARE && group->val2 > 0 )
- skill->delunit(unit);
+ skill->delunit(su);
else {
clif->changetraplook(bl, group->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS);
- group->limit = DIFF_TICK(tick, group->tick) + 1500;
+ group->limit = DIFF_TICK32(tick, group->tick) + 1500;
group->unit_id = UNT_USED_TRAPS;
}
}
break;
case UNT_REVERBERATION:
- if( unit->val1 <= 0 ){
- clif->changetraplook(bl,UNT_USED_TRAPS);
- iMap->foreachinrange(skill->trap_splash, bl, skill->get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick);
- group->limit = DIFF_TICK(tick,group->tick)+1000;
- unit->limit = DIFF_TICK(tick,group->tick)+1000;
- group->unit_id = UNT_USED_TRAPS;
- }
+ if( su->val1 <= 0 )
+ su->limit = DIFF_TICK32(tick + 700,group->tick);
break;
case UNT_WALLOFTHORN:
- if( unit->val1 <= 0 ) {
+ if( su->val1 <= 0 ) {
group->unit_id = UNT_USED_TRAPS;
- group->limit = DIFF_TICK(tick, group->tick) + 1500;
+ group->limit = DIFF_TICK32(tick, group->tick) + 1500;
}
break;
}
}
//Don't continue if unit or even group is expired and has been deleted.
- if( !group || !unit->alive )
+ if( !group || !su->alive )
return 0;
- dissonance = skill->dance_switch(unit, 0);
+ dissonance = skill->dance_switch(su, 0);
- if( unit->range >= 0 && group->interval != -1 )
- {
+ if( su->range >= 0 && group->interval != -1 ) {
if( battle_config.skill_wall_check )
- iMap->foreachinshootrange(skill->unit_timer_sub_onplace, bl, unit->range, group->bl_flag, bl,tick);
+ map->foreachinshootrange(skill->unit_timer_sub_onplace, bl, su->range, group->bl_flag, bl,tick);
else
- iMap->foreachinrange(skill->unit_timer_sub_onplace, bl, unit->range, group->bl_flag, bl,tick);
+ map->foreachinrange(skill->unit_timer_sub_onplace, bl, su->range, group->bl_flag, bl,tick);
- if(unit->range == -1) //Unit disabled, but it should not be deleted yet.
+ if(su->range == -1) //Unit disabled, but it should not be deleted yet.
group->unit_id = UNT_USED_TRAPS;
else if( group->unit_id == UNT_TATAMIGAESHI ) {
- unit->range = -1; //Disable processed cell.
+ su->range = -1; //Disable processed cell.
if (--group->val1 <= 0) { // number of live cells
//All tiles were processed, disable skill.
group->target_flag=BCT_NOONE;
@@ -15576,33 +16143,32 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) {
}
}
- if( dissonance ) skill->dance_switch(unit, 1);
+ if( dissonance ) skill->dance_switch(su, 1);
return 0;
}
/*==========================================
- * Executes on all skill units every SKILLUNITTIMER_INTERVAL miliseconds.
+ * Executes on all skill units every SKILLUNITTIMER_INTERVAL milliseconds.
*------------------------------------------*/
-int skill_unit_timer(int tid, unsigned int tick, int id, intptr_t data) {
- iMap->freeblock_lock();
+int skill_unit_timer(int tid, int64 tick, int id, intptr_t data) {
+ map->freeblock_lock();
- skillunit_db->foreach(skillunit_db, skill->unit_timer_sub, tick);
+ skill->unit_db->foreach(skill->unit_db, skill->unit_timer_sub, tick);
- iMap->freeblock_unlock();
+ map->freeblock_unlock();
return 0;
}
-static int skill_unit_temp[20]; // temporary storage for tracking skill unit skill ids as players move in/out of them
/*==========================================
*
*------------------------------------------*/
-int skill_unit_move_sub (struct block_list* bl, va_list ap) {
- struct skill_unit* unit = (struct skill_unit *)bl;
- struct skill_unit_group* group = unit->group;
+int skill_unit_move_sub(struct block_list* bl, va_list ap) {
+ struct skill_unit* su = (struct skill_unit *)bl;
+ struct skill_unit_group* group = su->group;
struct block_list* target = va_arg(ap,struct block_list*);
- unsigned int tick = va_arg(ap,unsigned int);
+ int64 tick = va_arg(ap,int64);
int flag = va_arg(ap,int);
bool dissonance;
@@ -15611,37 +16177,37 @@ int skill_unit_move_sub (struct block_list* bl, va_list ap) {
nullpo_ret(group);
- if( !unit->alive || target->prev == NULL )
+ if( !su->alive || target->prev == NULL )
return 0;
- if( flag&1 && ( unit->group->skill_id == PF_SPIDERWEB || unit->group->skill_id == GN_THORNS_TRAP ) )
+ if( flag&1 && ( su->group->skill_id == PF_SPIDERWEB || su->group->skill_id == GN_THORNS_TRAP ) )
return 0; // Fiberlock is never supposed to trigger on skill->unit_move. [Inkfish]
- dissonance = skill->dance_switch(unit, 0);
+ dissonance = skill->dance_switch(su, 0);
//Necessary in case the group is deleted after calling on_place/on_out [Skotlex]
- skill_id = unit->group->skill_id;
+ skill_id = su->group->skill_id;
- if( unit->group->interval != -1 && !(skill->get_unit_flag(skill_id)&UF_DUALMODE) && skill_id != BD_LULLABY ) //Lullaby is the exception, bugreport:411
+ if( su->group->interval != -1 && !(skill->get_unit_flag(skill_id)&UF_DUALMODE) && skill_id != BD_LULLABY ) //Lullaby is the exception, bugreport:411
{ //Non-dualmode unit skills with a timer don't trigger when walking, so just return
- if( dissonance ) skill->dance_switch(unit, 1);
+ if( dissonance ) skill->dance_switch(su, 1);
return 0;
}
//Target-type check.
- if( !(group->bl_flag&target->type && battle->check_target(&unit->bl,target,group->target_flag) > 0) ) {
+ if( !(group->bl_flag&target->type && battle->check_target(&su->bl,target,group->target_flag) > 0) ) {
if( group->src_id == target->id && group->state.song_dance&0x2 ) { //Ensemble check to see if they went out/in of the area [Skotlex]
if( flag&1 ) {
if( flag&2 ) { //Clear this skill id.
- ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == skill_id );
- if( i < ARRAYLENGTH(skill_unit_temp) )
- skill_unit_temp[i] = 0;
+ ARR_FIND( 0, ARRAYLENGTH(skill->unit_temp), i, skill->unit_temp[i] == skill_id );
+ if( i < ARRAYLENGTH(skill->unit_temp) )
+ skill->unit_temp[i] = 0;
}
} else {
if( flag&2 ) { //Store this skill id.
- ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == 0 );
- if( i < ARRAYLENGTH(skill_unit_temp) )
- skill_unit_temp[i] = skill_id;
+ ARR_FIND( 0, ARRAYLENGTH(skill->unit_temp), i, skill->unit_temp[i] == 0 );
+ if( i < ARRAYLENGTH(skill->unit_temp) )
+ skill->unit_temp[i] = skill_id;
else
ShowError("skill_unit_move_sub: Reached limit of unit objects per cell!\n");
}
@@ -15652,32 +16218,29 @@ int skill_unit_move_sub (struct block_list* bl, va_list ap) {
skill->unit_onleft(skill_id,target,tick);
}
- if( dissonance ) skill->dance_switch(unit, 1);
+ if( dissonance ) skill->dance_switch(su, 1);
return 0;
} else {
if( flag&1 ) {
- int result = skill->unit_onplace(unit,target,tick);
+ int result = skill->unit_onplace(su,target,tick);
if( flag&2 && result ) { //Clear skill ids we have stored in onout.
- ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == result );
- if( i < ARRAYLENGTH(skill_unit_temp) )
- skill_unit_temp[i] = 0;
+ ARR_FIND( 0, ARRAYLENGTH(skill->unit_temp), i, skill->unit_temp[i] == result );
+ if( i < ARRAYLENGTH(skill->unit_temp) )
+ skill->unit_temp[i] = 0;
}
} else {
- int result = skill->unit_onout(unit,target,tick);
+ int result = skill->unit_onout(su,target,tick);
if( flag&2 && result ) { //Store this unit id.
- ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == 0 );
- if( i < ARRAYLENGTH(skill_unit_temp) )
- skill_unit_temp[i] = skill_id;
+ ARR_FIND( 0, ARRAYLENGTH(skill->unit_temp), i, skill->unit_temp[i] == 0 );
+ if( i < ARRAYLENGTH(skill->unit_temp) )
+ skill->unit_temp[i] = skill_id;
else
ShowError("skill_unit_move_sub: Reached limit of unit objects per cell!\n");
}
}
- //TODO: Normally, this is dangerous since the unit and group could be freed
- //inside the onout/onplace functions. Currently it is safe because we know song/dance
- //cells do not get deleted within them. [Skotlex]
- if( dissonance ) skill->dance_switch(unit, 1);
+ if( dissonance ) skill->dance_switch(su, 1);
if( flag&4 )
skill->unit_onleft(skill_id,target,tick);
@@ -15694,23 +16257,23 @@ int skill_unit_move_sub (struct block_list* bl, va_list ap) {
* units to figure out when they have left a group.
* flag&4: Force a onleft event (triggered when the bl is killed, for example)
*------------------------------------------*/
-int skill_unit_move (struct block_list *bl, unsigned int tick, int flag) {
+int skill_unit_move(struct block_list *bl, int64 tick, int flag) {
nullpo_ret(bl);
if( bl->prev == NULL )
return 0;
if( flag&2 && !(flag&1) ) { //Onout, clear data
- memset(skill_unit_temp, 0, sizeof(skill_unit_temp));
+ memset(skill->unit_temp, 0, sizeof(skill->unit_temp));
}
- iMap->foreachincell(skill->unit_move_sub,bl->m,bl->x,bl->y,BL_SKILL,bl,tick,flag);
+ map->foreachincell(skill->unit_move_sub,bl->m,bl->x,bl->y,BL_SKILL,bl,tick,flag);
if( flag&2 && flag&1 ) { //Onplace, check any skill units you have left.
int i;
- for( i = 0; i < ARRAYLENGTH(skill_unit_temp); i++ )
- if( skill_unit_temp[i] )
- skill->unit_onleft(skill_unit_temp[i], bl, tick);
+ for( i = 0; i < ARRAYLENGTH(skill->unit_temp); i++ )
+ if( skill->unit_temp[i] )
+ skill->unit_onleft(skill->unit_temp[i], bl, tick);
}
return 0;
@@ -15719,13 +16282,12 @@ int skill_unit_move (struct block_list *bl, unsigned int tick, int flag) {
/*==========================================
*
*------------------------------------------*/
-int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 dx, int16 dy)
-{
+int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx, int16 dy) {
int i,j;
- unsigned int tick = iTimer->gettick();
+ int64 tick = timer->gettick();
int *m_flag;
- struct skill_unit *unit1;
- struct skill_unit *unit2;
+ struct skill_unit *su1;
+ struct skill_unit *su2;
if (group == NULL)
return 0;
@@ -15746,49 +16308,47 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 d
// 1: Unit will move to a slot that had another unit of the same group (skill_unit_onplace not needed)
// 2: Another unit from same group will end up positioned on this unit (skill_unit_onout not needed)
// 3: Both 1+2.
- for(i=0;i<group->unit_count;i++){
- unit1=&group->unit[i];
- if (!unit1->alive || unit1->bl.m!=m)
+ for(i=0;i<group->unit_count;i++) {
+ su1=&group->unit[i];
+ if (!su1->alive || su1->bl.m!=m)
continue;
- for(j=0;j<group->unit_count;j++){
- unit2=&group->unit[j];
- if (!unit2->alive)
+ for(j=0;j<group->unit_count;j++) {
+ su2=&group->unit[j];
+ if (!su2->alive)
continue;
- if (unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){
+ if (su1->bl.x+dx==su2->bl.x && su1->bl.y+dy==su2->bl.y) {
m_flag[i] |= 0x1;
}
- if (unit1->bl.x-dx==unit2->bl.x && unit1->bl.y-dy==unit2->bl.y){
+ if (su1->bl.x-dx==su2->bl.x && su1->bl.y-dy==su2->bl.y) {
m_flag[i] |= 0x2;
}
}
}
j = 0;
for (i=0;i<group->unit_count;i++) {
- unit1=&group->unit[i];
- if (!unit1->alive)
+ su1=&group->unit[i];
+ if (!su1->alive)
continue;
if (!(m_flag[i]&0x2)) {
if (group->state.song_dance&0x1) //Cancel dissonance effect.
- skill->dance_overlap(unit1, 0);
- iMap->foreachincell(skill->unit_effect,unit1->bl.m,unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,4);
+ skill->dance_overlap(su1, 0);
+ map->foreachincell(skill->unit_effect,su1->bl.m,su1->bl.x,su1->bl.y,group->bl_flag,&su1->bl,tick,4);
}
//Move Cell using "smart" criteria (avoid useless moving around)
- switch(m_flag[i])
- {
+ switch(m_flag[i]) {
case 0:
//Cell moves independently, safely move it.
- iMap->moveblock(&unit1->bl, unit1->bl.x+dx, unit1->bl.y+dy, tick);
+ map->moveblock(&su1->bl, su1->bl.x+dx, su1->bl.y+dy, tick);
break;
case 1:
//Cell moves unto another cell, look for a replacement cell that won't collide
//and has no cell moving into it (flag == 2)
- for(;j<group->unit_count;j++)
- {
+ for(;j<group->unit_count;j++) {
if(m_flag[j]!=2 || !group->unit[j].alive)
continue;
//Move to where this cell would had moved.
- unit2 = &group->unit[j];
- iMap->moveblock(&unit1->bl, unit2->bl.x+dx, unit2->bl.y+dy, tick);
+ su2 = &group->unit[j];
+ map->moveblock(&su1->bl, su2->bl.x+dx, su2->bl.y+dy, tick);
j++; //Skip this cell as we have used it.
break;
}
@@ -15799,9 +16359,9 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 d
}
if (!(m_flag[i]&0x2)) { //We only moved the cell in 0-1
if (group->state.song_dance&0x1) //Check for dissonance effect.
- skill->dance_overlap(unit1, 1);
- clif->skill_setunit(unit1);
- iMap->foreachincell(skill->unit_effect,unit1->bl.m,unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,1);
+ skill->dance_overlap(su1, 1);
+ clif->getareachar_skillunit(&su1->bl,su1,AREA);
+ map->foreachincell(skill->unit_effect,su1->bl.m,su1->bl.x,su1->bl.y,group->bl_flag,&su1->bl,tick,1);
}
}
aFree(m_flag);
@@ -15821,9 +16381,9 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger,
return 0;
for(i=0;i<MAX_SKILL_PRODUCE_DB;i++){
- if(skill_produce_db[i].nameid == nameid ){
- if((j=skill_produce_db[i].req_skill)>0 &&
- pc->checkskill(sd,j) < skill_produce_db[i].req_skill_lv)
+ if(skill->produce_db[i].nameid == nameid ){
+ if((j=skill->produce_db[i].req_skill)>0 &&
+ pc->checkskill(sd,j) < skill->produce_db[i].req_skill_lv)
continue; // must iterate again to check other skills that produce it. [malufett]
if( j > 0 && sd->menuskill_id > 0 && sd->menuskill_id != j )
continue; // special case
@@ -15841,30 +16401,29 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger,
if(trigger>=0){
if(trigger>20) { // Non-weapon, non-food item (itemlv must match)
- if(skill_produce_db[i].itemlv!=trigger)
+ if(skill->produce_db[i].itemlv!=trigger)
return 0;
} else if(trigger>10) { // Food (any item level between 10 and 20 will do)
- if(skill_produce_db[i].itemlv<=10 || skill_produce_db[i].itemlv>20)
+ if(skill->produce_db[i].itemlv<=10 || skill->produce_db[i].itemlv>20)
return 0;
} else { // Weapon (itemlv must be higher or equal)
- if(skill_produce_db[i].itemlv>trigger)
+ if(skill->produce_db[i].itemlv>trigger)
return 0;
}
}
for(j=0;j<MAX_PRODUCE_RESOURCE;j++){
int id,x,y;
- if( (id=skill_produce_db[i].mat_id[j]) <= 0 )
+ if( (id=skill->produce_db[i].mat_id[j]) <= 0 )
continue;
- if(skill_produce_db[i].mat_amount[j] <= 0) {
- if(pc->search_inventory(sd,id) < 0)
+ if (skill->produce_db[i].mat_amount[j] <= 0) {
+ if (pc->search_inventory(sd,id) == INDEX_NOT_FOUND)
return 0;
- }
- else {
+ } else {
for(y=0,x=0;y<MAX_INVENTORY;y++)
if( sd->status.inventory[y].nameid == id )
x+=sd->status.inventory[y].amount;
- if(x<qty*skill_produce_db[i].mat_amount[j])
+ if(x<qty*skill->produce_db[i].mat_amount[j])
return 0;
}
}
@@ -15874,16 +16433,15 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger,
/*==========================================
*
*------------------------------------------*/
-int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, int slot1, int slot2, int slot3, int qty)
-{
+int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, int slot1, int slot2, int slot3, int qty) {
int slot[3];
int i,sc,ele,idx,equip,wlv,make_per = 0,flag = 0,skill_lv = 0;
int num = -1; // exclude the recipe
- struct status_data *status;
+ struct status_data *st;
struct item_data* data;
nullpo_ret(sd);
- status = status_get_status_data(&sd->bl);
+ st = status->get_status_data(&sd->bl);
if( sd->skill_id_old == skill_id )
skill_lv = sd->skill_lv_old;
@@ -15896,7 +16454,7 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
qty = 1;
if (!skill_id) //A skill can be specified for some override cases.
- skill_id = skill_produce_db[idx].req_skill;
+ skill_id = skill->produce_db[idx].req_skill;
if( skill_id == GC_RESEARCHNEWPOISON )
skill_id = GC_CREATENEWPOISON;
@@ -15910,13 +16468,13 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
if( slot[i]<=0 )
continue;
j = pc->search_inventory(sd,slot[i]);
- if(j < 0)
+ if (j == INDEX_NOT_FOUND)
continue;
- if(slot[i]==1000){ /* Star Crumb */
+ if( slot[i]==ITEMID_STAR_CRUMB ) {
pc->delitem(sd,j,1,1,0,LOG_TYPE_PRODUCE);
sc++;
}
- if(slot[i]>=994 && slot[i]<=997 && ele==0){ /* Flame Heart . . . Great Nature */
+ if( slot[i] >= ITEMID_FLAME_HEART && slot[i] <= ITEMID_GREAT_NATURE && ele == 0 ) {
static const int ele_table[4]={3,1,4,2};
pc->delitem(sd,j,1,1,0,LOG_TYPE_PRODUCE);
ele=ele_table[slot[i]-994];
@@ -15924,11 +16482,11 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
}
if( skill_id == RK_RUNEMASTERY ) {
- int temp_qty, skill_lv = pc->checkskill(sd,skill_id);
- data = itemdb_search(nameid);
+ int temp_qty, rune_skill_lv = pc->checkskill(sd,skill_id);
+ data = itemdb->search(nameid);
- if( skill_lv == 10 ) temp_qty = 1 + rnd()%3;
- else if( skill_lv > 5 ) temp_qty = 1 + rnd()%2;
+ if( rune_skill_lv == 10 ) temp_qty = 1 + rnd()%3;
+ else if( rune_skill_lv > 5 ) temp_qty = 1 + rnd()%2;
else temp_qty = 1;
if (data->stack.inventory) {
@@ -15953,15 +16511,15 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
for(i=0;i<MAX_PRODUCE_RESOURCE;i++){
int j,id,x;
- if( (id=skill_produce_db[idx].mat_id[i]) <= 0 )
+ if( (id=skill->produce_db[idx].mat_id[i]) <= 0 )
continue;
num++;
- x=( skill_id == RK_RUNEMASTERY ? 1 : qty)*skill_produce_db[idx].mat_amount[i];
+ x=( skill_id == RK_RUNEMASTERY ? 1 : qty)*skill->produce_db[idx].mat_amount[i];
do{
int y=0;
j = pc->search_inventory(sd,id);
- if(j >= 0){
+ if (j != INDEX_NOT_FOUND) {
y = sd->status.inventory[j].amount;
if(y>x)y=x;
pc->delitem(sd,j,y,0,0,LOG_TYPE_PRODUCE);
@@ -15972,7 +16530,7 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
}while( j>=0 && x>0 );
}
- if( (equip = (itemdb_isequip(nameid) && skill_id != GN_CHANGEMATERIAL && skill_id != GN_MAKEBOMB )) )
+ if( (equip = (itemdb->isequip(nameid) && skill_id != GN_CHANGEMATERIAL && skill_id != GN_MAKEBOMB )) )
wlv = itemdb_wlv(nameid);
if(!equip) {
switch(skill_id){
@@ -15981,24 +16539,24 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
case BS_ENCHANTEDSTONE:
// Ores & Metals Refining - skill bonuses are straight from kRO website [DracoRPG]
i = pc->checkskill(sd,skill_id);
- make_per = sd->status.job_level*20 + status->dex*10 + status->luk*10; //Base chance
+ make_per = sd->status.job_level*20 + st->dex*10 + st->luk*10; //Base chance
switch(nameid){
- case 998: // Iron
+ case ITEMID_IRON:
make_per += 4000+i*500; // Temper Iron bonus: +26/+32/+38/+44/+50
break;
- case 999: // Steel
+ case ITEMID_STEEL:
make_per += 3000+i*500; // Temper Steel bonus: +35/+40/+45/+50/+55
break;
- case 1000: //Star Crumb
+ case ITEMID_STAR_CRUMB:
make_per = 100000; // Star Crumbs are 100% success crafting rate? (made 1000% so it succeeds even after penalties) [Skotlex]
break;
default: // Enchanted Stones
- make_per += 1000+i*500; // Enchantedstone Craft bonus: +15/+20/+25/+30/+35
+ make_per += 1000+i*500; // Enchanted stone Craft bonus: +15/+20/+25/+30/+35
break;
}
break;
case ASC_CDP:
- make_per = (2000 + 40*status->dex + 20*status->luk);
+ make_per = (2000 + 40*st->dex + 20*st->luk);
break;
case AL_HOLYWATER:
/**
@@ -16013,39 +16571,39 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
case AM_TWILIGHT3:
make_per = pc->checkskill(sd,AM_LEARNINGPOTION)*50
+ pc->checkskill(sd,AM_PHARMACY)*300 + sd->status.job_level*20
- + (status->int_/2)*10 + status->dex*10+status->luk*10;
+ + (st->int_/2)*10 + st->dex*10+st->luk*10;
if(homun_alive(sd->hd)) {//Player got a homun
- int skill;
- if((skill=homun->checkskill(sd->hd,HVAN_INSTRUCT)) > 0) //His homun is a vanil with instruction change
- make_per += skill*100; //+1% bonus per level
+ int skill2_lv;
+ if((skill2_lv=homun->checkskill(sd->hd,HVAN_INSTRUCT)) > 0) //His homun is a vanil with instruction change
+ make_per += skill2_lv*100; //+1% bonus per level
}
switch(nameid){
- case 501: // Red Potion
- case 503: // Yellow Potion
- case 504: // White Potion
+ case ITEMID_RED_POTION:
+ case ITEMID_YELLOW_POTION:
+ case ITEMID_WHITE_POTION:
make_per += (1+rnd()%100)*10 + 2000;
break;
- case 970: // Alcohol
+ case ITEMID_ALCHOL:
make_per += (1+rnd()%100)*10 + 1000;
break;
- case 7135: // Bottle Grenade
- case 7136: // Acid Bottle
- case 7137: // Plant Bottle
- case 7138: // Marine Sphere Bottle
+ case ITEMID_FIRE_BOTTLE:
+ case ITEMID_ACID_BOTTLE:
+ case ITEMID_MENEATER_PLANT_BOTTLE:
+ case ITEMID_MINI_BOTTLE:
make_per += (1+rnd()%100)*10;
break;
- case 546: // Condensed Yellow Potion
+ case ITEMID_YELLOW_SLIM_POTION:
make_per -= (1+rnd()%50)*10;
break;
- case 547: // Condensed White Potion
- case 7139: // Glistening Coat
+ case ITEMID_WHITE_SLIM_POTION:
+ case ITEMID_COATING_BOTTLE:
make_per -= (1+rnd()%100)*10;
break;
- //Common items, recieve no bonus or penalty, listed just because they are commonly produced
- case 505: // Blue Potion
- case 545: // Condensed Red Potion
- case 605: // Anodyne
- case 606: // Aloevera
+ //Common items, receive no bonus or penalty, listed just because they are commonly produced
+ case ITEMID_BLUE_POTION:
+ case ITEMID_RED_SLIM_POTION:
+ case ITEMID_ANODYNE:
+ case ITEMID_ALOEBERA:
default:
break;
}
@@ -16061,22 +16619,23 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
case RK_RUNEMASTERY:
{
int A = 5100 + 200 * pc->checkskill(sd, skill_id);
- int B = 10 * status->dex / 3 + (status->luk + sd->status.job_level);
+ int B = 10 * st->dex / 3 + (st->luk + sd->status.job_level);
int C = 100 * cap_value(sd->itemid,0,100); //itemid depend on makerune()
int D = 2500;
switch (nameid) { //rune rank it_diff 9 craftable rune
- case ITEMID_RAIDO:
- case ITEMID_THURISAZ:
- case ITEMID_HAGALAZ:
- case ITEMID_OTHILA:
+ case ITEMID_RAIDO:
+ case ITEMID_THURISAZ:
+ case ITEMID_HAGALAZ:
+ case ITEMID_OTHILA:
D -= 500; //Rank C
- case ITEMID_ISA:
- case ITEMID_WYRD:
+ case ITEMID_ISA:
+ case ITEMID_WYRD:
D -= 500; //Rank B
- case ITEMID_NAUTHIZ:
- case ITEMID_URUZ:
+ case ITEMID_NAUTHIZ:
+ case ITEMID_URUZ:
D -= 500; //Rank A
- case ITEMID_BERKANA:
+ case ITEMID_BERKANA:
+ case ITEMID_LUX_ANIMA:
D -= 500; //Rank S
}
make_per = A + B + C - D;
@@ -16087,17 +16646,17 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
**/
case GC_CREATENEWPOISON:
{
- const int min[] = {2, 2, 3, 3, 4, 4, 5, 5, 6, 6};
- const int max[] = {4, 5, 5, 6, 6, 7, 7, 8, 8, 9};
- uint16 lv = pc->checkskill(sd,GC_RESEARCHNEWPOISON);
- make_per = 3000 + 500 * lv ;
- qty = min[lv] + rand()%(max[lv] - min[lv]);
+ const int min[10] = {2, 2, 3, 3, 4, 4, 5, 5, 6, 6};
+ const int max[10] = {4, 5, 5, 6, 6, 7, 7, 8, 8, 9};
+ int lv = max(0, pc->checkskill(sd,GC_RESEARCHNEWPOISON) - 1);
+ qty = min[lv] + rnd()%(max[lv] - min[lv]);
+ make_per = 3000 + 500 * lv + st->dex / 3 * 10 + st->luk * 10 + sd->status.job_level * 10;
}
break;
case GN_CHANGEMATERIAL:
for(i=0; i<MAX_SKILL_PRODUCE_DB; i++)
- if( skill_changematerial_db[i].itemid == nameid ){
- make_per = skill_changematerial_db[i].rate * 10;
+ if( skill->changematerial_db[i].itemid == nameid ){
+ make_per = skill->changematerial_db[i].rate * 10;
break;
}
break;
@@ -16107,26 +16666,32 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
difficulty = (620 - 20 * skill_lv);// (620 - 20 * Skill Level)
- make_per = status->int_ + status->dex/2 + status->luk + sd->status.job_level + (30+rnd()%120) + // (Caster?s INT) + (Caster?s DEX / 2) + (Caster?s LUK) + (Caster?s Job Level) + Random number between (30 ~ 150) +
+ make_per = st->int_ + st->dex/2 + st->luk + sd->status.job_level + (30+rnd()%120) + // (Caster?s INT) + (Caster?s DEX / 2) + (Caster?s LUK) + (Caster?s Job Level) + Random number between (30 ~ 150) +
(sd->status.base_level-100) + pc->checkskill(sd, AM_LEARNINGPOTION) + pc->checkskill(sd, CR_FULLPROTECTION)*(4+rnd()%6); // (Caster?s Base Level - 100) + (Potion Research x 5) + (Full Chemical Protection Skill Level) x (Random number between 4 ~ 10)
switch(nameid){// difficulty factor
- case 12422: case 12425:
- case 12428:
+ case ITEMID_HP_INCREASE_POTIONS:
+ case ITEMID_SP_INCREASE_POTIONS:
+ case ITEMID_ENRICH_WHITE_POTIONZ:
difficulty += 10;
break;
- case 6212: case 12426:
+ case ITEMID_BOMB_MUSHROOM_SPORE:
+ case ITEMID_SP_INCREASE_POTIONM:
difficulty += 15;
break;
- case 13264: case 12423:
- case 12427: case 12436:
+ case ITEMID_BANANA_BOMB:
+ case ITEMID_HP_INCREASE_POTIONM:
+ case ITEMID_SP_INCREASE_POTIONL:
+ case ITEMID_VITATA500:
difficulty += 20;
break;
- case 6210: case 6211:
- case 12437:
+ case ITEMID_SEED_OF_HORNY_PLANT:
+ case ITEMID_BLOODSUCK_PLANT_SEED:
+ case ITEMID_ENRICH_CELERMINE_JUICE:
difficulty += 30;
break;
- case 12424: case 12475:
+ case ITEMID_HP_INCREASE_POTIONL:
+ case ITEMID_CURE_FREE:
difficulty += 40;
break;
}
@@ -16149,22 +16714,27 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
{
int difficulty = 30 + rnd()%120; // Random number between (30 ~ 150)
- make_per = sd->status.job_level / 4 + status->luk / 2 + status->dex / 3; // (Caster?s Job Level / 4) + (Caster?s LUK / 2) + (Caster?s DEX / 3)
+ make_per = sd->status.job_level / 4 + st->luk / 2 + st->dex / 3; // (Caster?s Job Level / 4) + (Caster?s LUK / 2) + (Caster?s DEX / 3)
qty = ~(5 + rnd()%5) + 1;
switch(nameid){// difficulty factor
- case 13260:
+ case ITEMID_APPLE_BOMB:
difficulty += 5;
break;
- case 13261: case 13262:
+ case ITEMID_COCONUT_BOMB:
+ case ITEMID_MELON_BOMB:
difficulty += 10;
break;
- case 12429: case 12430: case 12431:
- case 12432: case 12433: case 12434:
- case 13263:
+ case ITEMID_SAVAGE_BBQ:
+ case ITEMID_WUG_BLOOD_COCKTAIL:
+ case ITEMID_MINOR_BRISKET:
+ case ITEMID_SIROMA_ICETEA:
+ case ITEMID_DROCERA_HERB_STEW:
+ case ITEMID_PETTI_TAIL_NOODLE:
+ case ITEMID_PINEAPPLE_BOMB:
difficulty += 15;
break;
- case 13264:
+ case ITEMID_BANANA_BOMB:
difficulty += 20;
break;
}
@@ -16197,10 +16767,10 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
else
make_per = 1200 * (sd->menuskill_val - 10)
+ 20 * (sd->status.base_level + 1)
- + 20 * (status->dex + 1)
+ + 20 * (st->dex + 1)
+ 100 * (rnd()%(30+5*(sd->cook_mastery/400) - (6+sd->cook_mastery/80)) + (6+sd->cook_mastery/80))
- - 400 * (skill_produce_db[idx].itemlv - 11 + 1)
- - 10 * (100 - status->luk + 1)
+ - 400 * (skill->produce_db[idx].itemlv - 11 + 1)
+ - 10 * (100 - st->luk + 1)
- 500 * (num - 1)
- 100 * (rnd()%4 + 1);
break;
@@ -16209,14 +16779,18 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
break;
}
} else { // Weapon Forging - skill bonuses are straight from kRO website, other things from a jRO calculator [DracoRPG]
- make_per = 5000 + sd->status.job_level*20 + status->dex*10 + status->luk*10; // Base
+ make_per = 5000 + sd->status.job_level*20 + st->dex*10 + st->luk*10; // Base
make_per += pc->checkskill(sd,skill_id)*500; // Smithing skills bonus: +5/+10/+15
make_per += pc->checkskill(sd,BS_WEAPONRESEARCH)*100 +((wlv >= 3)? pc->checkskill(sd,BS_ORIDEOCON)*100:0); // Weaponry Research bonus: +1/+2/+3/+4/+5/+6/+7/+8/+9/+10, Oridecon Research bonus (custom): +1/+2/+3/+4/+5
make_per -= (ele?2000:0) + sc*1500 + (wlv>1?wlv*1000:0); // Element Stone: -20%, Star Crumb: -15% each, Weapon level malus: -0/-20/-30
- if(pc->search_inventory(sd,989) > 0) make_per+= 1000; // Emperium Anvil: +10
- else if(pc->search_inventory(sd,988) > 0) make_per+= 500; // Golden Anvil: +5
- else if(pc->search_inventory(sd,987) > 0) make_per+= 300; // Oridecon Anvil: +3
- else if(pc->search_inventory(sd,986) > 0) make_per+= 0; // Anvil: +0?
+ if (pc->search_inventory(sd,ITEMID_EMPERIUM_ANVIL) != INDEX_NOT_FOUND)
+ make_per+= 1000; // +10
+ else if(pc->search_inventory(sd,ITEMID_GOLDEN_ANVIL) != INDEX_NOT_FOUND)
+ make_per+= 500; // +5
+ else if(pc->search_inventory(sd,ITEMID_ORIDECON_ANVIL) != INDEX_NOT_FOUND)
+ make_per+= 300; // +3
+ else if(pc->search_inventory(sd,ITEMID_ANVIL) != INDEX_NOT_FOUND)
+ make_per+= 0; // +0?
if(battle_config.wp_rate != 100)
make_per = make_per * battle_config.wp_rate / 100;
}
@@ -16298,7 +16872,7 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
}
if (rnd()%10000 < make_per || qty == 1) { //Success
tmp_item.amount++;
- if(nameid < 545 || nameid > 547)
+ if(nameid < ITEMID_RED_SLIM_POTION || nameid > ITEMID_WHITE_SLIM_POTION)
continue;
if( skill_id != AM_PHARMACY &&
skill_id != AM_TWILIGHT1 &&
@@ -16349,11 +16923,11 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
clif->misceffect(&sd->bl,5);
break;
default: //Those that don't require a skill?
- if( skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20)
+ if( skill->produce_db[idx].itemlv > 10 && skill->produce_db[idx].itemlv <= 20)
{ //Cooking items.
clif->specialeffect(&sd->bl, 608, AREA);
if( sd->cook_mastery < 1999 )
- pc_setglobalreg(sd, "COOK_MASTERY",sd->cook_mastery + ( 1 << ( (skill_produce_db[idx].itemlv - 11) / 2 ) ) * 5);
+ pc_setglobalreg(sd, script->add_str("COOK_MASTERY"),sd->cook_mastery + ( 1 << ( (skill->produce_db[idx].itemlv - 11) / 2 ) ) * 5);
}
break;
}
@@ -16361,13 +16935,13 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
if ( skill_id == GN_CHANGEMATERIAL && tmp_item.amount) { //Success
int j, k = 0;
for(i=0; i<MAX_SKILL_PRODUCE_DB; i++)
- if( skill_changematerial_db[i].itemid == nameid ){
+ if( skill->changematerial_db[i].itemid == nameid ){
for(j=0; j<5; j++){
- if( rnd()%1000 < skill_changematerial_db[i].qty_rate[j] ){
- tmp_item.amount = qty * skill_changematerial_db[i].qty[j];
+ if( rnd()%1000 < skill->changematerial_db[i].qty_rate[j] ){
+ tmp_item.amount = qty * skill->changematerial_db[i].qty[j];
if((flag = pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) {
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
k++;
}
@@ -16381,7 +16955,7 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
} else if (tmp_item.amount) { //Success
if((flag = pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) {
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
if( skill_id == GN_MIX_COOKING || skill_id == GN_MAKEBOMB || skill_id == GN_S_PHARMACY )
clif->msg_skill(sd,skill_id,0x627);
@@ -16421,7 +16995,13 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
break;
case GN_MIX_COOKING: {
struct item tmp_item;
- const int compensation[5] = {13265, 13266, 13267, 12435, 13268};
+ const int compensation[5] = {
+ ITEMID_BLACK_LUMP,
+ ITEMID_BLACK_HARD_LUMP,
+ ITEMID_VERY_HARD_LUMP,
+ ITEMID_BLACK_THING,
+ ITEMID_MYSTERIOUS_POWDER,
+ };
int rate = rnd()%500;
memset(&tmp_item,0,sizeof(tmp_item));
if( rate < 50) i = 4;
@@ -16433,7 +17013,7 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
tmp_item.identify = 1;
if( pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE) ) {
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
clif->msg_skill(sd,skill_id,0x628);
}
@@ -16444,11 +17024,11 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid,
clif->msg_skill(sd,skill_id,0x628);
break;
default:
- if( skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20 )
+ if( skill->produce_db[idx].itemlv > 10 && skill->produce_db[idx].itemlv <= 20 )
{ //Cooking items.
clif->specialeffect(&sd->bl, 609, AREA);
if( sd->cook_mastery > 0 )
- pc_setglobalreg(sd, "COOK_MASTERY", sd->cook_mastery - ( 1 << ((skill_produce_db[idx].itemlv - 11) / 2) ) - ( ( ( 1 << ((skill_produce_db[idx].itemlv - 11) / 2) ) >> 1 ) * 3 ));
+ pc_setglobalreg(sd, script->add_str("COOK_MASTERY"), sd->cook_mastery - ( 1 << ((skill->produce_db[idx].itemlv - 11) / 2) ) - ( ( ( 1 << ((skill->produce_db[idx].itemlv - 11) / 2) ) >> 1 ) * 3 ));
}
}
}
@@ -16466,20 +17046,20 @@ int skill_arrow_create (struct map_session_data *sd, int nameid)
return 1;
for(i=0;i<MAX_SKILL_ARROW_DB;i++)
- if(nameid == skill_arrow_db[i].nameid) {
+ if(nameid == skill->arrow_db[i].nameid) {
index = i;
break;
}
- if(index < 0 || (j = pc->search_inventory(sd,nameid)) < 0)
+ if(index < 0 || (j = pc->search_inventory(sd,nameid)) == INDEX_NOT_FOUND)
return 1;
pc->delitem(sd,j,1,0,0,LOG_TYPE_PRODUCE);
for(i=0;i<MAX_ARROW_RESOURCE;i++) {
memset(&tmp_item,0,sizeof(tmp_item));
tmp_item.identify = 1;
- tmp_item.nameid = skill_arrow_db[index].cre_id[i];
- tmp_item.amount = skill_arrow_db[index].cre_amount[i];
+ tmp_item.nameid = skill->arrow_db[index].cre_id[i];
+ tmp_item.amount = skill->arrow_db[index].cre_amount[i];
if(battle_config.produce_item_name_input&0x4) {
tmp_item.card[0]=CARD0_CREATE;
tmp_item.card[1]=0;
@@ -16490,7 +17070,7 @@ int skill_arrow_create (struct map_session_data *sd, int nameid)
continue;
if((flag = pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) {
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
@@ -16500,34 +17080,35 @@ int skill_poisoningweapon( struct map_session_data *sd, int nameid) {
sc_type type;
int chance, i;
nullpo_ret(sd);
- if( nameid <= 0 || (i = pc->search_inventory(sd,nameid)) < 0 || pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) ) {
+ if( nameid <= 0 || (i = pc->search_inventory(sd,nameid)) == INDEX_NOT_FOUND || pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) ) {
clif->skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0);
return 0;
}
switch( nameid )
{ // t_lv used to take duration from skill->get_time2
- case PO_PARALYSE: type = SC_PARALYSE; break;
- case PO_PYREXIA: type = SC_PYREXIA; break;
- case PO_DEATHHURT: type = SC_DEATHHURT; break;
- case PO_LEECHESEND: type = SC_LEECHESEND; break;
- case PO_VENOMBLEED: type = SC_VENOMBLEED; break;
- case PO_TOXIN: type = SC_TOXIN; break;
- case PO_MAGICMUSHROOM: type = SC_MAGICMUSHROOM; break;
- case PO_OBLIVIONCURSE: type = SC_OBLIVIONCURSE; break;
+ case ITEMID_POISON_PARALYSIS: type = SC_PARALYSE; break;
+ case ITEMID_POISON_FEVER: type = SC_PYREXIA; break;
+ case ITEMID_POISON_CONTAMINATION: type = SC_DEATHHURT; break;
+ case ITEMID_POISON_LEECH: type = SC_LEECHESEND; break;
+ case ITEMID_POISON_FATIGUE: type = SC_VENOMBLEED; break;
+ case ITEMID_POISON_NUMB: type = SC_TOXIN; break;
+ case ITEMID_POISON_LAUGHING: type = SC_MAGICMUSHROOM; break;
+ case ITEMID_POISON_OBLIVION: type = SC_OBLIVIONCURSE; break;
default:
clif->skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0);
return 0;
}
+ status_change_end(&sd->bl, SC_POISONINGWEAPON, -1);//Status must be forced to end so that a new poison will be applied if a player decides to change poisons. [Rytech]
chance = 2 + 2 * sd->menuskill_val; // 2 + 2 * skill_lv
- sc_start4(&sd->bl, SC_POISONINGWEAPON, 100, pc->checkskill(sd, GC_RESEARCHNEWPOISON), //in Aegis it store the level of GC_RESEARCHNEWPOISON in val1
+ sc_start4(&sd->bl, &sd->bl, SC_POISONINGWEAPON, 100, pc->checkskill(sd, GC_RESEARCHNEWPOISON), //in Aegis it store the level of GC_RESEARCHNEWPOISON in val1
type, chance, 0, skill->get_time(GC_POISONINGWEAPON, sd->menuskill_val));
return 0;
}
void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) {
- struct status_change *sc = status_get_sc(bl);
+ struct status_change *sc = status->get_sc(bl);
// non-offensive and non-magic skills do not affect the status
if (skill->get_nk(skill_id)&NK_NO_DAMAGE || !(skill->get_type(skill_id)&BF_MAGIC))
@@ -16538,7 +17119,7 @@ void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) {
status_change_end(bl, SC_MAGICPOWER, INVALID_TIMER);
} else {
sc->data[SC_MAGICPOWER]->val4 = 1;
- status_calc_bl(bl, status_sc2scb_flag(SC_MAGICPOWER));
+ status_calc_bl(bl, status->sc2scb_flag(SC_MAGICPOWER));
#ifndef RENEWAL
if(bl->type == BL_PC){// update current display.
clif->updatestatus(((TBL_PC *)bl),SP_MATK1);
@@ -16556,8 +17137,9 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) {
nullpo_ret(sd);
skill_id = sd->menuskill_val;
- if( nameid <= 0 || !itemdb_is_element(nameid) || (i = pc->search_inventory(sd,nameid)) < 0 || !skill_id || pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) )
- {
+ if (nameid <= 0 || !itemdb_is_element(nameid) || (i = pc->search_inventory(sd,nameid)) == INDEX_NOT_FOUND
+ || !skill_id || pc->delitem(sd,i,1,0,0,LOG_TYPE_CONSUME)
+ ) {
clif->skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0);
return 0;
}
@@ -16569,17 +17151,17 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) {
sd->sc.comet_x = sd->sc.comet_y = 0;
sd->menuskill_val = 0;
- class_ = (nameid == 990 || nameid == 991) ? 2043 + nameid - 990 : (nameid == 992) ? 2046 : 2045;
+ class_ = (nameid == ITEMID_BOODY_RED || nameid == ITEMID_CRYSTAL_BLUE) ? 2043 + nameid - ITEMID_BOODY_RED : (nameid == ITEMID_WIND_OF_VERDURE) ? 2046 : 2045;
- md = mob_once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_SMALL, AI_NONE);
+ md = mob->once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_MEDIUM, AI_NONE);
if( md ) {
md->master_id = sd->bl.id;
md->special_state.ai = AI_FLORA;
if( md->deletetimer != INVALID_TIMER )
- iTimer->delete_timer(md->deletetimer, mob_timer_delete);
- md->deletetimer = iTimer->add_timer (iTimer->gettick() + skill->get_time(NC_MAGICDECOY,skill_id), mob_timer_delete, md->bl.id, 0);
- mob_spawn(md);
+ timer->delete(md->deletetimer, mob->timer_delete);
+ md->deletetimer = timer->add(timer->gettick() + skill->get_time(NC_MAGICDECOY,skill_id), mob->timer_delete, md->bl.id, 0);
+ mob->spawn(md);
md->status.matk_min = md->status.matk_max = 250 + (50 * skill_id);
}
@@ -16593,7 +17175,7 @@ int skill_spellbook (struct map_session_data *sd, int nameid) {
nullpo_ret(sd);
- sc = status_get_sc(&sd->bl);
+ sc = status->get_sc(&sd->bl);
status_change_end(&sd->bl, SC_STOP, INVALID_TIMER);
for(i=SC_SPELLBOOK1; i <= SC_SPELLBOOK7; i++) if( sc && !sc->data[i] ) break;
@@ -16603,18 +17185,18 @@ int skill_spellbook (struct map_session_data *sd, int nameid) {
return 0;
}
- ARR_FIND(0,MAX_SKILL_SPELLBOOK_DB,i,skill_spellbook_db[i].nameid == nameid); // Search for information of this item
+ ARR_FIND(0,MAX_SKILL_SPELLBOOK_DB,i,skill->spellbook_db[i].nameid == nameid); // Search for information of this item
if( i == MAX_SKILL_SPELLBOOK_DB ) return 0;
- if( !pc->checkskill(sd, (skill_id = skill_spellbook_db[i].skill_id)) )
+ if( !pc->checkskill(sd, (skill_id = skill->spellbook_db[i].skill_id)) )
{ // User don't know the skill
- sc_start(&sd->bl, SC_SLEEP, 100, 1, skill->get_time(WL_READING_SB, pc->checkskill(sd,WL_READING_SB)));
+ sc_start(&sd->bl, &sd->bl, SC_SLEEP, 100, 1, skill->get_time(WL_READING_SB, pc->checkskill(sd,WL_READING_SB)));
clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP, 0);
return 0;
}
max_preserve = 4 * pc->checkskill(sd, WL_FREEZE_SP) + (status_get_int(&sd->bl) + sd->status.base_level) / 10;
- point = skill_spellbook_db[i].point;
+ point = skill->spellbook_db[i].point;
if( sc && sc->data[SC_READING_SB] ) {
if( (sc->data[SC_READING_SB]->val2 + point) > max_preserve ) {
@@ -16624,13 +17206,13 @@ int skill_spellbook (struct map_session_data *sd, int nameid) {
for(i = SC_SPELLBOOK7; i >= SC_SPELLBOOK1; i--){ // This is how official saves spellbook. [malufett]
if( !sc->data[i] ){
sc->data[SC_READING_SB]->val2 += point; // increase points
- sc_start4(&sd->bl, (sc_type)i, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER);
+ sc_start4(&sd->bl,&sd->bl, (sc_type)i, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER);
break;
}
}
}else{
- sc_start2(&sd->bl, SC_READING_SB, 100, 0, point, INVALID_TIMER);
- sc_start4(&sd->bl, SC_SPELLBOOK7, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER);
+ sc_start2(&sd->bl,&sd->bl, SC_READING_SB, 100, 0, point, INVALID_TIMER);
+ sc_start4(&sd->bl,&sd->bl, SC_SPELLBOOK7, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER);
}
return 1;
@@ -16655,7 +17237,7 @@ int skill_select_menu(struct map_session_data *sd,uint16 skill_id) {
lv = (aslvl + 1) / 2; // The level the skill will be autocasted
lv = min(lv,sd->status.skill[idx].lv);
prob = (aslvl == 10) ? 15 : (32 - 2 * aslvl); // Probability at level 10 was increased to 15.
- sc_start4(&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill->get_time(SC_AUTOSHADOWSPELL,aslvl));
+ sc_start4(&sd->bl,&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill->get_time(SC_AUTOSHADOWSPELL,aslvl));
return 0;
}
int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, unsigned short* item_list) {
@@ -16685,15 +17267,15 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv,
switch( nameid ) {
// Level 1
- case 994: product = 990; break; // Flame Heart -> Red Blood.
- case 995: product = 991; break; // Mystic Frozen -> Crystal Blue.
- case 996: product = 992; break; // Rough Wind -> Wind of Verdure.
- case 997: product = 993; break; // Great Nature -> Green Live.
+ case ITEMID_FLAME_HEART: product = ITEMID_BOODY_RED; break;
+ case ITEMID_MISTIC_FROZEN: product = ITEMID_CRYSTAL_BLUE; break;
+ case ITEMID_ROUGH_WIND: product = ITEMID_WIND_OF_VERDURE; break;
+ case ITEMID_GREAT_NATURE: product = ITEMID_YELLOW_LIVE; break;
// Level 2
- case 990: product = 994; break; // Red Blood -> Flame Heart.
- case 991: product = 995; break; // Crystal Blue -> Mystic Frozen.
- case 992: product = 996; break; // Wind of Verdure -> Rough Wind.
- case 993: product = 997; break; // Green Live -> Great Nature.
+ case ITEMID_BOODY_RED: product = ITEMID_FLAME_HEART; break;
+ case ITEMID_CRYSTAL_BLUE: product = ITEMID_MISTIC_FROZEN; break;
+ case ITEMID_WIND_OF_VERDURE: product = ITEMID_ROUGH_WIND; break;
+ case ITEMID_YELLOW_LIVE: product = ITEMID_GREAT_NATURE; break;
default:
clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0);
return 1;
@@ -16718,7 +17300,7 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv,
if( tmp_item.amount ) {
if( (flag = pc->additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_CONSUME)) ) {
clif->additem(sd,0,0,flag);
- iMap->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
+ map->addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
}
}
@@ -16735,13 +17317,13 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite
// Search for objects that can be created.
for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) {
- if( skill_produce_db[i].itemlv == 26 ) {
+ if( skill->produce_db[i].itemlv == 26 ) {
p = 0;
do {
c = 0;
// Verification of overlap between the objects required and the list submitted.
for( j = 0; j < MAX_PRODUCE_RESOURCE; j++ ) {
- if( skill_produce_db[i].mat_id[j] > 0 ) {
+ if( skill->produce_db[i].mat_id[j] > 0 ) {
for( k = 0; k < n; k++ ) {
int idx = item_list[k*2+0]-2;
nameid = sd->status.inventory[idx].nameid;
@@ -16750,8 +17332,8 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite
clif->msg_skill(sd,GN_CHANGEMATERIAL,0x62D);
return 0;
}
- if( nameid == skill_produce_db[i].mat_id[j] && (amount-p*skill_produce_db[i].mat_amount[j]) >= skill_produce_db[i].mat_amount[j]
- && (amount-p*skill_produce_db[i].mat_amount[j])%skill_produce_db[i].mat_amount[j] == 0 ) // must be in exact amount
+ if( nameid == skill->produce_db[i].mat_id[j] && (amount-p*skill->produce_db[i].mat_amount[j]) >= skill->produce_db[i].mat_amount[j]
+ && (amount-p*skill->produce_db[i].mat_amount[j])%skill->produce_db[i].mat_amount[j] == 0 ) // must be in exact amount
c++; // match
}
}
@@ -16762,7 +17344,7 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite
} while(n == j && c == n);
p--;
if ( p > 0 ) {
- skill->produce_mix(sd,GN_CHANGEMATERIAL,skill_produce_db[i].nameid,0,0,0,p);
+ skill->produce_mix(sd,GN_CHANGEMATERIAL,skill->produce_db[i].nameid,0,0,0,p);
return 1;
}
}
@@ -16776,27 +17358,29 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite
/**
* for Royal Guard's LG_TRAMPLE
**/
-int skill_destroy_trap( struct block_list *bl, va_list ap ) {
+int skill_destroy_trap(struct block_list *bl, va_list ap) {
struct skill_unit *su = (struct skill_unit *)bl;
struct skill_unit_group *sg;
- unsigned int tick;
+ int64 tick;
nullpo_ret(su);
- tick = va_arg(ap, unsigned int);
+ tick = va_arg(ap, int64);
if (su->alive && (sg = su->group) && skill->get_inf2(sg->skill_id)&INF2_TRAP) {
switch( sg->unit_id ) {
- case UNT_LANDMINE:
case UNT_CLAYMORETRAP:
+ case UNT_FIRINGTRAP:
+ case UNT_ICEBOUNDTRAP:
+ map->foreachinrange(skill->trap_splash,&su->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &su->bl,tick);
+ break;
+ case UNT_LANDMINE:
case UNT_BLASTMINE:
case UNT_SHOCKWAVE:
case UNT_SANDMAN:
case UNT_FLASHER:
case UNT_FREEZINGTRAP:
case UNT_CLUSTERBOMB:
- case UNT_FIRINGTRAP:
- case UNT_ICEBOUNDTRAP:
- iMap->foreachinrange(skill->trap_splash,&su->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick);
+ map->foreachinrange(skill->trap_splash,&su->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick);
break;
}
// Traps aren't recovered.
@@ -16807,53 +17391,62 @@ int skill_destroy_trap( struct block_list *bl, va_list ap ) {
/*==========================================
*
*------------------------------------------*/
-int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) {
- struct map_session_data *sd = iMap->id2sd(id);
+int skill_blockpc_end(int tid, int64 tick, int id, intptr_t data) {
+ struct map_session_data *sd = map->id2sd(id);
struct skill_cd * cd = NULL;
if (data <= 0 || data >= MAX_SKILL)
return 0;
- if (!sd) return 0;
- if (sd->blockskill[data] != (0x1|(tid&0xFE))) return 0;
-
- if( ( cd = idb_get(skillcd_db,sd->status.char_id) ) ) {
- int i,cursor;
- ARR_FIND( 0, cd->cursor+1, cursor, cd->skidx[cursor] == data );
- cd->duration[cursor] = 0;
- cd->skidx[cursor] = 0;
- cd->nameid[cursor] = 0;
- // compact the cool down list
- for( i = 0, cursor = 0; i < cd->cursor; i++ ) {
- if( cd->duration[i] == 0 )
- continue;
- if( cursor != i ) {
- cd->duration[cursor] = cd->duration[i];
- cd->skidx[cursor] = cd->skidx[i];
- cd->nameid[cursor] = cd->nameid[i];
+ if (!sd || !sd->blockskill[data])
+ return 0;
+
+ if( ( cd = idb_get(skill->cd_db,sd->status.char_id) ) ) {
+ int i;
+
+ for( i = 0; i < cd->cursor; i++ ) {
+ if( cd->entry[i]->skidx == data )
+ break;
+ }
+
+ if (i == cd->cursor) {
+ ShowError("skill_blockpc_end: '%s': no data found for '%"PRIdPTR"'\n", sd->status.name, data);
+ } else {
+ int cursor = 0;
+
+ ers_free(skill->cd_entry_ers, cd->entry[i]);
+
+ cd->entry[i] = NULL;
+
+ for( i = 0, cursor = 0; i < cd->cursor; i++ ) {
+ if( !cd->entry[i] )
+ continue;
+ if( cursor != i )
+ cd->entry[cursor] = cd->entry[i];
+ cursor++;
+ }
+
+ if( (cd->cursor = cursor) == 0 ) {
+ idb_remove(skill->cd_db,sd->status.char_id);
+ ers_free(skill->cd_ers, cd);
}
- cursor++;
}
- if( cursor == 0 )
- idb_remove(skillcd_db,sd->status.char_id);
- else
- cd->cursor = cursor;
}
-
- sd->blockskill[data] = 0;
+
+ sd->blockskill[data] = false;
return 1;
}
/**
* flags a singular skill as being blocked from persistent usage.
* @param sd the player the skill delay affects
- * @param skill_id the skill which should be delayed
+ * @param skill_id the skill which should be delayed
* @param tick the length of time the delay should last
- * @param load whether this assignment is being loaded upon player login
* @return 0 if successful, -1 otherwise
*/
-int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, bool load) {
+int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick) {
struct skill_cd* cd = NULL;
uint16 idx = skill->get_index(skill_id);
+ int64 now = timer->gettick();
nullpo_retr (-1, sd);
@@ -16861,32 +17454,61 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick,
return -1;
if (tick < 1) {
- sd->blockskill[idx] = 0;
+ sd->blockskill[idx] = false;
return -1;
}
if( battle_config.display_status_timers )
clif->skill_cooldown(sd, skill_id, tick);
-
- if( !load ) {// not being loaded initially so ensure the skill delay is recorded
- if( !(cd = idb_get(skillcd_db,sd->status.char_id)) ) {// create a new skill cooldown object for map storage
- CREATE( cd, struct skill_cd, 1 );
- idb_put( skillcd_db, sd->status.char_id, cd );
+
+ if( !(cd = idb_get(skill->cd_db,sd->status.char_id)) ) {// create a new skill cooldown object for map storage
+ cd = ers_alloc(skill->cd_ers, struct skill_cd);
+
+ idb_put( skill->cd_db, sd->status.char_id, cd );
+ } else {
+ int i;
+
+ for(i = 0; i < MAX_SKILL_TREE; i++) {
+ if( cd->entry[i] && cd->entry[i]->skidx == idx )
+ break;
}
-
- // record the skill duration in the database map
- cd->duration[cd->cursor] = tick;
- cd->skidx[cd->cursor] = idx;
- cd->nameid[cd->cursor] = skill_id;
- cd->cursor++;
+
+ if( i != MAX_SKILL_TREE ) {/* duplicate, update necessary */
+ cd->entry[i]->duration = tick;
+#if PACKETVER >= 20120604
+ cd->entry[i]->total = tick;
+#endif
+ cd->entry[i]->started = now;
+ timer->settick(cd->entry[i]->timer,now+tick);
+ return 0;
+ }
+
+ }
+
+ if( cd->cursor == MAX_SKILL_TREE ) {
+ ShowError("skill_blockpc_start: '%s' got over '%d' skill cooldowns, no room to save!\n",sd->status.name,MAX_SKILL_TREE);
+ return -1;
}
+
+ cd->entry[cd->cursor] = ers_alloc(skill->cd_entry_ers,struct skill_cd_entry);
+
+ cd->entry[cd->cursor]->duration = tick;
+#if PACKETVER >= 20120604
+ cd->entry[cd->cursor]->total = tick;
+#endif
+ cd->entry[cd->cursor]->skidx = idx;
+ cd->entry[cd->cursor]->skill_id = skill_id;
+ cd->entry[cd->cursor]->started = now;
+ cd->entry[cd->cursor]->timer = timer->add(now+tick,skill->blockpc_end,sd->bl.id,idx);
+
+ cd->cursor++;
- sd->blockskill[idx] = 0x1|(0xFE&iTimer->add_timer(iTimer->gettick()+tick,skill->blockpc_end,sd->bl.id,idx));
+ sd->blockskill[idx] = true;
return 0;
}
-int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) { //[orn]
- struct homun_data *hd = (TBL_HOM*) iMap->id2bl(id);
+int skill_blockhomun_end(int tid, int64 tick, int id, intptr_t data) { // [orn]
+ struct homun_data *hd = (TBL_HOM*)map->id2bl(id);
if (data <= 0 || data >= MAX_SKILL)
return 0;
if (hd) hd->blockskill[data] = 0;
@@ -16894,7 +17516,7 @@ int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) { //
return 1;
}
-int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { //[orn]
+int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { // [orn]
uint16 idx = skill->get_index(skill_id);
nullpo_retr (-1, hd);
@@ -16907,11 +17529,11 @@ int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { /
return -1;
}
hd->blockskill[idx] = 1;
- return iTimer->add_timer(iTimer->gettick() + tick, skill->blockhomun_end, hd->bl.id, idx);
+ return timer->add(timer->gettick() + tick, skill->blockhomun_end, hd->bl.id, idx);
}
-int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr_t data) {//[orn]
- struct mercenary_data *md = (TBL_MER*)iMap->id2bl(id);
+int skill_blockmerc_end(int tid, int64 tick, int id, intptr_t data) {// [orn]
+ struct mercenary_data *md = (TBL_MER*)map->id2bl(id);
if( data <= 0 || data >= MAX_SKILL )
return 0;
if( md ) md->blockskill[data] = 0;
@@ -16932,20 +17554,20 @@ int skill_blockmerc_start(struct mercenary_data *md, uint16 skill_id, int tick)
return -1;
}
md->blockskill[idx] = 1;
- return iTimer->add_timer(iTimer->gettick() + tick, skill->blockmerc_end, md->bl.id, idx);
+ return timer->add(timer->gettick() + tick, skill->blockmerc_end, md->bl.id, idx);
}
/**
* Adds a new skill unit entry for this player to recast after map load
**/
void skill_usave_add(struct map_session_data * sd, uint16 skill_id, uint16 skill_lv) {
- struct skill_usave * sus = NULL;
+ struct skill_unit_save * sus = NULL;
- if( idb_exists(skillusave_db,sd->status.char_id) ) {
- idb_remove(skillusave_db,sd->status.char_id);
+ if( idb_exists(skill->usave_db,sd->status.char_id) ) {
+ idb_remove(skill->usave_db,sd->status.char_id);
}
- CREATE( sus, struct skill_usave, 1 );
- idb_put( skillusave_db, sd->status.char_id, sus );
+ CREATE( sus, struct skill_unit_save, 1 );
+ idb_put( skill->usave_db, sd->status.char_id, sus );
sus->skill_id = skill_id;
sus->skill_lv = skill_lv;
@@ -16953,15 +17575,15 @@ void skill_usave_add(struct map_session_data * sd, uint16 skill_id, uint16 skill
return;
}
void skill_usave_trigger(struct map_session_data *sd) {
- struct skill_usave * sus = NULL;
+ struct skill_unit_save * sus = NULL;
- if( ! (sus = idb_get(skillusave_db,sd->status.char_id)) ) {
+ if( ! (sus = idb_get(skill->usave_db,sd->status.char_id)) ) {
return;
}
skill->unitsetting(&sd->bl,sus->skill_id,sus->skill_lv,sd->bl.x,sd->bl.y,0);
- idb_remove(skillusave_db,sd->status.char_id);
+ idb_remove(skill->usave_db,sd->status.char_id);
return;
}
@@ -17029,25 +17651,27 @@ int skill_split_atoi (char *str, int *val) {
void skill_init_unit_layout (void) {
int i,j,size,pos = 0;
- memset(skill_unit_layout,0,sizeof(skill_unit_layout));
+ //when != it was already cleared during skill_defaults() no need to repeat
+ if( runflag == MAPSERVER_ST_RUNNING )
+ memset(skill->unit_layout,0,sizeof(skill->unit_layout));
// standard square layouts go first
for (i=0; i<=MAX_SQUARE_LAYOUT; i++) {
size = i*2+1;
- skill_unit_layout[i].count = size*size;
+ skill->unit_layout[i].count = size*size;
for (j=0; j<size*size; j++) {
- skill_unit_layout[i].dx[j] = (j%size-i);
- skill_unit_layout[i].dy[j] = (j/size-i);
+ skill->unit_layout[i].dx[j] = (j%size-i);
+ skill->unit_layout[i].dy[j] = (j/size-i);
}
}
// afterwards add special ones
pos = i;
for (i=0;i<MAX_SKILL_DB;i++) {
- if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1)
+ if (!skill->db[i].unit_id[0] || skill->db[i].unit_layout_type[0] != -1)
continue;
- switch (skill_db[i].nameid) {
+ switch (skill->db[i].nameid) {
case MG_FIREWALL:
case WZ_ICEWALL:
case WL_EARTHSTRAIN://Warlock
@@ -17061,9 +17685,9 @@ void skill_init_unit_layout (void) {
static const int dy[]={
-2,-2,-2,-1,-1,-1,-1,-1, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2};
- skill_unit_layout[pos].count = 21;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ skill->unit_layout[pos].count = 21;
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
case PR_MAGNUS: {
@@ -17075,18 +17699,18 @@ void skill_init_unit_layout (void) {
-3,-3,-3,-2,-2,-2,-1,-1,-1,-1,
-1,-1,-1, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3};
- skill_unit_layout[pos].count = 33;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ skill->unit_layout[pos].count = 33;
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
case MH_POISON_MIST:
case AS_VENOMDUST: {
static const int dx[] = {-1, 0, 0, 0, 1};
static const int dy[] = { 0,-1, 0, 1, 0};
- skill_unit_layout[pos].count = 5;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ skill->unit_layout[pos].count = 5;
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
case CR_GRANDCROSS:
@@ -17099,9 +17723,9 @@ void skill_init_unit_layout (void) {
-4,-3,-2,-2,-2,-1,-1,-1,-1,-1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 2, 2, 2, 3, 4};
- skill_unit_layout[pos].count = 29;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ skill->unit_layout[pos].count = 29;
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
case PF_FOGWALL: {
@@ -17109,9 +17733,9 @@ void skill_init_unit_layout (void) {
-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2};
static const int dy[] = {
-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
- skill_unit_layout[pos].count = 15;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ skill->unit_layout[pos].count = 15;
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
case PA_GOSPEL: {
@@ -17125,17 +17749,17 @@ void skill_init_unit_layout (void) {
-1,-1,-1, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
3, 3, 3};
- skill_unit_layout[pos].count = 33;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ skill->unit_layout[pos].count = 33;
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
case NJ_KAENSIN: {
static const int dx[] = {-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2};
static const int dy[] = { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2};
- skill_unit_layout[pos].count = 24;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ skill->unit_layout[pos].count = 24;
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
case NJ_TATAMIGAESHI: {
@@ -17150,29 +17774,29 @@ void skill_init_unit_layout (void) {
static const int dy3[] = { 0, 0, 0, 0, 0, 0,-3,-2,-1, 1, 2, 3};
//lv1
j = 0;
- skill_unit_layout[pos].count = 4;
- memcpy(skill_unit_layout[pos].dx,dx1,sizeof(dx1));
- memcpy(skill_unit_layout[pos].dy,dy1,sizeof(dy1));
- skill_db[i].unit_layout_type[j] = pos;
+ skill->unit_layout[pos].count = 4;
+ memcpy(skill->unit_layout[pos].dx,dx1,sizeof(dx1));
+ memcpy(skill->unit_layout[pos].dy,dy1,sizeof(dy1));
+ skill->db[i].unit_layout_type[j] = pos;
//lv2/3
j++;
pos++;
- skill_unit_layout[pos].count = 8;
- memcpy(skill_unit_layout[pos].dx,dx2,sizeof(dx2));
- memcpy(skill_unit_layout[pos].dy,dy2,sizeof(dy2));
- skill_db[i].unit_layout_type[j] = pos;
- skill_db[i].unit_layout_type[++j] = pos;
+ skill->unit_layout[pos].count = 8;
+ memcpy(skill->unit_layout[pos].dx,dx2,sizeof(dx2));
+ memcpy(skill->unit_layout[pos].dy,dy2,sizeof(dy2));
+ skill->db[i].unit_layout_type[j] = pos;
+ skill->db[i].unit_layout_type[++j] = pos;
//lv4/5
j++;
pos++;
- skill_unit_layout[pos].count = 12;
- memcpy(skill_unit_layout[pos].dx,dx3,sizeof(dx3));
- memcpy(skill_unit_layout[pos].dy,dy3,sizeof(dy3));
- skill_db[i].unit_layout_type[j] = pos;
- skill_db[i].unit_layout_type[++j] = pos;
+ skill->unit_layout[pos].count = 12;
+ memcpy(skill->unit_layout[pos].dx,dx3,sizeof(dx3));
+ memcpy(skill->unit_layout[pos].dy,dy3,sizeof(dy3));
+ skill->db[i].unit_layout_type[j] = pos;
+ skill->db[i].unit_layout_type[++j] = pos;
//Fill in the rest using lv 5.
for (;j<MAX_SKILL_LEVEL;j++)
- skill_db[i].unit_layout_type[j] = pos;
+ skill->db[i].unit_layout_type[j] = pos;
//Skip, this way the check below will fail and continue to the next skill.
pos++;
}
@@ -17180,104 +17804,104 @@ void skill_init_unit_layout (void) {
case GN_WALLOFTHORN: {
static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0};
static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2};
- skill_unit_layout[pos].count = 16;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ skill->unit_layout[pos].count = 16;
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
case EL_FIRE_MANTLE: {
static const int dx[] = {-1, 0, 1, 1, 1, 0,-1,-1};
static const int dy[] = { 1, 1, 1, 0,-1,-1,-1, 0};
- skill_unit_layout[pos].count = 8;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ skill->unit_layout[pos].count = 8;
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
default:
ShowError("unknown unit layout at skill %d\n",i);
break;
}
- if (!skill_unit_layout[pos].count)
+ if (!skill->unit_layout[pos].count)
continue;
for (j=0;j<MAX_SKILL_LEVEL;j++)
- skill_db[i].unit_layout_type[j] = pos;
+ skill->db[i].unit_layout_type[j] = pos;
pos++;
}
// firewall and icewall have 8 layouts (direction-dependent)
- firewall_unit_pos = pos;
+ skill->firewall_unit_pos = pos;
for (i=0;i<8;i++) {
if (i&1) {
- skill_unit_layout[pos].count = 5;
+ skill->unit_layout[pos].count = 5;
if (i&0x2) {
int dx[] = {-1,-1, 0, 0, 1};
int dy[] = { 1, 0, 0,-1,-1};
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
} else {
int dx[] = { 1, 1 ,0, 0,-1};
int dy[] = { 1, 0, 0,-1,-1};
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
} else {
- skill_unit_layout[pos].count = 3;
+ skill->unit_layout[pos].count = 3;
if (i%4==0) {
int dx[] = {-1, 0, 1};
int dy[] = { 0, 0, 0};
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
} else {
int dx[] = { 0, 0, 0};
int dy[] = {-1, 0, 1};
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
}
pos++;
}
- icewall_unit_pos = pos;
+ skill->icewall_unit_pos = pos;
for (i=0;i<8;i++) {
- skill_unit_layout[pos].count = 5;
+ skill->unit_layout[pos].count = 5;
if (i&1) {
if (i&0x2) {
int dx[] = {-2,-1, 0, 1, 2};
int dy[] = { 2, 1, 0,-1,-2};
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
} else {
int dx[] = { 2, 1 ,0,-1,-2};
int dy[] = { 2, 1, 0,-1,-2};
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
} else {
if (i%4==0) {
int dx[] = {-2,-1, 0, 1, 2};
int dy[] = { 0, 0, 0, 0, 0};
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
} else {
int dx[] = { 0, 0, 0, 0, 0};
int dy[] = {-2,-1, 0, 1, 2};
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
}
pos++;
}
- earthstrain_unit_pos = pos;
+ skill->earthstrain_unit_pos = pos;
for( i = 0; i < 8; i++ )
{ // For each Direction
- skill_unit_layout[pos].count = 15;
+ skill->unit_layout[pos].count = 15;
switch( i )
{
case 0: case 1: case 3: case 4: case 5: case 7:
{
int dx[] = {-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7};
int dy[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
case 2:
@@ -17285,8 +17909,8 @@ void skill_init_unit_layout (void) {
{
int dx[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int dy[] = {-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7};
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ memcpy(skill->unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill->unit_layout[pos].dy,dy,sizeof(dy));
}
break;
}
@@ -17297,7 +17921,7 @@ void skill_init_unit_layout (void) {
int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) {
int inf = 0;
- struct status_change *sc = status_get_sc(bl);
+ struct status_change *sc = status->get_sc(bl);
if( !sc || !bl || !skill_id )
return 0; // Can do it
@@ -17305,7 +17929,7 @@ int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) {
switch(type){
case SC_STASIS:
inf = skill->get_inf2(skill_id);
- if( inf == INF2_SONG_DANCE || /*skill->get_inf2(skill_id) == INF2_CHORUS_SKILL ||*/ inf == INF2_SPIRIT_SKILL )
+ if( inf == INF2_SONG_DANCE || skill->get_inf2(skill_id) == INF2_CHORUS_SKILL || inf == INF2_SPIRIT_SKILL )
return 1; // Can't do it.
switch( skill_id ) {
case NV_FIRSTAID: case TF_HIDING: case AS_CLOAKING: case WZ_SIGHTRASHER:
@@ -17370,25 +17994,58 @@ int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) {
}
/**
+ * update stored skill cooldowns for player logout
+ * @param sd the affected player structure
+ */
+void skill_cooldown_save(struct map_session_data * sd) {
+ int i;
+ struct skill_cd* cd = NULL;
+ int64 now = 0;
+
+ // always check to make sure the session properly exists
+ nullpo_retv(sd);
+
+ if( !(cd = idb_get(skill->cd_db, sd->status.char_id)) ) {// no skill cooldown is associated with this character
+ return;
+ }
+
+ now = timer->gettick();
+
+ // process each individual cooldown associated with the character
+ for( i = 0; i < cd->cursor; i++ ) {
+ cd->entry[i]->duration = DIFF_TICK32(cd->entry[i]->started+cd->entry[i]->duration,now);
+ if( cd->entry[i]->timer != INVALID_TIMER ) {
+ timer->delete(cd->entry[i]->timer,skill->blockpc_end);
+ cd->entry[i]->timer = INVALID_TIMER;
+ }
+ }
+}
+
+/**
* reload stored skill cooldowns when a player logs in.
* @param sd the affected player structure
*/
-void skill_cooldown_load(struct map_session_data * sd)
-{
+void skill_cooldown_load(struct map_session_data * sd) {
int i;
struct skill_cd* cd = NULL;
+ int64 now = 0;
// always check to make sure the session properly exists
nullpo_retv(sd);
- if( !(cd = idb_get(skillcd_db, sd->status.char_id)) ) {// no skill cooldown is associated with this character
+ if( !(cd = idb_get(skill->cd_db, sd->status.char_id)) ) {// no skill cooldown is associated with this character
return;
}
+ clif->cooldown_list(sd->fd,cd);
+
+ now = timer->gettick();
+
// process each individual cooldown associated with the character
for( i = 0; i < cd->cursor; i++ ) {
- // block the skill from usage but ensure it is not recorded (load = true)
- skill->blockpc_start( sd, cd->nameid[i], cd->duration[i], true );
+ cd->entry[i]->started = now;
+ cd->entry[i]->timer = timer->add(timer->gettick()+cd->entry[i]->duration,skill->blockpc_end,sd->bl.id,cd->entry[i]->skidx);
+ sd->blockskill[cd->entry[i]->skidx] = true;
}
}
@@ -17412,35 +18069,36 @@ bool skill_parse_row_skilldb(char* split[], int columns, int current) {
if( !idx ) // invalid skill id
return false;
- skill_db[idx].nameid = skill_id;
- skill->split_atoi(split[1],skill_db[idx].range);
- skill_db[idx].hit = atoi(split[2]);
- skill_db[idx].inf = atoi(split[3]);
- skill->split_atoi(split[4],skill_db[idx].element);
- skill_db[idx].nk = (int)strtol(split[5], NULL, 0);
- skill->split_atoi(split[6],skill_db[idx].splash);
- skill_db[idx].max = atoi(split[7]);
- skill->split_atoi(split[8],skill_db[idx].num);
+ skill->db[idx].nameid = skill_id;
+ skill->split_atoi(split[1],skill->db[idx].range);
+ skill->db[idx].hit = atoi(split[2]);
+ skill->db[idx].inf = atoi(split[3]);
+ skill->split_atoi(split[4],skill->db[idx].element);
+ skill->db[idx].nk = (int)strtol(split[5], NULL, 0);
+ skill->split_atoi(split[6],skill->db[idx].splash);
+ skill->db[idx].max = atoi(split[7]);
+ skill->split_atoi(split[8],skill->db[idx].num);
if( strcmpi(split[9],"yes") == 0 )
- skill_db[idx].castcancel = 1;
+ skill->db[idx].castcancel = 1;
else
- skill_db[idx].castcancel = 0;
- skill_db[idx].cast_def_rate = atoi(split[10]);
- skill_db[idx].inf2 = (int)strtol(split[11], NULL, 0);
- skill->split_atoi(split[12],skill_db[idx].maxcount);
+ skill->db[idx].castcancel = 0;
+ skill->db[idx].cast_def_rate = atoi(split[10]);
+ skill->db[idx].inf2 = (int)strtol(split[11], NULL, 0);
+ skill->split_atoi(split[12],skill->db[idx].maxcount);
if( strcmpi(split[13],"weapon") == 0 )
- skill_db[idx].skill_type = BF_WEAPON;
+ skill->db[idx].skill_type = BF_WEAPON;
else if( strcmpi(split[13],"magic") == 0 )
- skill_db[idx].skill_type = BF_MAGIC;
+ skill->db[idx].skill_type = BF_MAGIC;
else if( strcmpi(split[13],"misc") == 0 )
- skill_db[idx].skill_type = BF_MISC;
+ skill->db[idx].skill_type = BF_MISC;
else
- skill_db[idx].skill_type = 0;
- skill->split_atoi(split[14],skill_db[idx].blewcount);
- safestrncpy(skill_db[idx].name, trim(split[15]), sizeof(skill_db[idx].name));
- safestrncpy(skill_db[idx].desc, trim(split[16]), sizeof(skill_db[idx].desc));
- strdb_iput(skilldb_name2id, skill_db[idx].name, skill_id);
+ skill->db[idx].skill_type = 0;
+ skill->split_atoi(split[14],skill->db[idx].blewcount);
+ safestrncpy(skill->db[idx].name, trim(split[15]), sizeof(skill->db[idx].name));
+ safestrncpy(skill->db[idx].desc, trim(split[16]), sizeof(skill->db[idx].desc));
+ strdb_iput(skill->name2id_db, skill->db[idx].name, skill_id);
+ script->set_constant2(skill->db[idx].name,(int)skill_id,0);
return true;
}
@@ -17455,22 +18113,22 @@ bool skill_parse_row_requiredb(char* split[], int columns, int current) {
if( !idx ) // invalid skill id
return false;
- skill->split_atoi(split[1],skill_db[idx].hp);
- skill->split_atoi(split[2],skill_db[idx].mhp);
- skill->split_atoi(split[3],skill_db[idx].sp);
- skill->split_atoi(split[4],skill_db[idx].hp_rate);
- skill->split_atoi(split[5],skill_db[idx].sp_rate);
- skill->split_atoi(split[6],skill_db[idx].zeny);
+ skill->split_atoi(split[1],skill->db[idx].hp);
+ skill->split_atoi(split[2],skill->db[idx].mhp);
+ skill->split_atoi(split[3],skill->db[idx].sp);
+ skill->split_atoi(split[4],skill->db[idx].hp_rate);
+ skill->split_atoi(split[5],skill->db[idx].sp_rate);
+ skill->split_atoi(split[6],skill->db[idx].zeny);
- //Wich weapon type are required, see doc/item_db for types
+ //Which weapon type are required, see doc/item_db for types
p = split[7];
for( j = 0; j < 32; j++ ) {
int l = atoi(p);
if( l == 99 ) { // Any weapon
- skill_db[idx].weapon = 0;
+ skill->db[idx].weapon = 0;
break;
} else
- skill_db[idx].weapon |= 1<<l;
+ skill->db[idx].weapon |= 1<<l;
p = strchr(p,':');
if(!p)
break;
@@ -17482,49 +18140,49 @@ bool skill_parse_row_requiredb(char* split[], int columns, int current) {
for( j = 0; j < 32; j++ ) {
int l = atoi(p);
if( l == 99 ) { // Any ammo type
- skill_db[idx].ammo = 0xFFFFFFFF;
+ skill->db[idx].ammo = 0xFFFFFFFF;
break;
} else if( l ) // 0 stands for no requirement
- skill_db[idx].ammo |= 1<<l;
+ skill->db[idx].ammo |= 1<<l;
p = strchr(p,':');
if( !p )
break;
p++;
}
- skill->split_atoi(split[9],skill_db[idx].ammo_qty);
-
- if( strcmpi(split[10],"hiding") == 0 ) skill_db[idx].state = ST_HIDING;
- else if( strcmpi(split[10],"cloaking") == 0 ) skill_db[idx].state = ST_CLOAKING;
- else if( strcmpi(split[10],"hidden") == 0 ) skill_db[idx].state = ST_HIDDEN;
- else if( strcmpi(split[10],"riding") == 0 ) skill_db[idx].state = ST_RIDING;
- else if( strcmpi(split[10],"falcon") == 0 ) skill_db[idx].state = ST_FALCON;
- else if( strcmpi(split[10],"cart") == 0 ) skill_db[idx].state = ST_CART;
- else if( strcmpi(split[10],"shield") == 0 ) skill_db[idx].state = ST_SHIELD;
- else if( strcmpi(split[10],"sight") == 0 ) skill_db[idx].state = ST_SIGHT;
- else if( strcmpi(split[10],"explosionspirits") == 0 ) skill_db[idx].state = ST_EXPLOSIONSPIRITS;
- else if( strcmpi(split[10],"cartboost") == 0 ) skill_db[idx].state = ST_CARTBOOST;
- else if( strcmpi(split[10],"recover_weight_rate") == 0 ) skill_db[idx].state = ST_RECOV_WEIGHT_RATE;
- else if( strcmpi(split[10],"move_enable") == 0 ) skill_db[idx].state = ST_MOVE_ENABLE;
- else if( strcmpi(split[10],"water") == 0 ) skill_db[idx].state = ST_WATER;
- else if( strcmpi(split[10],"dragon") == 0 ) skill_db[idx].state = ST_RIDINGDRAGON;
- else if( strcmpi(split[10],"warg") == 0 ) skill_db[idx].state = ST_WUG;
- else if( strcmpi(split[10],"ridingwarg") == 0 ) skill_db[idx].state = ST_RIDINGWUG;
- else if( strcmpi(split[10],"mado") == 0 ) skill_db[idx].state = ST_MADO;
- else if( strcmpi(split[10],"elementalspirit") == 0 ) skill_db[idx].state = ST_ELEMENTALSPIRIT;
- else if( strcmpi(split[10],"poisonweapon") == 0 ) skill_db[idx].state = ST_POISONINGWEAPON;
- else if( strcmpi(split[10],"rollingcutter") == 0 ) skill_db[idx].state = ST_ROLLINGCUTTER;
- else if( strcmpi(split[10],"mh_fighting") == 0 ) skill_db[idx].state = ST_MH_FIGHTING;
- else if( strcmpi(split[10],"mh_grappling") == 0 ) skill_db[idx].state = ST_MH_GRAPPLING;
- else if( strcmpi(split[10],"peco") == 0 ) skill_db[idx].state = ST_PECO;
+ skill->split_atoi(split[9],skill->db[idx].ammo_qty);
+
+ if( strcmpi(split[10],"hiding") == 0 ) skill->db[idx].state = ST_HIDING;
+ else if( strcmpi(split[10],"cloaking") == 0 ) skill->db[idx].state = ST_CLOAKING;
+ else if( strcmpi(split[10],"hidden") == 0 ) skill->db[idx].state = ST_HIDDEN;
+ else if( strcmpi(split[10],"riding") == 0 ) skill->db[idx].state = ST_RIDING;
+ else if( strcmpi(split[10],"falcon") == 0 ) skill->db[idx].state = ST_FALCON;
+ else if( strcmpi(split[10],"cart") == 0 ) skill->db[idx].state = ST_CART;
+ else if( strcmpi(split[10],"shield") == 0 ) skill->db[idx].state = ST_SHIELD;
+ else if( strcmpi(split[10],"sight") == 0 ) skill->db[idx].state = ST_SIGHT;
+ else if( strcmpi(split[10],"explosionspirits") == 0 ) skill->db[idx].state = ST_EXPLOSIONSPIRITS;
+ else if( strcmpi(split[10],"cartboost") == 0 ) skill->db[idx].state = ST_CARTBOOST;
+ else if( strcmpi(split[10],"recover_weight_rate") == 0 ) skill->db[idx].state = ST_RECOV_WEIGHT_RATE;
+ else if( strcmpi(split[10],"move_enable") == 0 ) skill->db[idx].state = ST_MOVE_ENABLE;
+ else if( strcmpi(split[10],"water") == 0 ) skill->db[idx].state = ST_WATER;
+ else if( strcmpi(split[10],"dragon") == 0 ) skill->db[idx].state = ST_RIDINGDRAGON;
+ else if( strcmpi(split[10],"warg") == 0 ) skill->db[idx].state = ST_WUG;
+ else if( strcmpi(split[10],"ridingwarg") == 0 ) skill->db[idx].state = ST_RIDINGWUG;
+ else if( strcmpi(split[10],"mado") == 0 ) skill->db[idx].state = ST_MADO;
+ else if( strcmpi(split[10],"elementalspirit") == 0 ) skill->db[idx].state = ST_ELEMENTALSPIRIT;
+ else if( strcmpi(split[10],"poisonweapon") == 0 ) skill->db[idx].state = ST_POISONINGWEAPON;
+ else if( strcmpi(split[10],"rollingcutter") == 0 ) skill->db[idx].state = ST_ROLLINGCUTTER;
+ else if( strcmpi(split[10],"mh_fighting") == 0 ) skill->db[idx].state = ST_MH_FIGHTING;
+ else if( strcmpi(split[10],"mh_grappling") == 0 ) skill->db[idx].state = ST_MH_GRAPPLING;
+ else if( strcmpi(split[10],"peco") == 0 ) skill->db[idx].state = ST_PECO;
/**
* Unknown or no state
**/
- else skill_db[idx].state = ST_NONE;
+ else skill->db[idx].state = ST_NONE;
- skill->split_atoi(split[11],skill_db[idx].spiritball);
+ skill->split_atoi(split[11],skill->db[idx].spiritball);
for( j = 0; j < MAX_SKILL_ITEM_REQUIRE; j++ ) {
- skill_db[idx].itemid[j] = atoi(split[12+ 2*j]);
- skill_db[idx].amount[j] = atoi(split[13+ 2*j]);
+ skill->db[idx].itemid[j] = atoi(split[12+ 2*j]);
+ skill->db[idx].amount[j] = atoi(split[13+ 2*j]);
}
return true;
@@ -17537,14 +18195,14 @@ bool skill_parse_row_castdb(char* split[], int columns, int current) {
if( !idx ) // invalid skill id
return false;
- skill->split_atoi(split[1],skill_db[idx].cast);
- skill->split_atoi(split[2],skill_db[idx].delay);
- skill->split_atoi(split[3],skill_db[idx].walkdelay);
- skill->split_atoi(split[4],skill_db[idx].upkeep_time);
- skill->split_atoi(split[5],skill_db[idx].upkeep_time2);
- skill->split_atoi(split[6],skill_db[idx].cooldown);
+ skill->split_atoi(split[1],skill->db[idx].cast);
+ skill->split_atoi(split[2],skill->db[idx].delay);
+ skill->split_atoi(split[3],skill->db[idx].walkdelay);
+ skill->split_atoi(split[4],skill->db[idx].upkeep_time);
+ skill->split_atoi(split[5],skill->db[idx].upkeep_time2);
+ skill->split_atoi(split[6],skill->db[idx].cooldown);
#ifdef RENEWAL_CAST
- skill->split_atoi(split[7],skill_db[idx].fixed_cast);
+ skill->split_atoi(split[7],skill->db[idx].fixed_cast);
#endif
return true;
}
@@ -17556,9 +18214,9 @@ bool skill_parse_row_castnodexdb(char* split[], int columns, int current) {
if( !idx ) // invalid skill id
return false;
- skill->split_atoi(split[1],skill_db[idx].castnodex);
+ skill->split_atoi(split[1],skill->db[idx].castnodex);
if( split[2] ) // optional column
- skill->split_atoi(split[2],skill_db[idx].delaynodex);
+ skill->split_atoi(split[2],skill->db[idx].delaynodex);
return true;
}
@@ -17570,37 +18228,37 @@ bool skill_parse_row_unitdb(char* split[], int columns, int current) {
if( !idx ) // invalid skill id
return false;
- skill_db[idx].unit_id[0] = strtol(split[1],NULL,16);
- skill_db[idx].unit_id[1] = strtol(split[2],NULL,16);
- skill->split_atoi(split[3],skill_db[idx].unit_layout_type);
- skill->split_atoi(split[4],skill_db[idx].unit_range);
- skill_db[idx].unit_interval = atoi(split[5]);
-
- if( strcmpi(split[6],"noenemy")==0 ) skill_db[idx].unit_target = BCT_NOENEMY;
- else if( strcmpi(split[6],"friend")==0 ) skill_db[idx].unit_target = BCT_NOENEMY;
- else if( strcmpi(split[6],"party")==0 ) skill_db[idx].unit_target = BCT_PARTY;
- else if( strcmpi(split[6],"ally")==0 ) skill_db[idx].unit_target = BCT_PARTY|BCT_GUILD;
- else if( strcmpi(split[6],"guild")==0 ) skill_db[idx].unit_target = BCT_GUILD;
- else if( strcmpi(split[6],"all")==0 ) skill_db[idx].unit_target = BCT_ALL;
- else if( strcmpi(split[6],"enemy")==0 ) skill_db[idx].unit_target = BCT_ENEMY;
- else if( strcmpi(split[6],"self")==0 ) skill_db[idx].unit_target = BCT_SELF;
- else if( strcmpi(split[6],"sameguild")==0 ) skill_db[idx].unit_target = BCT_GUILD|BCT_SAMEGUILD;
- else if( strcmpi(split[6],"noone")==0 ) skill_db[idx].unit_target = BCT_NOONE;
- else skill_db[idx].unit_target = strtol(split[6],NULL,16);
-
- skill_db[idx].unit_flag = strtol(split[7],NULL,16);
-
- if (skill_db[idx].unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy)
- skill_db[idx].unit_target = BCT_NOENEMY;
+ skill->db[idx].unit_id[0] = (int)strtol(split[1],NULL,16);
+ skill->db[idx].unit_id[1] = (int)strtol(split[2],NULL,16);
+ skill->split_atoi(split[3],skill->db[idx].unit_layout_type);
+ skill->split_atoi(split[4],skill->db[idx].unit_range);
+ skill->db[idx].unit_interval = atoi(split[5]);
+
+ if( strcmpi(split[6],"noenemy")==0 ) skill->db[idx].unit_target = BCT_NOENEMY;
+ else if( strcmpi(split[6],"friend")==0 ) skill->db[idx].unit_target = BCT_NOENEMY;
+ else if( strcmpi(split[6],"party")==0 ) skill->db[idx].unit_target = BCT_PARTY;
+ else if( strcmpi(split[6],"ally")==0 ) skill->db[idx].unit_target = BCT_PARTY|BCT_GUILD;
+ else if( strcmpi(split[6],"guild")==0 ) skill->db[idx].unit_target = BCT_GUILD;
+ else if( strcmpi(split[6],"all")==0 ) skill->db[idx].unit_target = BCT_ALL;
+ else if( strcmpi(split[6],"enemy")==0 ) skill->db[idx].unit_target = BCT_ENEMY;
+ else if( strcmpi(split[6],"self")==0 ) skill->db[idx].unit_target = BCT_SELF;
+ else if( strcmpi(split[6],"sameguild")==0 ) skill->db[idx].unit_target = BCT_GUILD|BCT_SAMEGUILD;
+ else if( strcmpi(split[6],"noone")==0 ) skill->db[idx].unit_target = BCT_NOONE;
+ else skill->db[idx].unit_target = (int)strtol(split[6],NULL,16);
+
+ skill->db[idx].unit_flag = (int)strtol(split[7],NULL,16);
+
+ if (skill->db[idx].unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy)
+ skill->db[idx].unit_target = BCT_NOENEMY;
//By default, target just characters.
- skill_db[idx].unit_target |= BL_CHAR;
- if (skill_db[idx].unit_flag&UF_NOPC)
- skill_db[idx].unit_target &= ~BL_PC;
- if (skill_db[idx].unit_flag&UF_NOMOB)
- skill_db[idx].unit_target &= ~BL_MOB;
- if (skill_db[idx].unit_flag&UF_SKILL)
- skill_db[idx].unit_target |= BL_SKILL;
+ skill->db[idx].unit_target |= BL_CHAR;
+ if (skill->db[idx].unit_flag&UF_NOPC)
+ skill->db[idx].unit_target &= ~BL_PC;
+ if (skill->db[idx].unit_flag&UF_NOMOB)
+ skill->db[idx].unit_target &= ~BL_MOB;
+ if (skill->db[idx].unit_flag&UF_SKILL)
+ skill->db[idx].unit_target |= BL_SKILL;
return true;
}
@@ -17613,14 +18271,14 @@ bool skill_parse_row_producedb(char* split[], int columns, int current) {
if( !i )
return false;
- skill_produce_db[current].nameid = i;
- skill_produce_db[current].itemlv = atoi(split[1]);
- skill_produce_db[current].req_skill = atoi(split[2]);
- skill_produce_db[current].req_skill_lv = atoi(split[3]);
+ skill->produce_db[current].nameid = i;
+ skill->produce_db[current].itemlv = atoi(split[1]);
+ skill->produce_db[current].req_skill = atoi(split[2]);
+ skill->produce_db[current].req_skill_lv = atoi(split[3]);
for( x = 4, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_PRODUCE_RESOURCE; x += 2, y++ ) {
- skill_produce_db[current].mat_id[y] = atoi(split[x]);
- skill_produce_db[current].mat_amount[y] = atoi(split[x+1]);
+ skill->produce_db[current].mat_id[y] = atoi(split[x]);
+ skill->produce_db[current].mat_amount[y] = atoi(split[x+1]);
}
return true;
@@ -17634,11 +18292,11 @@ bool skill_parse_row_createarrowdb(char* split[], int columns, int current) {
if( !i )
return false;
- skill_arrow_db[current].nameid = i;
+ skill->arrow_db[current].nameid = i;
for( x = 1, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_ARROW_RESOURCE; x += 2, y++ ) {
- skill_arrow_db[current].cre_id[y] = atoi(split[x]);
- skill_arrow_db[current].cre_amount[y] = atoi(split[x+1]);
+ skill->arrow_db[current].cre_id[y] = atoi(split[x]);
+ skill->arrow_db[current].cre_amount[y] = atoi(split[x+1]);
}
return true;
@@ -17657,9 +18315,9 @@ bool skill_parse_row_spellbookdb(char* split[], int columns, int current) {
if( points < 1 )
ShowError("spellbook_db: PreservePoints have to be 1 or above! (%d/%s)\n", skill_id, skill->get_name(skill_id));
else {
- skill_spellbook_db[current].skill_id = skill_id;
- skill_spellbook_db[current].point = points;
- skill_spellbook_db[current].nameid = nameid;
+ skill->spellbook_db[current].skill_id = skill_id;
+ skill->spellbook_db[current].point = points;
+ skill->spellbook_db[current].nameid = nameid;
return true;
}
@@ -17686,8 +18344,8 @@ bool skill_parse_row_improvisedb(char* split[], int columns, int current) {
if( current >= MAX_SKILL_IMPROVISE_DB ) {
ShowError("skill_improvise_db: Maximum amount of entries reached (%d), increase MAX_SKILL_IMPROVISE_DB\n",MAX_SKILL_IMPROVISE_DB);
}
- skill_improvise_db[current].skill_id = skill_id;
- skill_improvise_db[current].per = j; // Still need confirm it.
+ skill->improvise_db[current].skill_id = skill_id;
+ skill->improvise_db[current].per = j; // Still need confirm it.
return true;
}
@@ -17704,7 +18362,7 @@ bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) {
return false;
}
- skill_magicmushroom_db[current].skill_id = skill_id;
+ skill->magicmushroom_db[current].skill_id = skill_id;
return true;
}
@@ -17715,7 +18373,7 @@ bool skill_parse_row_reproducedb(char* split[], int column, int current) {
if( !idx )
return false;
- skill_reproduce_db[idx] = true;
+ skill->reproduce_db[idx] = true;
return true;
}
@@ -17733,9 +18391,9 @@ bool skill_parse_row_abradb(char* split[], int columns, int current) {
return false;
}
- skill_abra_db[current].skill_id = skill_id;
- skill_abra_db[current].req_lv = atoi(split[2]);
- skill_abra_db[current].per = atoi(split[3]);
+ skill->abra_db[current].skill_id = skill_id;
+ skill->abra_db[current].req_lv = atoi(split[2]);
+ skill->abra_db[current].per = atoi(split[3]);
return true;
}
@@ -17747,8 +18405,8 @@ bool skill_parse_row_changematerialdb(char* split[], int columns, int current) {
int x,y;
for(x=0; x<MAX_SKILL_PRODUCE_DB; x++){
- if( skill_produce_db[x].nameid == skill_id )
- if( skill_produce_db[x].req_skill == GN_CHANGEMATERIAL )
+ if( skill->produce_db[x].nameid == skill_id )
+ if( skill->produce_db[x].req_skill == GN_CHANGEMATERIAL )
break;
}
@@ -17761,12 +18419,12 @@ bool skill_parse_row_changematerialdb(char* split[], int columns, int current) {
ShowError("skill_changematerial_db: Maximum amount of entries reached (%d), increase MAX_SKILL_PRODUCE_DB\n",MAX_SKILL_PRODUCE_DB);
}
- skill_changematerial_db[current].itemid = skill_id;
- skill_changematerial_db[current].rate = j;
+ skill->changematerial_db[current].itemid = skill_id;
+ skill->changematerial_db[current].rate = j;
for( x = 2, y = 0; x+1 < columns && split[x] && split[x+1] && y < 5; x += 2, y++ ) {
- skill_changematerial_db[current].qty[y] = atoi(split[x]);
- skill_changematerial_db[current].qty_rate[y] = atoi(split[x+1]);
+ skill->changematerial_db[current].qty[y] = atoi(split[x]);
+ skill->changematerial_db[current].qty_rate[y] = atoi(split[x+1]);
}
return true;
@@ -17784,43 +18442,59 @@ bool skill_parse_row_changematerialdb(char* split[], int columns, int current) {
* create_arrow_db.txt
* abra_db.txt
*------------------------------*/
-void skill_readdb(void) {
+void skill_readdb(bool minimal) {
// init skill db structures
- db_clear(skilldb_name2id);
- memset(skill_db,0,sizeof(skill_db));
- memset(skill_produce_db,0,sizeof(skill_produce_db));
- memset(skill_arrow_db,0,sizeof(skill_arrow_db));
- memset(skill_abra_db,0,sizeof(skill_abra_db));
- memset(skill_spellbook_db,0,sizeof(skill_spellbook_db));
- memset(skill_magicmushroom_db,0,sizeof(skill_magicmushroom_db));
- memset(skill_reproduce_db,0,sizeof(skill_reproduce_db));
- memset(skill_changematerial_db,0,sizeof(skill_changematerial_db));
+ db_clear(skill->name2id_db);
+
+ /* when != it was called during init and this procedure was already performed by skill_defaults() */
+ if( runflag == MAPSERVER_ST_RUNNING ) {
+ memset(skill->db,0,sizeof(skill->db)
+ + sizeof(skill->produce_db)
+ + sizeof(skill->arrow_db)
+ + sizeof(skill->abra_db)
+ + sizeof(skill->magicmushroom_db)
+ + sizeof(skill->improvise_db)
+ + sizeof(skill->changematerial_db)
+ + sizeof(skill->spellbook_db)
+ + sizeof(skill->reproduce_db)
+ );
+ }
// load skill databases
- safestrncpy(skill_db[0].name, "UNKNOWN_SKILL", sizeof(skill_db[0].name));
- safestrncpy(skill_db[0].desc, "Unknown Skill", sizeof(skill_db[0].desc));
+ safestrncpy(skill->db[0].name, "UNKNOWN_SKILL", sizeof(skill->db[0].name));
+ safestrncpy(skill->db[0].desc, "Unknown Skill", sizeof(skill->db[0].desc));
+
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = DBPATH"skill_db.txt";
+#endif // ENABLE_CASE_CHECK
+ sv->readdb(map->db_path, DBPATH"skill_db.txt", ',', 17, 17, MAX_SKILL_DB, skill->parse_row_skilldb);
+#ifdef ENABLE_CASE_CHECK
+ script->parser_current_file = NULL;
+#endif // ENABLE_CASE_CHECK
+
+ if (minimal)
+ return;
- sv->readdb(iMap->db_path, DBPATH"skill_db.txt" , ',', 17, 17, MAX_SKILL_DB, skill->parse_row_skilldb);
- sv->readdb(iMap->db_path, DBPATH"skill_require_db.txt" , ',', 32, 32, MAX_SKILL_DB, skill->parse_row_requiredb);
+ sv->readdb(map->db_path, DBPATH"skill_require_db.txt", ',', 32, 32, MAX_SKILL_DB, skill->parse_row_requiredb);
#ifdef RENEWAL_CAST
- sv->readdb(iMap->db_path, "re/skill_cast_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill->parse_row_castdb);
+ sv->readdb(map->db_path, "re/skill_cast_db.txt", ',', 8, 8, MAX_SKILL_DB, skill->parse_row_castdb);
#else
- sv->readdb(iMap->db_path, "pre-re/skill_cast_db.txt" , ',', 7, 7, MAX_SKILL_DB, skill->parse_row_castdb);
+ sv->readdb(map->db_path, "pre-re/skill_cast_db.txt", ',', 7, 7, MAX_SKILL_DB, skill->parse_row_castdb);
#endif
- sv->readdb(iMap->db_path, DBPATH"skill_castnodex_db.txt", ',', 2, 3, MAX_SKILL_DB, skill->parse_row_castnodexdb);
- sv->readdb(iMap->db_path, DBPATH"skill_unit_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill->parse_row_unitdb);
+ sv->readdb(map->db_path, DBPATH"skill_castnodex_db.txt", ',', 2, 3, MAX_SKILL_DB, skill->parse_row_castnodexdb);
+ sv->readdb(map->db_path, DBPATH"skill_unit_db.txt", ',', 8, 8, MAX_SKILL_DB, skill->parse_row_unitdb);
skill->init_unit_layout();
- sv->readdb(iMap->db_path, "produce_db.txt" , ',', 4, 4+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill->parse_row_producedb);
- sv->readdb(iMap->db_path, "create_arrow_db.txt" , ',', 1+2, 1+2*MAX_ARROW_RESOURCE, MAX_SKILL_ARROW_DB, skill->parse_row_createarrowdb);
- sv->readdb(iMap->db_path, "abra_db.txt" , ',', 4, 4, MAX_SKILL_ABRA_DB, skill->parse_row_abradb);
+ sv->readdb(map->db_path, "produce_db.txt", ',', 4, 4+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill->parse_row_producedb);
+ sv->readdb(map->db_path, "create_arrow_db.txt", ',', 1+2, 1+2*MAX_ARROW_RESOURCE, MAX_SKILL_ARROW_DB, skill->parse_row_createarrowdb);
+ sv->readdb(map->db_path, "abra_db.txt", ',', 4, 4, MAX_SKILL_ABRA_DB, skill->parse_row_abradb);
//Warlock
- sv->readdb(iMap->db_path, "spellbook_db.txt" , ',', 3, 3, MAX_SKILL_SPELLBOOK_DB, skill->parse_row_spellbookdb);
+ sv->readdb(map->db_path, "spellbook_db.txt", ',', 3, 3, MAX_SKILL_SPELLBOOK_DB, skill->parse_row_spellbookdb);
//Guillotine Cross
- sv->readdb(iMap->db_path, "magicmushroom_db.txt" , ',', 1, 1, MAX_SKILL_MAGICMUSHROOM_DB, skill->parse_row_magicmushroomdb);
- sv->readdb(iMap->db_path, "skill_reproduce_db.txt", ',', 1, 1, MAX_SKILL_DB, skill->parse_row_reproducedb);
- sv->readdb(iMap->db_path, "skill_improvise_db.txt" , ',', 2, 2, MAX_SKILL_IMPROVISE_DB, skill->parse_row_improvisedb);
- sv->readdb(iMap->db_path, "skill_changematerial_db.txt" , ',', 4, 4+2*5, MAX_SKILL_PRODUCE_DB, skill->parse_row_changematerialdb);
+ sv->readdb(map->db_path, "magicmushroom_db.txt", ',', 1, 1, MAX_SKILL_MAGICMUSHROOM_DB, skill->parse_row_magicmushroomdb);
+ sv->readdb(map->db_path, "skill_reproduce_db.txt", ',', 1, 1, MAX_SKILL_DB, skill->parse_row_reproducedb);
+ sv->readdb(map->db_path, "skill_improvise_db.txt", ',', 2, 2, MAX_SKILL_IMPROVISE_DB, skill->parse_row_improvisedb);
+ sv->readdb(map->db_path, "skill_changematerial_db.txt", ',', 4, 4+2*5, MAX_SKILL_PRODUCE_DB, skill->parse_row_changematerialdb);
}
void skill_reload (void) {
@@ -17828,21 +18502,21 @@ void skill_reload (void) {
struct map_session_data *sd;
int i,c,k;
- skill->read_db();
+ skill->read_db(false);
//[Ind/Hercules] refresh index cache
for(c = 0; c < CLASS_COUNT; c++) {
for( i = 0; i < MAX_SKILL_TREE; i++ ) {
- if( skill_tree[c][i].id ) {
- skill_tree[c][i].idx = skill->get_index(skill_tree[c][i].id);
+ if( pc->skill_tree[c][i].id ) {
+ pc->skill_tree[c][i].idx = skill->get_index(pc->skill_tree[c][i].id);
for(k = 0; k < MAX_PC_SKILL_REQUIRE; k++) {
- if( skill_tree[c][i].need[k].id )
- skill_tree[c][i].need[k].idx = skill->get_index(skill_tree[c][i].need[k].id);
+ if( pc->skill_tree[c][i].need[k].id )
+ pc->skill_tree[c][i].need[k].idx = skill->get_index(pc->skill_tree[c][i].need[k].id);
}
}
}
}
- chrif_skillid2idx(0);
+ chrif->skillid2idx(0);
/* lets update all players skill tree : so that if any skill modes were changed they're properly updated */
iter = mapit_getallusers();
for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) )
@@ -17854,47 +18528,97 @@ void skill_reload (void) {
/*==========================================
*
*------------------------------------------*/
-int do_init_skill (void) {
- skilldb_name2id = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 0);
- skill->read_db();
-
- group_db = idb_alloc(DB_OPT_BASE);
- skillunit_db = idb_alloc(DB_OPT_BASE);
- skillcd_db = idb_alloc(DB_OPT_RELEASE_DATA);
- skillusave_db = idb_alloc(DB_OPT_RELEASE_DATA);
- skill_unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.c::skill_unit_ers",ERS_OPT_NONE);
- skill_timer_ers = ers_new(sizeof(struct skill_timerskill),"skill.c::skill_timer_ers",ERS_OPT_NONE);
+int do_init_skill(bool minimal) {
+ skill->name2id_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, MAX_SKILL_NAME_LENGTH);
+ skill->read_db(minimal);
- iTimer->add_timer_func_list(skill->unit_timer,"skill_unit_timer");
- iTimer->add_timer_func_list(skill->castend_id,"skill_castend_id");
- iTimer->add_timer_func_list(skill->castend_pos,"skill_castend_pos");
- iTimer->add_timer_func_list(skill->timerskill,"skill_timerskill");
- iTimer->add_timer_func_list(skill->blockpc_end, "skill_blockpc_end");
+ if (minimal)
+ return 0;
- iTimer->add_timer_interval(iTimer->gettick()+SKILLUNITTIMER_INTERVAL,skill->unit_timer,0,0,SKILLUNITTIMER_INTERVAL);
+ skill->group_db = idb_alloc(DB_OPT_BASE);
+ skill->unit_db = idb_alloc(DB_OPT_BASE);
+ skill->cd_db = idb_alloc(DB_OPT_BASE);
+ skill->usave_db = idb_alloc(DB_OPT_RELEASE_DATA);
+ skill->bowling_db = idb_alloc(DB_OPT_BASE);
+ skill->unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.c::skill_unit_ers",ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
+ skill->timer_ers = ers_new(sizeof(struct skill_timerskill),"skill.c::skill_timer_ers",ERS_OPT_NONE|ERS_OPT_FLEX_CHUNK);
+ skill->cd_ers = ers_new(sizeof(struct skill_cd),"skill.c::skill_cd_ers",ERS_OPT_CLEAR|ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
+ skill->cd_entry_ers = ers_new(sizeof(struct skill_cd_entry),"skill.c::skill_cd_entry_ers",ERS_OPT_CLEAR|ERS_OPT_FLEX_CHUNK);
+
+ ers_chunk_size(skill->cd_ers, 25);
+ ers_chunk_size(skill->cd_entry_ers, 100);
+ ers_chunk_size(skill->unit_ers, 150);
+ ers_chunk_size(skill->timer_ers, 150);
+
+ timer->add_func_list(skill->unit_timer,"skill_unit_timer");
+ timer->add_func_list(skill->castend_id,"skill_castend_id");
+ timer->add_func_list(skill->castend_pos,"skill_castend_pos");
+ timer->add_func_list(skill->timerskill,"skill_timerskill");
+ timer->add_func_list(skill->blockpc_end, "skill_blockpc_end");
+ timer->add_interval(timer->gettick()+SKILLUNITTIMER_INTERVAL,skill->unit_timer,0,0,SKILLUNITTIMER_INTERVAL);
+
return 0;
}
-int do_final_skill(void)
-{
- db_destroy(skilldb_name2id);
- db_destroy(group_db);
- db_destroy(skillunit_db);
- db_destroy(skillcd_db);
- db_destroy(skillusave_db);
- ers_destroy(skill_unit_ers);
- ers_destroy(skill_timer_ers);
+int do_final_skill(void) {
+
+ db_destroy(skill->name2id_db);
+ db_destroy(skill->group_db);
+ db_destroy(skill->unit_db);
+ db_destroy(skill->cd_db);
+ db_destroy(skill->usave_db);
+ db_destroy(skill->bowling_db);
+ ers_destroy(skill->unit_ers);
+ ers_destroy(skill->timer_ers);
+ ers_destroy(skill->cd_ers);
+ ers_destroy(skill->cd_entry_ers);
return 0;
}
/* initialize the interface */
void skill_defaults(void) {
+ const int skill_enchant_eff[5] = { 10, 14, 17, 19, 20 };
+ const int skill_deluge_eff[5] = { 5, 9, 12, 14, 15 };
+
skill = &skill_s;
skill->init = do_init_skill;
skill->final = do_final_skill;
skill->reload = skill_reload;
skill->read_db = skill_readdb;
- /* accesssors */
+ /* */
+ skill->cd_db = NULL;
+ skill->name2id_db = NULL;
+ skill->unit_db = NULL;
+ skill->usave_db = NULL;
+ skill->bowling_db = NULL;
+ skill->group_db = NULL;
+ /* */
+ skill->unit_ers = NULL;
+ skill->timer_ers = NULL;
+ skill->cd_ers = NULL;
+ skill->cd_entry_ers = NULL;
+ /* one huge 0, follows skill.h order */
+ memset(skill->db,0,sizeof(skill->db)
+ + sizeof(skill->produce_db)
+ + sizeof(skill->arrow_db)
+ + sizeof(skill->abra_db)
+ + sizeof(skill->magicmushroom_db)
+ + sizeof(skill->improvise_db)
+ + sizeof(skill->changematerial_db)
+ + sizeof(skill->spellbook_db)
+ + sizeof(skill->reproduce_db)
+ + sizeof(skill->unit_layout)
+ );
+ /* */
+ memcpy(skill->enchant_eff, skill_enchant_eff, sizeof(skill->enchant_eff));
+ memcpy(skill->deluge_eff, skill_deluge_eff, sizeof(skill->deluge_eff));
+ skill->firewall_unit_pos = 0;
+ skill->icewall_unit_pos = 0;
+ skill->earthstrain_unit_pos = 0;
+ memset(&skill->area_temp,0,sizeof(skill->area_temp));
+ memset(&skill->unit_temp,0,sizeof(skill->unit_temp));
+ skill->unit_group_newid = 0;
+ /* accessors */
skill->get_index = skill_get_index;
skill->get_type = skill_get_type;
skill->get_hit = skill_get_hit;
@@ -17909,6 +18633,7 @@ void skill_defaults(void) {
skill->get_mhp = skill_get_mhp;
skill->get_sp = skill_get_sp;
skill->get_state = skill_get_state;
+ skill->get_spiritball = skill_get_spiritball;
skill->get_zeny = skill_get_zeny;
skill->get_num = skill_get_num;
skill->get_cast = skill_get_cast;
@@ -17931,7 +18656,6 @@ void skill_defaults(void) {
skill->get_unit_target = skill_get_unit_target;
skill->get_unit_interval = skill_get_unit_interval;
skill->get_unit_bl_target = skill_get_unit_bl_target;
- skill->get_spiritball = skill_get_spiritball;
skill->get_unit_layout_type = skill_get_unit_layout_type;
skill->get_unit_range = skill_get_unit_range;
skill->get_cooldown = skill_get_cooldown;
@@ -17941,6 +18665,7 @@ void skill_defaults(void) {
skill->chk = skill_chk;
skill->get_casttype = skill_get_casttype;
skill->get_casttype2 = skill_get_casttype2;
+ skill->is_combo = skill_is_combo;
skill->name2id = skill_name2id;
skill->isammotype = skill_isammotype;
skill->castend_id = skill_castend_id;
@@ -17964,22 +18689,18 @@ void skill_defaults(void) {
skill->unit_onplace = skill_unit_onplace;
skill->unit_ondamaged = skill_unit_ondamaged;
skill->cast_fix = skill_castfix;
- skill->cast_fix_sc = skill_castfix_sc;
-#ifdef RENEWAL_CAST
+ skill->cast_fix_sc = skill_castfix_sc;
skill->vf_cast_fix = skill_vfcastfix;
-#endif
skill->delay_fix = skill_delay_fix;
skill->check_condition_castbegin = skill_check_condition_castbegin;
skill->check_condition_castend = skill_check_condition_castend;
- skill->check_condition_char_sub = skill_check_condition_char_sub;
+ skill->consume_requirement = skill_consume_requirement;
skill->get_requirement = skill_get_requirement;
skill->check_pc_partner = skill_check_pc_partner;
- skill->consume_requirement = skill_consume_requirement;
skill->unit_move = skill_unit_move;
- skill->unit_move_unit_group = skill_unit_move_unit_group;
skill->unit_onleft = skill_unit_onleft;
skill->unit_onout = skill_unit_onout;
- skill->guildaura_sub = skill_guildaura_sub;
+ skill->unit_move_unit_group = skill_unit_move_unit_group;
skill->sit = skill_sit;
skill->brandishspear = skill_brandishspear;
skill->repairweapon = skill_repairweapon;
@@ -17988,6 +18709,8 @@ void skill_defaults(void) {
skill->autospell = skill_autospell;
skill->calc_heal = skill_calc_heal;
skill->check_cloaking = skill_check_cloaking;
+ skill->check_cloaking_end = skill_check_cloaking_end;
+ skill->can_cloak = skill_can_cloak;
skill->enchant_elemental_end = skill_enchant_elemental_end;
skill->not_ok = skillnotok;
skill->not_ok_hom = skillnotok_hom;
@@ -18019,7 +18742,7 @@ void skill_defaults(void) {
skill->check_condition_mercenary = skill_check_condition_mercenary;
skill->locate_element_field = skill_locate_element_field;
skill->graffitiremover = skill_graffitiremover;
- skill->activate_reverberation = skill_activate_reverbetion;
+ skill->activate_reverberation = skill_activate_reverberation;
skill->dance_overlap = skill_dance_overlap;
skill->dance_overlap_sub = skill_dance_overlap_sub;
skill->get_unit_layout = skill_get_unit_layout;
@@ -18033,9 +18756,7 @@ void skill_defaults(void) {
skill->check_condition_mob_master_sub = skill_check_condition_mob_master_sub;
skill->brandishspear_first = skill_brandishspear_first;
skill->brandishspear_dir = skill_brandishspear_dir;
-#ifdef RENEWAL_CAST
skill->get_fixed_cast = skill_get_fixed_cast;
-#endif
skill->sit_count = skill_sit_count;
skill->sit_in = skill_sit_in;
skill->sit_out = skill_sit_out;
@@ -18077,5 +18798,7 @@ void skill_defaults(void) {
skill->elementalanalysis = skill_elementalanalysis;
skill->changematerial = skill_changematerial;
skill->get_elemental_type = skill_get_elemental_type;
-
+ skill->cooldown_save = skill_cooldown_save;
+ skill->get_new_group_id = skill_get_new_group_id;
+ skill->check_shadowform = skill_check_shadowform;
}
diff --git a/src/map/skill.h b/src/map/skill.h
index cc9ac4bfc..6373d9275 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -2,22 +2,26 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _SKILL_H_
-#define _SKILL_H_
+#ifndef MAP_SKILL_H
+#define MAP_SKILL_H
+
+#include "../config/core.h" // RENEWAL_CAST
-#include "../common/mmo.h" // MAX_SKILL, struct square
-#include "../common/db.h"
#include "map.h" // struct block_list
+#include "status.h" // enum sc_type
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/mmo.h" // MAX_SKILL, struct square
/**
* Declarations
**/
-struct map_session_data;
struct homun_data;
+struct map_session_data;
+struct mercenary_data;
struct skill_unit;
-struct skill_unit_group;
-struct status_change_entry;
struct square;
+struct status_change_entry;
/**
* Defines
@@ -37,6 +41,7 @@ struct square;
#define MAX_SKILLUNITGROUP 25
#define MAX_SKILL_ITEM_REQUIRE 10
#define MAX_SKILLUNITGROUPTICKSET 25
+#define MAX_SKILL_NAME_LENGTH 30
// (Epoque:) To-do: replace this macro with some sort of skill tree check (rather than hard-coded skill names)
#define skill_ischangesex(id) ( \
@@ -161,7 +166,7 @@ enum {
enum e_skill {
NV_BASIC = 1,
-
+
SM_SWORD,
SM_TWOHAND,
SM_RECOVERY,
@@ -169,7 +174,7 @@ enum e_skill {
SM_PROVOKE,
SM_MAGNUM,
SM_ENDURE,
-
+
MG_SRECOVERY,
MG_SIGHT,
MG_NAPALMBEAT,
@@ -183,7 +188,7 @@ enum e_skill {
MG_FIREBOLT,
MG_LIGHTNINGBOLT,
MG_THUNDERSTORM,
-
+
AL_DP,
AL_DEMONBANE,
AL_RUWACH,
@@ -198,7 +203,7 @@ enum e_skill {
AL_ANGELUS,
AL_BLESSING,
AL_CURE,
-
+
MC_INCCARRY,
MC_DISCOUNT,
MC_OVERCHARGE,
@@ -206,22 +211,22 @@ enum e_skill {
MC_IDENTIFY,
MC_VENDING,
MC_MAMMONITE,
-
+
AC_OWL,
AC_VULTURE,
AC_CONCENTRATION,
AC_DOUBLE,
AC_SHOWER,
-
+
TF_DOUBLE,
TF_MISS,
TF_STEAL,
TF_HIDING,
TF_POISON,
TF_DETOXIFY,
-
+
ALL_RESURRECTION,
-
+
KN_SPEARMASTERY,
KN_PIERCE,
KN_BRANDISHSPEAR,
@@ -232,7 +237,7 @@ enum e_skill {
KN_BOWLINGBASH,
KN_RIDING,
KN_CAVALIERMASTERY,
-
+
PR_MACEMASTERY,
PR_IMPOSITIO,
PR_SUFFRAGIUM,
@@ -248,7 +253,7 @@ enum e_skill {
PR_TURNUNDEAD,
PR_LEXAETERNA,
PR_MAGNUS,
-
+
WZ_FIREPILLAR,
WZ_SIGHTRASHER,
WZ_FIREIVY,
@@ -263,7 +268,7 @@ enum e_skill {
WZ_HEAVENDRIVE,
WZ_QUAGMIRE,
WZ_ESTIMATION,
-
+
BS_IRON,
BS_STEEL,
BS_ENCHANTEDSTONE,
@@ -285,7 +290,7 @@ enum e_skill {
BS_WEAPONPERFECT,
BS_OVERTHRUST,
BS_MAXIMIZE,
-
+
HT_SKIDTRAP,
HT_LANDMINE,
HT_ANKLESNARE,
@@ -303,7 +308,7 @@ enum e_skill {
HT_BLITZBEAT,
HT_DETECTING,
HT_SPRINGTRAP,
-
+
AS_RIGHT,
AS_LEFT,
AS_KATAR,
@@ -314,7 +319,7 @@ enum e_skill {
AS_POISONREACT,
AS_VENOMDUST,
AS_SPLASHER,
-
+
NV_FIRSTAID,
NV_TRICKDEAD,
SM_MOVINGRECOVERY,
@@ -331,7 +336,7 @@ enum e_skill {
MC_LOUD,
AL_HOLYLIGHT,
MG_ENERGYCOAT,
-
+
NPC_PIERCINGATT,
NPC_MENTALBREAKER,
NPC_RANGEATTACK,
@@ -384,7 +389,7 @@ enum e_skill {
NPC_HALLUCINATION,
NPC_REBIRTH,
NPC_SUMMONMONSTER,
-
+
RG_SNATCHER,
RG_STEALCOIN,
RG_BACKSTAP,
@@ -401,7 +406,7 @@ enum e_skill {
RG_GANGSTER,
RG_COMPULSION,
RG_PLAGIARISM,
-
+
AM_AXEMASTERY,
AM_LEARNINGPOTION,
AM_PHARMACY,
@@ -424,7 +429,7 @@ enum e_skill {
AM_DRILLMASTER,
AM_HEALHOMUN,
AM_RESURRECTHOMUN,
-
+
CR_TRUST,
CR_AUTOGUARD,
CR_SHIELDCHARGE,
@@ -436,7 +441,7 @@ enum e_skill {
CR_PROVIDENCE,
CR_DEFENDER,
CR_SPEARQUICKEN,
-
+
MO_IRONHAND,
MO_SPIRITSRECOVERY,
MO_CALLSPIRITS,
@@ -452,7 +457,7 @@ enum e_skill {
MO_EXTREMITYFIST,
MO_CHAINCOMBO,
MO_COMBOFINISH,
-
+
SA_ADVANCEDBOOK,
SA_CASTCANCEL,
SA_MAGICROD,
@@ -483,7 +488,7 @@ enum e_skill {
SA_INSTANTDEATH,
SA_FULLRECOVERY,
SA_COMA,
-
+
BD_ADAPTATION,
BD_ENCORE,
BD_LULLABY,
@@ -495,7 +500,7 @@ enum e_skill {
BD_INTOABYSS,
BD_SIEGFRIED,
BD_RAGNAROK,
-
+
BA_MUSICALLESSON,
BA_MUSICALSTRIKE,
BA_DISSONANCE,
@@ -504,7 +509,7 @@ enum e_skill {
BA_ASSASSINCROSS,
BA_POEMBRAGI,
BA_APPLEIDUN,
-
+
DC_DANCINGLESSON,
DC_THROWARROW,
DC_UGLYDANCE,
@@ -513,17 +518,17 @@ enum e_skill {
DC_DONTFORGETME,
DC_FORTUNEKISS,
DC_SERVICEFORYOU,
-
+
NPC_RANDOMMOVE,
NPC_SPEEDUP,
NPC_REVENGE,
-
+
WE_MALE,
WE_FEMALE,
WE_CALLPARTNER,
-
+
ITM_TOMAHAWK,
-
+
NPC_DARKCROSS,
NPC_GRANDDARKNESS,
NPC_DARKSTRIKE,
@@ -541,7 +546,7 @@ enum e_skill {
NPC_CALLSLAVE,
NPC_INVISIBLE,
NPC_RUN,
-
+
LK_AURABLADE,
LK_PARRYING,
LK_CONCENTRATION,
@@ -595,10 +600,11 @@ enum e_skill {
PF_SPIDERWEB,
ASC_METEORASSAULT,
ASC_CDP,
+
WE_BABY,
WE_CALLPARENT,
WE_CALLBABY,
-
+
TK_RUN,
TK_READYSTORM,
TK_STORMKICK,
@@ -615,7 +621,7 @@ enum e_skill {
TK_POWER,
TK_SEVENWIND,
TK_HIGHJUMP,
-
+
SG_FEEL,
SG_SUN_WARM,
SG_MOON_WARM,
@@ -634,7 +640,7 @@ enum e_skill {
SG_FRIEND,
SG_KNOWLEDGE,
SG_FUSION,
-
+
SL_ALCHEMIST,
AM_BERSERKPITCHER,
SL_MONK,
@@ -663,7 +669,7 @@ enum e_skill {
SL_SWOO,
SL_SKE,
SL_SKA,
-
+
SM_SELFPROVOKE,
NPC_EMOTION_ON,
ST_PRESERVE,
@@ -691,7 +697,7 @@ enum e_skill {
AM_TWILIGHT2,
AM_TWILIGHT3,
HT_POWER,
-
+
GS_GLITTERING,
GS_FLING,
GS_TRIPLEACTION,
@@ -714,7 +720,7 @@ enum e_skill {
GS_FULLBUSTER,
GS_SPREADATTACK,
GS_GROUNDDRIFT,
-
+
NJ_TOBIDOUGU,
NJ_SYURIKEN,
NJ_KUNAI,
@@ -738,7 +744,7 @@ enum e_skill {
NJ_KAMAITACHI,
NJ_NEN,
NJ_ISSEN,
-
+
MB_FIGHTING,
MB_NEUTRAL,
MB_TAIMING_PUTI,
@@ -766,7 +772,7 @@ enum e_skill {
MB_M_WALLCRASH,
MB_M_REINCARNATION,
MB_B_EQUIP,
-
+
SL_DEATHKNIGHT,
SL_COLLECTOR,
SL_NINJA,
@@ -775,7 +781,7 @@ enum e_skill {
DA_RESET,
DE_BERSERKAIZER,
DA_DARKPOWER,
-
+
DE_PASSIVE,
DE_PATTACK,
DE_PSPEED,
@@ -815,7 +821,7 @@ enum e_skill {
DE_TWINATTACK,
DE_WINDATTACK,
DE_WATERATTACK,
-
+
DA_ENERGY,
DA_CLOUD,
DA_FIRSTSLOT,
@@ -850,7 +856,7 @@ enum e_skill {
ALL_TIMEIN,
DA_ZENYRANK,
DA_ACCESSORYMIX,
-
+
NPC_EARTHQUAKE,
NPC_FIREBREATH,
NPC_ICEBREATH,
@@ -879,7 +885,6 @@ enum e_skill {
NPC_WIDESTUN,
NPC_VAMPIRE_GIFT,
NPC_WIDESOULDRAIN,
-
ALL_INCCARRY,
NPC_TALK,
NPC_HELLPOWER,
@@ -908,7 +913,31 @@ enum e_skill {
NPC_VENOMFOG,
NPC_MILLENNIUMSHIELD,
NPC_COMET,
-
+// TODO: What PACKETVER are these skills added? [Panikon]
+// After this addition all skills from NPC_WIDEWEB to NPC_LEX_AETERNA
+// will have their IDs changed
+#if PACKETVER >= 20140205
+ NPC_ICEMINE,
+ NPC_ICEEXPLO,
+ NPC_FLAMECROSS,
+ NPC_PULSESTRIKE2,
+ NPC_DANCINGBLADE,
+ NPC_DANCINGBLADE_ATK,
+ NPC_DARKPIERCING,
+ NPC_MAXPAIN,
+ NPC_MAXPAIN_ATK,
+ NPC_DEATHSUMMON,
+ NPC_HELLBURNING,
+ NPC_JACKFROST,
+#endif
+ NPC_WIDEWEB,
+ NPC_WIDESUCK,
+ NPC_STORMGUST2,
+ NPC_FIRESTORM,
+ NPC_REVERBERATION,
+ NPC_REVERBERATION_ATK,
+ NPC_LEX_AETERNA,
+
KN_CHARGEATK = 1001,
CR_SHRINK,
AS_SONICACCEL,
@@ -928,7 +957,7 @@ enum e_skill {
SA_ELEMENTGROUND,
SA_ELEMENTFIRE,
SA_ELEMENTWIND,
-
+
RK_ENCHANTBLADE = 2001,
RK_SONICWAVE,
RK_DEATHBOUND,
@@ -949,7 +978,7 @@ enum e_skill {
RK_FIGHTINGSPIRIT,
RK_ABUNDANCE,
RK_PHANTOMTHRUST,
-
+
GC_VENOMIMPRESS,
GC_CROSSIMPACT,
GC_DARKILLUSION,
@@ -967,7 +996,7 @@ enum e_skill {
GC_HALLUCINATIONWALK,
GC_ROLLINGCUTTER,
GC_CROSSRIPPERSLASHER,
-
+
AB_JUDEX,
AB_ANCILLA,
AB_ADORAMUS,
@@ -988,7 +1017,7 @@ enum e_skill {
AB_DUPLELIGHT_MELEE,
AB_DUPLELIGHT_MAGIC,
AB_SILENTIUM,
-
+
WL_WHITEIMPRISON = 2201,
WL_SOULEXPANSION,
WL_FROSTMISTY,
@@ -1021,7 +1050,7 @@ enum e_skill {
WL_RELEASE,
WL_READING_SB,
WL_FREEZE_SP,
-
+
RA_ARROWSTORM,
RA_FEARBREEZE,
RA_RANGERMAIN,
@@ -1044,7 +1073,7 @@ enum e_skill {
RA_VERDURETRAP,
RA_FIRINGTRAP,
RA_ICEBOUNDTRAP,
-
+
NC_MADOLICENCE,
NC_BOOSTKNUCKLE,
NC_PILEBUNKER,
@@ -1074,7 +1103,7 @@ enum e_skill {
NC_SILVERSNIPER,
NC_MAGICDECOY,
NC_DISJOINT,
-
+
SC_FATALMENACE,
SC_REPRODUCE,
SC_AUTOSHADOWSPELL,
@@ -1096,7 +1125,7 @@ enum e_skill {
SC_MAELSTROM,
SC_BLOODYLUST,
SC_FEINTBOMB,
-
+
LG_CANNONSPEAR = 2307,
LG_BANISHINGPOINT,
LG_TRAMPLE,
@@ -1116,7 +1145,7 @@ enum e_skill {
LG_EARTHDRIVE,
LG_HESPERUSLIT,
LG_INSPIRATION,
-
+
SR_DRAGONCOMBO,
SR_SKYNETBLOW,
SR_EARTHSHAKER,
@@ -1140,15 +1169,15 @@ enum e_skill {
SR_GENTLETOUCH_ENERGYGAIN,
SR_GENTLETOUCH_CHANGE,
SR_GENTLETOUCH_REVITALIZE,
-
+
WA_SWING_DANCE = 2350,
WA_SYMPHONY_OF_LOVER,
WA_MOONLIT_SERENADE,
-
+
MI_RUSH_WINDMILL = 2381,
MI_ECHOSONG,
MI_HARMONIZE,
-
+
WM_LESSON = 2412,
WM_METALICSOUND,
WM_REVERBERATION,
@@ -1172,7 +1201,7 @@ enum e_skill {
WM_MELODYOFSINK,
WM_BEYOND_OF_WARCRY,
WM_UNLIMITED_HUMMING_VOICE,
-
+
SO_FIREWALK = 2443,
SO_ELECTRICWALK,
SO_SPELLFIST,
@@ -1199,7 +1228,7 @@ enum e_skill {
SO_WATER_INSIGNIA,
SO_WIND_INSIGNIA,
SO_EARTH_INSIGNIA,
-
+
GN_TRAINING_SWORD = 2474,
GN_REMODELING_CART,
GN_CART_TORNADO,
@@ -1225,14 +1254,14 @@ enum e_skill {
GN_MAKEBOMB,
GN_S_PHARMACY,
GN_SLINGITEM_RANGEMELEEATK,
-
+
AB_SECRAMENT = 2515,
WM_SEVERE_RAINSTORM_MELEE,
SR_HOWLINGOFLION,
SR_RIDEINLIGHTNING,
LG_OVERBRAND_BRANDISH,
LG_OVERBRAND_PLUSATK,
-
+
ALL_ODINS_RECALL = 2533,
RETURN_TO_ELDICASTES,
ALL_BUYING_STORE,
@@ -1245,7 +1274,37 @@ enum e_skill {
ALL_TETANY,
ALL_RAY_OF_PROTECTION,
MC_CARTDECORATE,
-
+ GM_ITEM_ATKMAX,
+ GM_ITEM_ATKMIN,
+ GM_ITEM_MATKMAX,
+ GM_ITEM_MATKMIN,
+ ALL_LIGHTGUARD,
+
+ RL_GLITTERING_GREED = 2551,
+ RL_RICHS_COIN,
+ RL_MASS_SPIRAL,
+ RL_BANISHING_BUSTER,
+ RL_B_TRAP,
+ RL_FLICKER,
+ RL_S_STORM,
+ RL_E_CHAIN,
+ RL_QD_SHOT,
+ RL_C_MARKER,
+ RL_FIREDANCE,
+ RL_H_MINE,
+ RL_P_ALTER,
+ RL_FALLEN_ANGEL,
+ RL_R_TRIP,
+ RL_D_TAIL,
+ RL_FIRE_RAIN,
+ RL_HEAT_BARREL,
+ RL_AM_BLAST,
+ RL_SLUGSHOT,
+ RL_HAMMER_OF_GOD,
+ RL_R_TRIP_PLUSATK,
+ RL_B_FLICKER_ATK,
+ RL_GLITTERING_GREED_ATK,
+
KO_YAMIKUMO = 3001,
KO_RIGHT,
KO_LEFT,
@@ -1275,12 +1334,17 @@ enum e_skill {
OB_OBOROGENSOU,
OB_OBOROGENSOU_TRANSITION_ATK,
OB_AKAITSUKI,
-
+
ECL_SNOWFLIP = 3031,
ECL_PEONYMAMY,
ECL_SADAGUI,
ECL_SEQUOIADUST,
ECLAGE_RECALL,
+ BA_POEMBRAGI2,
+ DC_FORTUNEKISS2,
+ ITEM_OPTION_SPLASH_ATTACK,
+ GM_FORCE_TRANSFER,
+ GM_WIDE_RESURRECTION,
GC_DARKCROW = 5001,
RA_UNLIMIT,
@@ -1296,10 +1360,7 @@ enum e_skill {
WL_TELEKINESIS_INTENSE,
LG_KINGS_GRACE,
ALL_FULL_THROTTLE,
- SR_FLASHCOMBO_ATK_STEP1,
- SR_FLASHCOMBO_ATK_STEP2,
- SR_FLASHCOMBO_ATK_STEP3,
- SR_FLASHCOMBO_ATK_STEP4,
+ NC_MAGMA_ERUPTION_DOTDAMAGE,
HLIF_HEAL = 8001,
HLIF_AVOID,
@@ -1344,7 +1405,7 @@ enum e_skill {
MH_LAVA_SLIDE,
MH_PYROCLASTIC,
MH_VOLCANIC_ASH,
-
+
MS_BASH = 8201,
MS_MAGNUM,
MS_BOWLINGBASH,
@@ -1385,7 +1446,8 @@ enum e_skill {
MER_KYRIE,
MER_BLESSING,
MER_INCAGI,
-
+ MER_INVINCIBLEOFF2,
+
EL_CIRCLE_OF_FIRE = 8401,
EL_FIRE_CLOAK,
EL_FIRE_MANTLE,
@@ -1560,10 +1622,14 @@ enum {
UNT_ZENKAI_WIND,
UNT_MAKIBISHI,
UNT_VENOMFOG,
- UNT_ICEMINE,
- UNT_FLAMECROSS,
- UNT_HELLBURNING,
- UNT_MAGMA_ERUPTION,
+ UNT_ICEMINE,
+ UNT_FLAMECROSS,
+ UNT_HELLBURNING,
+ UNT_MAGMA_ERUPTION,
+ UNT_KINGS_GRACE,
+ UNT_GLITTERING_GREED,
+ UNT_B_TRAP,
+ UNT_FIRE_RAIN,
/**
* Guild Auras
@@ -1576,17 +1642,6 @@ enum {
UNT_MAX = 0x190
};
-enum gx_poison {
- PO_PARALYSE = 12717,
- PO_LEECHESEND,
- PO_OBLIVIONCURSE,
- PO_DEATHHURT,
- PO_TOXIN,
- PO_PYREXIA,
- PO_MAGICMUSHROOM,
- PO_VENOMBLEED
-};
-
/**
* Structures
**/
@@ -1599,7 +1654,7 @@ struct skill_condition {
// Database skills
struct s_skill_db {
unsigned short nameid;
- char name[NAME_LENGTH];
+ char name[MAX_SKILL_NAME_LENGTH];
char desc[40];
int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max;
int num[MAX_SKILL_LEVEL];
@@ -1623,7 +1678,6 @@ struct s_skill_db {
int unit_target;
int unit_flag;
};
-extern struct s_skill_db skill_db[MAX_SKILL_DB];
struct s_skill_unit_layout {
int count;
@@ -1650,7 +1704,7 @@ struct skill_unit_group {
int map;
int target_flag; //Holds BCT_* flag for battle_check_target
int bl_flag; //Holds BL_* flag for map_foreachin* functions
- unsigned int tick;
+ int64 tick;
int limit,interval;
uint16 skill_id,skill_lv;
@@ -1679,7 +1733,7 @@ struct skill_unit {
};
struct skill_unit_group_tickset {
- unsigned int tick;
+ int64 tick;
int id;
};
@@ -1689,14 +1743,12 @@ struct s_skill_produce_db {
int req_skill,req_skill_lv,itemlv;
int mat_id[MAX_PRODUCE_RESOURCE],mat_amount[MAX_PRODUCE_RESOURCE];
};
-extern struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB];
// Creating database arrow
struct s_skill_arrow_db {
int nameid, trigger;
int cre_id[MAX_ARROW_RESOURCE],cre_amount[MAX_ARROW_RESOURCE];
};
-extern struct s_skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB];
// Abracadabra database
struct s_skill_abra_db {
@@ -1704,29 +1756,101 @@ struct s_skill_abra_db {
int req_lv;
int per;
};
-extern struct s_skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB];
//GCross magic mushroom database
struct s_skill_magicmushroom_db {
uint16 skill_id;
};
-extern struct s_skill_magicmushroom_db skill_magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB];
+
+struct skill_cd_entry {
+ int duration;//milliseconds
+#if PACKETVER >= 20120604
+ int total;/* used for display on newer clients */
+#endif
+ short skidx;//the skill index entries belong to
+ int64 started;/* gettick() of when it started, used vs duration to measure how much left upon logout */
+ int timer;/* timer id */
+ uint16 skill_id;//skill id
+};
+
+/**
+ * Skill Cool Down Delay Saving
+ * Struct skill_cd is not a member of struct map_session_data
+ * to keep cooldowns in memory between player log-ins.
+ * All cooldowns are reset when server is restarted.
+ **/
+struct skill_cd {
+ struct skill_cd_entry *entry[MAX_SKILL_TREE];
+ unsigned char cursor;
+};
/**
- * Vars
+ * Skill Unit Persistency during endack routes (mostly for songs see bugreport:4574)
**/
-extern int enchant_eff[5];
-extern int deluge_eff[5];
-DBMap* skilldb_name2id;
+struct skill_unit_save {
+ uint16 skill_id, skill_lv;
+};
+
+struct s_skill_improvise_db {
+ uint16 skill_id;
+ short per;//1-10000
+};
+
+struct s_skill_changematerial_db {
+ int itemid;
+ short rate;
+ int qty[5];
+ short qty_rate[5];
+};
+
+struct s_skill_spellbook_db {
+ int nameid;
+ uint16 skill_id;
+ int point;
+};
+
+typedef int (*SkillFunc)(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 tick, int flag);
/**
* Skill.c Interface
**/
struct skill_interface {
- int (*init) (void);
+ int (*init) (bool minimal);
int (*final) (void);
void (*reload) (void);
- void (*read_db) (void);
+ void (*read_db) (bool minimal);
+ /* */
+ DBMap* cd_db; // char_id -> struct skill_cd
+ DBMap* name2id_db;
+ DBMap* unit_db; // int id -> struct skill_unit*
+ DBMap* usave_db; // char_id -> struct skill_unit_save
+ DBMap* group_db;// int group_id -> struct skill_unit_group*
+ DBMap* bowling_db;// int mob_id -> struct mob_data*s
+ /* */
+ struct eri *unit_ers; //For handling skill_unit's [Skotlex]
+ struct eri *timer_ers; //For handling skill_timerskills [Skotlex]
+ struct eri *cd_ers; // ERS Storage for skill cool down managers [Ind/Hercules]
+ struct eri *cd_entry_ers; // ERS Storage for skill cool down entries [Ind/Hercules]
+ /* */
+ struct s_skill_db db[MAX_SKILL_DB];
+ struct s_skill_produce_db produce_db[MAX_SKILL_PRODUCE_DB];
+ struct s_skill_arrow_db arrow_db[MAX_SKILL_ARROW_DB];
+ struct s_skill_abra_db abra_db[MAX_SKILL_ABRA_DB];
+ struct s_skill_magicmushroom_db magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB];
+ struct s_skill_improvise_db improvise_db[MAX_SKILL_IMPROVISE_DB];
+ struct s_skill_changematerial_db changematerial_db[MAX_SKILL_PRODUCE_DB];
+ struct s_skill_spellbook_db spellbook_db[MAX_SKILL_SPELLBOOK_DB];
+ bool reproduce_db[MAX_SKILL_DB];
+ struct s_skill_unit_layout unit_layout[MAX_SKILL_UNIT_LAYOUT];
+ /* */
+ int enchant_eff[5];
+ int deluge_eff[5];
+ int firewall_unit_pos;
+ int icewall_unit_pos;
+ int earthstrain_unit_pos;
+ int area_temp[8];
+ int unit_temp[20]; // temporary storage for tracking skill unit skill ids as players move in/out of them
+ int unit_group_newid;
/* accesssors */
int (*get_index) ( uint16 skill_id );
int (*get_type) ( uint16 skill_id );
@@ -1772,56 +1896,56 @@ struct skill_interface {
const char* (*get_name) ( uint16 skill_id );
const char* (*get_desc) ( uint16 skill_id );
/* check */
- void (*chk) (int16* skill_id);
+ void (*chk) (uint16* skill_id);
/* whether its CAST_GROUND, CAST_DAMAGE or CAST_NODAMAGE */
int (*get_casttype) (uint16 skill_id);
int (*get_casttype2) (uint16 index);
+ bool (*is_combo) (int skill_id);
int (*name2id) (const char* name);
- int (*isammotype) (struct map_session_data *sd, int skill);
- int (*castend_id) (int tid, unsigned int tick, int id, intptr_t data);
- int (*castend_pos) (int tid, unsigned int tick, int id, intptr_t data);
- int (*castend_map) ( struct map_session_data *sd,uint16 skill_id, const char *map);
+ int (*isammotype) (struct map_session_data *sd, int skill_id);
+ int (*castend_id) (int tid, int64 tick, int id, intptr_t data);
+ int (*castend_pos) (int tid, int64 tick, int id, intptr_t data);
+ int (*castend_map) ( struct map_session_data *sd,uint16 skill_id, const char *mapname);
int (*cleartimerskill) (struct block_list *src);
- int (*addtimerskill) (struct block_list *src,unsigned int tick,int target,int x,int y,uint16 skill_id,uint16 skill_lv,int type,int flag);
- int (*additional_effect) ( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,int attack_type,int dmg_lv,unsigned int tick);
- int (*counter_additional_effect) ( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,int attack_type,unsigned int tick);
+ int (*addtimerskill) (struct block_list *src, int64 tick, int target, int x, int y, uint16 skill_id, uint16 skill_lv, int type, int flag);
+ int (*additional_effect) (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int dmg_lv, int64 tick);
+ int (*counter_additional_effect) (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int64 tick);
int (*blown) (struct block_list* src, struct block_list* target, int count, int8 dir, int flag);
int (*break_equip) (struct block_list *bl, unsigned short where, int rate, int flag);
int (*strip_equip) (struct block_list *bl, unsigned short where, int rate, int lv, int time);
struct skill_unit_group* (*id2group) (int group_id);
struct skill_unit_group *(*unitsetting) (struct block_list* src, uint16 skill_id, uint16 skill_lv, short x, short y, int flag);
struct skill_unit *(*initunit) (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2);
- int (*delunit) (struct skill_unit *unit);
+ int (*delunit) (struct skill_unit *su);
struct skill_unit_group *(*init_unitgroup) (struct block_list* src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval);
int (*del_unitgroup) (struct skill_unit_group *group, const char* file, int line, const char* func);
int (*clear_unitgroup) (struct block_list *src);
int (*clear_group) (struct block_list *bl, int flag);
- int (*unit_onplace) (struct skill_unit *src, struct block_list *bl, unsigned int tick);
- int (*unit_ondamaged) (struct skill_unit *src,struct block_list *bl,int damage,unsigned int tick);
+ int (*unit_onplace) (struct skill_unit *src, struct block_list *bl, int64 tick);
+ int (*unit_ondamaged) (struct skill_unit *src, struct block_list *bl, int64 damage, int64 tick);
int (*cast_fix) ( struct block_list *bl, uint16 skill_id, uint16 skill_lv);
int (*cast_fix_sc) ( struct block_list *bl, int time);
-#ifdef RENEWAL_CAST
int (*vf_cast_fix) ( struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv);
-#endif
int (*delay_fix) ( struct block_list *bl, uint16 skill_id, uint16 skill_lv);
int (*check_condition_castbegin) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
int (*check_condition_castend) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
int (*consume_requirement) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type);
struct skill_condition (*get_requirement) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
- int (*check_pc_partner) (struct map_session_data *sd, uint16 skill_id, short* skill_lv, int range, int cast_flag);
- int (*unit_move) (struct block_list *bl,unsigned int tick,int flag);
- int (*unit_onleft) (uint16 skill_id, struct block_list *bl,unsigned int tick);
- int (*unit_onout) (struct skill_unit *src, struct block_list *bl, unsigned int tick);
+ int (*check_pc_partner) (struct map_session_data *sd, uint16 skill_id, uint16* skill_lv, int range, int cast_flag);
+ int (*unit_move) (struct block_list *bl, int64 tick, int flag);
+ int (*unit_onleft) (uint16 skill_id, struct block_list *bl, int64 tick);
+ int (*unit_onout) (struct skill_unit *src, struct block_list *bl, int64 tick);
int (*unit_move_unit_group) ( struct skill_unit_group *group, int16 m,int16 dx,int16 dy);
- int (*guildaura_sub) (struct map_session_data* sd, int id, int strvit, int agidex);
int (*sit) (struct map_session_data *sd, int type);
- void (*brandishspear) (struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag);
+ void (*brandishspear) (struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag);
void (*repairweapon) (struct map_session_data *sd, int idx);
void (*identify) (struct map_session_data *sd,int idx);
void (*weaponrefine) (struct map_session_data *sd,int idx);
int (*autospell) (struct map_session_data *md,uint16 skill_id);
int (*calc_heal) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, bool heal);
bool (*check_cloaking) (struct block_list *bl, struct status_change_entry *sce);
+ int (*check_cloaking_end) (struct block_list *bl, va_list ap);
+ bool (*can_cloak) (struct map_session_data *sd);
int (*enchant_elemental_end) (struct block_list *bl, int type);
int (*not_ok) (uint16 skill_id, struct map_session_data *sd);
int (*not_ok_hom) (uint16 skill_id, struct homun_data *hd);
@@ -1830,59 +1954,57 @@ struct skill_interface {
int (*can_produce_mix) ( struct map_session_data *sd, int nameid, int trigger, int qty);
int (*produce_mix) ( struct map_session_data *sd, uint16 skill_id, int nameid, int slot1, int slot2, int slot3, int qty );
int (*arrow_create) ( struct map_session_data *sd,int nameid);
- int (*castend_nodamage_id) ( struct block_list *src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag );
- int (*castend_damage_id) ( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag );
- int (*castend_pos2) ( struct block_list *src, int x,int y,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag);
- int (*blockpc_start) (struct map_session_data*, uint16 skill_id, int, bool);
- int (*blockhomun_start) (struct homun_data*,uint16 skill_id,int);
- int (*blockmerc_start) (struct mercenary_data*,uint16 skill_id,int);
- int (*attack) ( int attack_type, struct block_list* src, struct block_list *dsrc,struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag );
+ int (*castend_nodamage_id) (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag);
+ int (*castend_damage_id) (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick,int flag);
+ int (*castend_pos2) (struct block_list *src, int x, int y, uint16 skill_id, uint16 skill_lv, int64 tick, int flag);
+ int (*blockpc_start) (struct map_session_data *sd, uint16 skill_id, int tick);
+ int (*blockhomun_start) (struct homun_data *hd, uint16 skill_id, int tick);
+ int (*blockmerc_start) (struct mercenary_data *md, uint16 skill_id, int tick);
+ int (*attack) (int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag);
int (*attack_area) (struct block_list *bl,va_list ap);
int (*area_sub) (struct block_list *bl, va_list ap);
- int (*area_sub_count) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag);
+ int (*area_sub_count) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 tick, int flag);
int (*check_unit_range) (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv);
int (*check_unit_range_sub) (struct block_list *bl, va_list ap);
int (*check_unit_range2) (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv);
int (*check_unit_range2_sub) (struct block_list *bl, va_list ap);
void (*toggle_magicpower) (struct block_list *bl, uint16 skill_id);
int (*magic_reflect) (struct block_list* src, struct block_list* bl, int type);
- int (*onskillusage) (struct map_session_data *sd, struct block_list *bl, uint16 skill_id, unsigned int tick);
+ int (*onskillusage) (struct map_session_data *sd, struct block_list *bl, uint16 skill_id, int64 tick);
int (*cell_overlap) (struct block_list *bl, va_list ap);
- int (*timerskill) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*timerskill) (int tid, int64 tick, int id, intptr_t data);
int (*trap_splash) (struct block_list *bl, va_list ap);
int (*check_condition_mercenary) (struct block_list *bl, int skill_id, int lv, int type);
struct skill_unit_group *(*locate_element_field) (struct block_list *bl);
int (*graffitiremover) (struct block_list *bl, va_list ap);
int (*activate_reverberation) ( struct block_list *bl, va_list ap);
int (*dance_overlap_sub) (struct block_list* bl, va_list ap);
- int (*dance_overlap) (struct skill_unit* unit, int flag);
+ int (*dance_overlap) (struct skill_unit* su, int flag);
struct s_skill_unit_layout *(*get_unit_layout) (uint16 skill_id, uint16 skill_lv, struct block_list* src, int x, int y);
int (*frostjoke_scream) (struct block_list *bl, va_list ap);
int (*greed) (struct block_list *bl, va_list ap);
int (*destroy_trap) ( struct block_list *bl, va_list ap );
int (*icewall_block) (struct block_list *bl,va_list ap);
- struct skill_unit_group_tickset *(*unitgrouptickset_search) (struct block_list *bl, struct skill_unit_group *group, int tick);
- bool (*dance_switch) (struct skill_unit* unit, int flag);
+ struct skill_unit_group_tickset *(*unitgrouptickset_search) (struct block_list *bl, struct skill_unit_group *group, int64 tick);
+ bool (*dance_switch) (struct skill_unit* su, int flag);
int (*check_condition_char_sub) (struct block_list *bl, va_list ap);
int (*check_condition_mob_master_sub) (struct block_list *bl, va_list ap);
void (*brandishspear_first) (struct square *tc, uint8 dir, int16 x, int16 y);
void (*brandishspear_dir) (struct square* tc, uint8 dir, int are);
-#ifdef RENEWAL_CAST
- int (*get_fixed_cast) ( uint16 skill_id ,uint16 skill_lv );
-#endif
+ int (*get_fixed_cast) ( uint16 skill_id ,uint16 skill_lv );
int (*sit_count) (struct block_list *bl, va_list ap);
int (*sit_in) (struct block_list *bl, va_list ap);
int (*sit_out) (struct block_list *bl, va_list ap);
void (*unitsetmapcell) (struct skill_unit *src, uint16 skill_id, uint16 skill_lv, cell_t cell, bool flag);
- int (*unit_onplace_timer) (struct skill_unit *src, struct block_list *bl, unsigned int tick);
+ int (*unit_onplace_timer) (struct skill_unit *src, struct block_list *bl, int64 tick);
int (*unit_effect) (struct block_list* bl, va_list ap);
int (*unit_timer_sub_onplace) (struct block_list* bl, va_list ap);
int (*unit_move_sub) (struct block_list* bl, va_list ap);
- int (*blockpc_end) (int tid, unsigned int tick, int id, intptr_t data);
- int (*blockhomun_end) (int tid, unsigned int tick, int id, intptr_t data);
- int (*blockmerc_end) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*blockpc_end) (int tid, int64 tick, int id, intptr_t data);
+ int (*blockhomun_end) (int tid, int64 tick, int id, intptr_t data);
+ int (*blockmerc_end) (int tid, int64 tick, int id, intptr_t data);
int (*split_atoi) (char *str, int *val);
- int (*unit_timer) (int tid, unsigned int tick, int id, intptr_t data);
+ int (*unit_timer) (int tid, int64 tick, int id, intptr_t data);
int (*unit_timer_sub) (DBKey key, DBData *data, va_list ap);
void (*init_unit_layout) (void);
bool (*parse_row_skilldb) (char* split[], int columns, int current);
@@ -1916,10 +2038,13 @@ struct skill_interface {
int (*elementalanalysis) (struct map_session_data *sd, int n, uint16 skill_lv, unsigned short *item_list);
int (*changematerial) (struct map_session_data *sd, int n, unsigned short *item_list);
int (*get_elemental_type) (uint16 skill_id, uint16 skill_lv);
-} skill_s;
+ void (*cooldown_save) (struct map_session_data * sd);
+ int (*get_new_group_id) (void);
+ bool (*check_shadowform) (struct block_list *bl, int64 damage, int hit);
+};
struct skill_interface *skill;
void skill_defaults(void);
-#endif /* _SKILL_H_ */
+#endif /* MAP_SKILL_H */
diff --git a/src/map/sql/CMakeLists.txt b/src/map/sql/CMakeLists.txt
deleted file mode 100644
index 1b2c19979..000000000
--- a/src/map/sql/CMakeLists.txt
+++ /dev/null
@@ -1,116 +0,0 @@
-
-#
-# map sql
-#
-if( BUILD_SQL_SERVERS )
-message( STATUS "Creating target map-server" )
-set( SQL_MAP_HEADERS
- "${SQL_MAP_SOURCE_DIR}/atcommand.h"
- "${SQL_MAP_SOURCE_DIR}/battle.h"
- "${SQL_MAP_SOURCE_DIR}/battleground.h"
- "${SQL_MAP_SOURCE_DIR}/buyingstore.h"
- "${SQL_MAP_SOURCE_DIR}/chat.h"
- "${SQL_MAP_SOURCE_DIR}/chrif.h"
- "${SQL_MAP_SOURCE_DIR}/clif.h"
- "${SQL_MAP_SOURCE_DIR}/date.h"
- "${SQL_MAP_SOURCE_DIR}/duel.h"
- "${SQL_MAP_SOURCE_DIR}/elemental.h"
- "${SQL_MAP_SOURCE_DIR}/guild.h"
- "${SQL_MAP_SOURCE_DIR}/homunculus.h"
- "${SQL_MAP_SOURCE_DIR}/instance.h"
- "${SQL_MAP_SOURCE_DIR}/intif.h"
- "${SQL_MAP_SOURCE_DIR}/irc-bot.h"
- "${SQL_MAP_SOURCE_DIR}/itemdb.h"
- "${SQL_MAP_SOURCE_DIR}/log.h"
- "${SQL_MAP_SOURCE_DIR}/mail.h"
- "${SQL_MAP_SOURCE_DIR}/map.h"
- "${SQL_MAP_SOURCE_DIR}/mapreg.h"
- "${SQL_MAP_SOURCE_DIR}/mercenary.h"
- "${SQL_MAP_SOURCE_DIR}/mob.h"
- "${SQL_MAP_SOURCE_DIR}/npc.h"
- "${SQL_MAP_SOURCE_DIR}/packets.h"
- "${SQL_MAP_SOURCE_DIR}/packets_struct.h"
- "${SQL_MAP_SOURCE_DIR}/party.h"
- "${SQL_MAP_SOURCE_DIR}/path.h"
- "${SQL_MAP_SOURCE_DIR}/pc.h"
- "${SQL_MAP_SOURCE_DIR}/pc_groups.h"
- "${SQL_MAP_SOURCE_DIR}/pet.h"
- "${SQL_MAP_SOURCE_DIR}/quest.h"
- "${SQL_MAP_SOURCE_DIR}/script.h"
- "${SQL_MAP_SOURCE_DIR}/searchstore.h"
- "${SQL_MAP_SOURCE_DIR}/skill.h"
- "${SQL_MAP_SOURCE_DIR}/status.h"
- "${SQL_MAP_SOURCE_DIR}/storage.h"
- "${SQL_MAP_SOURCE_DIR}/trade.h"
- "${SQL_MAP_SOURCE_DIR}/unit.h"
- "${SQL_MAP_SOURCE_DIR}/vending.h"
- )
-set( SQL_MAP_SOURCES
- "${SQL_MAP_SOURCE_DIR}/atcommand.c"
- "${SQL_MAP_SOURCE_DIR}/battle.c"
- "${SQL_MAP_SOURCE_DIR}/battleground.c"
- "${SQL_MAP_SOURCE_DIR}/buyingstore.c"
- "${SQL_MAP_SOURCE_DIR}/chat.c"
- "${SQL_MAP_SOURCE_DIR}/chrif.c"
- "${SQL_MAP_SOURCE_DIR}/clif.c"
- "${SQL_MAP_SOURCE_DIR}/date.c"
- "${SQL_MAP_SOURCE_DIR}/duel.c"
- "${SQL_MAP_SOURCE_DIR}/elemental.c"
- "${SQL_MAP_SOURCE_DIR}/guild.c"
- "${SQL_MAP_SOURCE_DIR}/homunculus.c"
- "${SQL_MAP_SOURCE_DIR}/instance.c"
- "${SQL_MAP_SOURCE_DIR}/intif.c"
- "${SQL_MAP_SOURCE_DIR}/irc-bot.c"
- "${SQL_MAP_SOURCE_DIR}/itemdb.c"
- "${SQL_MAP_SOURCE_DIR}/log.c"
- "${SQL_MAP_SOURCE_DIR}/mail.c"
- "${SQL_MAP_SOURCE_DIR}/map.c"
- "${SQL_MAP_SOURCE_DIR}/mapreg_sql.c"
- "${SQL_MAP_SOURCE_DIR}/mercenary.c"
- "${SQL_MAP_SOURCE_DIR}/mob.c"
- "${SQL_MAP_SOURCE_DIR}/npc.c"
- "${SQL_MAP_SOURCE_DIR}/npc_chat.c"
- "${SQL_MAP_SOURCE_DIR}/party.c"
- "${SQL_MAP_SOURCE_DIR}/path.c"
- "${SQL_MAP_SOURCE_DIR}/pc.c"
- "${SQL_MAP_SOURCE_DIR}/pc_groups.c"
- "${SQL_MAP_SOURCE_DIR}/pet.c"
- "${SQL_MAP_SOURCE_DIR}/quest.c"
- "${SQL_MAP_SOURCE_DIR}/script.c"
- "${SQL_MAP_SOURCE_DIR}/searchstore.c"
- "${SQL_MAP_SOURCE_DIR}/skill.c"
- "${SQL_MAP_SOURCE_DIR}/status.c"
- "${SQL_MAP_SOURCE_DIR}/storage.c"
- "${SQL_MAP_SOURCE_DIR}/trade.c"
- "${SQL_MAP_SOURCE_DIR}/unit.c"
- "${SQL_MAP_SOURCE_DIR}/vending.c"
- )
-set( DEPENDENCIES common_sql )
-set( LIBRARIES ${GLOBAL_LIBRARIES} )
-set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${COMMON_BASE_INCLUDE_DIRS} )
-set( DEFINITIONS "${GLOBAL_DEFINITIONS} ${COMMON_BASE_DEFINITIONS}" )
-if( WITH_PCRE )
- message( STATUS "Enabled PCRE code" )
- set( LIBRARIES ${LIBRARIES} ${PCRE_LIBRARIES} )
- set( INCLUDE_DIRS ${INCLUDE_DIRS} ${PCRE_INCLUDE_DIRS} )
- set( DEFINITIONS "${DEFINITIONS} -DPCRE_SUPPORT" )
-else()
- message( STATUS "Disabled PCRE code" )
-endif()
-set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ${SQL_MAP_HEADERS} ${SQL_MAP_SOURCES} )
-source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} )
-source_group( map FILES ${SQL_MAP_HEADERS} ${SQL_MAP_SOURCES} )
-include_directories( ${INCLUDE_DIRS} )
-add_executable( map-server ${SOURCE_FILES} )
-add_dependencies( map-server ${DEPENDENCIES} )
-target_link_libraries( map-server ${LIBRARIES} ${DEPENDENCIES} )
-set_target_properties( map-server PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" )
-if( INSTALL_COMPONENT_RUNTIME )
- cpack_add_component( Runtime_mapserver_sql DESCRIPTION "map-server (sql version)" DISPLAY_NAME "map-server" GROUP Runtime )
- install( TARGETS map-server
- DESTINATION "."
- COMPONENT Runtime_mapserver_sql )
-endif( INSTALL_COMPONENT_RUNTIME )
-set( TARGET_LIST ${TARGET_LIST} map-server CACHE INTERNAL "" )
-message( STATUS "Creating target map-server - done" )
-endif( BUILD_SQL_SERVERS )
diff --git a/src/map/status.c b/src/map/status.c
index 992cc0855..4a2a6c344 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -2,103 +2,69 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/malloc.h"
-#include "../common/utils.h"
-#include "../common/ers.h"
-#include "../common/strlib.h"
+#define HERCULES_CORE
+#include "../config/core.h" // ANTI_MAYAP_CHEAT, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, DEVOTION_REFLECT_DAMAGE, RENEWAL, RENEWAL_ASPD, RENEWAL_EDP
+#include "status.h"
+
+#include <math.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "battle.h"
+#include "chrif.h"
+#include "clif.h"
+#include "elemental.h"
+#include "guild.h"
+#include "homunculus.h"
+#include "itemdb.h"
#include "map.h"
+#include "mercenary.h"
+#include "mob.h"
+#include "npc.h"
#include "path.h"
#include "pc.h"
#include "pet.h"
-#include "npc.h"
-#include "mob.h"
-#include "clif.h"
-#include "guild.h"
+#include "script.h"
#include "skill.h"
-#include "itemdb.h"
-#include "battle.h"
-#include "chrif.h"
#include "skill.h"
-#include "status.h"
-#include "script.h"
#include "unit.h"
-#include "homunculus.h"
-#include "mercenary.h"
-#include "elemental.h"
#include "vending.h"
+#include "../common/cbasetypes.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <string.h>
-#include <math.h>
-
-//Regen related flags.
-enum e_regen
-{
- RGN_HP = 0x01,
- RGN_SP = 0x02,
- RGN_SHP = 0x04,
- RGN_SSP = 0x08,
-};
-
-static int max_weight_base[CLASS_COUNT];
-static int hp_coefficient[CLASS_COUNT];
-static int hp_coefficient2[CLASS_COUNT];
-static int hp_sigma_val[CLASS_COUNT][MAX_LEVEL+1];
-static int sp_coefficient[CLASS_COUNT];
-#ifdef RENEWAL_ASPD
- static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1];
-#else
- static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE]; //[blackhole89]
-#endif
-
-// bonus values and upgrade chances for refining equipment
-static struct {
- int chance[MAX_REFINE]; // success chance
- int bonus[MAX_REFINE]; // cumulative fixed bonus damage
- int randombonus_max[MAX_REFINE]; // cumulative maximum random bonus damage
-} refine_info[REFINE_TYPE_MAX];
-
-static int atkmods[3][MAX_WEAPON_TYPE]; //ATK weapon modification for size (size_fix.txt)
-static char job_bonus[CLASS_COUNT][MAX_LEVEL];
-static sc_conf_type sc_conf[SC_MAX];
-
-static struct eri *sc_data_ers; //For sc_data entries
-static struct status_data dummy_status;
-
-int current_equip_item_index; //Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus]
-int current_equip_card_id; //To prevent card-stacking (from jA) [Skotlex]
-//we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only
-//to avoid cards exploits
+struct status_interface status_s;
/**
- * Returns the status change associated with a skill.
- * @param skill The skill to look up
- * @return The status registered for this skill
- **/
+* Returns the status change associated with a skill.
+* @param skill The skill to look up
+* @return The status registered for this skill
+**/
sc_type status_skill2sc(int skill_id) {
int idx;
if( (idx = skill->get_index(skill_id)) == 0 ) {
- ShowError("status_skill2sc: Unsupported skill id %d\n", skill);
+ ShowError("status_skill2sc: Unsupported skill id %d\n", skill_id);
return SC_NONE;
}
- return SkillStatusChangeTable[idx];
+ return status->Skill2SCTable[idx];
}
/**
- * Returns the FIRST skill (in order of definition in initChangeTables) to use a given status change.
- * Utilized for various duration lookups. Use with caution!
- * @param sc The status to look up
- * @return A skill associated with the status
- **/
+* Returns the FIRST skill (in order of definition in initChangeTables) to use a given status change.
+* Utilized for various duration lookups. Use with caution!
+* @param sc The status to look up
+* @return A skill associated with the status
+**/
int status_sc2skill(sc_type sc)
{
if( sc < 0 || sc >= SC_MAX ) {
@@ -106,14 +72,14 @@ int status_sc2skill(sc_type sc)
return 0;
}
- return StatusSkillChangeTable[sc];
+ return status->SkillChangeTable[sc];
}
/**
- * Returns the status calculation flag associated with a given status change.
- * @param sc The status to look up
- * @return The scb_flag registered for this status (see enum scb_flag)
- **/
+* Returns the status calculation flag associated with a given status change.
+* @param sc The status to look up
+* @return The scb_flag registered for this status (see enum scb_flag)
+**/
unsigned int status_sc2scb_flag(sc_type sc)
{
if( sc < 0 || sc >= SC_MAX ) {
@@ -121,28 +87,24 @@ unsigned int status_sc2scb_flag(sc_type sc)
return SCB_NONE;
}
- return StatusChangeFlagTable[sc];
+ return status->ChangeFlagTable[sc];
}
/**
- * Returns the bl types which require a status change packet to be sent for a given client status identifier.
- * @param type The client-side status identifier to look up (see enum si_type)
- * @return The bl types relevant to the type (see enum bl_type)
- **/
+* Returns the bl types which require a status change packet to be sent for a given client status identifier.
+* @param type The client-side status identifier to look up (see enum si_type)
+* @return The bl types relevant to the type (see enum bl_type)
+**/
int status_type2relevant_bl_types(int type)
{
if( type < 0 || type >= SI_MAX ) {
ShowError("status_type2relevant_bl_types: Unsupported type %d\n", type);
- return SI_BLANK;
+ return BL_NUL;
}
- return StatusRelevantBLTypes[type];
+ return status->RelevantBLTypes[type];
}
-#define add_sc(skill,sc) set_sc(skill,sc,SI_BLANK,SCB_NONE)
-// indicates that the status displays a visual effect for the affected unit, and should be sent to the client for all supported units
-#define set_sc_with_vfx(skill, sc, icon, flag) set_sc((skill), (sc), (icon), (flag)); if((icon) < SI_MAX) StatusRelevantBLTypes[(icon)] |= BL_SCEFFECT
-
static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) {
uint16 idx;
if( (idx = skill->get_index(skill_id)) == 0 ) {
@@ -154,31 +116,35 @@ static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) {
return;
}
- if( StatusSkillChangeTable[sc] == 0 )
- StatusSkillChangeTable[sc] = skill_id;
- if( StatusIconChangeTable[sc] == SI_BLANK )
- StatusIconChangeTable[sc] = icon;
- StatusChangeFlagTable[sc] |= flag;
+ if( status->SkillChangeTable[sc] == 0 )
+ status->SkillChangeTable[sc] = skill_id;
+ if( status->IconChangeTable[sc] == SI_BLANK )
+ status->IconChangeTable[sc] = icon;
+ status->ChangeFlagTable[sc] |= flag;
- if( SkillStatusChangeTable[idx] == SC_NONE )
- SkillStatusChangeTable[idx] = sc;
+ if( status->Skill2SCTable[idx] == SC_NONE )
+ status->Skill2SCTable[idx] = sc;
}
void initChangeTables(void) {
+#define add_sc(skill,sc) set_sc((skill),(sc),SI_BLANK,SCB_NONE)
+// indicates that the status displays a visual effect for the affected unit, and should be sent to the client for all supported units
+#define set_sc_with_vfx(skill, sc, icon, flag) do { set_sc((skill), (sc), (icon), (flag)); if((icon) < SI_MAX) status->RelevantBLTypes[(icon)] |= BL_SCEFFECT; } while(0)
+
int i;
for (i = 0; i < SC_MAX; i++)
- StatusIconChangeTable[i] = SI_BLANK;
+ status->IconChangeTable[i] = SI_BLANK;
for (i = 0; i < MAX_SKILL; i++)
- SkillStatusChangeTable[i] = SC_NONE;
+ status->Skill2SCTable[i] = SC_NONE;
for (i = 0; i < SI_MAX; i++)
- StatusRelevantBLTypes[i] = BL_PC;
+ status->RelevantBLTypes[i] = BL_PC;
- memset(StatusSkillChangeTable, 0, sizeof(StatusSkillChangeTable));
- memset(StatusChangeFlagTable, 0, sizeof(StatusChangeFlagTable));
- memset(StatusDisplayType, 0, sizeof(StatusDisplayType));
+ memset(status->SkillChangeTable, 0, sizeof(status->SkillChangeTable));
+ memset(status->ChangeFlagTable, 0, sizeof(status->ChangeFlagTable));
+ memset(status->DisplayType, 0, sizeof(status->DisplayType));
//First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex]
set_sc( NPC_PETRIFYATTACK , SC_STONE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF );
@@ -196,7 +162,7 @@ void initChangeTables(void) {
//The main status definitions
add_sc( SM_BASH , SC_STUN );
set_sc( SM_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
- add_sc( SM_MAGNUM , SC_WATK_ELEMENT );
+ add_sc( SM_MAGNUM , SC_SUB_WEAPONPROPERTY );
set_sc( SM_ENDURE , SC_ENDURE , SI_ENDURE , SCB_MDEF|SCB_DSPD );
add_sc( MG_SIGHT , SC_SIGHT );
add_sc( MG_SAFETYWALL , SC_SAFETYWALL );
@@ -214,7 +180,12 @@ void initChangeTables(void) {
add_sc( TF_POISON , SC_POISON );
set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SI_TWOHANDQUICKEN , SCB_ASPD );
add_sc( KN_AUTOCOUNTER , SC_AUTOCOUNTER );
- set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO , SCB_WATK );
+ set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO ,
+#ifdef RENEWAL
+ SCB_NONE );
+#else
+ SCB_WATK );
+#endif
set_sc( PR_SUFFRAGIUM , SC_SUFFRAGIUM , SI_SUFFRAGIUM , SCB_NONE );
set_sc( PR_ASPERSIO , SC_ASPERSIO , SI_ASPERSIO , SCB_ATK_ELE );
set_sc( PR_BENEDICTIO , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE );
@@ -233,7 +204,7 @@ void initChangeTables(void) {
set_sc( BS_WEAPONPERFECT , SC_WEAPONPERFECT , SI_WEAPONPERFECT, SCB_NONE );
set_sc( BS_OVERTHRUST , SC_OVERTHRUST , SI_OVERTHRUST , SCB_NONE );
set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SI_MAXIMIZE , SCB_REGEN );
- add_sc( HT_LANDMINE , SC_STUN );
+ add_sc( HT_LANDMINE , SC_STUN );
set_sc( HT_ANKLESNARE , SC_ANKLESNARE , SI_ANKLESNARE , SCB_NONE );
add_sc( HT_SANDMAN , SC_SLEEP );
add_sc( HT_FLASHER , SC_BLIND );
@@ -348,9 +319,9 @@ void initChangeTables(void) {
set_sc( LK_AURABLADE , SC_AURABLADE , SI_AURABLADE , SCB_NONE );
set_sc( LK_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE );
#ifndef RENEWAL
- set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_CONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2);
+ set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_LKCONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2);
#else
- set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_CONCENTRATION , SCB_HIT|SCB_DEF);
+ set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_LKCONCENTRATION , SCB_HIT|SCB_DEF);
#endif
set_sc( LK_TENSIONRELAX , SC_TENSIONRELAX , SI_TENSIONRELAX , SCB_REGEN );
set_sc( LK_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
@@ -427,10 +398,20 @@ void initChangeTables(void) {
add_sc( GS_CRACKER , SC_STUN );
add_sc( GS_DISARM , SC_NOEQUIPWEAPON );
add_sc( GS_PIERCINGSHOT , SC_BLOODING );
- set_sc( GS_MADNESSCANCEL , SC_GS_MADNESSCANCEL , SI_GS_MADNESSCANCEL , SCB_BATK|SCB_ASPD );
+ set_sc( GS_MADNESSCANCEL , SC_GS_MADNESSCANCEL , SI_GS_MADNESSCANCEL , SCB_ASPD
+#ifndef RENEWAL
+ |SCB_BATK );
+#else
+ );
+#endif
set_sc( GS_ADJUSTMENT , SC_GS_ADJUSTMENT , SI_GS_ADJUSTMENT , SCB_HIT|SCB_FLEE );
set_sc( GS_INCREASING , SC_GS_ACCURACY , SI_GS_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT );
- set_sc( GS_GATLINGFEVER , SC_GS_GATLINGFEVER , SI_GS_GATLINGFEVER , SCB_BATK|SCB_FLEE|SCB_SPEED|SCB_ASPD );
+ set_sc( GS_GATLINGFEVER , SC_GS_GATLINGFEVER , SI_GS_GATLINGFEVER , SCB_FLEE|SCB_SPEED|SCB_ASPD
+#ifndef RENEWAL
+ |SCB_BATK );
+#else
+ );
+#endif
set_sc( NJ_TATAMIGAESHI , SC_NJ_TATAMIGAESHI , SI_BLANK , SCB_NONE );
set_sc( NJ_SUITON , SC_NJ_SUITON , SI_NJ_SUITON , SCB_AGI|SCB_SPEED );
add_sc( NJ_HYOUSYOURAKU , SC_FREEZE );
@@ -467,7 +448,7 @@ void initChangeTables(void) {
set_sc( CASH_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE );
set_sc( ALL_PARTYFLEE , SC_PARTYFLEE , SI_PARTYFLEE , SCB_NONE );
- set_sc( ALL_ODINS_POWER , SC_ODINS_POWER , SI_ODINS_POWER , SCB_MATK|SCB_BATK|SCB_MDEF|SCB_DEF );
+ set_sc( ALL_ODINS_POWER , SC_ODINS_POWER , SI_ODINS_POWER , SCB_WATK | SCB_MATK | SCB_MDEF | SCB_DEF);
set_sc( CR_SHRINK , SC_CR_SHRINK , SI_CR_SHRINK , SCB_NONE );
set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE );
@@ -488,13 +469,13 @@ void initChangeTables(void) {
set_sc( HAMI_BLOODLUST , SC_HAMI_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK );
// Homunculus S
+ set_sc( MH_LIGHT_OF_REGENE , SC_LIGHT_OF_REGENE , SI_LIGHT_OF_REGENE , SCB_NONE );
+ set_sc( MH_OVERED_BOOST , SC_OVERED_BOOST , SI_OVERED_BOOST , SCB_FLEE|SCB_ASPD|SCB_DEF );
+
add_sc(MH_STAHL_HORN, SC_STUN);
set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP);
set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP);
add_sc( MH_STEINWAND, SC_SAFETYWALL );
- add_sc(MH_ERASER_CUTTER, SC_ERASER_CUTTER);
- set_sc(MH_OVERED_BOOST, SC_OVERED_BOOST, SI_BLANK, SCB_FLEE|SCB_ASPD);
- add_sc(MH_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE);
set_sc(MH_VOLCANIC_ASH, SC_VOLCANIC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE);
set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SI_GRANITIC_ARMOR, SCB_NONE);
set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SI_MAGMA_FLOW, SCB_NONE);
@@ -504,14 +485,14 @@ void initChangeTables(void) {
add_sc(MH_POISON_MIST, SC_BLIND);
set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD);
- add_sc(MH_STYLE_CHANGE, SC_STYLE_CHANGE);
- set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE );
+ set_sc( MH_SILENT_BREEZE , SC_SILENCE , SI_SILENT_BREEZE , SCB_NONE );
+ add_sc( MH_STYLE_CHANGE , SC_STYLE_CHANGE);
+ set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE );
set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_M , SI_RG_CCONFINE_M , SCB_FLEE );
-
add_sc( MER_CRASH , SC_STUN );
set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
- add_sc( MS_MAGNUM , SC_WATK_ELEMENT );
+ add_sc( MS_MAGNUM , SC_SUB_WEAPONPROPERTY );
add_sc( MER_SIGHT , SC_SIGHT );
set_sc( MER_DECAGI , SC_DEC_AGI , SI_DEC_AGI , SCB_AGI|SCB_SPEED );
set_sc( MER_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN );
@@ -541,13 +522,13 @@ void initChangeTables(void) {
set_sc( GD_REGENERATION , SC_GDSKILL_REGENERATION , SI_BLANK , SCB_REGEN );
/**
- * Rune Knight
- **/
+ * Rune Knight
+ **/
set_sc( RK_ENCHANTBLADE , SC_ENCHANTBLADE , SI_ENCHANTBLADE , SCB_NONE );
set_sc( RK_DRAGONHOWLING , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT );
set_sc( RK_DEATHBOUND , SC_DEATHBOUND , SI_DEATHBOUND , SCB_NONE );
set_sc( RK_WINDCUTTER , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT );
- set_sc( RK_DRAGONBREATH , SC_BURNING , SI_BLANK , SCB_MDEF );
+ add_sc( RK_DRAGONBREATH , SC_BURNING );
set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_BLANK , SCB_NONE );
set_sc( RK_REFRESH , SC_REFRESH , SI_REFRESH , SCB_NONE );
set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR );
@@ -558,8 +539,8 @@ void initChangeTables(void) {
set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SI_CRUSHSTRIKE , SCB_NONE );
add_sc( RK_DRAGONBREATH_WATER, SC_FROSTMISTY );
/**
- * GC Guillotine Cross
- **/
+ * GC Guillotine Cross
+ **/
set_sc_with_vfx( GC_VENOMIMPRESS , SC_VENOMIMPRESS , SI_VENOMIMPRESS , SCB_NONE );
set_sc( GC_POISONINGWEAPON , SC_POISONINGWEAPON , SI_POISONINGWEAPON , SCB_NONE );
set_sc( GC_WEAPONBLOCKING , SC_WEAPONBLOCKING , SI_WEAPONBLOCKING , SCB_NONE );
@@ -568,8 +549,8 @@ void initChangeTables(void) {
set_sc( GC_ROLLINGCUTTER , SC_ROLLINGCUTTER , SI_ROLLINGCUTTER , SCB_NONE );
set_sc_with_vfx( GC_DARKCROW , SC_DARKCROW , SI_DARKCROW , SCB_NONE );
/**
- * Arch Bishop
- **/
+ * Arch Bishop
+ **/
set_sc( AB_ADORAMUS , SC_ADORAMUS , SI_ADORAMUS , SCB_AGI|SCB_SPEED );
add_sc( AB_CLEMENTIA , SC_BLESSING );
add_sc( AB_CANTO , SC_INC_AGI );
@@ -584,17 +565,17 @@ void initChangeTables(void) {
set_sc( AB_SECRAMENT , SC_SECRAMENT , SI_SECRAMENT , SCB_NONE );
set_sc( AB_OFFERTORIUM , SC_OFFERTORIUM , SI_OFFERTORIUM , SCB_NONE );
/**
- * Warlock
- **/
+ * Warlock
+ **/
add_sc( WL_WHITEIMPRISON , SC_WHITEIMPRISON );
set_sc_with_vfx( WL_FROSTMISTY , SC_FROSTMISTY , SI_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF );
set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , SI_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_AGI|SCB_DEX );
- set_sc(WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SI_RECOGNIZEDSPELL , SCB_MATK);
+ set_sc(WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SI_RECOGNIZEDSPELL , SCB_MATK);
set_sc( WL_STASIS , SC_STASIS , SI_STASIS , SCB_NONE );
set_sc( WL_TELEKINESIS_INTENSE, SC_TELEKINESIS_INTENSE , SI_TELEKINESIS_INTENSE , SCB_MATK );
/**
- * Ranger
- **/
+ * Ranger
+ **/
set_sc( RA_FEARBREEZE , SC_FEARBREEZE , SI_FEARBREEZE , SCB_NONE );
set_sc( RA_ELECTRICSHOCKER , SC_ELECTRICSHOCKER , SI_ELECTRICSHOCKER , SCB_NONE );
set_sc( RA_WUGDASH , SC_WUGDASH , SI_WUGDASH , SCB_SPEED );
@@ -605,35 +586,33 @@ void initChangeTables(void) {
add_sc( RA_VERDURETRAP , SC_ARMOR_PROPERTY );
add_sc( RA_FIRINGTRAP , SC_BURNING );
add_sc( RA_ICEBOUNDTRAP , SC_FROSTMISTY );
- set_sc( RA_UNLIMIT , SC_UNLIMIT , SI_UNLIMIT , SCB_NONE );
+ set_sc( RA_UNLIMIT , SC_UNLIMIT , SI_UNLIMIT , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
/**
- * Mechanic
- **/
+ * Mechanic
+ **/
set_sc( NC_ACCELERATION , SC_ACCELERATION , SI_ACCELERATION , SCB_SPEED );
set_sc( NC_HOVERING , SC_HOVERING , SI_HOVERING , SCB_SPEED );
set_sc( NC_SHAPESHIFT , SC_SHAPESHIFT , SI_SHAPESHIFT , SCB_DEF_ELE );
set_sc( NC_INFRAREDSCAN , SC_INFRAREDSCAN , SI_INFRAREDSCAN , SCB_FLEE );
set_sc( NC_ANALYZE , SC_ANALYZE , SI_ANALYZE , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
set_sc( NC_MAGNETICFIELD , SC_MAGNETICFIELD , SI_MAGNETICFIELD , SCB_NONE );
- set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SI_NEUTRALBARRIER , SCB_NONE );
+ set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SI_NEUTRALBARRIER , SCB_DEF|SCB_MDEF );
set_sc( NC_STEALTHFIELD , SC_STEALTHFIELD , SI_STEALTHFIELD , SCB_NONE );
/**
- * Royal Guard
- **/
+ * Royal Guard
+ **/
set_sc( LG_REFLECTDAMAGE , SC_LG_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE );
- set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP|SCB_DEF );
+ set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP );
set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE );
set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF );
set_sc( LG_BANDING , SC_BANDING , SI_BANDING , SCB_DEF2|SCB_WATK );// Renewal: atk2 & def2
set_sc( LG_PIETY , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE );
set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD );
set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK);
- set_sc( LG_SHIELDSPELL , SC_SHIELDSPELL_DEF , SI_SHIELDSPELL_DEF , SCB_WATK );
- set_sc( LG_SHIELDSPELL , SC_SHIELDSPELL_REF , SI_SHIELDSPELL_REF , SCB_DEF );
set_sc( LG_KINGS_GRACE , SC_KINGS_GRACE , SI_KINGS_GRACE , SCB_NONE );
/**
- * Shadow Chaser
- **/
+ * Shadow Chaser
+ **/
set_sc( SC_REPRODUCE , SC__REPRODUCE , SI_REPRODUCE , SCB_NONE );
set_sc( SC_AUTOSHADOWSPELL , SC__AUTOSHADOWSPELL, SI_AUTOSHADOWSPELL , SCB_NONE );
set_sc( SC_SHADOWFORM , SC__SHADOWFORM , SI_SHADOWFORM , SCB_NONE );
@@ -648,13 +627,16 @@ void initChangeTables(void) {
set_sc( SC_WEAKNESS , SC__WEAKNESS , SI_WEAKNESS , SCB_FLEE2|SCB_MAXHP );
set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSARY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK );
set_sc_with_vfx( SC_MANHOLE , SC__MANHOLE , SI_MANHOLE , SCB_NONE );
- add_sc( SC_CHAOSPANIC , SC_CONFUSION );
- set_sc_with_vfx( SC_BLOODYLUST , SC__BLOODYLUST , SI_BLOODYLUST , SCB_DEF | SCB_DEF2 | SCB_MDEF | SCB_MDEF2 | SCB_FLEE | SCB_SPEED | SCB_ASPD | SCB_MAXHP | SCB_REGEN );
+ add_sc( SC_CHAOSPANIC , SC__CHAOS );
+ add_sc( SC_MAELSTROM , SC__MAELSTROM );
+ add_sc( SC_BLOODYLUST , SC_BERSERK );
+
/**
- * Sura
- **/
+ * Sura
+ **/
add_sc( SR_DRAGONCOMBO , SC_STUN );
add_sc( SR_EARTHSHAKER , SC_STUN );
+ set_sc( SR_FALLENEMPIRE , SC_FALLENEMPIRE , SI_FALLENEMPIRE , SCB_NONE );
set_sc( SR_CRESCENTELBOW , SC_CRESCENTELBOW , SI_CRESCENTELBOW , SCB_NONE );
set_sc_with_vfx( SR_CURSEDCIRCLE , SC_CURSEDCIRCLE_TARGET, SI_CURSEDCIRCLE_TARGET , SCB_NONE );
set_sc( SR_LIGHTNINGWALK , SC_LIGHTNINGWALK , SI_LIGHTNINGWALK , SCB_NONE );
@@ -662,16 +644,17 @@ void initChangeTables(void) {
set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GENTLETOUCH_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN, SCB_NONE );
set_sc( SR_GENTLETOUCH_CHANGE , SC_GENTLETOUCH_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP );
set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GENTLETOUCH_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_REGEN );
+ set_sc( SR_FLASHCOMBO , SC_FLASHCOMBO , SI_FLASHCOMBO , SCB_WATK );
/**
- * Wanderer / Minstrel
- **/
+ * Wanderer / Minstrel
+ **/
set_sc( WA_SWING_DANCE , SC_SWING , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD );
set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONY_LOVE , SI_SYMPHONYOFLOVERS , SCB_MDEF );
set_sc( WA_MOONLIT_SERENADE , SC_MOONLIT_SERENADE , SI_MOONLITSERENADE , SCB_MATK );
- set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SI_RUSHWINDMILL , SCB_BATK );
+ set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SI_RUSHWINDMILL , SCB_WATK );
set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 );
set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
- set_sc_with_vfx( WM_POEMOFNETHERWORLD , SC_NETHERWORLD , SI_NETHERWORLD , SCB_NONE );
+ set_sc( WM_POEMOFNETHERWORLD , SC_STOP , SI_NETHERWORLD , SCB_NONE );
set_sc_with_vfx( WM_VOICEOFSIREN , SC_SIREN , SI_SIREN , SCB_NONE );
set_sc_with_vfx( WM_LULLABY_DEEPSLEEP , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE );
set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE );
@@ -680,19 +663,19 @@ void initChangeTables(void) {
set_sc( WM_DANCE_WITH_WUG , SC_DANCE_WITH_WUG , SI_DANCEWITHWUG , SCB_ASPD );
set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAY_NIGHT_FEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN );
set_sc( WM_LERADS_DEW , SC_LERADS_DEW , SI_LERADSDEW , SCB_MAXHP );
- set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_BATK|SCB_MATK );
- set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SI_WARCRYOFBEYOND , SCB_BATK|SCB_MATK );
+ set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_INT );
+ set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SI_WARCRYOFBEYOND , SCB_STR|SCB_CRI|SCB_MAXHP );
set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITED_HUMMING_VOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE );
set_sc( WM_FRIGG_SONG , SC_FRIGG_SONG , SI_FRIGG_SONG , SCB_MAXHP );
-
+
/**
- * Sorcerer
- **/
+ * Sorcerer
+ **/
set_sc( SO_FIREWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
set_sc( SO_ELECTRICWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
set_sc( SO_SPELLFIST , SC_SPELLFIST , SI_SPELLFIST , SCB_NONE );
- set_sc_with_vfx( SO_DIAMONDDUST , SC_CRYSTALIZE , SI_COLD , SCB_NONE ); // it does show the snow icon on mobs but doesn't affect it.
- add_sc( SO_CLOUD_KILL , SC_POISON );
+ set_sc_with_vfx( SO_DIAMONDDUST , SC_COLD , SI_COLD , SCB_NONE ); // it does show the snow icon on mobs but doesn't affect it.
+ set_sc( SO_CLOUD_KILL , SC_POISON , SI_CLOUDKILL , SCB_NONE );
set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI );
set_sc( SO_WARMER , SC_WARMER , SI_WARMER , SCB_NONE );
set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE );
@@ -701,9 +684,10 @@ void initChangeTables(void) {
set_sc( SO_WATER_INSIGNIA , SC_WATER_INSIGNIA , SI_WATER_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
set_sc( SO_WIND_INSIGNIA , SC_WIND_INSIGNIA , SI_WIND_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
set_sc( SO_EARTH_INSIGNIA , SC_EARTH_INSIGNIA , SI_EARTH_INSIGNIA , SCB_MDEF|SCB_DEF|SCB_MAXHP|SCB_MAXSP|SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
+ add_sc( SO_ELEMENTAL_SHIELD , SC_SAFETYWALL );
/**
- * Genetic
- **/
+ * Genetic
+ **/
set_sc( GN_CARTBOOST , SC_GN_CARTBOOST, SI_CARTSBOOST , SCB_SPEED );
set_sc( GN_THORNS_TRAP , SC_THORNS_TRAP , SI_THORNTRAP , SCB_NONE );
set_sc_with_vfx( GN_BLOOD_SUCKER , SC_BLOOD_SUCKER , SI_BLOODSUCKER , SCB_NONE );
@@ -717,7 +701,7 @@ void initChangeTables(void) {
set_sc( EL_FIRE_CLOAK , SC_FIRE_CLOAK_OPTION , SI_FIRE_CLOAK_OPTION , SCB_ALL );
set_sc( EL_WATER_SCREEN , SC_WATER_SCREEN_OPTION , SI_WATER_SCREEN_OPTION , SCB_NONE );
set_sc( EL_WATER_DROP , SC_WATER_DROP_OPTION , SI_WATER_DROP_OPTION , SCB_ALL );
- set_sc( EL_WATER_BARRIER , SC_WATER_BARRIER , SI_WATER_BARRIER , SCB_MDEF|SCB_WATK|SCB_MATK|SCB_FLEE );
+ set_sc( EL_WATER_BARRIER , SC_WATER_BARRIER , SI_WATER_BARRIER , SCB_WATK|SCB_FLEE );
set_sc( EL_WIND_STEP , SC_WIND_STEP_OPTION , SI_WIND_STEP_OPTION , SCB_SPEED|SCB_FLEE );
set_sc( EL_WIND_CURTAIN , SC_WIND_CURTAIN_OPTION , SI_WIND_CURTAIN_OPTION , SCB_ALL );
set_sc( EL_ZEPHYR , SC_ZEPHYR , SI_ZEPHYR , SCB_FLEE );
@@ -734,8 +718,8 @@ void initChangeTables(void) {
set_sc( EL_BLAST , SC_BLAST_OPTION , SI_BLAST_OPTION , SCB_ASPD );
set_sc( EL_WILD_STORM , SC_WILD_STORM_OPTION , SI_WILD_STORM_OPTION , SCB_ASPD );
set_sc( EL_PETROLOGY , SC_PETROLOGY_OPTION , SI_PETROLOGY_OPTION , SCB_MAXHP );
- set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SI_CURSED_SOIL_OPTION , SCB_NONE );
- set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_NONE );
+ set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SI_CURSED_SOIL_OPTION , SCB_MAXHP );
+ set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_MAXHP );
set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL );
set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF );
set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED );
@@ -757,302 +741,340 @@ void initChangeTables(void) {
set_sc( ALL_FULL_THROTTLE , SC_FULL_THROTTLE , SI_FULL_THROTTLE , SCB_SPEED|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ add_sc( ALL_REVERSEORCISH , SC_ORCISH );
+ set_sc( ALL_ANGEL_PROTECT , SC_ANGEL_PROTECT , SI_ANGEL_PROTECT , SCB_REGEN );
+
+ add_sc( NPC_WIDEHEALTHFEAR , SC_FEAR );
+ add_sc( NPC_WIDEBODYBURNNING , SC_BURNING );
+ add_sc( NPC_WIDEFROSTMISTY , SC_FROSTMISTY );
+ add_sc( NPC_WIDECOLD , SC_COLD );
+ add_sc( NPC_WIDE_DEEP_SLEEP , SC_DEEP_SLEEP );
+ add_sc( NPC_WIDESIREN , SC_SIREN );
+
+ set_sc_with_vfx( GN_ILLUSIONDOPING , SC_ILLUSIONDOPING , SI_ILLUSIONDOPING , SCB_HIT );
+
// Storing the target job rather than simply SC_SOULLINK simplifies code later on.
- SkillStatusChangeTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST,
- SkillStatusChangeTable[SL_MONK] = (sc_type)MAPID_MONK,
- SkillStatusChangeTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR,
- SkillStatusChangeTable[SL_SAGE] = (sc_type)MAPID_SAGE,
- SkillStatusChangeTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER,
- SkillStatusChangeTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE,
- SkillStatusChangeTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT,
- SkillStatusChangeTable[SL_WIZARD] = (sc_type)MAPID_WIZARD,
- SkillStatusChangeTable[SL_PRIEST] = (sc_type)MAPID_PRIEST,
- SkillStatusChangeTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER,
- SkillStatusChangeTable[SL_ROGUE] = (sc_type)MAPID_ROGUE,
- SkillStatusChangeTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN,
- SkillStatusChangeTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH,
- SkillStatusChangeTable[SL_HUNTER] = (sc_type)MAPID_HUNTER,
- SkillStatusChangeTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER,
+ status->Skill2SCTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST,
+ status->Skill2SCTable[SL_MONK] = (sc_type)MAPID_MONK,
+ status->Skill2SCTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR,
+ status->Skill2SCTable[SL_SAGE] = (sc_type)MAPID_SAGE,
+ status->Skill2SCTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER,
+ status->Skill2SCTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE,
+ status->Skill2SCTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT,
+ status->Skill2SCTable[SL_WIZARD] = (sc_type)MAPID_WIZARD,
+ status->Skill2SCTable[SL_PRIEST] = (sc_type)MAPID_PRIEST,
+ status->Skill2SCTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER,
+ status->Skill2SCTable[SL_ROGUE] = (sc_type)MAPID_ROGUE,
+ status->Skill2SCTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN,
+ status->Skill2SCTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH,
+ status->Skill2SCTable[SL_HUNTER] = (sc_type)MAPID_HUNTER,
+ status->Skill2SCTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER,
//Status that don't have a skill associated.
- StatusIconChangeTable[SC_WEIGHTOVER50] = SI_WEIGHTOVER50;
- StatusIconChangeTable[SC_WEIGHTOVER90] = SI_WEIGHTOVER90;
- StatusIconChangeTable[SC_ATTHASTE_POTION1] = SI_ATTHASTE_POTION1;
- StatusIconChangeTable[SC_ATTHASTE_POTION2] = SI_ATTHASTE_POTION2;
- StatusIconChangeTable[SC_ATTHASTE_POTION3] = SI_ATTHASTE_POTION3;
- StatusIconChangeTable[SC_ATTHASTE_INFINITY] = SI_ATTHASTE_INFINITY;
- StatusIconChangeTable[SC_MOVHASTE_HORSE] = SI_MOVHASTE_HORSE;
- StatusIconChangeTable[SC_MOVHASTE_INFINITY] = SI_MOVHASTE_INFINITY;
- StatusIconChangeTable[SC_CHASEWALK2] = SI_INCSTR;
- StatusIconChangeTable[SC_MIRACLE] = SI_SOULLINK;
- StatusIconChangeTable[SC_CLAIRVOYANCE] = SI_CLAIRVOYANCE;
- StatusIconChangeTable[SC_FOOD_STR] = SI_FOOD_STR;
- StatusIconChangeTable[SC_FOOD_AGI] = SI_FOOD_AGI;
- StatusIconChangeTable[SC_FOOD_VIT] = SI_FOOD_VIT;
- StatusIconChangeTable[SC_FOOD_INT] = SI_FOOD_INT;
- StatusIconChangeTable[SC_FOOD_DEX] = SI_FOOD_DEX;
- StatusIconChangeTable[SC_FOOD_LUK] = SI_FOOD_LUK;
- StatusIconChangeTable[SC_FOOD_BASICAVOIDANCE]= SI_FOOD_BASICAVOIDANCE;
- StatusIconChangeTable[SC_FOOD_BASICHIT] = SI_FOOD_BASICHIT;
- StatusIconChangeTable[SC_MANU_ATK] = SI_MANU_ATK;
- StatusIconChangeTable[SC_MANU_DEF] = SI_MANU_DEF;
- StatusIconChangeTable[SC_SPL_ATK] = SI_SPL_ATK;
- StatusIconChangeTable[SC_SPL_DEF] = SI_SPL_DEF;
- StatusIconChangeTable[SC_MANU_MATK] = SI_MANU_MATK;
- StatusIconChangeTable[SC_SPL_MATK] = SI_SPL_MATK;
- StatusIconChangeTable[SC_PLUSATTACKPOWER] = SI_PLUSATTACKPOWER;
- StatusIconChangeTable[SC_PLUSMAGICPOWER] = SI_PLUSMAGICPOWER;
+ status->IconChangeTable[SC_WEIGHTOVER50] = SI_WEIGHTOVER50;
+ status->IconChangeTable[SC_WEIGHTOVER90] = SI_WEIGHTOVER90;
+ status->IconChangeTable[SC_ATTHASTE_POTION1] = SI_ATTHASTE_POTION1;
+ status->IconChangeTable[SC_ATTHASTE_POTION2] = SI_ATTHASTE_POTION2;
+ status->IconChangeTable[SC_ATTHASTE_POTION3] = SI_ATTHASTE_POTION3;
+ status->IconChangeTable[SC_ATTHASTE_INFINITY] = SI_ATTHASTE_INFINITY;
+ status->IconChangeTable[SC_MOVHASTE_HORSE] = SI_MOVHASTE_HORSE;
+ status->IconChangeTable[SC_MOVHASTE_INFINITY] = SI_MOVHASTE_INFINITY;
+ status->IconChangeTable[SC_CHASEWALK2] = SI_INCSTR;
+ status->IconChangeTable[SC_MIRACLE] = SI_SOULLINK;
+ status->IconChangeTable[SC_CLAIRVOYANCE] = SI_CLAIRVOYANCE;
+ status->IconChangeTable[SC_FOOD_STR] = SI_FOOD_STR;
+ status->IconChangeTable[SC_FOOD_AGI] = SI_FOOD_AGI;
+ status->IconChangeTable[SC_FOOD_VIT] = SI_FOOD_VIT;
+ status->IconChangeTable[SC_FOOD_INT] = SI_FOOD_INT;
+ status->IconChangeTable[SC_FOOD_DEX] = SI_FOOD_DEX;
+ status->IconChangeTable[SC_FOOD_LUK] = SI_FOOD_LUK;
+ status->IconChangeTable[SC_FOOD_BASICAVOIDANCE]= SI_FOOD_BASICAVOIDANCE;
+ status->IconChangeTable[SC_FOOD_BASICHIT] = SI_FOOD_BASICHIT;
+ status->IconChangeTable[SC_MANU_ATK] = SI_MANU_ATK;
+ status->IconChangeTable[SC_MANU_DEF] = SI_MANU_DEF;
+ status->IconChangeTable[SC_SPL_ATK] = SI_SPL_ATK;
+ status->IconChangeTable[SC_SPL_DEF] = SI_SPL_DEF;
+ status->IconChangeTable[SC_MANU_MATK] = SI_MANU_MATK;
+ status->IconChangeTable[SC_SPL_MATK] = SI_SPL_MATK;
+ status->IconChangeTable[SC_PLUSATTACKPOWER] = SI_PLUSATTACKPOWER;
+ status->IconChangeTable[SC_PLUSMAGICPOWER] = SI_PLUSMAGICPOWER;
//Cash Items
- StatusIconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH;
- StatusIconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH;
- StatusIconChangeTable[SC_FOOD_VIT_CASH] = SI_FOOD_VIT_CASH;
- StatusIconChangeTable[SC_FOOD_DEX_CASH] = SI_FOOD_DEX_CASH;
- StatusIconChangeTable[SC_FOOD_INT_CASH] = SI_FOOD_INT_CASH;
- StatusIconChangeTable[SC_FOOD_LUK_CASH] = SI_FOOD_LUK_CASH;
- StatusIconChangeTable[SC_CASH_PLUSEXP] = SI_CASH_PLUSEXP;
- StatusIconChangeTable[SC_CASH_RECEIVEITEM] = SI_CASH_RECEIVEITEM;
- StatusIconChangeTable[SC_CASH_PLUSONLYJOBEXP] = SI_CASH_PLUSONLYJOBEXP;
- StatusIconChangeTable[SC_CASH_DEATHPENALTY] = SI_CASH_DEATHPENALTY;
- StatusIconChangeTable[SC_CASH_BOSS_ALARM] = SI_CASH_BOSS_ALARM;
- StatusIconChangeTable[SC_PROTECT_DEF] = SI_PROTECT_DEF;
- StatusIconChangeTable[SC_PROTECT_MDEF] = SI_PROTECT_MDEF;
- StatusIconChangeTable[SC_CRITICALPERCENT] = SI_CRITICALPERCENT;
- StatusIconChangeTable[SC_PLUSAVOIDVALUE] = SI_PLUSAVOIDVALUE;
- StatusIconChangeTable[SC_HEALPLUS] = SI_HEALPLUS;
- StatusIconChangeTable[SC_S_LIFEPOTION] = SI_S_LIFEPOTION;
- StatusIconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION;
- StatusIconChangeTable[SC_ATKER_BLOOD] = SI_ATKER_BLOOD;
- StatusIconChangeTable[SC_TARGET_BLOOD] = SI_TARGET_BLOOD;
+ status->IconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH;
+ status->IconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH;
+ status->IconChangeTable[SC_FOOD_VIT_CASH] = SI_FOOD_VIT_CASH;
+ status->IconChangeTable[SC_FOOD_DEX_CASH] = SI_FOOD_DEX_CASH;
+ status->IconChangeTable[SC_FOOD_INT_CASH] = SI_FOOD_INT_CASH;
+ status->IconChangeTable[SC_FOOD_LUK_CASH] = SI_FOOD_LUK_CASH;
+ status->IconChangeTable[SC_CASH_PLUSEXP] = SI_CASH_PLUSEXP;
+ status->IconChangeTable[SC_CASH_RECEIVEITEM] = SI_CASH_RECEIVEITEM;
+ status->IconChangeTable[SC_CASH_PLUSONLYJOBEXP] = SI_CASH_PLUSONLYJOBEXP;
+ status->IconChangeTable[SC_CASH_DEATHPENALTY] = SI_CASH_DEATHPENALTY;
+ status->IconChangeTable[SC_CASH_BOSS_ALARM] = SI_CASH_BOSS_ALARM;
+ status->IconChangeTable[SC_PROTECT_DEF] = SI_PROTECT_DEF;
+ status->IconChangeTable[SC_PROTECT_MDEF] = SI_PROTECT_MDEF;
+ status->IconChangeTable[SC_CRITICALPERCENT] = SI_CRITICALPERCENT;
+ status->IconChangeTable[SC_PLUSAVOIDVALUE] = SI_PLUSAVOIDVALUE;
+ status->IconChangeTable[SC_HEALPLUS] = SI_HEALPLUS;
+ status->IconChangeTable[SC_S_LIFEPOTION] = SI_S_LIFEPOTION;
+ status->IconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION;
+ status->IconChangeTable[SC_ATKER_BLOOD] = SI_ATKER_BLOOD;
+ status->IconChangeTable[SC_TARGET_BLOOD] = SI_TARGET_BLOOD;
// Mercenary Bonus Effects
- StatusIconChangeTable[SC_MER_FLEE] = SI_MER_FLEE;
- StatusIconChangeTable[SC_MER_ATK] = SI_MER_ATK;
- StatusIconChangeTable[SC_MER_HP] = SI_MER_HP;
- StatusIconChangeTable[SC_MER_SP] = SI_MER_SP;
- StatusIconChangeTable[SC_MER_HIT] = SI_MER_HIT;
+ status->IconChangeTable[SC_MER_FLEE] = SI_MER_FLEE;
+ status->IconChangeTable[SC_MER_ATK] = SI_MER_ATK;
+ status->IconChangeTable[SC_MER_HP] = SI_MER_HP;
+ status->IconChangeTable[SC_MER_SP] = SI_MER_SP;
+ status->IconChangeTable[SC_MER_HIT] = SI_MER_HIT;
// Warlock Spheres
- StatusIconChangeTable[SC_SUMMON1] = SI_SPHERE_1;
- StatusIconChangeTable[SC_SUMMON2] = SI_SPHERE_2;
- StatusIconChangeTable[SC_SUMMON3] = SI_SPHERE_3;
- StatusIconChangeTable[SC_SUMMON4] = SI_SPHERE_4;
- StatusIconChangeTable[SC_SUMMON5] = SI_SPHERE_5;
+ status->IconChangeTable[SC_SUMMON1] = SI_SPHERE_1;
+ status->IconChangeTable[SC_SUMMON2] = SI_SPHERE_2;
+ status->IconChangeTable[SC_SUMMON3] = SI_SPHERE_3;
+ status->IconChangeTable[SC_SUMMON4] = SI_SPHERE_4;
+ status->IconChangeTable[SC_SUMMON5] = SI_SPHERE_5;
// Warlock Preserved spells
- StatusIconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1;
- StatusIconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2;
- StatusIconChangeTable[SC_SPELLBOOK3] = SI_SPELLBOOK3;
- StatusIconChangeTable[SC_SPELLBOOK4] = SI_SPELLBOOK4;
- StatusIconChangeTable[SC_SPELLBOOK5] = SI_SPELLBOOK5;
- StatusIconChangeTable[SC_SPELLBOOK6] = SI_SPELLBOOK6;
- StatusIconChangeTable[SC_SPELLBOOK7] = SI_SPELLBOOK7;
-
- StatusIconChangeTable[SC_NEUTRALBARRIER_MASTER] = SI_NEUTRALBARRIER_MASTER;
- StatusIconChangeTable[SC_STEALTHFIELD_MASTER] = SI_STEALTHFIELD_MASTER;
- StatusIconChangeTable[SC_OVERHEAT] = SI_OVERHEAT;
- StatusIconChangeTable[SC_OVERHEAT_LIMITPOINT] = SI_OVERHEAT_LIMITPOINT;
-
- StatusIconChangeTable[SC_HALLUCINATIONWALK_POSTDELAY] = SI_HALLUCINATIONWALK_POSTDELAY;
- StatusIconChangeTable[SC_TOXIN] = SI_TOXIN;
- StatusIconChangeTable[SC_PARALYSE] = SI_PARALYSE;
- StatusIconChangeTable[SC_VENOMBLEED] = SI_VENOMBLEED;
- StatusIconChangeTable[SC_MAGICMUSHROOM] = SI_MAGICMUSHROOM;
- StatusIconChangeTable[SC_DEATHHURT] = SI_DEATHHURT;
- StatusIconChangeTable[SC_PYREXIA] = SI_PYREXIA;
- StatusIconChangeTable[SC_OBLIVIONCURSE] = SI_OBLIVIONCURSE;
- StatusIconChangeTable[SC_LEECHESEND] = SI_LEECHESEND;
-
- StatusIconChangeTable[SC_SHIELDSPELL_DEF] = SI_SHIELDSPELL_DEF;
- StatusIconChangeTable[SC_SHIELDSPELL_MDEF] = SI_SHIELDSPELL_MDEF;
- StatusIconChangeTable[SC_SHIELDSPELL_REF] = SI_SHIELDSPELL_REF;
- StatusIconChangeTable[SC_BANDING_DEFENCE] = SI_BANDING_DEFENCE;
-
- StatusIconChangeTable[SC_GLOOMYDAY_SK] = SI_GLOOMYDAY;
-
- StatusIconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER;
-
- StatusIconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE;
- StatusIconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER;
- StatusIconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB;
- StatusIconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB;
- StatusIconChangeTable[SC_BANANA_BOMB_SITDOWN_POSTDELAY] = SI_BANANA_BOMB_SITDOWN_POSTDELAY;
+ status->IconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1;
+ status->IconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2;
+ status->IconChangeTable[SC_SPELLBOOK3] = SI_SPELLBOOK3;
+ status->IconChangeTable[SC_SPELLBOOK4] = SI_SPELLBOOK4;
+ status->IconChangeTable[SC_SPELLBOOK5] = SI_SPELLBOOK5;
+ status->IconChangeTable[SC_SPELLBOOK6] = SI_SPELLBOOK6;
+ status->IconChangeTable[SC_SPELLBOOK7] = SI_SPELLBOOK7;
+
+ status->IconChangeTable[SC_NEUTRALBARRIER_MASTER] = SI_NEUTRALBARRIER_MASTER;
+ status->IconChangeTable[SC_STEALTHFIELD_MASTER] = SI_STEALTHFIELD_MASTER;
+ status->IconChangeTable[SC_OVERHEAT] = SI_OVERHEAT;
+ status->IconChangeTable[SC_OVERHEAT_LIMITPOINT] = SI_OVERHEAT_LIMITPOINT;
+
+ status->IconChangeTable[SC_HALLUCINATIONWALK_POSTDELAY] = SI_HALLUCINATIONWALK_POSTDELAY;
+ status->IconChangeTable[SC_TOXIN] = SI_TOXIN;
+ status->IconChangeTable[SC_PARALYSE] = SI_PARALYSE;
+ status->IconChangeTable[SC_VENOMBLEED] = SI_VENOMBLEED;
+ status->IconChangeTable[SC_MAGICMUSHROOM] = SI_MAGICMUSHROOM;
+ status->IconChangeTable[SC_DEATHHURT] = SI_DEATHHURT;
+ status->IconChangeTable[SC_PYREXIA] = SI_PYREXIA;
+ status->IconChangeTable[SC_OBLIVIONCURSE] = SI_OBLIVIONCURSE;
+ status->IconChangeTable[SC_LEECHESEND] = SI_LEECHESEND;
+
+ status->IconChangeTable[SC_SHIELDSPELL_DEF] = SI_SHIELDSPELL_DEF;
+ status->IconChangeTable[SC_SHIELDSPELL_MDEF] = SI_SHIELDSPELL_MDEF;
+ status->IconChangeTable[SC_SHIELDSPELL_REF] = SI_SHIELDSPELL_REF;
+ status->IconChangeTable[SC_BANDING_DEFENCE] = SI_BANDING_DEFENCE;
+
+ status->IconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER;
+
+ status->IconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE;
+ status->IconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER;
+ status->IconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB;
+ status->IconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB;
+ status->IconChangeTable[SC_BANANA_BOMB_SITDOWN_POSTDELAY] = SI_BANANA_BOMB_SITDOWN_POSTDELAY;
//Genetics New Food Items Status Icons
- StatusIconChangeTable[SC_SAVAGE_STEAK] = SI_SAVAGE_STEAK;
- StatusIconChangeTable[SC_COCKTAIL_WARG_BLOOD] = SI_COCKTAIL_WARG_BLOOD;
- StatusIconChangeTable[SC_MINOR_BBQ] = SI_MINOR_BBQ;
- StatusIconChangeTable[SC_SIROMA_ICE_TEA] = SI_SIROMA_ICE_TEA;
- StatusIconChangeTable[SC_DROCERA_HERB_STEAMED] = SI_DROCERA_HERB_STEAMED;
- StatusIconChangeTable[SC_PUTTI_TAILS_NOODLES] = SI_PUTTI_TAILS_NOODLES;
-
- StatusIconChangeTable[SC_BOOST500] |= SI_BOOST500;
- StatusIconChangeTable[SC_FULL_SWING_K] |= SI_FULL_SWING_K;
- StatusIconChangeTable[SC_MANA_PLUS] |= SI_MANA_PLUS;
- StatusIconChangeTable[SC_MUSTLE_M] |= SI_MUSTLE_M;
- StatusIconChangeTable[SC_LIFE_FORCE_F] |= SI_LIFE_FORCE_F;
- StatusIconChangeTable[SC_EXTRACT_WHITE_POTION_Z] |= SI_EXTRACT_WHITE_POTION_Z;
- StatusIconChangeTable[SC_VITATA_500] |= SI_VITATA_500;
- StatusIconChangeTable[SC_EXTRACT_SALAMINE_JUICE] |= SI_EXTRACT_SALAMINE_JUICE;
+ status->IconChangeTable[SC_SAVAGE_STEAK] = SI_SAVAGE_STEAK;
+ status->IconChangeTable[SC_COCKTAIL_WARG_BLOOD] = SI_COCKTAIL_WARG_BLOOD;
+ status->IconChangeTable[SC_MINOR_BBQ] = SI_MINOR_BBQ;
+ status->IconChangeTable[SC_SIROMA_ICE_TEA] = SI_SIROMA_ICE_TEA;
+ status->IconChangeTable[SC_DROCERA_HERB_STEAMED] = SI_DROCERA_HERB_STEAMED;
+ status->IconChangeTable[SC_PUTTI_TAILS_NOODLES] = SI_PUTTI_TAILS_NOODLES;
+
+ status->IconChangeTable[SC_BOOST500] |= SI_BOOST500;
+ status->IconChangeTable[SC_FULL_SWING_K] |= SI_FULL_SWING_K;
+ status->IconChangeTable[SC_MANA_PLUS] |= SI_MANA_PLUS;
+ status->IconChangeTable[SC_MUSTLE_M] |= SI_MUSTLE_M;
+ status->IconChangeTable[SC_LIFE_FORCE_F] |= SI_LIFE_FORCE_F;
+ status->IconChangeTable[SC_EXTRACT_WHITE_POTION_Z] |= SI_EXTRACT_WHITE_POTION_Z;
+ status->IconChangeTable[SC_VITATA_500] |= SI_VITATA_500;
+ status->IconChangeTable[SC_EXTRACT_SALAMINE_JUICE] |= SI_EXTRACT_SALAMINE_JUICE;
// Elemental Spirit's 'side' status change icons.
- StatusIconChangeTable[SC_CIRCLE_OF_FIRE] = SI_CIRCLE_OF_FIRE;
- StatusIconChangeTable[SC_FIRE_CLOAK] = SI_FIRE_CLOAK;
- StatusIconChangeTable[SC_WATER_SCREEN] = SI_WATER_SCREEN;
- StatusIconChangeTable[SC_WATER_DROP] = SI_WATER_DROP;
- StatusIconChangeTable[SC_WIND_STEP] = SI_WIND_STEP;
- StatusIconChangeTable[SC_WIND_CURTAIN] = SI_WIND_CURTAIN;
- StatusIconChangeTable[SC_SOLID_SKIN] = SI_SOLID_SKIN;
- StatusIconChangeTable[SC_STONE_SHIELD] = SI_STONE_SHIELD;
- StatusIconChangeTable[SC_PYROTECHNIC] = SI_PYROTECHNIC;
- StatusIconChangeTable[SC_HEATER] = SI_HEATER;
- StatusIconChangeTable[SC_TROPIC] = SI_TROPIC;
- StatusIconChangeTable[SC_AQUAPLAY] = SI_AQUAPLAY;
- StatusIconChangeTable[SC_COOLER] = SI_COOLER;
- StatusIconChangeTable[SC_CHILLY_AIR] = SI_CHILLY_AIR;
- StatusIconChangeTable[SC_GUST] = SI_GUST;
- StatusIconChangeTable[SC_BLAST] = SI_BLAST;
- StatusIconChangeTable[SC_WILD_STORM] = SI_WILD_STORM;
- StatusIconChangeTable[SC_PETROLOGY] = SI_PETROLOGY;
- StatusIconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL;
- StatusIconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL;
- StatusIconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART;
- StatusIconChangeTable[SC_REBOUND] = SI_REBOUND;
- StatusIconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING;
- StatusIconChangeTable[SC_MONSTER_TRANSFORM] = SI_MONSTER_TRANSFORM;
+ status->IconChangeTable[SC_CIRCLE_OF_FIRE] = SI_CIRCLE_OF_FIRE;
+ status->IconChangeTable[SC_FIRE_CLOAK] = SI_FIRE_CLOAK;
+ status->IconChangeTable[SC_WATER_SCREEN] = SI_WATER_SCREEN;
+ status->IconChangeTable[SC_WATER_DROP] = SI_WATER_DROP;
+ status->IconChangeTable[SC_WIND_STEP] = SI_WIND_STEP;
+ status->IconChangeTable[SC_WIND_CURTAIN] = SI_WIND_CURTAIN;
+ status->IconChangeTable[SC_SOLID_SKIN] = SI_SOLID_SKIN;
+ status->IconChangeTable[SC_STONE_SHIELD] = SI_STONE_SHIELD;
+ status->IconChangeTable[SC_PYROTECHNIC] = SI_PYROTECHNIC;
+ status->IconChangeTable[SC_HEATER] = SI_HEATER;
+ status->IconChangeTable[SC_TROPIC] = SI_TROPIC;
+ status->IconChangeTable[SC_AQUAPLAY] = SI_AQUAPLAY;
+ status->IconChangeTable[SC_COOLER] = SI_COOLER;
+ status->IconChangeTable[SC_CHILLY_AIR] = SI_CHILLY_AIR;
+ status->IconChangeTable[SC_GUST] = SI_GUST;
+ status->IconChangeTable[SC_BLAST] = SI_BLAST;
+ status->IconChangeTable[SC_WILD_STORM] = SI_WILD_STORM;
+ status->IconChangeTable[SC_PETROLOGY] = SI_PETROLOGY;
+ status->IconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL;
+ status->IconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL;
+ status->IconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART;
+ status->IconChangeTable[SC_REBOUND] = SI_REBOUND;
+ status->IconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING;
+ status->IconChangeTable[SC_MONSTER_TRANSFORM] = SI_MONSTER_TRANSFORM;
+ status->IconChangeTable[SC_MOONSTAR] = SI_MOONSTAR;
+ status->IconChangeTable[SC_SUPER_STAR] = SI_SUPER_STAR;
+ status->IconChangeTable[SC_STRANGELIGHTS] = SI_STRANGELIGHTS;
+ status->IconChangeTable[SC_DECORATION_OF_MUSIC] = SI_DECORATION_OF_MUSIC;
//Other SC which are not necessarily associated to skills.
- StatusChangeFlagTable[SC_ATTHASTE_POTION1] = SCB_ASPD;
- StatusChangeFlagTable[SC_ATTHASTE_POTION2] = SCB_ASPD;
- StatusChangeFlagTable[SC_ATTHASTE_POTION3] = SCB_ASPD;
- StatusChangeFlagTable[SC_ATTHASTE_INFINITY] = SCB_ASPD;
- StatusChangeFlagTable[SC_MOVHASTE_HORSE] = SCB_SPEED;
- StatusChangeFlagTable[SC_MOVHASTE_INFINITY] = SCB_SPEED;
- StatusChangeFlagTable[SC_PLUSATTACKPOWER] = SCB_BATK;
- StatusChangeFlagTable[SC_PLUSMAGICPOWER] = SCB_MATK;
- StatusChangeFlagTable[SC_INCALLSTATUS] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK;
- StatusChangeFlagTable[SC_CHASEWALK2] |= SCB_STR;
- StatusChangeFlagTable[SC_INCAGI] |= SCB_AGI;
- StatusChangeFlagTable[SC_INCVIT] |= SCB_VIT;
- StatusChangeFlagTable[SC_INCINT] |= SCB_INT;
- StatusChangeFlagTable[SC_INCDEX] |= SCB_DEX;
- StatusChangeFlagTable[SC_INCLUK] |= SCB_LUK;
- StatusChangeFlagTable[SC_INCHIT] |= SCB_HIT;
- StatusChangeFlagTable[SC_INCHITRATE] |= SCB_HIT;
- StatusChangeFlagTable[SC_INCFLEE] |= SCB_FLEE;
- StatusChangeFlagTable[SC_INCFLEERATE] |= SCB_FLEE;
- StatusChangeFlagTable[SC_CRITICALPERCENT] |= SCB_CRI;
- StatusChangeFlagTable[SC_INCASPDRATE] |= SCB_ASPD;
- StatusChangeFlagTable[SC_PLUSAVOIDVALUE] |= SCB_FLEE2;
- StatusChangeFlagTable[SC_INCMHPRATE] |= SCB_MAXHP;
- StatusChangeFlagTable[SC_INCMSPRATE] |= SCB_MAXSP;
- StatusChangeFlagTable[SC_INCMHP] |= SCB_MAXHP;
- StatusChangeFlagTable[SC_INCMSP] |= SCB_MAXSP;
- StatusChangeFlagTable[SC_INCATKRATE] |= SCB_BATK|SCB_WATK;
- StatusChangeFlagTable[SC_INCMATKRATE] |= SCB_MATK;
- StatusChangeFlagTable[SC_INCDEFRATE] |= SCB_DEF;
- StatusChangeFlagTable[SC_FOOD_STR] |= SCB_STR;
- StatusChangeFlagTable[SC_FOOD_AGI] |= SCB_AGI;
- StatusChangeFlagTable[SC_FOOD_VIT] |= SCB_VIT;
- StatusChangeFlagTable[SC_FOOD_INT] |= SCB_INT;
- StatusChangeFlagTable[SC_FOOD_DEX] |= SCB_DEX;
- StatusChangeFlagTable[SC_FOOD_LUK] |= SCB_LUK;
- StatusChangeFlagTable[SC_FOOD_BASICHIT] |= SCB_HIT;
- StatusChangeFlagTable[SC_FOOD_BASICAVOIDANCE] |= SCB_FLEE;
- StatusChangeFlagTable[SC_BATKFOOD] |= SCB_BATK;
- StatusChangeFlagTable[SC_WATKFOOD] |= SCB_WATK;
- StatusChangeFlagTable[SC_MATKFOOD] |= SCB_MATK;
- StatusChangeFlagTable[SC_ARMORPROPERTY] |= SCB_ALL;
- StatusChangeFlagTable[SC_ARMOR_RESIST] |= SCB_ALL;
- StatusChangeFlagTable[SC_ATKER_BLOOD] |= SCB_ALL;
- StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED;
- StatusChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL;
+ status->ChangeFlagTable[SC_ATTHASTE_POTION1] = SCB_ASPD;
+ status->ChangeFlagTable[SC_ATTHASTE_POTION2] = SCB_ASPD;
+ status->ChangeFlagTable[SC_ATTHASTE_POTION3] = SCB_ASPD;
+ status->ChangeFlagTable[SC_ATTHASTE_INFINITY] = SCB_ASPD;
+ status->ChangeFlagTable[SC_MOVHASTE_HORSE] = SCB_SPEED;
+ status->ChangeFlagTable[SC_MOVHASTE_INFINITY] = SCB_SPEED;
+ status->ChangeFlagTable[SC_PLUSATTACKPOWER] = SCB_BATK;
+ status->ChangeFlagTable[SC_PLUSMAGICPOWER] = SCB_MATK;
+ status->ChangeFlagTable[SC_INCALLSTATUS] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK;
+ status->ChangeFlagTable[SC_CHASEWALK2] |= SCB_STR;
+ status->ChangeFlagTable[SC_INCAGI] |= SCB_AGI;
+ status->ChangeFlagTable[SC_INCVIT] |= SCB_VIT;
+ status->ChangeFlagTable[SC_INCINT] |= SCB_INT;
+ status->ChangeFlagTable[SC_INCDEX] |= SCB_DEX;
+ status->ChangeFlagTable[SC_INCLUK] |= SCB_LUK;
+ status->ChangeFlagTable[SC_INCHIT] |= SCB_HIT;
+ status->ChangeFlagTable[SC_INCHITRATE] |= SCB_HIT;
+ status->ChangeFlagTable[SC_INCFLEE] |= SCB_FLEE;
+ status->ChangeFlagTable[SC_INCFLEERATE] |= SCB_FLEE;
+ status->ChangeFlagTable[SC_CRITICALPERCENT] |= SCB_CRI;
+ status->ChangeFlagTable[SC_INCASPDRATE] |= SCB_ASPD;
+ status->ChangeFlagTable[SC_PLUSAVOIDVALUE] |= SCB_FLEE2;
+ status->ChangeFlagTable[SC_INCMHPRATE] |= SCB_MAXHP;
+ status->ChangeFlagTable[SC_INCMSPRATE] |= SCB_MAXSP;
+ status->ChangeFlagTable[SC_INCMHP] |= SCB_MAXHP;
+ status->ChangeFlagTable[SC_INCMSP] |= SCB_MAXSP;
+ status->ChangeFlagTable[SC_INCATKRATE] |= SCB_BATK|SCB_WATK;
+ status->ChangeFlagTable[SC_INCMATKRATE] |= SCB_MATK;
+ status->ChangeFlagTable[SC_INCDEFRATE] |= SCB_DEF;
+ status->ChangeFlagTable[SC_FOOD_STR] |= SCB_STR;
+ status->ChangeFlagTable[SC_FOOD_AGI] |= SCB_AGI;
+ status->ChangeFlagTable[SC_FOOD_VIT] |= SCB_VIT;
+ status->ChangeFlagTable[SC_FOOD_INT] |= SCB_INT;
+ status->ChangeFlagTable[SC_FOOD_DEX] |= SCB_DEX;
+ status->ChangeFlagTable[SC_FOOD_LUK] |= SCB_LUK;
+ status->ChangeFlagTable[SC_FOOD_BASICHIT] |= SCB_HIT;
+ status->ChangeFlagTable[SC_FOOD_BASICAVOIDANCE] |= SCB_FLEE;
+ status->ChangeFlagTable[SC_BATKFOOD] |= SCB_BATK;
+ status->ChangeFlagTable[SC_WATKFOOD] |= SCB_WATK;
+ status->ChangeFlagTable[SC_MATKFOOD] |= SCB_MATK;
+ status->ChangeFlagTable[SC_ARMORPROPERTY] |= SCB_ALL;
+ status->ChangeFlagTable[SC_ARMOR_RESIST] |= SCB_ALL;
+ status->ChangeFlagTable[SC_ATKER_BLOOD] |= SCB_ALL;
+ status->ChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED;
+ status->ChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL;
// Cash Items
- StatusChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR;
- StatusChangeFlagTable[SC_FOOD_AGI_CASH] = SCB_AGI;
- StatusChangeFlagTable[SC_FOOD_VIT_CASH] = SCB_VIT;
- StatusChangeFlagTable[SC_FOOD_DEX_CASH] = SCB_DEX;
- StatusChangeFlagTable[SC_FOOD_INT_CASH] = SCB_INT;
- StatusChangeFlagTable[SC_FOOD_LUK_CASH] = SCB_LUK;
+ status->ChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR;
+ status->ChangeFlagTable[SC_FOOD_AGI_CASH] = SCB_AGI;
+ status->ChangeFlagTable[SC_FOOD_VIT_CASH] = SCB_VIT;
+ status->ChangeFlagTable[SC_FOOD_DEX_CASH] = SCB_DEX;
+ status->ChangeFlagTable[SC_FOOD_INT_CASH] = SCB_INT;
+ status->ChangeFlagTable[SC_FOOD_LUK_CASH] = SCB_LUK;
// Mercenary Bonus Effects
- StatusChangeFlagTable[SC_MER_FLEE] |= SCB_FLEE;
- StatusChangeFlagTable[SC_MER_ATK] |= SCB_WATK;
- StatusChangeFlagTable[SC_MER_HP] |= SCB_MAXHP;
- StatusChangeFlagTable[SC_MER_SP] |= SCB_MAXSP;
- StatusChangeFlagTable[SC_MER_HIT] |= SCB_HIT;
+ status->ChangeFlagTable[SC_MER_FLEE] |= SCB_FLEE;
+ status->ChangeFlagTable[SC_MER_ATK] |= SCB_WATK;
+ status->ChangeFlagTable[SC_MER_HP] |= SCB_MAXHP;
+ status->ChangeFlagTable[SC_MER_SP] |= SCB_MAXSP;
+ status->ChangeFlagTable[SC_MER_HIT] |= SCB_HIT;
// Guillotine Cross Poison Effects
- StatusChangeFlagTable[SC_PARALYSE] |= SCB_ASPD|SCB_FLEE|SCB_SPEED;
- StatusChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN;
- StatusChangeFlagTable[SC_VENOMBLEED] |= SCB_MAXHP;
- StatusChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN;
-
- StatusChangeFlagTable[SC_SAVAGE_STEAK] |= SCB_STR;
- StatusChangeFlagTable[SC_COCKTAIL_WARG_BLOOD] |= SCB_INT;
- StatusChangeFlagTable[SC_MINOR_BBQ] |= SCB_VIT;
- StatusChangeFlagTable[SC_SIROMA_ICE_TEA] |= SCB_DEX;
- StatusChangeFlagTable[SC_DROCERA_HERB_STEAMED] |= SCB_AGI;
- StatusChangeFlagTable[SC_PUTTI_TAILS_NOODLES] |= SCB_LUK;
- StatusChangeFlagTable[SC_BOOST500] |= SCB_ASPD;
- StatusChangeFlagTable[SC_FULL_SWING_K] |= SCB_BATK;
- StatusChangeFlagTable[SC_MANA_PLUS] |= SCB_MATK;
- StatusChangeFlagTable[SC_MUSTLE_M] |= SCB_MAXHP;
- StatusChangeFlagTable[SC_LIFE_FORCE_F] |= SCB_MAXSP;
- StatusChangeFlagTable[SC_EXTRACT_WHITE_POTION_Z] |= SCB_REGEN;
- StatusChangeFlagTable[SC_VITATA_500] |= SCB_REGEN;
- StatusChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD;
- StatusChangeFlagTable[SC_REBOUND] |= SCB_SPEED|SCB_REGEN;
-
- StatusChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED;
-
- /* StatusDisplayType Table [Ind/Hercules] */
- StatusDisplayType[SC_ALL_RIDING] = true;
- StatusDisplayType[SC_PUSH_CART] = true;
- StatusDisplayType[SC_SUMMON1] = true;
- StatusDisplayType[SC_SUMMON2] = true;
- StatusDisplayType[SC_SUMMON3] = true;
- StatusDisplayType[SC_SUMMON4] = true;
- StatusDisplayType[SC_SUMMON5] = true;
- StatusDisplayType[SC_CAMOUFLAGE] = true;
- StatusDisplayType[SC_DUPLELIGHT] = true;
- StatusDisplayType[SC_ORATIO] = true;
- StatusDisplayType[SC_FROSTMISTY] = true;
- StatusDisplayType[SC_VENOMIMPRESS] = true;
- StatusDisplayType[SC_HALLUCINATIONWALK] = true;
- StatusDisplayType[SC_ROLLINGCUTTER] = true;
- StatusDisplayType[SC_BANDING] = true;
- StatusDisplayType[SC_CRYSTALIZE] = true;
- StatusDisplayType[SC_DEEP_SLEEP] = true;
- StatusDisplayType[SC_CURSEDCIRCLE_ATKER]= true;
- StatusDisplayType[SC_CURSEDCIRCLE_TARGET]= true;
- StatusDisplayType[SC_BLOOD_SUCKER] = true;
- StatusDisplayType[SC__SHADOWFORM] = true;
- StatusDisplayType[SC__MANHOLE] = true;
- StatusDisplayType[SC_MONSTER_TRANSFORM] = true;
-
+ status->ChangeFlagTable[SC_PARALYSE] |= SCB_FLEE|SCB_SPEED|SCB_ASPD;
+ status->ChangeFlagTable[SC_VENOMBLEED] |= SCB_MAXHP;
+ status->ChangeFlagTable[SC_MAGICMUSHROOM] |= SCB_REGEN;
+ status->ChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN;
+ status->ChangeFlagTable[SC_PYREXIA] |= SCB_HIT|SCB_FLEE;
+ status->ChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN;
+ // RG status
+ status->ChangeFlagTable[SC_SHIELDSPELL_DEF] |= SCB_WATK;
+ status->ChangeFlagTable[SC_SHIELDSPELL_REF] |= SCB_DEF;
+ // Meca status
+ status->ChangeFlagTable[SC_STEALTHFIELD_MASTER] |= SCB_SPEED;
+
+ status->ChangeFlagTable[SC_SAVAGE_STEAK] |= SCB_STR;
+ status->ChangeFlagTable[SC_COCKTAIL_WARG_BLOOD] |= SCB_INT;
+ status->ChangeFlagTable[SC_MINOR_BBQ] |= SCB_VIT;
+ status->ChangeFlagTable[SC_SIROMA_ICE_TEA] |= SCB_DEX;
+ status->ChangeFlagTable[SC_DROCERA_HERB_STEAMED] |= SCB_AGI;
+ status->ChangeFlagTable[SC_PUTTI_TAILS_NOODLES] |= SCB_LUK;
+ status->ChangeFlagTable[SC_BOOST500] |= SCB_ASPD;
+ status->ChangeFlagTable[SC_FULL_SWING_K] |= SCB_BATK;
+ status->ChangeFlagTable[SC_MANA_PLUS] |= SCB_MATK;
+ status->ChangeFlagTable[SC_MUSTLE_M] |= SCB_MAXHP;
+ status->ChangeFlagTable[SC_LIFE_FORCE_F] |= SCB_MAXSP;
+ status->ChangeFlagTable[SC_EXTRACT_WHITE_POTION_Z] |= SCB_REGEN;
+ status->ChangeFlagTable[SC_VITATA_500] |= SCB_REGEN;
+ status->ChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD;
+ status->ChangeFlagTable[SC_REBOUND] |= SCB_SPEED|SCB_REGEN;
+ status->ChangeFlagTable[SC_DEFSET] |= SCB_DEF|SCB_DEF2;
+ status->ChangeFlagTable[SC_MDEFSET] |= SCB_MDEF|SCB_MDEF2;
+
+ status->ChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED;
+ status->ChangeFlagTable[SC_WEDDING] = SCB_SPEED;
+
+ status->ChangeFlagTable[SC_MTF_ASPD] = SCB_ASPD|SCB_HIT;
+ status->ChangeFlagTable[SC_MTF_MATK] = SCB_MATK;
+ status->ChangeFlagTable[SC_MTF_MLEATKED] |= SCB_ALL;
+
+ status->ChangeFlagTable[SC_MOONSTAR] |= SCB_NONE;
+ status->ChangeFlagTable[SC_SUPER_STAR] |= SCB_NONE;
+ status->ChangeFlagTable[SC_STRANGELIGHTS] |= SCB_NONE;
+ status->ChangeFlagTable[SC_DECORATION_OF_MUSIC] |= SCB_NONE;
+
+ /* status->DisplayType Table [Ind/Hercules] */
+ status->DisplayType[SC_ALL_RIDING] = true;
+ status->DisplayType[SC_PUSH_CART] = true;
+ status->DisplayType[SC_SUMMON1] = true;
+ status->DisplayType[SC_SUMMON2] = true;
+ status->DisplayType[SC_SUMMON3] = true;
+ status->DisplayType[SC_SUMMON4] = true;
+ status->DisplayType[SC_SUMMON5] = true;
+ status->DisplayType[SC_CAMOUFLAGE] = true;
+ status->DisplayType[SC_DUPLELIGHT] = true;
+ status->DisplayType[SC_ORATIO] = true;
+ status->DisplayType[SC_FROSTMISTY] = true;
+ status->DisplayType[SC_VENOMIMPRESS] = true;
+ status->DisplayType[SC_HALLUCINATIONWALK] = true;
+ status->DisplayType[SC_ROLLINGCUTTER] = true;
+ status->DisplayType[SC_BANDING] = true;
+ status->DisplayType[SC_COLD] = true;
+ status->DisplayType[SC_DEEP_SLEEP] = true;
+ status->DisplayType[SC_CURSEDCIRCLE_ATKER]= true;
+ status->DisplayType[SC_CURSEDCIRCLE_TARGET]= true;
+ status->DisplayType[SC_BLOOD_SUCKER] = true;
+ status->DisplayType[SC__SHADOWFORM] = true;
+ status->DisplayType[SC_MONSTER_TRANSFORM] = true;
+ status->DisplayType[SC_MOONSTAR] = true;
+ status->DisplayType[SC_SUPER_STAR] = true;
+ status->DisplayType[SC_STRANGELIGHTS] = true;
+ status->DisplayType[SC_DECORATION_OF_MUSIC] = true;
+
#ifdef RENEWAL_EDP
// renewal EDP increases your weapon atk
- StatusChangeFlagTable[SC_EDP] |= SCB_WATK;
+ status->ChangeFlagTable[SC_EDP] |= SCB_WATK;
#endif
if( !battle_config.display_hallucination ) //Disable Hallucination.
- StatusIconChangeTable[SC_ILLUSION] = SI_BLANK;
+ status->IconChangeTable[SC_ILLUSION] = SI_BLANK;
+#undef add_sc
+#undef set_sc_with_vfx
}
-static void initDummyData(void)
+void initDummyData(void)
{
- memset(&dummy_status, 0, sizeof(dummy_status));
- dummy_status.hp =
- dummy_status.max_hp =
- dummy_status.max_sp =
- dummy_status.str =
- dummy_status.agi =
- dummy_status.vit =
- dummy_status.int_ =
- dummy_status.dex =
- dummy_status.luk =
- dummy_status.hit = 1;
- dummy_status.speed = 2000;
- dummy_status.adelay = 4000;
- dummy_status.amotion = 2000;
- dummy_status.dmotion = 2000;
- dummy_status.ele_lv = 1; //Min elemental level.
- dummy_status.mode = MD_CANMOVE;
+ memset(&status->dummy, 0, sizeof(status->dummy));
+ status->dummy.hp =
+ status->dummy.max_hp =
+ status->dummy.max_sp =
+ status->dummy.str =
+ status->dummy.agi =
+ status->dummy.vit =
+ status->dummy.int_ =
+ status->dummy.dex =
+ status->dummy.luk =
+ status->dummy.hit = 1;
+ status->dummy.speed = 2000;
+ status->dummy.adelay = 4000;
+ status->dummy.amotion = 2000;
+ status->dummy.dmotion = 2000;
+ status->dummy.ele_lv = 1; //Min elemental level.
+ status->dummy.mode = MD_CANMOVE;
}
@@ -1062,107 +1084,123 @@ static inline void status_cpy(struct status_data* a, const struct status_data* b
memcpy((void*)&a->max_hp, (const void*)&b->max_hp, sizeof(struct status_data)-(sizeof(a->hp)+sizeof(a->sp)));
}
-//Sets HP to given value. Flag is the flag passed to status_heal in case
+//Sets HP to given value. Flag is the flag passed to status->heal in case
//final value is higher than current (use 2 to make a healing effect display
//on players) It will always succeed (overrides Berserk block), but it can't kill.
-int status_set_hp(struct block_list *bl, unsigned int hp, int flag)
-{
- struct status_data *status;
+int status_set_hp(struct block_list *bl, unsigned int hp, int flag) {
+ struct status_data *st;
if (hp < 1) return 0;
- status = status_get_status_data(bl);
- if (status == &dummy_status)
+ st = status->get_status_data(bl);
+ if (st == &status->dummy)
return 0;
- if (hp > status->max_hp) hp = status->max_hp;
- if (hp == status->hp) return 0;
- if (hp > status->hp)
- return status_heal(bl, hp - status->hp, 0, 1|flag);
- return status_zap(bl, status->hp - hp, 0);
+ if (hp > st->max_hp) hp = st->max_hp;
+ if (hp == st->hp) return 0;
+ if (hp > st->hp)
+ return status->heal(bl, hp - st->hp, 0, 1|flag);
+ return status_zap(bl, st->hp - hp, 0);
}
-//Sets SP to given value. Flag is the flag passed to status_heal in case
+//Sets SP to given value. Flag is the flag passed to status->heal in case
//final value is higher than current (use 2 to make a healing effect display
//on players)
-int status_set_sp(struct block_list *bl, unsigned int sp, int flag)
-{
- struct status_data *status;
+int status_set_sp(struct block_list *bl, unsigned int sp, int flag) {
+ struct status_data *st;
- status = status_get_status_data(bl);
- if (status == &dummy_status)
+ st = status->get_status_data(bl);
+ if (st == &status->dummy)
return 0;
- if (sp > status->max_sp) sp = status->max_sp;
- if (sp == status->sp) return 0;
- if (sp > status->sp)
- return status_heal(bl, 0, sp - status->sp, 1|flag);
- return status_zap(bl, 0, status->sp - sp);
+ if (sp > st->max_sp) sp = st->max_sp;
+ if (sp == st->sp) return 0;
+ if (sp > st->sp)
+ return status->heal(bl, 0, sp - st->sp, 1|flag);
+ return status_zap(bl, 0, st->sp - sp);
}
-int status_charge(struct block_list* bl, int hp, int sp)
-{
+int status_charge(struct block_list* bl, int64 hp, int64 sp) {
if(!(bl->type&BL_CONSUME))
- return hp+sp; //Assume all was charged so there are no 'not enough' fails.
- return status_damage(NULL, bl, hp, sp, 0, 3);
+ return (int)(hp+sp); //Assume all was charged so there are no 'not enough' fails.
+ return status->damage(NULL, bl, hp, sp, 0, 3);
}
//Inflicts damage on the target with the according walkdelay.
-//If flag&1, damage is passive and does not triggers cancelling status changes.
-//If flag&2, fail if target does not has enough to substract.
+//If flag&1, damage is passive and does not triggers canceling status changes.
+//If flag&2, fail if target does not has enough to subtract.
//If flag&4, if killed, mob must not give exp/loot.
//flag will be set to &8 when damaging sp of a dead character
-int status_damage(struct block_list *src,struct block_list *target,int hp, int sp, int walkdelay, int flag)
-{
- struct status_data *status;
+int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, int64 in_sp, int walkdelay, int flag) {
+ struct status_data *st;
struct status_change *sc;
+ int hp,sp;
+ /* here onwards we consider it a 32-type, the client does not support higher and from here onwards the value doesn't get thru percentage modifiers */
+ hp = (int)cap_value(in_hp,INT_MIN,INT_MAX);
+ sp = (int)cap_value(in_sp,INT_MIN,INT_MAX);
+
if(sp && !(target->type&BL_CONSUME))
sp = 0; //Not a valid SP target.
if (hp < 0) { //Assume absorbed damage.
- status_heal(target, -hp, 0, 1);
+ status->heal(target, -hp, 0, 1);
hp = 0;
}
if (sp < 0) {
- status_heal(target, 0, -sp, 1);
+ status->heal(target, 0, -sp, 1);
sp = 0;
}
if (target->type == BL_SKILL)
- return skill->unit_ondamaged((struct skill_unit *)target, src, hp, iTimer->gettick());
+ return skill->unit_ondamaged((struct skill_unit *)target, src, hp, timer->gettick());
- status = status_get_status_data(target);
- if( status == &dummy_status )
+ st = status->get_status_data(target);
+ if( st == &status->dummy )
return 0;
- if ((unsigned int)hp >= status->hp) {
+ if ((unsigned int)hp >= st->hp) {
if (flag&2) return 0;
- hp = status->hp;
+ hp = st->hp;
}
- if ((unsigned int)sp > status->sp) {
+ if ((unsigned int)sp > st->sp) {
if (flag&2) return 0;
- sp = status->sp;
+ sp = st->sp;
}
if (!hp && !sp)
return 0;
- if( !status->hp )
+ if( !st->hp )
flag |= 8;
-// Let through. battle.c/skill.c have the whole logic of when it's possible or
-// not to hurt someone (and this check breaks pet catching) [Skotlex]
-// if (!target->prev && !(flag&2))
-// return 0; //Cannot damage a bl not on a map, except when "charging" hp/sp
+ // Let through. battle.c/skill.c have the whole logic of when it's possible or
+ // not to hurt someone (and this check breaks pet catching) [Skotlex]
+ // if (!target->prev && !(flag&2))
+ // return 0; //Cannot damage a bl not on a map, except when "charging" hp/sp
- sc = status_get_sc(target);
+ sc = status->get_sc(target);
if( hp && battle_config.invincible_nodamage && src && sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
hp = 1;
if( hp && !(flag&1) ) {
if( sc ) {
struct status_change_entry *sce;
+
+#ifdef DEVOTION_REFLECT_DAMAGE
+ if(src && (sce = sc->data[SC_DEVOTION])) {
+ struct block_list *d_bl = map->id2bl(sce->val1);
+
+ if(d_bl &&((d_bl->type == BL_MER && ((TBL_MER *)d_bl)->master && ((TBL_MER *)d_bl)->master->bl.id == target->id)
+ || (d_bl->type == BL_PC && ((TBL_PC *)d_bl)->devotion[sce->val2] == target->id)) && check_distance_bl(target, d_bl, sce->val3)) {
+ clif->damage(d_bl, d_bl, 0, 0, hp, 0, 0, 0);
+ status_fix_damage(NULL, d_bl, hp, 0);
+ return 0;
+ }
+ status_change_end(target, SC_DEVOTION, INVALID_TIMER);
+ }
+#endif
+
if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
status_change_end(target, SC_STONE, INVALID_TIMER);
status_change_end(target, SC_FREEZE, INVALID_TIMER);
@@ -1174,12 +1212,10 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
status_change_end(target, SC_CLOAKING, INVALID_TIMER);
status_change_end(target, SC_CHASEWALK, INVALID_TIMER);
status_change_end(target, SC_CAMOUFLAGE, INVALID_TIMER);
- status_change_end(target, SC__INVISIBILITY, INVALID_TIMER);
- status_change_end(target, SC_DEEP_SLEEP, INVALID_TIMER);
if ((sce=sc->data[SC_ENDURE]) && !sce->val4 && !sc->data[SC_LKCONCENTRATION]) {
//Endure count is only reduced by non-players on non-gvg maps.
//val4 signals infinite endure. [Skotlex]
- if (src && src->type != BL_PC && !map_flag_gvg(target->m) && !map[target->m].flag.battleground && --(sce->val2) < 0)
+ if (src && src->type != BL_PC && !map_flag_gvg2(target->m) && !map->list[target->m].flag.battleground && --(sce->val2) < 0)
status_change_end(target, SC_ENDURE, INVALID_TIMER);
}
if ((sce=sc->data[SC_GRAVITATION]) && sce->val3 == BCT_SELF) {
@@ -1190,82 +1226,80 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
status_change_end(target, SC_GRAVITATION, INVALID_TIMER);
}
}
- if(sc->data[SC_DANCING] && (unsigned int)hp > status->max_hp>>2)
+ if(sc->data[SC_DANCING] && (unsigned int)hp > st->max_hp>>2)
status_change_end(target, SC_DANCING, INVALID_TIMER);
if(sc->data[SC_CLOAKINGEXCEED] && --(sc->data[SC_CLOAKINGEXCEED]->val2) <= 0)
status_change_end(target, SC_CLOAKINGEXCEED, INVALID_TIMER);
if(sc->data[SC_KAGEMUSYA] && --(sc->data[SC_KAGEMUSYA]->val3) <= 0)
status_change_end(target, SC_KAGEMUSYA, INVALID_TIMER);
}
- unit_skillcastcancel(target, 2);
+ unit->skillcastcancel(target, 2);
}
- status->hp-= hp;
- status->sp-= sp;
+ st->hp-= hp;
+ st->sp-= sp;
- if (sc && hp && status->hp) {
+ if (sc && hp && st->hp) {
if (sc->data[SC_AUTOBERSERK] &&
(!sc->data[SC_PROVOKE] || !sc->data[SC_PROVOKE]->val2) &&
- status->hp < status->max_hp>>2)
- sc_start4(target,SC_PROVOKE,100,10,1,0,0,0);
- if (sc->data[SC_BERSERK] && status->hp <= 100)
+ st->hp < st->max_hp>>2)
+ sc_start4(src,target,SC_PROVOKE,100,10,1,0,0,0);
+ if (sc->data[SC_BERSERK] && st->hp <= 100)
status_change_end(target, SC_BERSERK, INVALID_TIMER);
- if( sc->data[SC_RAISINGDRAGON] && status->hp <= 1000 )
+ if( sc->data[SC_RAISINGDRAGON] && st->hp <= 1000 )
status_change_end(target, SC_RAISINGDRAGON, INVALID_TIMER);
- if (sc->data[SC_SATURDAY_NIGHT_FEVER] && status->hp <= 100)
+ if (sc->data[SC_SATURDAY_NIGHT_FEVER] && st->hp <= 100)
status_change_end(target, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER);
- if (sc->data[SC__BLOODYLUST] && status->hp <= 100)
- status_change_end(target, SC__BLOODYLUST, INVALID_TIMER);
}
switch (target->type) {
- case BL_PC: pc->damage((TBL_PC*)target,src,hp,sp); break;
- case BL_MOB: mob_damage((TBL_MOB*)target, src, hp); break;
- case BL_HOM: homun->damaged((TBL_HOM*)target); break;
- case BL_MER: mercenary_heal((TBL_MER*)target,hp,sp); break;
- case BL_ELEM: elemental_heal((TBL_ELEM*)target,hp,sp); break;
+ case BL_PC: pc->damage((TBL_PC*)target,src,hp,sp); break;
+ case BL_MOB: mob->damage((TBL_MOB*)target, src, hp); break;
+ case BL_HOM: homun->damaged((TBL_HOM*)target); break;
+ case BL_MER: mercenary->heal((TBL_MER*)target,hp,sp); break;
+ case BL_ELEM: elemental->heal((TBL_ELEM*)target,hp,sp); break;
}
- if( src && target->type == BL_PC && ((TBL_PC*)target)->disguise ) {// stop walking when attacked in disguise to prevent walk-delay bug
- unit_stop_walking( target, 1 );
+ if( src && target->type == BL_PC && (((TBL_PC*)target)->disguise) > 0 ) {// stop walking when attacked in disguise to prevent walk-delay bug
+ unit->stop_walking( target, 1 );
}
- if( status->hp || (flag&8) )
- { //Still lives or has been dead before this damage.
+ if( st->hp || (flag&8) )
+ { //Still lives or has been dead before this damage.
if (walkdelay)
- unit_set_walkdelay(target, iTimer->gettick(), walkdelay, 0);
- return hp+sp;
+ unit->set_walkdelay(target, timer->gettick(), walkdelay, 0);
+ return (int)(hp+sp);
}
- status->hp = 1; //To let the dead function cast skills and all that.
+ st->hp = 1; //To let the dead function cast skills and all that.
//NOTE: These dead functions should return: [Skotlex]
- //0: Death cancelled, auto-revived.
+ //0: Death canceled, auto-revived.
//Non-zero: Standard death. Clear status, cancel move/attack, etc
//&2: Also remove object from map.
//&4: Also delete object from memory.
switch (target->type) {
- case BL_PC: flag = pc->dead((TBL_PC*)target,src); break;
- case BL_MOB: flag = mob_dead((TBL_MOB*)target, src, flag&4?3:0); break;
- case BL_HOM: flag = homun->dead((TBL_HOM*)target); break;
- case BL_MER: flag = mercenary_dead((TBL_MER*)target); break;
- case BL_ELEM: flag = elemental_dead((TBL_ELEM*)target); break;
- default: //Unhandled case, do nothing to object.
- flag = 0;
- break;
+ case BL_PC: flag = pc->dead((TBL_PC*)target,src); break;
+ case BL_MOB: flag = mob->dead((TBL_MOB*)target, src, flag&4?3:0); break;
+ case BL_HOM: flag = homun->dead((TBL_HOM*)target); break;
+ case BL_MER: flag = mercenary->dead((TBL_MER*)target); break;
+ case BL_ELEM: flag = elemental->dead((TBL_ELEM*)target); break;
+ default: //Unhandled case, do nothing to object.
+ flag = 0;
+ break;
}
- if(!flag) //Death cancelled.
- return hp+sp;
+ if(!flag) //Death canceled.
+ return (int)(hp+sp);
//Normal death
- status->hp = 0;
+ st->hp = 0;
if (battle_config.clear_unit_ondeath &&
battle_config.clear_unit_ondeath&target->type)
skill->clear_unitgroup(target);
- if(target->type&BL_REGEN)
- { //Reset regen ticks.
- struct regen_data *regen = status_get_regen_data(target);
+ if(target->type&BL_REGEN) {
+ //Reset regen ticks.
+ struct regen_data *regen = status->get_regen_data(target);
if (regen) {
memset(&regen->tick, 0, sizeof(regen->tick));
if (regen->sregen)
@@ -1275,129 +1309,123 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
}
}
- if( sc && sc->data[SC_KAIZEL] && !map_flag_gvg(target->m) )
- { //flag&8 = disable Kaizel
+ if( sc && sc->data[SC_KAIZEL] && !map_flag_gvg2(target->m) ) {
+ //flag&8 = disable Kaizel
int time = skill->get_time2(SL_KAIZEL,sc->data[SC_KAIZEL]->val1);
//Look for Osiris Card's bonus effect on the character and revive 100% or revive normally
if ( target->type == BL_PC && BL_CAST(BL_PC,target)->special_state.restart_full_recover )
- status_revive(target, 100, 100);
+ status->revive(target, 100, 100);
else
- status_revive(target, sc->data[SC_KAIZEL]->val2, 0);
- status_change_clear(target,0);
+ status->revive(target, sc->data[SC_KAIZEL]->val2, 0);
+ status->change_clear(target,0);
clif->skill_nodamage(target,target,ALL_RESURRECTION,1,1);
- sc_start(target,status_skill2sc(PR_KYRIE),100,10,time);
+ sc_start(target,target,status->skill2sc(PR_KYRIE),100,10,time);
if( target->type == BL_MOB )
((TBL_MOB*)target)->state.rebirth = 1;
- return hp+sp;
- }
- if(target->type == BL_PC){
- TBL_PC *sd = BL_CAST(BL_PC,target);
- TBL_HOM *hd = sd->hd;
- if(hd && hd->sc.data[SC_LIGHT_OF_REGENE]){
- clif->skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill->get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage
- clif->skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, status_revive(&sd->bl,10*hd->sc.data[SC_LIGHT_OF_REGENE]->val1,0));
- status_change_end(&sd->hd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER);
- return hp + sp;
- }
- }
- if (target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*) target)->state.rebirth) {// Ensure the monster has not already rebirthed before doing so.
- status_revive(target, sc->data[SC_REBIRTH]->val2, 0);
- status_change_clear(target,0);
+ return (int)(hp+sp);
+ }
+
+ if (target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*) target)->state.rebirth) {
+ // Ensure the monster has not already rebirthed before doing so.
+ status->revive(target, sc->data[SC_REBIRTH]->val2, 0);
+ status->change_clear(target,0);
((TBL_MOB*)target)->state.rebirth = 1;
- return hp+sp;
+ return (int)(hp+sp);
}
- status_change_clear(target,0);
+ status->change_clear(target,0);
if(flag&4) //Delete from memory. (also invokes map removal code)
- unit_free(target,CLR_DEAD);
- else
- if(flag&2) //remove from map
- unit_remove_map(target,CLR_DEAD);
- else
- { //Some death states that would normally be handled by unit_remove_map
- unit_stop_attack(target);
- unit_stop_walking(target,1);
- unit_skillcastcancel(target,0);
+ unit->free(target,CLR_DEAD);
+ else if(flag&2) //remove from map
+ unit->remove_map(target,CLR_DEAD,ALC_MARK);
+ else { //Some death states that would normally be handled by unit_remove_map
+ unit->stop_attack(target);
+ unit->stop_walking(target,1);
+ unit->skillcastcancel(target,0);
clif->clearunit_area(target,CLR_DEAD);
- skill->unit_move(target,iTimer->gettick(),4);
+ skill->unit_move(target,timer->gettick(),4);
skill->cleartimerskill(target);
}
- return hp+sp;
+ return (int)(hp+sp);
}
//Heals a character. If flag&1, this is forced healing (otherwise stuff like Berserk can block it)
//If flag&2, when the player is healed, show the HP/SP heal effect.
-int status_heal(struct block_list *bl,int hp,int sp, int flag)
-{
- struct status_data *status;
+int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) {
+ struct status_data *st;
struct status_change *sc;
+ int hp,sp;
- status = status_get_status_data(bl);
+ st = status->get_status_data(bl);
- if (status == &dummy_status || !status->hp)
+ if (st == &status->dummy || !st->hp)
return 0;
- sc = status_get_sc(bl);
+ /* here onwards we consider it a 32-type, the client does not support higher and from here onwards the value doesn't get thru percentage modifiers */
+ hp = (int)cap_value(in_hp,INT_MIN,INT_MAX);
+ sp = (int)cap_value(in_sp,INT_MIN,INT_MAX);
+
+ sc = status->get_sc(bl);
if (sc && !sc->count)
sc = NULL;
if (hp < 0) {
if (hp == INT_MIN) hp++; //-INT_MIN == INT_MIN in some architectures!
- status_damage(NULL, bl, -hp, 0, 0, 1);
+ status->damage(NULL, bl, -hp, 0, 0, 1);
hp = 0;
}
if(hp) {
- if( sc && (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) ) {
+ if( sc && sc->data[SC_BERSERK] ) {
if( flag&1 )
flag &= ~2;
else
hp = 0;
}
- if((unsigned int)hp > status->max_hp - status->hp)
- hp = status->max_hp - status->hp;
+ if((unsigned int)hp > st->max_hp - st->hp)
+ hp = st->max_hp - st->hp;
}
if(sp < 0) {
if (sp==INT_MIN) sp++;
- status_damage(NULL, bl, 0, -sp, 0, 1);
+ status->damage(NULL, bl, 0, -sp, 0, 1);
sp = 0;
}
if(sp) {
- if((unsigned int)sp > status->max_sp - status->sp)
- sp = status->max_sp - status->sp;
+ if((unsigned int)sp > st->max_sp - st->sp)
+ sp = st->max_sp - st->sp;
}
if(!sp && !hp) return 0;
- status->hp+= hp;
- status->sp+= sp;
+ st->hp+= hp;
+ st->sp+= sp;
- if(hp && sc &&
- sc->data[SC_AUTOBERSERK] &&
- sc->data[SC_PROVOKE] &&
- sc->data[SC_PROVOKE]->val2==1 &&
- status->hp>=status->max_hp>>2
- ) //End auto berserk.
+ if( hp && sc
+ && sc->data[SC_AUTOBERSERK]
+ && sc->data[SC_PROVOKE]
+ && sc->data[SC_PROVOKE]->val2==1
+ && st->hp>=st->max_hp>>2
+ ) //End auto berserk.
status_change_end(bl, SC_PROVOKE, INVALID_TIMER);
// send hp update to client
switch(bl->type) {
case BL_PC: pc->heal((TBL_PC*)bl,hp,sp,flag&2?1:0); break;
- case BL_MOB: mob_heal((TBL_MOB*)bl,hp); break;
+ case BL_MOB: mob->heal((TBL_MOB*)bl,hp); break;
case BL_HOM: homun->healed((TBL_HOM*)bl); break;
- case BL_MER: mercenary_heal((TBL_MER*)bl,hp,sp); break;
- case BL_ELEM: elemental_heal((TBL_ELEM*)bl,hp,sp); break;
+ case BL_MER: mercenary->heal((TBL_MER*)bl,hp,sp); break;
+ case BL_ELEM: elemental->heal((TBL_ELEM*)bl,hp,sp); break;
}
- return hp+sp;
+ return (int)(hp+sp);
}
//Does percentual non-flinching damage/heal. If mob is killed this way,
@@ -1405,146 +1433,174 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag)
//If rates are > 0, percent is of current HP/SP
//If rates are < 0, percent is of max HP/SP
//If !flag, this is heal, otherwise it is damage.
-//Furthermore, if flag==2, then the target must not die from the substraction.
-int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag)
-{
- struct status_data *status;
- unsigned int hp =0, sp = 0;
-
- status = status_get_status_data(target);
-
-
- //It's safe now [MarkZD]
- if (hp_rate > 99)
- hp = status->hp;
- else if (hp_rate > 0)
- hp = status->hp>10000?
- hp_rate*(status->hp/100):
- ((int64)hp_rate*status->hp)/100;
- else if (hp_rate < -99)
- hp = status->max_hp;
- else if (hp_rate < 0)
- hp = status->max_hp>10000?
- (-hp_rate)*(status->max_hp/100):
- ((int64)-hp_rate*status->max_hp)/100;
+//Furthermore, if flag==2, then the target must not die from the subtraction.
+int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag) {
+ struct status_data *st;
+ unsigned int hp = 0, sp = 0;
+
+ st = status->get_status_data(target);
+
+ if (hp_rate > 100)
+ hp_rate = 100;
+ else if (hp_rate < -100)
+ hp_rate = -100;
+ if (hp_rate > 0)
+ hp = APPLY_RATE(st->hp, hp_rate);
+ else
+ hp = APPLY_RATE(st->max_hp, -hp_rate);
if (hp_rate && !hp)
hp = 1;
- if (flag == 2 && hp >= status->hp)
- hp = status->hp-1; //Must not kill target.
-
- if (sp_rate > 99)
- sp = status->sp;
- else if (sp_rate > 0)
- sp = ((int64)sp_rate*status->sp)/100;
- else if (sp_rate < -99)
- sp = status->max_sp;
- else if (sp_rate < 0)
- sp = ((int64)-sp_rate)*status->max_sp/100;
+ if (flag == 2 && hp >= st->hp)
+ hp = st->hp-1; //Must not kill target.
+
+ if (sp_rate > 100)
+ sp_rate = 100;
+ else if (sp_rate < -100)
+ sp_rate = -100;
+ if (sp_rate > 0)
+ sp = APPLY_RATE(st->sp, sp_rate);
+ else
+ sp = APPLY_RATE(st->max_sp, -sp_rate);
if (sp_rate && !sp)
sp = 1;
//Ugly check in case damage dealt is too much for the received args of
- //status_heal / status_damage. [Skotlex]
+ //status->heal / status->damage. [Skotlex]
if (hp > INT_MAX) {
- hp -= INT_MAX;
+ hp -= INT_MAX;
if (flag)
- status_damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1));
+ status->damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1));
else
- status_heal(target, INT_MAX, 0, 0);
+ status->heal(target, INT_MAX, 0, 0);
}
- if (sp > INT_MAX) {
+ if (sp > INT_MAX) {
sp -= INT_MAX;
if (flag)
- status_damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1));
+ status->damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1));
else
- status_heal(target, 0, INT_MAX, 0);
+ status->heal(target, 0, INT_MAX, 0);
}
if (flag)
- return status_damage(src, target, hp, sp, 0, (!src||src==target?5:1));
- return status_heal(target, hp, sp, 0);
+ return status->damage(src, target, hp, sp, 0, (!src||src==target?5:1));
+ return status->heal(target, hp, sp, 0);
}
-int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp)
-{
- struct status_data *status;
+int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp) {
+ struct status_data *st;
unsigned int hp, sp;
- if (!status_isdead(bl)) return 0;
+ if (!status->isdead(bl)) return 0;
- status = status_get_status_data(bl);
- if (status == &dummy_status)
+ st = status->get_status_data(bl);
+ if (st == &status->dummy)
return 0; //Invalid target.
- hp = (int64)status->max_hp * per_hp/100;
- sp = (int64)status->max_sp * per_sp/100;
+ hp = APPLY_RATE(st->max_hp, per_hp);
+ sp = APPLY_RATE(st->max_sp, per_sp);
- if(hp > status->max_hp - status->hp)
- hp = status->max_hp - status->hp;
+ if(hp > st->max_hp - st->hp)
+ hp = st->max_hp - st->hp;
else if (per_hp && !hp)
hp = 1;
- if(sp > status->max_sp - status->sp)
- sp = status->max_sp - status->sp;
+ if(sp > st->max_sp - st->sp)
+ sp = st->max_sp - st->sp;
else if (per_sp && !sp)
sp = 1;
- status->hp += hp;
- status->sp += sp;
+ st->hp += hp;
+ st->sp += sp;
if (bl->prev) //Animation only if character is already on a map.
clif->resurrection(bl, 1);
+
switch (bl->type) {
case BL_PC: pc->revive((TBL_PC*)bl, hp, sp); break;
- case BL_MOB: mob_revive((TBL_MOB*)bl, hp); break;
+ case BL_MOB: mob->revive((TBL_MOB*)bl, hp); break;
+ case BL_HOM: homun->revive((TBL_HOM*)bl, hp, sp); break;
+ }
+
+ return 1;
+}
+
+int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int per_sp) {
+ struct status_data *st;
+ unsigned int hp, sp;
+ if (!status->isdead(bl)) return 0;
+
+ st = status->get_status_data(bl);
+ if (st == &status->dummy)
+ return 0; //Invalid target.
+
+ hp = per_hp;
+ sp = per_sp;
+
+ if(hp > st->max_hp - st->hp)
+ hp = st->max_hp - st->hp;
+ else if (per_hp && !hp)
+ hp = 1;
+
+ if(sp > st->max_sp - st->sp)
+ sp = st->max_sp - st->sp;
+ else if (per_sp && !sp)
+ sp = 1;
+
+ st->hp += hp;
+ st->sp += sp;
+
+ if (bl->prev) //Animation only if character is already on a map.
+ clif->resurrection(bl, 1);
+ switch (bl->type) {
+ case BL_PC: pc->revive((TBL_PC*)bl, hp, sp); break;
+ case BL_MOB: mob->revive((TBL_MOB*)bl, hp); break;
case BL_HOM: homun->revive((TBL_HOM*)bl, hp, sp); break;
}
return 1;
}
/*==========================================
- * Checks whether the src can use the skill on the target,
- * taking into account status/option of both source/target. [Skotlex]
- * flag:
- * 0 - Trying to use skill on target.
- * 1 - Cast bar is done.
- * 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones.
- * src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack.
- * target MAY Be null, in which case the checks are only to see
- * whether the source can cast or not the skill on the ground.
- *------------------------------------------*/
-int status_check_skilluse(struct block_list *src, struct block_list *target, uint16 skill_id, int flag)
-{
- struct status_data *status;
+* Checks whether the src can use the skill on the target,
+* taking into account status/option of both source/target. [Skotlex]
+* flag:
+* 0 - Trying to use skill on target.
+* 1 - Cast bar is done.
+* 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones.
+* src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack.
+* target MAY Be null, in which case the checks are only to see
+* whether the source can cast or not the skill on the ground.
+*------------------------------------------*/
+int status_check_skilluse(struct block_list *src, struct block_list *target, uint16 skill_id, int flag) {
+ struct status_data *st;
struct status_change *sc=NULL, *tsc;
int hide_flag;
- status = src?status_get_status_data(src):&dummy_status;
+ st = src ? status->get_status_data(src) : &status->dummy;
- if (src && src->type != BL_PC && status_isdead(src))
+ if (src && src->type != BL_PC && status->isdead(src))
return 0;
if (!skill_id) { //Normal attack checks.
- if (!(status->mode&MD_CANATTACK))
+ if (!(st->mode&MD_CANATTACK))
return 0; //This mode is only needed for melee attacking.
//Dead state is not checked for skills as some skills can be used
//on dead characters, said checks are left to skill.c [Skotlex]
- if (target && status_isdead(target))
+ if (target && status->isdead(target))
return 0;
- if( src && (sc = status_get_sc(src)) && sc->data[SC_CRYSTALIZE] && src->type != BL_MOB)
+ if( src && (sc = status->get_sc(src)) && sc->data[SC_COLD] && src->type != BL_MOB)
return 0;
}
if( skill_id ) {
-
+
if( src && !(src->type == BL_PC && ((TBL_PC*)src)->skillitem)) { // Items that cast skills using 'itemskill' will not be handled by map_zone_db.
int i;
-
- for(i = 0; i < map[src->m].zone->disabled_skills_count; i++) {
- if( skill_id == map[src->m].zone->disabled_skills[i]->nameid && (map[src->m].zone->disabled_skills[i]->type&src->type) ) {
+
+ for(i = 0; i < map->list[src->m].zone->disabled_skills_count; i++) {
+ if( skill_id == map->list[src->m].zone->disabled_skills[i]->nameid && (map->list[src->m].zone->disabled_skills[i]->type&src->type) ) {
if( src->type == BL_PC )
clif->msg((TBL_PC*)src, SKILL_CANT_USE_AREA); // This skill cannot be used within this area
- else if( src->type == BL_MOB && map[src->m].zone->disabled_skills[i]->subtype != MZS_NONE ) {
- if( (status->mode&MD_BOSS) && !(map[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS) )
+ else if( src->type == BL_MOB && map->list[src->m].zone->disabled_skills[i]->subtype != MZS_NONE ) {
+ if( (st->mode&MD_BOSS) && !(map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS) )
break;
}
return 0;
@@ -1556,19 +1612,19 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
case PA_PRESSURE:
if( flag && target ) {
//Gloria Avoids pretty much everything....
- tsc = status_get_sc(target);
+ tsc = status->get_sc(target);
if(tsc && tsc->option&OPTION_HIDE)
return 0;
}
break;
case GN_WALLOFTHORN:
- if( target && status_isdead(target) )
+ if( target && status->isdead(target) )
return 0;
break;
case AL_TELEPORT:
//Should fail when used on top of Land Protector [Skotlex]
- if (src && iMap->getcell(src->m, src->x, src->y, CELL_CHKLANDPROTECTOR)
- && !(status->mode&MD_BOSS)
+ if (src && map->getcell(src->m, src->x, src->y, CELL_CHKLANDPROTECTOR)
+ && !(st->mode&MD_BOSS)
&& (src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_id))
return 0;
break;
@@ -1577,28 +1633,28 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
}
}
- if ( src ) sc = status_get_sc(src);
+ if ( src ) sc = status->get_sc(src);
if( sc && sc->count ) {
- if (skill_id != RK_REFRESH && sc->opt1 >0 && !(sc->opt1 == OPT1_CRYSTALIZE && src->type == BL_MOB) && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { //Stuned/Frozen/etc
+ if (skill_id != RK_REFRESH && sc->opt1 >0 && !(sc->opt1 == OPT1_CRYSTALIZE && src->type == BL_MOB) && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { //Stunned/Frozen/etc
if (flag != 1) //Can't cast, casted stuff can't damage.
return 0;
if (!(skill->get_inf(skill_id)&INF_GROUND_SKILL))
- return 0; //Targetted spells can't come off.
+ return 0; //Targeted spells can't come off.
}
if (
(sc->data[SC_TRICKDEAD] && skill_id != NV_TRICKDEAD)
- || (sc->data[SC_AUTOCOUNTER] && !flag)
+ || (sc->data[SC_AUTOCOUNTER] && !flag && skill_id)
|| (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF && skill_id != PA_GOSPEL)
|| (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF && flag != 2)
- )
+ )
return 0;
if (sc->data[SC_DC_WINKCHARM] && target && !flag) { //Prevents skill usage
- if( unit_bl2ud(src) && (unit_bl2ud(src))->walktimer == INVALID_TIMER )
- unit_walktobl(src, iMap->id2bl(sc->data[SC_DC_WINKCHARM]->val2), 3, 1);
+ if( unit->bl2ud(src) && (unit->bl2ud(src))->walktimer == INVALID_TIMER )
+ unit->walktobl(src, map->id2bl(sc->data[SC_DC_WINKCHARM]->val2), 3, 1);
clif->emotion(src, E_LV);
return 0;
}
@@ -1606,11 +1662,11 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
if (sc->data[SC_BLADESTOP]) {
switch (sc->data[SC_BLADESTOP]->val1)
{
- case 5: if (skill_id == MO_EXTREMITYFIST) break;
- case 4: if (skill_id == MO_CHAINCOMBO) break;
- case 3: if (skill_id == MO_INVESTIGATE) break;
- case 2: if (skill_id == MO_FINGEROFFENSIVE) break;
- default: return 0;
+ case 5: if (skill_id == MO_EXTREMITYFIST) break;
+ case 4: if (skill_id == MO_CHAINCOMBO) break;
+ case 3: if (skill_id == MO_INVESTIGATE) break;
+ case 2: if (skill_id == MO_FINGEROFFENSIVE) break;
+ default: return 0;
}
}
@@ -1622,17 +1678,17 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
} else if(sc->data[SC_LONGING]) { //Allow everything except dancing/re-dancing. [Skotlex]
if (skill_id == BD_ENCORE ||
skill->get_inf2(skill_id)&(INF2_SONG_DANCE|INF2_ENSEMBLE_SKILL)
- )
+ )
return 0;
} else {
switch (skill_id) {
- case BD_ADAPTATION:
- case CG_LONGINGFREEDOM:
- case BA_MUSICALSTRIKE:
- case DC_THROWARROW:
- break;
- default:
- return 0;
+ case BD_ADAPTATION:
+ case CG_LONGINGFREEDOM:
+ case BA_MUSICALSTRIKE:
+ case DC_THROWARROW:
+ break;
+ default:
+ return 0;
}
}
if ((sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE && skill_id == BD_ADAPTATION)
@@ -1641,46 +1697,44 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
if (skill_id && //Do not block item-casted skills.
(src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_id)
- ) { //Skills blocked through status changes...
- if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through
- sc->data[SC_SILENCE] ||
- sc->data[SC_STEELBODY] ||
- sc->data[SC_BERSERK] ||
- sc->data[SC__BLOODYLUST] ||
- sc->data[SC_OBLIVIONCURSE] ||
- sc->data[SC_WHITEIMPRISON] ||
- sc->data[SC__INVISIBILITY] ||
- (sc->data[SC_CRYSTALIZE] && src->type != BL_MOB) ||
- sc->data[SC__IGNORANCE] ||
- sc->data[SC_DEEP_SLEEP] ||
- sc->data[SC_SATURDAY_NIGHT_FEVER] ||
- sc->data[SC_CURSEDCIRCLE_TARGET] ||
- (sc->data[SC_MARIONETTE_MASTER] && skill_id != CG_MARIONETTE) || //Only skill you can use is marionette again to cancel it
- (sc->data[SC_MARIONETTE] && skill_id == CG_MARIONETTE) || //Cannot use marionette if you are being buffed by another
- (sc->data[SC_STASIS] && skill->block_check(src, SC_STASIS, skill_id)) ||
- (sc->data[SC_KG_KAGEHUMI] && skill->block_check(src, SC_KG_KAGEHUMI, skill_id))
- ))
- return 0;
+ ) { //Skills blocked through status changes...
+ if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through
+ sc->data[SC_SILENCE] ||
+ sc->data[SC_STEELBODY] ||
+ sc->data[SC_BERSERK] ||
+ sc->data[SC_OBLIVIONCURSE] ||
+ sc->data[SC_WHITEIMPRISON] ||
+ sc->data[SC__INVISIBILITY] ||
+ (sc->data[SC_COLD] && src->type != BL_MOB) ||
+ sc->data[SC__IGNORANCE] ||
+ sc->data[SC_DEEP_SLEEP] ||
+ sc->data[SC_SATURDAY_NIGHT_FEVER] ||
+ sc->data[SC_CURSEDCIRCLE_TARGET] ||
+ (sc->data[SC_MARIONETTE_MASTER] && skill_id != CG_MARIONETTE) || //Only skill you can use is marionette again to cancel it
+ (sc->data[SC_MARIONETTE] && skill_id == CG_MARIONETTE) || //Cannot use marionette if you are being buffed by another
+ (sc->data[SC_STASIS] && skill->block_check(src, SC_STASIS, skill_id)) ||
+ (sc->data[SC_KG_KAGEHUMI] && skill->block_check(src, SC_KG_KAGEHUMI, skill_id))
+ ))
+ return 0;
- //Skill blocking.
- if (
- (sc->data[SC_VOLCANO] && skill_id == WZ_ICEWALL) ||
- (sc->data[SC_ROKISWEIL] && skill_id != BD_ADAPTATION) ||
- (sc->data[SC_HERMODE] && skill->get_inf(skill_id) & INF_SUPPORT_SKILL) ||
- (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOSKILL)
- )
- return 0;
+ //Skill blocking.
+ if (
+ (sc->data[SC_VOLCANO] && skill_id == WZ_ICEWALL) ||
+ (sc->data[SC_ROKISWEIL] && skill_id != BD_ADAPTATION) ||
+ (sc->data[SC_HERMODE] && skill->get_inf(skill_id) & INF_SUPPORT_SKILL) ||
+ (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOSKILL)
+ )
+ return 0;
- if( sc->data[SC__MANHOLE] || ((tsc = status_get_sc(target)) && tsc->data[SC__MANHOLE]) ) {
- switch(skill_id) {//##TODO## make this a flag in skill_db?
- // Skills that can be used even under Man Hole effects.
+ if( sc->data[SC__MANHOLE] || ((tsc = status->get_sc(target)) && tsc->data[SC__MANHOLE]) ) {
+ switch(skill_id) {//##TODO## make this a flag in skill_db?
+ // Skills that can be used even under Man Hole effects.
case SC_SHADOWFORM:
- case SC_STRIPACCESSARY:
break;
default:
return 0;
+ }
}
- }
}
}
@@ -1702,8 +1756,13 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
return 0;
}
}
- if (sc->option&OPTION_CHASEWALK && skill_id != ST_CHASEWALK)
- return 0;
+ if ( sc->option&OPTION_CHASEWALK ) {
+ if ( sc->data[SC__INVISIBILITY] ) {
+ if ( skill_id != 0 && skill_id != SC_INVISIBILITY )
+ return 0;
+ } else if ( skill_id != ST_CHASEWALK )
+ return 0;
+ }
if( sc->data[SC_ALL_RIDING] )
return 0;//New mounts can't attack nor use skills in the client; this check makes it cheat-safe [Ind]
}
@@ -1711,7 +1770,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
if (target == NULL || target == src) //No further checking needed.
return 1;
- tsc = status_get_sc(target);
+ tsc = status->get_sc(target);
if(tsc && tsc->count) {
/* attacks in invincible are capped to 1 damage and handled in batte.c; allow spell break and eske for sealed shrine GDB when in INVINCIBLE state. */
@@ -1724,35 +1783,46 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
return 0;
if(skill_id == PR_LEXAETERNA && (tsc->data[SC_FREEZE] || (tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE)))
return 0;
+ if( ( tsc->data[SC_STEALTHFIELD] || tsc->data[SC_CAMOUFLAGE] ) && !(st->mode&(MD_BOSS|MD_DETECTOR)) && flag == 4 )
+ return 0;
}
-
- //If targetting, cloak+hide protect you, otherwise only hiding does.
+ //If targeting, cloak+hide protect you, otherwise only hiding does.
hide_flag = flag?OPTION_HIDE:(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK);
- //You cannot hide from ground skills.
+ //You cannot hide from ground skills.
if( skill->get_ele(skill_id,1) == ELE_EARTH ) //TODO: Need Skill Lv here :/
hide_flag &= ~OPTION_HIDE;
+ else {
+ switch ( skill_id ) {
+ case MO_ABSORBSPIRITS: // it works when already casted and target suddenly hides.
+ case SA_DISPELL:
+ hide_flag &= ~OPTION_HIDE;
+ break;
+ }
+ }
switch( target->type ) {
case BL_PC: {
struct map_session_data *sd = (TBL_PC*) target;
- bool is_boss = (status->mode&MD_BOSS);
- bool is_detect = ((status->mode&MD_DETECTOR)?true:false);//god-knows-why gcc doesn't shut up until this happens
+ bool is_boss = (st->mode&MD_BOSS);
+ bool is_detect = ((st->mode&MD_DETECTOR)?true:false);//god-knows-why gcc doesn't shut up until this happens
if (pc_isinvisible(sd))
return 0;
- if (tsc->option&hide_flag && !is_boss &&
- ((sd->special_state.perfect_hiding || !is_detect) ||
- (tsc->data[SC_CLOAKINGEXCEED] && is_detect)))
- return 0;
- if( tsc->data[SC_CAMOUFLAGE] && !(is_boss || is_detect) && !skill_id )
- return 0;
- if( tsc->data[SC_STEALTHFIELD] && !is_boss )
- return 0;
+ if( tsc ) {
+ if (tsc->option&hide_flag && !is_boss &&
+ ((sd->special_state.perfect_hiding || !is_detect) ||
+ (tsc->data[SC_CLOAKINGEXCEED] && is_detect)))
+ return 0;
+ if( tsc->data[SC_CAMOUFLAGE] && !(is_boss || is_detect) && (!skill_id || (flag == 0 && src && src->type != BL_PC)) )
+ return 0;
+ if( tsc->data[SC_STEALTHFIELD] && !is_boss )
+ return 0;
+ }
}
break;
- case BL_ITEM: //Allow targetting of items to pick'em up (or in the case of mobs, to loot them).
+ case BL_ITEM: //Allow targeting of items to pick'em up (or in the case of mobs, to loot them).
//TODO: Would be nice if this could be used to judge whether the player can or not pick up the item it targets. [Skotlex]
- if (status->mode&MD_LOOTER)
+ if (st->mode&MD_LOOTER)
return 1;
return 0;
case BL_HOM:
@@ -1767,64 +1837,66 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
default:
//Check for chase-walk/hiding/cloaking opponents.
if( tsc ) {
- if( tsc->option&hide_flag && !(status->mode&(MD_BOSS|MD_DETECTOR)))
+ if( tsc->option&hide_flag && !(st->mode&(MD_BOSS|MD_DETECTOR)))
return 0;
- if( tsc->data[SC_STEALTHFIELD] && !(status->mode&MD_BOSS) )
+ if( tsc->data[SC_STEALTHFIELD] && !(st->mode&MD_BOSS) )
return 0;
}
}
+
return 1;
}
//Checks whether the source can see and chase target.
-int status_check_visibility(struct block_list *src, struct block_list *target)
-{
+int status_check_visibility(struct block_list *src, struct block_list *target) {
int view_range;
- struct status_data* status = status_get_status_data(src);
- struct status_change* tsc = status_get_sc(target);
+ struct status_change *tsc = NULL;
+
switch (src->type) {
- case BL_MOB:
- view_range = ((TBL_MOB*)src)->min_chase;
- break;
- case BL_PET:
- view_range = ((TBL_PET*)src)->db->range2;
- break;
- default:
- view_range = AREA_SIZE;
+ case BL_MOB:
+ view_range = ((TBL_MOB*)src)->min_chase;
+ break;
+ case BL_PET:
+ view_range = ((TBL_PET*)src)->db->range2;
+ break;
+ default:
+ view_range = AREA_SIZE;
}
if (src->m != target->m || !check_distance_bl(src, target, view_range))
return 0;
- if( tsc && tsc->data[SC_STEALTHFIELD] )
- return 0;
+ if( src->type == BL_NPC ) /* NPCs don't care for the rest */
+ return 1;
+
+ if( ( tsc = status->get_sc(target) ) ) {
+ struct status_data *st = status->get_status_data(src);
- switch (target->type)
- { //Check for chase-walk/hiding/cloaking opponents.
- case BL_PC:
- if ( tsc->data[SC_CLOAKINGEXCEED] && !(status->mode&MD_BOSS) )
- return 0;
- if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(status->mode&MD_BOSS) &&
- ( ((TBL_PC*)target)->special_state.perfect_hiding || !(status->mode&MD_DETECTOR) ) )
- return 0;
- break;
- default:
- if( tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(status->mode&(MD_BOSS|MD_DETECTOR)) )
- return 0;
+ switch (target->type) { //Check for chase-walk/hiding/cloaking opponents.
+ case BL_PC:
+ if ( tsc->data[SC_CLOAKINGEXCEED] && !(st->mode&MD_BOSS) )
+ return 0;
+ if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC_STEALTHFIELD] || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&MD_BOSS) &&
+ ( ((TBL_PC*)target)->special_state.perfect_hiding || !(st->mode&MD_DETECTOR) ) )
+ return 0;
+ break;
+ default:
+ if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&(MD_BOSS|MD_DETECTOR)) )
+ return 0;
+ }
}
return 1;
}
// Basic ASPD value
-int status_base_amotion_pc(struct map_session_data* sd, struct status_data* status)
-{
+int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) {
int amotion;
#ifdef RENEWAL_ASPD
short mod = -1;
- switch( sd->weapontype2 ){ // adjustment for dual weilding
+ switch( sd->weapontype2 ){ // adjustment for dual wielding
case W_DAGGER: mod = 0; break; // 0, 1, 1
case W_1HSWORD:
case W_1HAXE: mod = 1;
@@ -1833,33 +1905,37 @@ int status_base_amotion_pc(struct map_session_data* sd, struct status_data* stat
}
amotion = ( sd->status.weapon < MAX_WEAPON_TYPE && mod < 0 )
- ? (aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon
- : ((aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] // dual-wield
- + aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 6 / 10 + 10 * mod
- - aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]
- + aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]);
+ ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon
+ : ((status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] // dual-wield
+ + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 6 / 10 + 10 * mod
+ - status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]
+ + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]);
if ( sd->status.shield )
- amotion += ( 2000 - aspd_base[pc->class2idx(sd->status.class_)][W_FIST] ) +
- ( aspd_base[pc->class2idx(sd->status.class_)][MAX_WEAPON_TYPE] - 2000 );
+ amotion += ( 2000 - status->aspd_base[pc->class2idx(sd->status.class_)][W_FIST] ) +
+ ( status->aspd_base[pc->class2idx(sd->status.class_)][MAX_WEAPON_TYPE] - 2000 );
#else
// base weapon delay
amotion = (sd->status.weapon < MAX_WEAPON_TYPE)
- ? (aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon
- : (aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2])*7/10; // dual-wield
+ ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon
+ : (status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2])*7/10; // dual-wield
// percentual delay reduction from stats
- amotion -= amotion * (4*status->agi + status->dex)/1000;
+ amotion -= amotion * (4*st->agi + st->dex)/1000;
#endif
+
// raw delay adjustment from bAspd bonus
amotion += sd->bonus.aspd_add;
- return amotion;
+ /* angra manyu disregards aspd_base and similar */
+ if( sd->equip_index[EQI_HAND_R] >= 0 && sd->status.inventory[sd->equip_index[EQI_HAND_R]].nameid == ITEMID_ANGRA_MANYU )
+ return 0;
+
+ return amotion;
}
-static unsigned short status_base_atk(const struct block_list *bl, const struct status_data *status)
-{
+unsigned short status_base_atk(const struct block_list *bl, const struct status_data *st) {
int flag = 0, str, dex,
#ifdef RENEWAL
rstr,
@@ -1871,7 +1947,7 @@ static unsigned short status_base_atk(const struct block_list *bl, const struct
return 0;
if (bl->type == BL_PC)
- switch(((TBL_PC*)bl)->status.weapon){
+ switch(((TBL_PC*)bl)->status.weapon){
case W_BOW:
case W_MUSICAL:
case W_WHIP:
@@ -1886,14 +1962,14 @@ static unsigned short status_base_atk(const struct block_list *bl, const struct
#ifdef RENEWAL
rstr =
#endif
- str = status->dex;
- dex = status->str;
+ str = st->dex;
+ dex = st->str;
} else {
#ifdef RENEWAL
rstr =
#endif
- str = status->str;
- dex = status->dex;
+ str = st->str;
+ dex = st->dex;
}
//Normally only players have base-atk, but homunc have a different batk
// equation, hinting that perhaps non-players should use this for batk.
@@ -1902,99 +1978,104 @@ static unsigned short status_base_atk(const struct block_list *bl, const struct
str += dstr*dstr;
if (bl->type == BL_PC)
#ifdef RENEWAL
- str = (int)(rstr + (float)dex/5 + (float)status->luk/3 + (float)((TBL_PC*)bl)->status.base_level/4);
+ str = (int)(rstr + (float)dex/5 + (float)st->luk/3 + (float)((TBL_PC*)bl)->status.base_level/4);
else if(bl->type == BL_MOB)
str = rstr + ((TBL_MOB*)bl)->level;
#else
- str+= dex/5 + status->luk/5;
+ str+= dex/5 + st->luk/5;
#endif
return cap_value(str, 0, USHRT_MAX);
}
-static inline unsigned short status_base_matk_min(const struct status_data* status){ return status->int_+(status->int_/7)*(status->int_/7); }
-static inline unsigned short status_base_matk_max(const struct status_data* status){ return status->int_+(status->int_/5)*(status->int_/5); }
+#ifndef RENEWAL
+static inline unsigned short status_base_matk_min(const struct status_data *st){ return st->int_+(st->int_/7)*(st->int_/7); }
+#endif // not RENEWAL
+static inline unsigned short status_base_matk_max(const struct status_data *st){ return st->int_+(st->int_/5)*(st->int_/5); }
+
+unsigned short status_base_matk(const struct status_data *st, int level) {
#ifdef RENEWAL
-unsigned short status_base_matk(const struct status_data* status, int level){ return status->int_+(status->int_/2)+(status->dex/5)+(status->luk/3)+(level/4); }
+ return st->int_+(st->int_/2)+(st->dex/5)+(st->luk/3)+(level/4);
+#else
+ return 0;
#endif
+}
//Fills in the misc data that can be calculated from the other status info (except for level)
-void status_calc_misc(struct block_list *bl, struct status_data *status, int level)
-{
+void status_calc_misc(struct block_list *bl, struct status_data *st, int level) {
//Non players get the value set, players need to stack with previous bonuses.
if( bl->type != BL_PC )
- status->batk =
- status->hit = status->flee =
- status->def2 = status->mdef2 =
- status->cri = status->flee2 = 0;
+ st->batk =
+ st->hit = st->flee =
+ st->def2 = st->mdef2 =
+ st->cri = st->flee2 = 0;
#ifdef RENEWAL // renewal formulas
- status->matk_min = status->matk_max = bl->type == BL_PC ? status_base_matk(status, level) : level + status->int_;
- status->hit += level + status->dex + (bl->type == BL_PC ? status->luk/3 + 175 : 150); //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175
- status->flee += level + status->agi + (bl->type == BL_PC ? status->luk/5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100
- status->def2 += (int)(((float)level + status->vit)/2 + ( bl->type == BL_PC ? ((float)status->agi/5) : 0 )); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def)
- status->mdef2 += (int)( bl->type == BL_PC ?(status->int_ + ((float)level/4) + ((float)(status->dex+status->vit)/5)):((float)(status->int_ + level)/4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef)
-#else
- status->matk_min = status_base_matk_min(status);
- status->matk_max = status_base_matk_max(status);
- status->hit += level + status->dex;
- status->flee += level + status->agi;
- status->def2 += status->vit;
- status->mdef2 += status->int_ + (status->vit>>1);
-#endif
+ st->matk_min = st->matk_max = bl->type == BL_PC ? status->base_matk(st, level) : level + st->int_;
+ st->hit += level + st->dex + (bl->type == BL_PC ? st->luk/3 + 175 : 150); //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175
+ st->flee += level + st->agi + (bl->type == BL_PC ? st->luk/5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100
+ st->def2 += (int)(((float)level + st->vit)/2 + ( bl->type == BL_PC ? ((float)st->agi/5) : 0 )); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def)
+ st->mdef2 += (int)( bl->type == BL_PC ?(st->int_ + ((float)level/4) + ((float)(st->dex+st->vit)/5)):((float)(st->int_ + level)/4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef)
+#else // not RENEWAL
+ st->matk_min = status_base_matk_min(st);
+ st->matk_max = status_base_matk_max(st);
+ st->hit += level + st->dex;
+ st->flee += level + st->agi;
+ st->def2 += st->vit;
+ st->mdef2 += st->int_ + (st->vit>>1);
+#endif // RENEWAL
if( bl->type&battle_config.enable_critical )
- status->cri += 10 + (status->luk*10/3); //(every 1 luk = +0.3 critical)
+ st->cri += 10 + (st->luk*10/3); //(every 1 luk = +0.3 critical)
else
- status->cri = 0;
+ st->cri = 0;
if (bl->type&battle_config.enable_perfect_flee)
- status->flee2 += status->luk + 10; //(every 10 luk = +1 perfect flee)
+ st->flee2 += st->luk + 10; //(every 10 luk = +1 perfect flee)
else
- status->flee2 = 0;
+ st->flee2 = 0;
- if (status->batk) {
- int temp = status->batk + status_base_atk(bl, status);
- status->batk = cap_value(temp, 0, USHRT_MAX);
+ if (st->batk) {
+ int temp = st->batk + status->base_atk(bl, st);
+ st->batk = cap_value(temp, 0, USHRT_MAX);
} else
- status->batk = status_base_atk(bl, status);
- if (status->cri)
- switch (bl->type) {
- case BL_MOB:
- if(battle_config.mob_critical_rate != 100)
- status->cri = status->cri*battle_config.mob_critical_rate/100;
- if(!status->cri && battle_config.mob_critical_rate)
- status->cri = 10;
- break;
- case BL_PC:
- //Players don't have a critical adjustment setting as of yet.
- break;
- case BL_MER:
+ st->batk = status->base_atk(bl, st);
+ if (st->cri)
+ switch (bl->type) {
+ case BL_MOB:
+ if(battle_config.mob_critical_rate != 100)
+ st->cri = st->cri*battle_config.mob_critical_rate/100;
+ if(!st->cri && battle_config.mob_critical_rate)
+ st->cri = 10;
+ break;
+ case BL_PC:
+ //Players don't have a critical adjustment setting as of yet.
+ break;
+ case BL_MER:
#ifdef RENEWAL
- status->matk_min = status->matk_max = status_base_matk_max(status);
- status->def2 = status->vit + level / 10 + status->vit / 5;
- status->mdef2 = level / 10 + status->int_ / 5;
+ st->matk_min = st->matk_max = status_base_matk_max(st);
+ st->def2 = st->vit + level / 10 + st->vit / 5;
+ st->mdef2 = level / 10 + st->int_ / 5;
#endif
- break;
- default:
- if(battle_config.critical_rate != 100)
- status->cri = status->cri*battle_config.critical_rate/100;
- if (!status->cri && battle_config.critical_rate)
- status->cri = 10;
+ break;
+ default:
+ if(battle_config.critical_rate != 100)
+ st->cri = st->cri*battle_config.critical_rate/100;
+ if (!st->cri && battle_config.critical_rate)
+ st->cri = 10;
}
if(bl->type&BL_REGEN)
- status_calc_regen(bl, status, status_get_regen_data(bl));
+ status->calc_regen(bl, st, status->get_regen_data(bl));
}
//Skotlex: Calculates the initial status for the given mob
//first will only be false when the mob leveled up or got a GuardUp level.
-int status_calc_mob_(struct mob_data* md, bool first)
-{
- struct status_data *status;
+int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
+ struct status_data *mstatus;
struct block_list *mbl = NULL;
int flag=0;
+ int guardup_lv = 0;
- if(first)
- { //Set basic level on respawn.
+ if(opt&SCO_FIRST) { //Set basic level on respawn.
if (md->level > 0 && md->level <= MAX_LEVEL && md->level != md->db->lv)
;
else
@@ -2008,9 +2089,8 @@ int status_calc_mob_(struct mob_data* md, bool first)
if (md->special_state.size)
flag|=2;
- if (md->guardian_data && md->guardian_data->guardup_lv)
- flag|=4;
- if (md->class_ == MOBID_EMPERIUM)
+ if( md->guardian_data && md->guardian_data->g
+ && (guardup_lv = guild->checkskill(md->guardian_data->g,GD_GUARDUP)) )
flag|=4;
if (battle_config.slaves_inherit_speed && md->master_id)
@@ -2025,142 +2105,145 @@ int status_calc_mob_(struct mob_data* md, bool first)
aFree(md->base_status);
md->base_status = NULL;
}
- if(first)
+ if(opt&SCO_FIRST)
memcpy(&md->status, &md->db->status, sizeof(struct status_data));
return 0;
}
if (!md->base_status)
md->base_status = (struct status_data*)aCalloc(1, sizeof(struct status_data));
- status = md->base_status;
- memcpy(status, &md->db->status, sizeof(struct status_data));
+ mstatus = md->base_status;
+ memcpy(mstatus, &md->db->status, sizeof(struct status_data));
if (flag&(8|16))
- mbl = iMap->id2bl(md->master_id);
+ mbl = map->id2bl(md->master_id);
if (flag&8 && mbl) {
- struct status_data *mstatus = status_get_base_status(mbl);
- if (mstatus &&
- battle_config.slaves_inherit_speed&(mstatus->mode&MD_CANMOVE?1:2))
- status->speed = mstatus->speed;
- if( status->speed < 2 ) /* minimum for the unit to function properly */
- status->speed = 2;
+ struct status_data *masterstatus = status->get_base_status(mbl);
+ if ( masterstatus ) {
+ if (battle_config.slaves_inherit_speed&(masterstatus->mode&MD_CANMOVE ? 1 : 2))
+ mstatus->speed = masterstatus->speed;
+ if (mstatus->speed < 2) /* minimum for the unit to function properly */
+ mstatus->speed = 2;
+ }
}
- if (flag&16 && mbl)
- { //Max HP setting from Summon Flora/marine Sphere
- struct unit_data *ud = unit_bl2ud(mbl);
+ if (flag&16 && mbl) {
+ //Max HP setting from Summon Flora/marine Sphere
+ struct unit_data *ud = unit->bl2ud(mbl);
//Remove special AI when this is used by regular mobs.
if (mbl->type == BL_MOB && !((TBL_MOB*)mbl)->special_state.ai)
md->special_state.ai = 0;
- if (ud)
- { // different levels of HP according to skill level
+ if (ud) {
+ // different levels of HP according to skill level
if (ud->skill_id == AM_SPHEREMINE) {
- status->max_hp = 2000 + 400*ud->skill_lv;
- } else if(ud->skill_id == KO_ZANZOU){
- status->max_hp = 3000 + 3000 * ud->skill_lv + status_get_max_sp(battle->get_master(mbl));
+ mstatus->max_hp = 2000 + 400*ud->skill_lv;
+ } else if(ud->skill_id == KO_ZANZOU) {
+ mstatus->max_hp = 3000 + 3000 * ud->skill_lv + status_get_max_sp(battle->get_master(mbl));
} else { //AM_CANNIBALIZE
- status->max_hp = 1500 + 200*ud->skill_lv + 10*status_get_lv(mbl);
- status->mode|= MD_CANATTACK|MD_AGGRESSIVE;
+ mstatus->max_hp = 1500 + 200*ud->skill_lv + 10*status->get_lv(mbl);
+ mstatus->mode|= MD_CANATTACK|MD_AGGRESSIVE;
}
- status->hp = status->max_hp;
+ mstatus->hp = mstatus->max_hp;
+ if( ud->skill_id == NC_SILVERSNIPER )
+ mstatus->rhw.atk = mstatus->rhw.atk2 = 200 * ud->skill_lv;
}
}
- if (flag&1)
- { // increase from mobs leveling up [Valaris]
+ if (flag&1) {
+ // increase from mobs leveling up [Valaris]
int diff = md->level - md->db->lv;
- status->str+= diff;
- status->agi+= diff;
- status->vit+= diff;
- status->int_+= diff;
- status->dex+= diff;
- status->luk+= diff;
- status->max_hp += diff*status->vit;
- status->max_sp += diff*status->int_;
- status->hp = status->max_hp;
- status->sp = status->max_sp;
- status->speed -= cap_value(diff, 0, status->speed - 10);
- }
-
-
- if (flag&2 && battle_config.mob_size_influence)
- { // change for sized monsters [Valaris]
- if (md->special_state.size==SZ_MEDIUM) {
- status->max_hp>>=1;
- status->max_sp>>=1;
- if (!status->max_hp) status->max_hp = 1;
- if (!status->max_sp) status->max_sp = 1;
- status->hp=status->max_hp;
- status->sp=status->max_sp;
- status->str>>=1;
- status->agi>>=1;
- status->vit>>=1;
- status->int_>>=1;
- status->dex>>=1;
- status->luk>>=1;
- if (!status->str) status->str = 1;
- if (!status->agi) status->agi = 1;
- if (!status->vit) status->vit = 1;
- if (!status->int_) status->int_ = 1;
- if (!status->dex) status->dex = 1;
- if (!status->luk) status->luk = 1;
+ mstatus->str+= diff;
+ mstatus->agi+= diff;
+ mstatus->vit+= diff;
+ mstatus->int_+= diff;
+ mstatus->dex+= diff;
+ mstatus->luk+= diff;
+ mstatus->max_hp += diff*mstatus->vit;
+ mstatus->max_sp += diff*mstatus->int_;
+ mstatus->hp = mstatus->max_hp;
+ mstatus->sp = mstatus->max_sp;
+ mstatus->speed -= cap_value(diff, 0, mstatus->speed - 10);
+ }
+
+
+ if (flag&2 && battle_config.mob_size_influence) {
+ // change for sized monsters [Valaris]
+ if (md->special_state.size==SZ_SMALL) {
+ mstatus->max_hp>>=1;
+ mstatus->max_sp>>=1;
+ if (!mstatus->max_hp) mstatus->max_hp = 1;
+ if (!mstatus->max_sp) mstatus->max_sp = 1;
+ mstatus->hp=mstatus->max_hp;
+ mstatus->sp=mstatus->max_sp;
+ mstatus->str>>=1;
+ mstatus->agi>>=1;
+ mstatus->vit>>=1;
+ mstatus->int_>>=1;
+ mstatus->dex>>=1;
+ mstatus->luk>>=1;
+ if (!mstatus->str) mstatus->str = 1;
+ if (!mstatus->agi) mstatus->agi = 1;
+ if (!mstatus->vit) mstatus->vit = 1;
+ if (!mstatus->int_) mstatus->int_ = 1;
+ if (!mstatus->dex) mstatus->dex = 1;
+ if (!mstatus->luk) mstatus->luk = 1;
} else if (md->special_state.size==SZ_BIG) {
- status->max_hp<<=1;
- status->max_sp<<=1;
- status->hp=status->max_hp;
- status->sp=status->max_sp;
- status->str<<=1;
- status->agi<<=1;
- status->vit<<=1;
- status->int_<<=1;
- status->dex<<=1;
- status->luk<<=1;
+ mstatus->max_hp<<=1;
+ mstatus->max_sp<<=1;
+ mstatus->hp=mstatus->max_hp;
+ mstatus->sp=mstatus->max_sp;
+ mstatus->str<<=1;
+ mstatus->agi<<=1;
+ mstatus->vit<<=1;
+ mstatus->int_<<=1;
+ mstatus->dex<<=1;
+ mstatus->luk<<=1;
}
}
- status_calc_misc(&md->bl, status, md->level);
+ status->calc_misc(&md->bl, mstatus, md->level);
if(flag&4)
{ // Strengthen Guardians - custom value +10% / lv
struct guild_castle *gc;
- gc=guild->mapname2gc(map[md->bl.m].name);
+ gc=guild->mapname2gc(map->list[md->bl.m].name);
if (!gc)
- ShowError("status_calc_mob: No castle set at map %s\n", map[md->bl.m].name);
+ ShowError("status_calc_mob: No castle set at map %s\n", map->list[md->bl.m].name);
else
- if(gc->castle_id < 24 || md->class_ == MOBID_EMPERIUM) {
+ if(gc->castle_id < 24 || md->class_ == MOBID_EMPERIUM) {
#ifdef RENEWAL
- status->max_hp += 50 * gc->defense;
- status->max_sp += 70 * gc->defense;
+ mstatus->max_hp += 50 * gc->defense;
+ mstatus->max_sp += 70 * gc->defense;
#else
- status->max_hp += 1000 * gc->defense;
- status->max_sp += 200 * gc->defense;
+ mstatus->max_hp += 1000 * gc->defense;
+ mstatus->max_sp += 200 * gc->defense;
#endif
- status->hp = status->max_hp;
- status->sp = status->max_sp;
- status->def += (gc->defense+2)/3;
- status->mdef += (gc->defense+2)/3;
- }
- if(md->class_ != MOBID_EMPERIUM) {
- status->batk += status->batk * 10*md->guardian_data->guardup_lv/100;
- status->rhw.atk += status->rhw.atk * 10*md->guardian_data->guardup_lv/100;
- status->rhw.atk2 += status->rhw.atk2 * 10*md->guardian_data->guardup_lv/100;
- status->aspd_rate -= 100*md->guardian_data->guardup_lv;
- }
+ mstatus->hp = mstatus->max_hp;
+ mstatus->sp = mstatus->max_sp;
+ mstatus->def += (gc->defense+2)/3;
+ mstatus->mdef += (gc->defense+2)/3;
+ }
+ if(md->class_ != MOBID_EMPERIUM) {
+ mstatus->batk += mstatus->batk * 10*guardup_lv/100;
+ mstatus->rhw.atk += mstatus->rhw.atk * 10*guardup_lv/100;
+ mstatus->rhw.atk2 += mstatus->rhw.atk2 * 10*guardup_lv/100;
+ mstatus->aspd_rate -= 100*guardup_lv;
+ }
}
- if( first ) //Initial battle status
- memcpy(&md->status, status, sizeof(struct status_data));
+ if( opt&SCO_FIRST ) //Initial battle status
+ memcpy(&md->status, mstatus, sizeof(struct status_data));
return 1;
}
//Skotlex: Calculates the stats of the given pet.
-int status_calc_pet_(struct pet_data *pd, bool first)
+int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt)
{
nullpo_ret(pd);
- if (first) {
+ if (opt&SCO_FIRST) {
memcpy(&pd->status, &pd->db->status, sizeof(struct status_data));
pd->status.mode = MD_CANMOVE; // pets discard all modes, except walking
pd->status.speed = pd->petDB->speed;
@@ -2171,45 +2254,43 @@ int status_calc_pet_(struct pet_data *pd, bool first)
}
}
- if (battle_config.pet_lv_rate && pd->msd)
- {
+ if (battle_config.pet_lv_rate && pd->msd) {
struct map_session_data *sd = pd->msd;
int lv;
lv =sd->status.base_level*battle_config.pet_lv_rate/100;
if (lv < 0)
lv = 1;
- if (lv != pd->pet.level || first)
- {
- struct status_data *bstat = &pd->db->status, *status = &pd->status;
+ if (lv != pd->pet.level || opt&SCO_FIRST) {
+ struct status_data *bstat = &pd->db->status, *pstatus = &pd->status;
pd->pet.level = lv;
- if (!first) //Lv Up animation
+ if (! (opt&SCO_FIRST) ) //Lv Up animation
clif->misceffect(&pd->bl, 0);
- status->rhw.atk = (bstat->rhw.atk*lv)/pd->db->lv;
- status->rhw.atk2 = (bstat->rhw.atk2*lv)/pd->db->lv;
- status->str = (bstat->str*lv)/pd->db->lv;
- status->agi = (bstat->agi*lv)/pd->db->lv;
- status->vit = (bstat->vit*lv)/pd->db->lv;
- status->int_ = (bstat->int_*lv)/pd->db->lv;
- status->dex = (bstat->dex*lv)/pd->db->lv;
- status->luk = (bstat->luk*lv)/pd->db->lv;
-
- status->rhw.atk = cap_value(status->rhw.atk, 1, battle_config.pet_max_atk1);
- status->rhw.atk2 = cap_value(status->rhw.atk2, 2, battle_config.pet_max_atk2);
- status->str = cap_value(status->str,1,battle_config.pet_max_stats);
- status->agi = cap_value(status->agi,1,battle_config.pet_max_stats);
- status->vit = cap_value(status->vit,1,battle_config.pet_max_stats);
- status->int_= cap_value(status->int_,1,battle_config.pet_max_stats);
- status->dex = cap_value(status->dex,1,battle_config.pet_max_stats);
- status->luk = cap_value(status->luk,1,battle_config.pet_max_stats);
-
- status_calc_misc(&pd->bl, &pd->status, lv);
-
- if (!first) //Not done the first time because the pet is not visible yet
+ pstatus->rhw.atk = (bstat->rhw.atk*lv)/pd->db->lv;
+ pstatus->rhw.atk2 = (bstat->rhw.atk2*lv)/pd->db->lv;
+ pstatus->str = (bstat->str*lv)/pd->db->lv;
+ pstatus->agi = (bstat->agi*lv)/pd->db->lv;
+ pstatus->vit = (bstat->vit*lv)/pd->db->lv;
+ pstatus->int_ = (bstat->int_*lv)/pd->db->lv;
+ pstatus->dex = (bstat->dex*lv)/pd->db->lv;
+ pstatus->luk = (bstat->luk*lv)/pd->db->lv;
+
+ pstatus->rhw.atk = cap_value(pstatus->rhw.atk, 1, battle_config.pet_max_atk1);
+ pstatus->rhw.atk2 = cap_value(pstatus->rhw.atk2, 2, battle_config.pet_max_atk2);
+ pstatus->str = cap_value(pstatus->str,1,battle_config.pet_max_stats);
+ pstatus->agi = cap_value(pstatus->agi,1,battle_config.pet_max_stats);
+ pstatus->vit = cap_value(pstatus->vit,1,battle_config.pet_max_stats);
+ pstatus->int_= cap_value(pstatus->int_,1,battle_config.pet_max_stats);
+ pstatus->dex = cap_value(pstatus->dex,1,battle_config.pet_max_stats);
+ pstatus->luk = cap_value(pstatus->luk,1,battle_config.pet_max_stats);
+
+ status->calc_misc(&pd->bl, &pd->status, lv);
+
+ if (! (opt&SCO_FIRST) ) //Not done the first time because the pet is not visible yet
clif->send_petstatus(sd);
}
- } else if (first) {
- status_calc_misc(&pd->bl, &pd->status, pd->db->lv);
+ } else if ( opt&SCO_FIRST ) {
+ status->calc_misc(&pd->bl, &pd->status, pd->db->lv);
if (!battle_config.pet_lv_rate && pd->pet.level != pd->db->lv)
pd->pet.level = pd->db->lv;
}
@@ -2223,23 +2304,23 @@ int status_calc_pet_(struct pet_data *pd, bool first)
}
/// Helper function for status_base_pc_maxhp(), used to pre-calculate the hp_sigma_val[] array
-static void status_calc_sigma(void)
+void status_calc_sigma(void)
{
int i,j;
for(i = 0; i < CLASS_COUNT; i++)
{
unsigned int k = 0;
- hp_sigma_val[i][0] = hp_sigma_val[i][1] = 0;
+ status->hp_sigma_val[i][0] = status->hp_sigma_val[i][1] = 0;
for(j = 2; j <= MAX_LEVEL; j++)
{
- k += (hp_coefficient[i]*j + 50) / 100;
- hp_sigma_val[i][j] = k;
+ k += (status->hp_coefficient[i]*j + 50) / 100;
+ status->hp_sigma_val[i][j] = k;
if (k >= INT_MAX)
break; //Overflow protection. [Skotlex]
}
for(; j <= MAX_LEVEL; j++)
- hp_sigma_val[i][j] = INT_MAX;
+ status->hp_sigma_val[i][j] = INT_MAX;
}
}
@@ -2248,33 +2329,31 @@ static void status_calc_sigma(void)
/// f(0) = 35 | f(x+1) = f(x) + A + (x + B)*C/D
/// which reduces to something close to
/// f(x) = 35 + x*(A + B*C/D) + sum(i=2..x){ i*C/D }
-static unsigned int status_base_pc_maxhp(struct map_session_data* sd, struct status_data* status)
-{
+unsigned int status_base_pc_maxhp(struct map_session_data *sd, struct status_data *st) {
uint64 val = pc->class2idx(sd->status.class_);
- val = 35 + sd->status.base_level*(int64)hp_coefficient2[val]/100 + hp_sigma_val[val][sd->status.base_level];
+ val = 35 + sd->status.base_level*(int64)status->hp_coefficient2[val]/100 + status->hp_sigma_val[val][sd->status.base_level];
- if((sd->class_&MAPID_UPPERMASK) == MAPID_NINJA || (sd->class_&MAPID_UPPERMASK) == MAPID_GUNSLINGER)
+ if((sd->class_&MAPID_UPPERMASK) == MAPID_NINJA || (sd->class_&MAPID_UPPERMASK) == MAPID_GUNSLINGER || (sd->class_&MAPID_UPPERMASK) == MAPID_REBELLION)
val += 100; //Since their HP can't be approximated well enough without this.
if((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON))
val *= 3; //Triple max HP for top ranking Taekwons over level 90.
if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99)
val += 2000; //Supernovice lvl99 hp bonus.
- val += val * status->vit/100; // +1% per each point of VIT
+ val += val * st->vit/100; // +1% per each point of VIT
if (sd->class_&JOBL_UPPER)
val += val * 25/100; //Trans classes get a 25% hp bonus
else if (sd->class_&JOBL_BABY)
val -= val * 30/100; //Baby classes get a 30% hp penalty
- return (unsigned int)val;
+ return (unsigned int)cap_value(val,0,UINT_MAX);
}
-static unsigned int status_base_pc_maxsp(struct map_session_data* sd, struct status_data *status)
-{
+unsigned int status_base_pc_maxsp(struct map_session_data* sd, struct status_data *st) {
uint64 val;
- val = 10 + sd->status.base_level*(int64)sp_coefficient[pc->class2idx(sd->status.class_)]/100;
- val += val * status->int_/100;
+ val = 10 + sd->status.base_level*(int64)status->sp_coefficient[pc->class2idx(sd->status.class_)]/100;
+ val += val * st->int_/100;
if (sd->class_&JOBL_UPPER)
val += val * 25/100;
@@ -2283,19 +2362,18 @@ static unsigned int status_base_pc_maxsp(struct map_session_data* sd, struct sta
if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON))
val *= 3; //Triple max SP for top ranking Taekwons over level 90.
- return (unsigned int)val;
+ return (unsigned int)cap_value(val,0,UINT_MAX);
}
//Calculates player data from scratch without counting SC adjustments.
//Should be invoked whenever players raise stats, learn passive skills or change equipment.
-int status_calc_pc_(struct map_session_data* sd, bool first)
-{
+int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
static int calculating = 0; //Check for recursive call preemption. [Skotlex]
- struct status_data *status; // pointer to the player's base status
+ struct status_data *bstatus; // pointer to the player's base status
const struct status_change *sc = &sd->sc;
struct s_skill b_skill[MAX_SKILL]; // previous skill tree
int b_weight, b_max_weight, b_cart_weight_max, // previous weight
- i, k, index, skill,refinedef=0;
+ i, k, index, skill_lv,refinedef=0;
int64 i64;
if (++calculating > 10) //Too many recursive calls!
@@ -2309,9 +2387,9 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
pc->calc_skilltree(sd); // SkillTree calculation
- sd->max_weight = max_weight_base[pc->class2idx(sd->status.class_)]+sd->status.str*300;
+ sd->max_weight = status->max_weight_base[pc->class2idx(sd->status.class_)]+sd->status.str*300;
- if(first) {
+ if(opt&SCO_FIRST) {
//Load Hp/SP from char-received data.
sd->battle_status.hp = sd->status.hp;
sd->battle_status.sp = sd->status.sp;
@@ -2333,7 +2411,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
}
}
- status = &sd->base_status;
+ bstatus = &sd->base_status;
// these are not zeroed. [zzo]
sd->hprate=100;
sd->sprate=100;
@@ -2371,7 +2449,6 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
+ sizeof(sd->expaddrace)
+ sizeof(sd->ignore_mdef)
+ sizeof(sd->ignore_def)
- + sizeof(sd->itemgrouphealrate)
+ sizeof(sd->sp_gain_race)
+ sizeof(sd->sp_gain_race_attack)
+ sizeof(sd->hp_gain_race_attack)
@@ -2384,26 +2461,32 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_CLAIRVOYANCE);
memset(&sd->special_state,0,sizeof(sd->special_state));
- memset(&status->max_hp, 0, sizeof(struct status_data)-(sizeof(status->hp)+sizeof(status->sp)));
-
+
+ if (!sd->state.permanent_speed) {
+ memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp)));
+ bstatus->speed = DEFAULT_WALK_SPEED;
+ } else {
+ int pSpeed = bstatus->speed;
+ memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp)));
+ bstatus->speed = pSpeed;
+ }
+
//FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex]
- if (!sd->state.permanent_speed)
- status->speed = DEFAULT_WALK_SPEED;
//Give them all modes except these (useful for clones)
- status->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
+ bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
- status->size = (sd->class_&JOBL_BABY)?SZ_SMALL:SZ_MEDIUM;
+ bstatus->size = (sd->class_&JOBL_BABY)?SZ_MEDIUM:SZ_SMALL;
if (battle_config.character_size && (pc_isriding(sd) || pc_isridingdragon(sd)) ) { //[Lupus]
if (sd->class_&JOBL_BABY) {
if (battle_config.character_size&SZ_BIG)
- status->size++;
+ bstatus->size++;
} else
- if(battle_config.character_size&SZ_MEDIUM)
- status->size++;
+ if(battle_config.character_size&SZ_SMALL)
+ bstatus->size++;
}
- status->aspd_rate = 1000;
- status->ele_lv = 1;
- status->race = RC_DEMIHUMAN;
+ bstatus->aspd_rate = 1000;
+ bstatus->ele_lv = 1;
+ bstatus->race = RC_DEMIHUMAN;
//zero up structures...
memset(&sd->autospell,0,sizeof(sd->autospell)
@@ -2433,7 +2516,9 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
+ sizeof(sd->skillfixcast)
+ sizeof(sd->skillvarcast)
+ sizeof(sd->skillfixcastrate)
- );
+ + sizeof(sd->def_set_race)
+ + sizeof(sd->mdef_set_race)
+ );
memset (&sd->bonus, 0,sizeof(sd->bonus));
@@ -2443,10 +2528,11 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
pc->delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus3),true);
// Parse equipment.
- for(i=0;i<EQI_MAX-1;i++) {
- current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
+ for(i=0;i<EQI_MAX;i++) {
+ status->current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to status->current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
if(index < 0)
continue;
+ if(i == EQI_AMMO) continue;/* ammo has special handler down there */
if(i == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index)
continue;
if(i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index)
@@ -2460,25 +2546,25 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
if(!sd->inventory_data[index])
continue;
- for(k = 0; k < map[sd->bl.m].zone->disabled_items_count; k++) {
- if( map[sd->bl.m].zone->disabled_items[k] == sd->inventory_data[index]->nameid ) {
+ for(k = 0; k < map->list[sd->bl.m].zone->disabled_items_count; k++) {
+ if( map->list[sd->bl.m].zone->disabled_items[k] == sd->inventory_data[index]->nameid ) {
break;
}
}
-
- if( k < map[sd->bl.m].zone->disabled_items_count )
+
+ if( k < map->list[sd->bl.m].zone->disabled_items_count )
continue;
-
- status->def += sd->inventory_data[index]->def;
- if(first && sd->inventory_data[index]->equip_script)
- { //Execute equip-script on login
- run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
+ bstatus->def += sd->inventory_data[index]->def;
+
+ if(opt&SCO_FIRST && sd->inventory_data[index]->equip_script)
+ { //Execute equip-script on login
+ script->run(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
if (!calculating)
return 1;
}
- // sanitize the refine level in case someone decreased the value inbetween
+ // sanitize the refine level in case someone decreased the value in between
if (sd->status.inventory[index].refine > MAX_REFINE)
sd->status.inventory[index].refine = MAX_REFINE;
@@ -2490,35 +2576,35 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
wlv = REFINE_TYPE_MAX - 1;
if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) {
wd = &sd->left_weapon; // Left-hand weapon
- wa = &status->lhw;
+ wa = &bstatus->lhw;
} else {
wd = &sd->right_weapon;
- wa = &status->rhw;
+ wa = &bstatus->rhw;
}
wa->atk += sd->inventory_data[index]->atk;
if ( (r = sd->status.inventory[index].refine) )
- wa->atk2 = refine_info[wlv].bonus[r-1] / 100;
+ wa->atk2 = status->refine_info[wlv].bonus[r-1] / 100;
#ifdef RENEWAL
- wa->matk += sd->inventory_data[index]->matk;
- wa->wlv = wlv;
+ wa->matk += sd->inventory_data[index]->matk;
+ wa->wlv = wlv;
if( r && sd->weapontype1 != W_BOW ) // renewal magic attack refine bonus
- wa->matk += refine_info[wlv].bonus[r-1] / 100;
+ wa->matk += status->refine_info[wlv].bonus[r-1] / 100;
#endif
- //Overrefine bonus.
+ //Overrefined bonus.
if (r)
- wd->overrefine = refine_info[wlv].randombonus_max[r-1] / 100;
+ wd->overrefine = status->refine_info[wlv].randombonus_max[r-1] / 100;
wa->range += sd->inventory_data[index]->range;
if(sd->inventory_data[index]->script) {
if (wd == &sd->left_weapon) {
sd->state.lr_flag = 1;
- run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
+ script->run(sd->inventory_data[index]->script,0,sd->bl.id,0);
sd->state.lr_flag = 0;
} else
- run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
- if (!calculating) //Abort, run_script retriggered this. [Skotlex]
+ script->run(sd->inventory_data[index]->script,0,sd->bl.id,0);
+ if (!calculating) //Abort, script->run retriggered this. [Skotlex]
return 1;
}
@@ -2536,14 +2622,14 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
else if(sd->inventory_data[index]->type == IT_ARMOR) {
int r;
if ( (r = sd->status.inventory[index].refine) )
- refinedef += refine_info[REFINE_TYPE_ARMOR].bonus[r-1];
+ refinedef += status->refine_info[REFINE_TYPE_ARMOR].bonus[r-1];
if(sd->inventory_data[index]->script) {
if( i == EQI_HAND_L ) //Shield
sd->state.lr_flag = 3;
- run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
+ script->run(sd->inventory_data[index]->script,0,sd->bl.id,0);
if( i == EQI_HAND_L ) //Shield
sd->state.lr_flag = 0;
- if (!calculating) //Abort, run_script retriggered this. [Skotlex]
+ if (!calculating) //Abort, script->run retriggered this. [Skotlex]
return 1;
}
}
@@ -2555,33 +2641,51 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
sd->bonus.arrow_atk += sd->inventory_data[index]->atk;
sd->state.lr_flag = 2;
if( !itemdb_is_GNthrowable(sd->inventory_data[index]->nameid) ) //don't run scripts on throwable items
- run_script(sd->inventory_data[index]->script,0,sd->bl.id,0);
+ script->run(sd->inventory_data[index]->script,0,sd->bl.id,0);
sd->state.lr_flag = 0;
- if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex]
+ if (!calculating) //Abort, script->run retriggered status_calc_pc. [Skotlex]
return 1;
}
}
/* we've got combos to process */
- if( sd->combos.count ) {
- for( i = 0; i < sd->combos.count; i++ ) {
- run_script(sd->combos.bonus[i],0,sd->bl.id,0);
- if (!calculating) //Abort, run_script retriggered this.
- return 1;
+ for( i = 0; i < sd->combo_count; i++ ) {
+ struct item_combo *combo = itemdb->id2combo(sd->combos[i].id);
+ unsigned char j;
+
+ /**
+ * ensure combo usage is allowed at this location
+ **/
+ for(j = 0; j < combo->count; j++) {
+ for(k = 0; k < map->list[sd->bl.m].zone->disabled_items_count; k++) {
+ if( map->list[sd->bl.m].zone->disabled_items[k] == combo->nameid[j] ) {
+ break;
+ }
+ }
+ if( k != map->list[sd->bl.m].zone->disabled_items_count )
+ break;
}
+
+ if( j != combo->count )
+ continue;
+
+ script->run(sd->combos[i].bonus,0,sd->bl.id,0);
+ if (!calculating) //Abort, script->run retriggered this.
+ return 1;
}
//Store equipment script bonuses
memcpy(sd->param_equip,sd->param_bonus,sizeof(sd->param_equip));
memset(sd->param_bonus, 0, sizeof(sd->param_bonus));
- status->def += (refinedef+50)/100;
+ bstatus->def += (refinedef+50)/100;
//Parse Cards
- for(i=0;i<EQI_MAX-1;i++) {
- current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
+ for(i=0;i<EQI_MAX;i++) {
+ status->current_equip_item_index = index = sd->equip_index[i]; //We pass INDEX to status->current_equip_item_index - for EQUIP_SCRIPT (new cards solution) [Lupus]
if(index < 0)
continue;
+ if(i == EQI_AMMO) continue;/* ammo doesn't have cards */
if(i == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index)
continue;
if(i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index)
@@ -2596,75 +2700,76 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
//Card script execution.
if(itemdb_isspecial(sd->status.inventory[index].card[0]))
continue;
- for(j=0;j<MAX_SLOTS;j++){ // Uses MAX_SLOTS to support Soul Bound system [Inkfish]
- current_equip_card_id= c= sd->status.inventory[index].card[j];
+ for(j=0;j<MAX_SLOTS;j++) {
+ // Uses MAX_SLOTS to support Soul Bound system [Inkfish]
+ status->current_equip_card_id= c= sd->status.inventory[index].card[j];
if(!c)
continue;
- data = itemdb_exists(c);
+ data = itemdb->exists(c);
if(!data)
continue;
- if(first && data->equip_script) {//Execute equip-script on login
- run_script(data->equip_script,0,sd->bl.id,0);
+
+ for(k = 0; k < map->list[sd->bl.m].zone->disabled_items_count; k++) {
+ if( map->list[sd->bl.m].zone->disabled_items[k] == data->nameid ) {
+ break;
+ }
+ }
+
+ if( k < map->list[sd->bl.m].zone->disabled_items_count )
+ continue;
+
+ if(opt&SCO_FIRST && data->equip_script) {//Execute equip-script on login
+ script->run(data->equip_script,0,sd->bl.id,0);
if (!calculating)
return 1;
}
+
if(!data->script)
continue;
-
- for(k = 0; k < map[sd->bl.m].zone->disabled_items_count; k++) {
- if( map[sd->bl.m].zone->disabled_items[k] == data->nameid ) {
- break;
- }
- }
-
- if( k < map[sd->bl.m].zone->disabled_items_count )
- continue;
-
+
if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) { //Left hand status.
sd->state.lr_flag = 1;
- run_script(data->script,0,sd->bl.id,0);
+ script->run(data->script,0,sd->bl.id,0);
sd->state.lr_flag = 0;
} else
- run_script(data->script,0,sd->bl.id,0);
- if (!calculating) //Abort, run_script his function. [Skotlex]
+ script->run(data->script,0,sd->bl.id,0);
+ if (!calculating) //Abort, script->run his function. [Skotlex]
return 1;
}
}
}
- if( sc->count && sc->data[SC_ITEMSCRIPT] )
- {
- struct item_data *data = itemdb_exists(sc->data[SC_ITEMSCRIPT]->val1);
+ if( sc->count && sc->data[SC_ITEMSCRIPT] ) {
+ struct item_data *data = itemdb->exists(sc->data[SC_ITEMSCRIPT]->val1);
if( data && data->script )
- run_script(data->script,0,sd->bl.id,0);
+ script->run(data->script,0,sd->bl.id,0);
}
- if( sd->pd )
- { // Pet Bonus
+ if( sd->pd ) { // Pet Bonus
struct pet_data *pd = sd->pd;
if( pd && pd->petDB && pd->petDB->equip_script && pd->pet.intimate >= battle_config.pet_equip_min_friendly )
- run_script(pd->petDB->equip_script,0,sd->bl.id,0);
+ script->run(pd->petDB->equip_script,0,sd->bl.id,0);
if( pd && pd->pet.intimate > 0 && (!battle_config.pet_equip_required || pd->pet.equip > 0) && pd->state.skillbonus == 1 && pd->bonus )
pc->bonus(sd,pd->bonus->type, pd->bonus->val);
}
//param_bonus now holds card bonuses.
- if(status->rhw.range < 1) status->rhw.range = 1;
- if(status->lhw.range < 1) status->lhw.range = 1;
- if(status->rhw.range < status->lhw.range)
- status->rhw.range = status->lhw.range;
+ if(bstatus->rhw.range < 1) bstatus->rhw.range = 1;
+ if(bstatus->lhw.range < 1) bstatus->lhw.range = 1;
+ if(bstatus->rhw.range < bstatus->lhw.range)
+ bstatus->rhw.range = bstatus->lhw.range;
sd->bonus.double_rate += sd->bonus.double_add_rate;
sd->bonus.perfect_hit += sd->bonus.perfect_hit_add;
sd->bonus.splash_range += sd->bonus.splash_add_range;
// Damage modifiers from weapon type
- sd->right_weapon.atkmods[0] = atkmods[0][sd->weapontype1];
- sd->right_weapon.atkmods[1] = atkmods[1][sd->weapontype1];
- sd->right_weapon.atkmods[2] = atkmods[2][sd->weapontype1];
- sd->left_weapon.atkmods[0] = atkmods[0][sd->weapontype2];
- sd->left_weapon.atkmods[1] = atkmods[1][sd->weapontype2];
- sd->left_weapon.atkmods[2] = atkmods[2][sd->weapontype2];
+ sd->right_weapon.atkmods[0] = status->atkmods[0][sd->weapontype1];
+ sd->right_weapon.atkmods[1] = status->atkmods[1][sd->weapontype1];
+ sd->right_weapon.atkmods[2] = status->atkmods[2][sd->weapontype1];
+ sd->left_weapon.atkmods[0] = status->atkmods[0][sd->weapontype2];
+ sd->left_weapon.atkmods[1] = status->atkmods[1][sd->weapontype2];
+ sd->left_weapon.atkmods[2] = status->atkmods[2][sd->weapontype2];
if( (pc_isriding(sd) || pc_isridingdragon(sd)) &&
(sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR))
@@ -2674,314 +2779,320 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
sd->left_weapon.atkmods[1] = sd->left_weapon.atkmods[2];
}
-// ----- STATS CALCULATION -----
+ // ----- STATS CALCULATION -----
// Job bonuses
index = pc->class2idx(sd->status.class_);
for(i=0;i<(int)sd->status.job_level && i<MAX_LEVEL;i++){
- if(!job_bonus[index][i])
+ if(!status->job_bonus[index][i])
continue;
- switch(job_bonus[index][i]) {
- case 1: status->str++; break;
- case 2: status->agi++; break;
- case 3: status->vit++; break;
- case 4: status->int_++; break;
- case 5: status->dex++; break;
- case 6: status->luk++; break;
+ switch(status->job_bonus[index][i]) {
+ case 1: bstatus->str++; break;
+ case 2: bstatus->agi++; break;
+ case 3: bstatus->vit++; break;
+ case 4: bstatus->int_++; break;
+ case 5: bstatus->dex++; break;
+ case 6: bstatus->luk++; break;
}
}
// If a Super Novice has never died and is at least joblv 70, he gets all stats +10
- if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->die_counter == 0 && sd->status.job_level >= 70){
- status->str += 10;
- status->agi += 10;
- status->vit += 10;
- status->int_+= 10;
- status->dex += 10;
- status->luk += 10;
+ if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->die_counter == 0 && sd->status.job_level >= 70) {
+ bstatus->str += 10;
+ bstatus->agi += 10;
+ bstatus->vit += 10;
+ bstatus->int_+= 10;
+ bstatus->dex += 10;
+ bstatus->luk += 10;
}
// Absolute modifiers from passive skills
if(pc->checkskill(sd,BS_HILTBINDING)>0)
- status->str++;
- if((skill=pc->checkskill(sd,SA_DRAGONOLOGY))>0)
- status->int_ += (skill+1)/2; // +1 INT / 2 lv
- if((skill=pc->checkskill(sd,AC_OWL))>0)
- status->dex += skill;
- if((skill = pc->checkskill(sd,RA_RESEARCHTRAP))>0)
- status->int_ += skill;
+ bstatus->str++;
+ if((skill_lv=pc->checkskill(sd,SA_DRAGONOLOGY))>0)
+ bstatus->int_ += (skill_lv+1)/2; // +1 INT / 2 lv
+ if((skill_lv=pc->checkskill(sd,AC_OWL))>0)
+ bstatus->dex += skill_lv;
+ if((skill_lv = pc->checkskill(sd,RA_RESEARCHTRAP))>0)
+ bstatus->int_ += skill_lv;
// Bonuses from cards and equipment as well as base stat, remember to avoid overflows.
- i = status->str + sd->status.str + sd->param_bonus[0] + sd->param_equip[0];
- status->str = cap_value(i,0,USHRT_MAX);
- i = status->agi + sd->status.agi + sd->param_bonus[1] + sd->param_equip[1];
- status->agi = cap_value(i,0,USHRT_MAX);
- i = status->vit + sd->status.vit + sd->param_bonus[2] + sd->param_equip[2];
- status->vit = cap_value(i,0,USHRT_MAX);
- i = status->int_+ sd->status.int_+ sd->param_bonus[3] + sd->param_equip[3];
- status->int_ = cap_value(i,0,USHRT_MAX);
- i = status->dex + sd->status.dex + sd->param_bonus[4] + sd->param_equip[4];
- status->dex = cap_value(i,0,USHRT_MAX);
- i = status->luk + sd->status.luk + sd->param_bonus[5] + sd->param_equip[5];
- status->luk = cap_value(i,0,USHRT_MAX);
-
-// ------ BASE ATTACK CALCULATION ------
-
- // Base batk value is set on status_calc_misc
+ i = bstatus->str + sd->status.str + sd->param_bonus[0] + sd->param_equip[0];
+ bstatus->str = cap_value(i,0,USHRT_MAX);
+ i = bstatus->agi + sd->status.agi + sd->param_bonus[1] + sd->param_equip[1];
+ bstatus->agi = cap_value(i,0,USHRT_MAX);
+ i = bstatus->vit + sd->status.vit + sd->param_bonus[2] + sd->param_equip[2];
+ bstatus->vit = cap_value(i,0,USHRT_MAX);
+ i = bstatus->int_+ sd->status.int_+ sd->param_bonus[3] + sd->param_equip[3];
+ bstatus->int_ = cap_value(i,0,USHRT_MAX);
+ i = bstatus->dex + sd->status.dex + sd->param_bonus[4] + sd->param_equip[4];
+ bstatus->dex = cap_value(i,0,USHRT_MAX);
+ i = bstatus->luk + sd->status.luk + sd->param_bonus[5] + sd->param_equip[5];
+ bstatus->luk = cap_value(i,0,USHRT_MAX);
+
+ // ------ BASE ATTACK CALCULATION ------
+
+ // Base batk value is set on status->calc_misc
// weapon-type bonus (FIXME: Why is the weapon_atk bonus applied to base attack?)
if (sd->status.weapon < MAX_WEAPON_TYPE && sd->weapon_atk[sd->status.weapon])
- status->batk += sd->weapon_atk[sd->status.weapon];
+ bstatus->batk += sd->weapon_atk[sd->status.weapon];
// Absolute modifiers from passive skills
#ifndef RENEWAL
- if((skill=pc->checkskill(sd,BS_HILTBINDING))>0) // it doesn't work in RE.
- status->batk += 4;
+ if((skill_lv=pc->checkskill(sd,BS_HILTBINDING))>0) // it doesn't work in RE.
+ bstatus->batk += 4;
#endif
-// ----- HP MAX CALCULATION -----
+ // ----- HP MAX CALCULATION -----
// Basic MaxHP value
//We hold the standard Max HP here to make it faster to recalculate on vit changes.
- sd->status.max_hp = status_base_pc_maxhp(sd,status);
+ sd->status.max_hp = status->base_pc_maxhp(sd,bstatus);
//This is done to handle underflows from negative Max HP bonuses
- i64 = sd->status.max_hp + (int)status->max_hp;
- status->max_hp = (unsigned int)cap_value(i64, 0, INT_MAX);
+ i64 = sd->status.max_hp + (int)bstatus->max_hp;
+ bstatus->max_hp = (unsigned int)cap_value(i64, 0, INT_MAX);
// Absolute modifiers from passive skills
- if((skill=pc->checkskill(sd,CR_TRUST))>0)
- status->max_hp += skill*200;
+ if((skill_lv=pc->checkskill(sd,CR_TRUST))>0)
+ bstatus->max_hp += skill_lv*200;
// Apply relative modifiers from equipment
if(sd->hprate < 0)
sd->hprate = 0;
if(sd->hprate!=100)
- status->max_hp = (int64)status->max_hp * sd->hprate/100;
+ bstatus->max_hp = APPLY_RATE(bstatus->max_hp, sd->hprate);
if(battle_config.hp_rate != 100)
- status->max_hp = (int64)status->max_hp * battle_config.hp_rate/100;
+ bstatus->max_hp = APPLY_RATE(bstatus->max_hp, battle_config.hp_rate);
- if(status->max_hp > (unsigned int)battle_config.max_hp)
- status->max_hp = battle_config.max_hp;
- else if(!status->max_hp)
- status->max_hp = 1;
+ if(bstatus->max_hp > (unsigned int)battle_config.max_hp)
+ bstatus->max_hp = battle_config.max_hp;
+ else if(!bstatus->max_hp)
+ bstatus->max_hp = 1;
-// ----- SP MAX CALCULATION -----
+ // ----- SP MAX CALCULATION -----
// Basic MaxSP value
- sd->status.max_sp = status_base_pc_maxsp(sd,status);
+ sd->status.max_sp = status->base_pc_maxsp(sd,bstatus);
//This is done to handle underflows from negative Max SP bonuses
- i64 = sd->status.max_sp + (int)status->max_sp;
- status->max_sp = (unsigned int)cap_value(i64, 0, INT_MAX);
+ i64 = sd->status.max_sp + (int)bstatus->max_sp;
+ bstatus->max_sp = (unsigned int)cap_value(i64, 0, INT_MAX);
// Absolute modifiers from passive skills
- if((skill=pc->checkskill(sd,SL_KAINA))>0)
- status->max_sp += 30*skill;
- if((skill=pc->checkskill(sd,HP_MEDITATIO))>0)
- status->max_sp += (int64)status->max_sp * skill/100;
- if((skill=pc->checkskill(sd,HW_SOULDRAIN))>0)
- status->max_sp += (int64)status->max_sp * 2*skill/100;
- if( (skill = pc->checkskill(sd,RA_RESEARCHTRAP)) > 0 )
- status->max_sp += 200 + 20 * skill;
- if( (skill = pc->checkskill(sd,WM_LESSON)) > 0 )
- status->max_sp += 30 * skill;
+ if((skill_lv=pc->checkskill(sd,SL_KAINA))>0)
+ bstatus->max_sp += 30*skill_lv;
+ if((skill_lv=pc->checkskill(sd,HP_MEDITATIO))>0)
+ bstatus->max_sp += (int64)bstatus->max_sp * skill_lv/100;
+ if((skill_lv=pc->checkskill(sd,HW_SOULDRAIN))>0)
+ bstatus->max_sp += (int64)bstatus->max_sp * 2*skill_lv/100;
+ if( (skill_lv = pc->checkskill(sd,RA_RESEARCHTRAP)) > 0 )
+ bstatus->max_sp += 200 + 20 * skill_lv;
+ if( (skill_lv = pc->checkskill(sd,WM_LESSON)) > 0 )
+ bstatus->max_sp += 30 * skill_lv;
// Apply relative modifiers from equipment
if(sd->sprate < 0)
sd->sprate = 0;
if(sd->sprate!=100)
- status->max_sp = (int64)status->max_sp * sd->sprate/100;
+ bstatus->max_sp = APPLY_RATE(bstatus->max_sp, sd->sprate);
if(battle_config.sp_rate != 100)
- status->max_sp = (int64)status->max_sp * battle_config.sp_rate/100;
+ bstatus->max_sp = APPLY_RATE(bstatus->max_sp, battle_config.sp_rate);
- if(status->max_sp > (unsigned int)battle_config.max_sp)
- status->max_sp = battle_config.max_sp;
- else if(!status->max_sp)
- status->max_sp = 1;
+ if(bstatus->max_sp > (unsigned int)battle_config.max_sp)
+ bstatus->max_sp = battle_config.max_sp;
+ else if(!bstatus->max_sp)
+ bstatus->max_sp = 1;
-// ----- RESPAWN HP/SP -----
-//
+ // ----- RESPAWN HP/SP -----
+ //
//Calc respawn hp and store it on base_status
if (sd->special_state.restart_full_recover)
{
- status->hp = status->max_hp;
- status->sp = status->max_sp;
+ bstatus->hp = bstatus->max_hp;
+ bstatus->sp = bstatus->max_sp;
} else {
if((sd->class_&MAPID_BASEMASK) == MAPID_NOVICE && !(sd->class_&JOBL_2)
&& battle_config.restart_hp_rate < 50)
- status->hp = status->max_hp>>1;
+ bstatus->hp = bstatus->max_hp>>1;
else
- status->hp = (int64)status->max_hp * battle_config.restart_hp_rate/100;
- if(!status->hp)
- status->hp = 1;
+ bstatus->hp = APPLY_RATE(bstatus->max_hp, battle_config.restart_hp_rate);
+ if(!bstatus->hp)
+ bstatus->hp = 1;
- status->sp = (int64)status->max_sp * battle_config.restart_sp_rate /100;
+ bstatus->sp = APPLY_RATE(bstatus->max_sp, battle_config.restart_sp_rate);
- if( !status->sp ) /* the minimum for the respawn setting is SP:1 */
- status->sp = 1;
+ if( !bstatus->sp ) /* the minimum for the respawn setting is SP:1 */
+ bstatus->sp = 1;
}
-// ----- MISC CALCULATION -----
- status_calc_misc(&sd->bl, status, sd->status.base_level);
+ // ----- MISC CALCULATION -----
+ status->calc_misc(&sd->bl, bstatus, sd->status.base_level);
//Equipment modifiers for misc settings
if(sd->matk_rate < 0)
sd->matk_rate = 0;
if(sd->matk_rate != 100){
- status->matk_max = status->matk_max * sd->matk_rate/100;
- status->matk_min = status->matk_min * sd->matk_rate/100;
+ bstatus->matk_max = bstatus->matk_max * sd->matk_rate/100;
+ bstatus->matk_min = bstatus->matk_min * sd->matk_rate/100;
}
if(sd->hit_rate < 0)
sd->hit_rate = 0;
if(sd->hit_rate != 100)
- status->hit = status->hit * sd->hit_rate/100;
+ bstatus->hit = bstatus->hit * sd->hit_rate/100;
if(sd->flee_rate < 0)
sd->flee_rate = 0;
if(sd->flee_rate != 100)
- status->flee = status->flee * sd->flee_rate/100;
+ bstatus->flee = bstatus->flee * sd->flee_rate/100;
if(sd->def2_rate < 0)
sd->def2_rate = 0;
if(sd->def2_rate != 100)
- status->def2 = status->def2 * sd->def2_rate/100;
+ bstatus->def2 = bstatus->def2 * sd->def2_rate/100;
if(sd->mdef2_rate < 0)
sd->mdef2_rate = 0;
if(sd->mdef2_rate != 100)
- status->mdef2 = status->mdef2 * sd->mdef2_rate/100;
+ bstatus->mdef2 = bstatus->mdef2 * sd->mdef2_rate/100;
if(sd->critical_rate < 0)
sd->critical_rate = 0;
if(sd->critical_rate != 100)
- status->cri = status->cri * sd->critical_rate/100;
+ bstatus->cri = bstatus->cri * sd->critical_rate/100;
if(sd->flee2_rate < 0)
sd->flee2_rate = 0;
if(sd->flee2_rate != 100)
- status->flee2 = status->flee2 * sd->flee2_rate/100;
+ bstatus->flee2 = bstatus->flee2 * sd->flee2_rate/100;
-// ----- HIT CALCULATION -----
+ // ----- HIT CALCULATION -----
// Absolute modifiers from passive skills
- if((skill=pc->checkskill(sd,BS_WEAPONRESEARCH))>0)
- status->hit += skill*2;
- if((skill=pc->checkskill(sd,AC_VULTURE))>0){
#ifndef RENEWAL
- status->hit += skill;
+ if((skill_lv=pc->checkskill(sd,BS_WEAPONRESEARCH))>0) // is this correct in pre? there is already hitrate bonus in battle.c
+ bstatus->hit += skill_lv*2;
+#endif
+ if((skill_lv=pc->checkskill(sd,AC_VULTURE))>0) {
+#ifndef RENEWAL
+ bstatus->hit += skill_lv;
#endif
if(sd->status.weapon == W_BOW)
- status->rhw.range += skill;
- }
- if(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)
- {
- if((skill=pc->checkskill(sd,GS_SINGLEACTION))>0)
- status->hit += 2*skill;
- if((skill=pc->checkskill(sd,GS_SNAKEEYE))>0) {
- status->hit += skill;
- status->rhw.range += skill;
+ bstatus->rhw.range += skill_lv;
+ }
+ if(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE) {
+ if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0)
+ bstatus->hit += 2*skill_lv;
+ if((skill_lv=pc->checkskill(sd,GS_SNAKEEYE))>0) {
+ bstatus->hit += skill_lv;
+ bstatus->rhw.range += skill_lv;
}
}
+ if( (sd->status.weapon == W_1HAXE || sd->status.weapon == W_2HAXE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0 )
+ bstatus->hit += 3*skill_lv;
+ if((sd->status.weapon == W_MACE || sd->status.weapon == W_2HMACE) && ((skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0))
+ bstatus->hit += 2*skill_lv;
-// ----- FLEE CALCULATION -----
+ // ----- FLEE CALCULATION -----
// Absolute modifiers from passive skills
- if((skill=pc->checkskill(sd,TF_MISS))>0)
- status->flee += skill*(sd->class_&JOBL_2 && (sd->class_&MAPID_BASEMASK) == MAPID_THIEF? 4 : 3);
- if((skill=pc->checkskill(sd,MO_DODGE))>0)
- status->flee += (skill*3)>>1;
-// ----- EQUIPMENT-DEF CALCULATION -----
+ if((skill_lv=pc->checkskill(sd,TF_MISS))>0)
+ bstatus->flee += skill_lv*(sd->class_&JOBL_2 && (sd->class_&MAPID_BASEMASK) == MAPID_THIEF? 4 : 3);
+ if((skill_lv=pc->checkskill(sd,MO_DODGE))>0)
+ bstatus->flee += (skill_lv*3)>>1;
+ // ----- EQUIPMENT-DEF CALCULATION -----
// Apply relative modifiers from equipment
if(sd->def_rate < 0)
sd->def_rate = 0;
if(sd->def_rate != 100) {
- i = status->def * sd->def_rate/100;
- status->def = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX);
+ i = bstatus->def * sd->def_rate/100;
+ bstatus->def = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX);
}
+ if( pc_ismadogear(sd) && (skill_lv = pc->checkskill(sd,NC_MAINFRAME)) > 0 )
+ bstatus->def += 20 + 20 * skill_lv;
+
#ifndef RENEWAL
- if (!battle_config.weapon_defense_type && status->def > battle_config.max_def)
- {
- status->def2 += battle_config.over_def_bonus*(status->def -battle_config.max_def);
- status->def = (unsigned char)battle_config.max_def;
+ if (!battle_config.weapon_defense_type && bstatus->def > battle_config.max_def) {
+ bstatus->def2 += battle_config.over_def_bonus*(bstatus->def -battle_config.max_def);
+ bstatus->def = (unsigned char)battle_config.max_def;
}
#endif
-// ----- EQUIPMENT-MDEF CALCULATION -----
+ // ----- EQUIPMENT-MDEF CALCULATION -----
// Apply relative modifiers from equipment
if(sd->mdef_rate < 0)
sd->mdef_rate = 0;
if(sd->mdef_rate != 100) {
- i = status->mdef * sd->mdef_rate/100;
- status->mdef = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX);
+ i = bstatus->mdef * sd->mdef_rate/100;
+ bstatus->mdef = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX);
}
#ifndef RENEWAL
- if (!battle_config.magic_defense_type && status->mdef > battle_config.max_def)
- {
- status->mdef2 += battle_config.over_def_bonus*(status->mdef -battle_config.max_def);
- status->mdef = (signed char)battle_config.max_def;
+ if (!battle_config.magic_defense_type && bstatus->mdef > battle_config.max_def) {
+ bstatus->mdef2 += battle_config.over_def_bonus*(bstatus->mdef -battle_config.max_def);
+ bstatus->mdef = (signed char)battle_config.max_def;
}
#endif
-// ----- ASPD CALCULATION -----
-// Unlike other stats, ASPD rate modifiers from skills/SCs/items/etc are first all added together, then the final modifier is applied
+ // ----- ASPD CALCULATION -----
+ // Unlike other stats, ASPD rate modifiers from skills/SCs/items/etc are first all added together, then the final modifier is applied
// Basic ASPD value
- i = status_base_amotion_pc(sd,status);
- status->amotion = cap_value(i,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000);
+ i = status->base_amotion_pc(sd,bstatus);
+ bstatus->amotion = cap_value(i,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000);
// Relative modifiers from passive skills
#ifndef RENEWAL_ASPD
- if((skill=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK)
- status->aspd_rate -= 5*skill;
- if((skill = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd))
- status->aspd_rate -= 30*skill;
- if((skill=pc->checkskill(sd,GS_SINGLEACTION))>0 &&
+ if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK)
+ bstatus->aspd_rate -= 5*skill_lv;
+ if((skill_lv = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd))
+ bstatus->aspd_rate -= 30*skill_lv;
+ if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 &&
(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE))
- status->aspd_rate -= ((skill+1)/2) * 10;
+ bstatus->aspd_rate -= ((skill_lv+1)/2) * 10;
if(pc_isriding(sd))
- status->aspd_rate += 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY);
+ bstatus->aspd_rate += 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY);
else if(pc_isridingdragon(sd))
- status->aspd_rate += 250-50*pc->checkskill(sd,RK_DRAGONTRAINING);
+ bstatus->aspd_rate += 250-50*pc->checkskill(sd,RK_DRAGONTRAINING);
#else // needs more info
- if((skill=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK)
- status->aspd_rate += 5*skill;
- if((skill = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd))
- status->aspd_rate += 30*skill;
- if((skill=pc->checkskill(sd,GS_SINGLEACTION))>0 &&
+ if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK)
+ bstatus->aspd_rate += 5*skill_lv;
+ if((skill_lv = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd))
+ bstatus->aspd_rate += 30*skill_lv;
+ if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 &&
(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE))
- status->aspd_rate += ((skill+1)/2) * 10;
+ bstatus->aspd_rate += ((skill_lv+1)/2) * 10;
if(pc_isriding(sd))
- status->aspd_rate -= 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY);
+ bstatus->aspd_rate -= 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY);
else if(pc_isridingdragon(sd))
- status->aspd_rate -= 250-50*pc->checkskill(sd,RK_DRAGONTRAINING);
+ bstatus->aspd_rate -= 250-50*pc->checkskill(sd,RK_DRAGONTRAINING);
#endif
- status->adelay = 2*status->amotion;
+ bstatus->adelay = 2*bstatus->amotion;
-// ----- DMOTION -----
-//
- i = 800-status->agi*4;
- status->dmotion = cap_value(i, 400, 800);
+ // ----- DMOTION -----
+ //
+ i = 800-bstatus->agi*4;
+ bstatus->dmotion = cap_value(i, 400, 800);
if(battle_config.pc_damage_delay_rate != 100)
- status->dmotion = status->dmotion*battle_config.pc_damage_delay_rate/100;
+ bstatus->dmotion = bstatus->dmotion*battle_config.pc_damage_delay_rate/100;
-// ----- MISC CALCULATIONS -----
+ // ----- MISC CALCULATIONS -----
// Weight
- if((skill=pc->checkskill(sd,MC_INCCARRY))>0)
- sd->max_weight += 2000*skill;
+ if((skill_lv=pc->checkskill(sd,MC_INCCARRY))>0)
+ sd->max_weight += 2000*skill_lv;
if(pc_isriding(sd) && pc->checkskill(sd,KN_RIDING)>0)
sd->max_weight += 10000;
else if(pc_isridingdragon(sd))
sd->max_weight += 5000+2000*pc->checkskill(sd,RK_DRAGONTRAINING);
if(sc->data[SC_KNOWLEDGE])
sd->max_weight += sd->max_weight*sc->data[SC_KNOWLEDGE]->val1/10;
- if((skill=pc->checkskill(sd,ALL_INCCARRY))>0)
- sd->max_weight += 2000*skill;
+ if((skill_lv=pc->checkskill(sd,ALL_INCCARRY))>0)
+ sd->max_weight += 2000*skill_lv;
sd->cart_weight_max = battle_config.max_cart_weight + (pc->checkskill(sd, GN_REMODELING_CART)*5000);
@@ -2991,8 +3102,8 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
sd->regen.state.walk = 0;
// Skill SP cost
- if((skill=pc->checkskill(sd,HP_MANARECHARGE))>0 )
- sd->dsprate -= 4*skill;
+ if((skill_lv=pc->checkskill(sd,HP_MANARECHARGE))>0 )
+ sd->dsprate -= 4*skill_lv;
if(sc->data[SC_SERVICEFORYOU])
sd->dsprate -= sc->data[SC_SERVICEFORYOU]->val3;
@@ -3013,30 +3124,45 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
sd->sprecov_rate = 0;
// Anti-element and anti-race
- if((skill=pc->checkskill(sd,CR_TRUST))>0)
- sd->subele[ELE_HOLY] += skill*5;
- if((skill=pc->checkskill(sd,BS_SKINTEMPER))>0) {
- sd->subele[ELE_NEUTRAL] += skill;
- sd->subele[ELE_FIRE] += skill*4;
- }
- if((skill=pc->checkskill(sd,NC_RESEARCHFE))>0) {
- sd->subele[ELE_EARTH] += skill*10;
- sd->subele[ELE_FIRE] += skill*10;
- }
- if((skill=pc->checkskill(sd,SA_DRAGONOLOGY))>0 ){
- skill = skill*4;
- sd->right_weapon.addrace[RC_DRAGON]+=skill;
- sd->left_weapon.addrace[RC_DRAGON]+=skill;
- sd->magic_addrace[RC_DRAGON]+=skill;
- sd->subrace[RC_DRAGON]+=skill;
- }
-
- if(sc->count){
- if(sc->data[SC_CONCENTRATION]) { //Update the card-bonus data
+ if((skill_lv=pc->checkskill(sd,CR_TRUST))>0)
+ sd->subele[ELE_HOLY] += skill_lv*5;
+ if((skill_lv=pc->checkskill(sd,BS_SKINTEMPER))>0) {
+ sd->subele[ELE_NEUTRAL] += skill_lv;
+ sd->subele[ELE_FIRE] += skill_lv*4;
+ }
+ if((skill_lv=pc->checkskill(sd,NC_RESEARCHFE))>0) {
+ sd->subele[ELE_EARTH] += skill_lv*10;
+ sd->subele[ELE_FIRE] += skill_lv*10;
+ }
+ if((skill_lv=pc->checkskill(sd,SA_DRAGONOLOGY))>0 ) {
+#ifdef RENEWAL
+ skill_lv = skill_lv*2;
+#else
+ skill_lv = skill_lv*4;
+#endif
+ sd->right_weapon.addrace[RC_DRAGON]+=skill_lv;
+ sd->left_weapon.addrace[RC_DRAGON]+=skill_lv;
+ sd->magic_addrace[RC_DRAGON]+=skill_lv;
+ sd->subrace[RC_DRAGON]+=skill_lv;
+ }
+
+ if( (skill_lv = pc->checkskill(sd, AB_EUCHARISTICA)) > 0 ) {
+ sd->right_weapon.addrace[RC_DEMON] += skill_lv;
+ sd->right_weapon.addele[ELE_DARK] += skill_lv;
+ sd->left_weapon.addrace[RC_DEMON] += skill_lv;
+ sd->left_weapon.addele[ELE_DARK] += skill_lv;
+ sd->magic_addrace[RC_DEMON] += skill_lv;
+ sd->magic_addele[ELE_DARK] += skill_lv;
+ sd->subrace[RC_DEMON] += skill_lv;
+ sd->subele[ELE_DARK] += skill_lv;
+ }
+
+ if(sc->count) {
+ if(sc->data[SC_CONCENTRATION]) { //Update the card-bonus data
sc->data[SC_CONCENTRATION]->val3 = sd->param_bonus[1]; //Agi
sc->data[SC_CONCENTRATION]->val4 = sd->param_bonus[4]; //Dex
}
- if(sc->data[SC_SIEGFRIED]){
+ if(sc->data[SC_SIEGFRIED]){
i = sc->data[SC_SIEGFRIED]->val2;
sd->subele[ELE_WATER] += i;
sd->subele[ELE_EARTH] += i;
@@ -3084,6 +3210,8 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
sd->subele[ELE_EARTH] += i;
sd->subele[ELE_FIRE] -= i;
}
+ if( sc->data[SC_MTF_MLEATKED] )
+ sd->subele[ELE_NEUTRAL] += 2;
if( sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3 )
sd->magic_addele[ELE_FIRE] += 25;
if( sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 3 )
@@ -3093,9 +3221,9 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
if( sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3 )
sd->magic_addele[ELE_EARTH] += 25;
}
- status_cpy(&sd->battle_status, status);
+ status_cpy(&sd->battle_status, bstatus);
-// ----- CLIENT-SIDE REFRESH -----
+ // ----- CLIENT-SIDE REFRESH -----
if(!sd->bl.prev) {
//Will update on LoadEndAck
calculating = 0;
@@ -3118,218 +3246,188 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
return 0;
}
-int status_calc_mercenary_(struct mercenary_data *md, bool first)
-{
- struct status_data *status = &md->base_status;
+int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt) {
+ struct status_data *mstatus = &md->base_status;
struct s_mercenary *merc = &md->mercenary;
- if( first )
- {
- memcpy(status, &md->db->status, sizeof(struct status_data));
- status->mode = MD_CANMOVE|MD_CANATTACK;
- status->hp = status->max_hp;
- status->sp = status->max_sp;
+ if( opt&SCO_FIRST ) {
+ memcpy(mstatus, &md->db->status, sizeof(struct status_data));
+ mstatus->mode = MD_CANMOVE|MD_CANATTACK;
+ mstatus->hp = mstatus->max_hp;
+ mstatus->sp = mstatus->max_sp;
md->battle_status.hp = merc->hp;
md->battle_status.sp = merc->sp;
}
- status_calc_misc(&md->bl, status, md->db->lv);
- status_cpy(&md->battle_status, status);
+ status->calc_misc(&md->bl, mstatus, md->db->lv);
+ status_cpy(&md->battle_status, mstatus);
return 0;
}
-int status_calc_homunculus_(struct homun_data *hd, bool first)
-{
- struct status_data *status = &hd->base_status;
+int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) {
+ struct status_data *hstatus = &hd->base_status;
struct s_homunculus *hom = &hd->homunculus;
- int skill;
+ int skill_lv;
int amotion;
- status->str = hom->str / 10;
- status->agi = hom->agi / 10;
- status->vit = hom->vit / 10;
- status->dex = hom->dex / 10;
- status->int_ = hom->int_ / 10;
- status->luk = hom->luk / 10;
+ hstatus->str = hom->str / 10;
+ hstatus->agi = hom->agi / 10;
+ hstatus->vit = hom->vit / 10;
+ hstatus->dex = hom->dex / 10;
+ hstatus->int_ = hom->int_ / 10;
+ hstatus->luk = hom->luk / 10;
- if (first) { //[orn]
+ if ( opt&SCO_FIRST ) { //[orn]
const struct s_homunculus_db *db = hd->homunculusDB;
- status->def_ele = db->element;
- status->ele_lv = 1;
- status->race = db->race;
- status->size = (hom->class_ == db->evo_class)?db->evo_size:db->base_size;
- status->rhw.range = 1 + status->size;
- status->mode = MD_CANMOVE|MD_CANATTACK;
- status->speed = DEFAULT_WALK_SPEED;
+ hstatus->def_ele = db->element;
+ hstatus->ele_lv = 1;
+ hstatus->race = db->race;
+ hstatus->size = (hom->class_ == db->evo_class)?db->evo_size:db->base_size;
+ hstatus->rhw.range = 1 + hstatus->size;
+ hstatus->mode = MD_CANMOVE|MD_CANATTACK;
+ hstatus->speed = DEFAULT_WALK_SPEED;
if (battle_config.hom_setting&0x8 && hd->master)
- status->speed = status_get_speed(&hd->master->bl);
+ hstatus->speed = status->get_speed(&hd->master->bl);
- status->hp = 1;
- status->sp = 1;
+ hstatus->hp = 1;
+ hstatus->sp = 1;
}
- skill = hom->level/10 + status->vit/5;
- status->def = cap_value(skill, 0, 99);
+ skill_lv = hom->level/10 + hstatus->vit/5;
+ hstatus->def = cap_value(skill_lv, 0, 99);
- skill = hom->level/10 + status->int_/5;
- status->mdef = cap_value(skill, 0, 99);
+ skill_lv = hom->level/10 + hstatus->int_/5;
+ hstatus->mdef = cap_value(skill_lv, 0, 99);
- status->max_hp = hom->max_hp ;
- status->max_sp = hom->max_sp ;
+ hstatus->max_hp = hom->max_hp;
+ hstatus->max_sp = hom->max_sp;
homun->calc_skilltree(hd, 0);
- if((skill=homun->checkskill(hd,HAMI_SKIN)) > 0)
- status->def += skill * 4;
+ if((skill_lv=homun->checkskill(hd,HAMI_SKIN)) > 0)
+ hstatus->def += skill_lv * 4;
- if((skill = homun->checkskill(hd,HVAN_INSTRUCT)) > 0) {
- status->int_ += 1 +skill/2 +skill/4 +skill/5;
- status->str += 1 +skill/3 +skill/3 +skill/4;
+ if((skill_lv = homun->checkskill(hd,HVAN_INSTRUCT)) > 0) {
+ hstatus->int_ += 1 +skill_lv/2 +skill_lv/4 +skill_lv/5;
+ hstatus->str += 1 +skill_lv/3 +skill_lv/3 +skill_lv/4;
}
- if((skill=homun->checkskill(hd,HAMI_SKIN)) > 0)
- status->max_hp += skill * 2 * status->max_hp / 100;
+ if((skill_lv=homun->checkskill(hd,HAMI_SKIN)) > 0)
+ hstatus->max_hp += skill_lv * 2 * hstatus->max_hp / 100;
- if((skill = homun->checkskill(hd,HLIF_BRAIN)) > 0)
- status->max_sp += (1 +skill/2 -skill/4 +skill/5) * status->max_sp / 100 ;
+ if((skill_lv = homun->checkskill(hd,HLIF_BRAIN)) > 0)
+ hstatus->max_sp += (1 +skill_lv/2 -skill_lv/4 +skill_lv/5) * hstatus->max_sp / 100;
- if (first) {
- hd->battle_status.hp = hom->hp ;
- hd->battle_status.sp = hom->sp ;
+ if ( opt&SCO_FIRST ) {
+ hd->battle_status.hp = hom->hp;
+ hd->battle_status.sp = hom->sp;
}
- status->rhw.atk = status->dex;
- status->rhw.atk2 = status->str + hom->level;
+ hstatus->rhw.atk = hstatus->dex;
+ hstatus->rhw.atk2 = hstatus->str + hom->level;
- status->aspd_rate = 1000;
+ hstatus->aspd_rate = 1000;
- amotion = (1000 -4*status->agi -status->dex) * hd->homunculusDB->baseASPD/1000;
- status->amotion = cap_value(amotion,battle_config.max_aspd,2000);
- status->adelay = status->amotion; //It seems adelay = amotion for Homunculus.
+ amotion = (1000 -4*hstatus->agi -hstatus->dex) * hd->homunculusDB->baseASPD/1000;
+ hstatus->amotion = cap_value(amotion,battle_config.max_aspd,2000);
+ hstatus->adelay = hstatus->amotion; //It seems adelay = amotion for Homunculus.
- status_calc_misc(&hd->bl, status, hom->level);
+ status->calc_misc(&hd->bl, hstatus, hom->level);
#ifdef RENEWAL
- status->matk_max = status->matk_min;
+ hstatus->matk_max = hstatus->matk_min;
#endif
- status_cpy(&hd->battle_status, status);
+ status_cpy(&hd->battle_status, hstatus);
return 1;
}
-int status_calc_elemental_(struct elemental_data *ed, bool first) {
- struct status_data *status = &ed->base_status;
+int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt) {
+ struct status_data *estatus = &ed->base_status;
struct s_elemental *ele = &ed->elemental;
struct map_session_data *sd = ed->master;
if( !sd )
return 0;
- if( first ) {
- memcpy(status, &ed->db->status, sizeof(struct status_data));
+ if( opt&SCO_FIRST ) {
+ memcpy(estatus, &ed->db->status, sizeof(struct status_data));
if( !ele->mode )
- status->mode = EL_MODE_PASSIVE;
+ estatus->mode = EL_MODE_PASSIVE;
else
- status->mode = ele->mode;
+ estatus->mode = ele->mode;
- status_calc_misc(&ed->bl, status, 0);
+ status->calc_misc(&ed->bl, estatus, 0);
- status->max_hp = ele->max_hp;
- status->max_sp = ele->max_sp;
- status->hp = ele->hp;
- status->sp = ele->sp;
- status->rhw.atk = ele->atk;
- status->rhw.atk2 = ele->atk2;
+ estatus->max_hp = ele->max_hp;
+ estatus->max_sp = ele->max_sp;
+ estatus->hp = ele->hp;
+ estatus->sp = ele->sp;
+ estatus->rhw.atk = ele->atk;
+ estatus->rhw.atk2 = ele->atk2;
- status->matk_min += ele->matk;
- status->def += ele->def;
- status->mdef += ele->mdef;
- status->flee = ele->flee;
- status->hit = ele->hit;
+ estatus->matk_min += ele->matk;
+ estatus->def += ele->def;
+ estatus->mdef += ele->mdef;
+ estatus->flee = ele->flee;
+ estatus->hit = ele->hit;
- memcpy(&ed->battle_status,status,sizeof(struct status_data));
+ memcpy(&ed->battle_status,estatus,sizeof(struct status_data));
} else {
- status_calc_misc(&ed->bl, status, 0);
- status_cpy(&ed->battle_status, status);
+ status->calc_misc(&ed->bl, estatus, 0);
+ status_cpy(&ed->battle_status, estatus);
}
return 0;
}
-int status_calc_npc_(struct npc_data *nd, bool first) {
- struct status_data *status = &nd->status;
+int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) {
+ struct status_data *nstatus = &nd->status;
if (!nd)
return 0;
- if (first) {
- status->hp = 1;
- status->sp = 1;
- status->max_hp = 1;
- status->max_sp = 1;
+ if ( opt&SCO_FIRST ) {
+ nstatus->hp = 1;
+ nstatus->sp = 1;
+ nstatus->max_hp = 1;
+ nstatus->max_sp = 1;
- status->def_ele = ELE_NEUTRAL;
- status->ele_lv = 1;
- status->race = RC_DEMIHUMAN;
- status->size = nd->size;
- status->rhw.range = 1 + status->size;
- status->mode = (MD_CANMOVE|MD_CANATTACK);
- status->speed = nd->speed;
+ nstatus->def_ele = ELE_NEUTRAL;
+ nstatus->ele_lv = 1;
+ nstatus->race = RC_DEMIHUMAN;
+ nstatus->size = nd->size;
+ nstatus->rhw.range = 1 + nstatus->size;
+ nstatus->mode = (MD_CANMOVE|MD_CANATTACK);
+ nstatus->speed = nd->speed;
}
- status->str = nd->stat_point;
- status->agi = nd->stat_point;
- status->vit = nd->stat_point;
- status->int_= nd->stat_point;
- status->dex = nd->stat_point;
- status->luk = nd->stat_point;
+ nstatus->str = nd->stat_point;
+ nstatus->agi = nd->stat_point;
+ nstatus->vit = nd->stat_point;
+ nstatus->int_= nd->stat_point;
+ nstatus->dex = nd->stat_point;
+ nstatus->luk = nd->stat_point;
- status_calc_misc(&nd->bl, status, nd->level);
- status_cpy(&nd->status, status);
+ status->calc_misc(&nd->bl, nstatus, nd->level);
+ status_cpy(&nd->status, nstatus);
return 0;
}
-static unsigned short status_calc_str(struct block_list *,struct status_change *,int);
-static unsigned short status_calc_agi(struct block_list *,struct status_change *,int);
-static unsigned short status_calc_vit(struct block_list *,struct status_change *,int);
-static unsigned short status_calc_int(struct block_list *,struct status_change *,int);
-static unsigned short status_calc_dex(struct block_list *,struct status_change *,int);
-static unsigned short status_calc_luk(struct block_list *,struct status_change *,int);
-static unsigned short status_calc_batk(struct block_list *,struct status_change *,int,bool);
-static unsigned short status_calc_watk(struct block_list *,struct status_change *,int,bool);
-static unsigned short status_calc_matk(struct block_list *,struct status_change *,int,bool);
-static signed short status_calc_hit(struct block_list *,struct status_change *,int,bool);
-static signed short status_calc_critical(struct block_list *,struct status_change *,int,bool);
-static signed short status_calc_flee(struct block_list *,struct status_change *,int,bool);
-static signed short status_calc_flee2(struct block_list *,struct status_change *,int,bool);
-static unsigned short status_calc_speed(struct block_list *,struct status_change *,int);
-static short status_calc_aspd_rate(struct block_list *,struct status_change *,int);
-static unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion);
-#ifdef RENEWAL_ASPD
-static short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag);
-#endif
-static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int);
-static unsigned int status_calc_maxhp(struct block_list *,struct status_change *, uint64);
-static unsigned int status_calc_maxsp(struct block_list *,struct status_change *,unsigned int);
-static unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element);
-static unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv);
-static unsigned short status_calc_mode(struct block_list *bl, struct status_change *sc, int mode);
-#ifdef RENEWAL
-static unsigned short status_calc_ematk(struct block_list *,struct status_change *,int);
-#endif
//Calculates base regen values.
-void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen)
-{
+void status_calc_regen(struct block_list *bl, struct status_data *st, struct regen_data *regen) {
struct map_session_data *sd;
- int val, skill, reg_flag;
+ int val, skill_lv, reg_flag;
+ nullpo_retv(bl);
+ nullpo_retv(st);
if( !(bl->type&BL_REGEN) || !regen )
return;
sd = BL_CAST(BL_PC,bl);
- val = 1 + (status->vit/5) + (status->max_hp/200);
+ val = 1 + (st->vit/5) + (st->max_hp/200);
if( sd && sd->hprecov_rate != 100 )
val = val*sd->hprecov_rate/100;
@@ -3338,38 +3436,36 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct
regen->hp = cap_value(val, reg_flag, SHRT_MAX);
- val = 1 + (status->int_/6) + (status->max_sp/100);
- if( status->int_ >= 120 )
- val += ((status->int_-120)>>1) + 4;
+ val = 1 + (st->int_/6) + (st->max_sp/100);
+ if( st->int_ >= 120 )
+ val += ((st->int_-120)>>1) + 4;
if( sd && sd->sprecov_rate != 100 )
val = val*sd->sprecov_rate/100;
regen->sp = cap_value(val, reg_flag, SHRT_MAX);
- if( sd )
- {
+ if( sd ) {
struct regen_data_sub *sregen;
- if( (skill=pc->checkskill(sd,HP_MEDITATIO)) > 0 )
- {
- val = regen->sp*(100+3*skill)/100;
+ if( (skill_lv=pc->checkskill(sd,HP_MEDITATIO)) > 0 ) {
+ val = regen->sp*(100+3*skill_lv)/100;
regen->sp = cap_value(val, 1, SHRT_MAX);
}
//Only players have skill/sitting skill regen for now.
sregen = regen->sregen;
val = 0;
- if( (skill=pc->checkskill(sd,SM_RECOVERY)) > 0 )
- val += skill*5 + skill*status->max_hp/500;
+ if( (skill_lv=pc->checkskill(sd,SM_RECOVERY)) > 0 )
+ val += skill_lv*5 + skill_lv*st->max_hp/500;
sregen->hp = cap_value(val, 0, SHRT_MAX);
val = 0;
- if( (skill=pc->checkskill(sd,MG_SRECOVERY)) > 0 )
- val += skill*3 + skill*status->max_sp/500;
- if( (skill=pc->checkskill(sd,NJ_NINPOU)) > 0 )
- val += skill*3 + skill*status->max_sp/500;
- if( (skill=pc->checkskill(sd,WM_LESSON)) > 0 )
- val += 3 + 3 * skill;
+ if( (skill_lv=pc->checkskill(sd,MG_SRECOVERY)) > 0 )
+ val += skill_lv*3 + skill_lv*st->max_sp/500;
+ if( (skill_lv=pc->checkskill(sd,NJ_NINPOU)) > 0 )
+ val += skill_lv*3 + skill_lv*st->max_sp/500;
+ if( (skill_lv=pc->checkskill(sd,WM_LESSON)) > 0 )
+ val += skill_lv*3 + skill_lv*st->max_sp/500;
sregen->sp = cap_value(val, 0, SHRT_MAX);
@@ -3377,46 +3473,45 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct
sregen = regen->ssregen;
val = 0;
- if( (skill=pc->checkskill(sd,MO_SPIRITSRECOVERY)) > 0 )
- val += skill*4 + skill*status->max_hp/500;
+ if( (skill_lv=pc->checkskill(sd,MO_SPIRITSRECOVERY)) > 0 )
+ val += skill_lv*4 + skill_lv*st->max_hp/500;
- if( (skill=pc->checkskill(sd,TK_HPTIME)) > 0 && sd->state.rest )
- val += skill*30 + skill*status->max_hp/500;
+ if( (skill_lv=pc->checkskill(sd,TK_HPTIME)) > 0 && sd->state.rest )
+ val += skill_lv*30 + skill_lv*st->max_hp/500;
sregen->hp = cap_value(val, 0, SHRT_MAX);
val = 0;
- if( (skill=pc->checkskill(sd,TK_SPTIME)) > 0 && sd->state.rest )
- {
- val += skill*3 + skill*status->max_sp/500;
- if ((skill=pc->checkskill(sd,SL_KAINA)) > 0) //Power up Enjoyable Rest
- val += (30+10*skill)*val/100;
+ if( (skill_lv=pc->checkskill(sd,TK_SPTIME)) > 0 && sd->state.rest ) {
+ val += skill_lv*3 + skill_lv*st->max_sp/500;
+ if ((skill_lv=pc->checkskill(sd,SL_KAINA)) > 0) //Power up Enjoyable Rest
+ val += (30+10*skill_lv)*val/100;
}
- if( (skill=pc->checkskill(sd,MO_SPIRITSRECOVERY)) > 0 )
- val += skill*2 + skill*status->max_sp/500;
+ if( (skill_lv=pc->checkskill(sd,MO_SPIRITSRECOVERY)) > 0 )
+ val += skill_lv*2 + skill_lv*st->max_sp/500;
sregen->sp = cap_value(val, 0, SHRT_MAX);
}
if( bl->type == BL_HOM ) {
struct homun_data *hd = (TBL_HOM*)bl;
- if( (skill = homun->checkskill(hd,HAMI_SKIN)) > 0 ) {
- val = regen->hp*(100+5*skill)/100;
+ if( (skill_lv = homun->checkskill(hd,HAMI_SKIN)) > 0 ) {
+ val = regen->hp*(100+5*skill_lv)/100;
regen->hp = cap_value(val, 1, SHRT_MAX);
}
- if( (skill = homun->checkskill(hd,HLIF_BRAIN)) > 0 ) {
- val = regen->sp*(100+3*skill)/100;
+ if( (skill_lv = homun->checkskill(hd,HLIF_BRAIN)) > 0 ) {
+ val = regen->sp*(100+3*skill_lv)/100;
regen->sp = cap_value(val, 1, SHRT_MAX);
}
} else if( bl->type == BL_MER ) {
- val = (status->max_hp * status->vit / 10000 + 1) * 6;
+ val = (st->max_hp * st->vit / 10000 + 1) * 6;
regen->hp = cap_value(val, 1, SHRT_MAX);
- val = (status->max_sp * (status->int_ + 10) / 750) + 1;
+ val = (st->max_sp * (st->int_ + 10) / 750) + 1;
regen->sp = cap_value(val, 1, SHRT_MAX);
} else if( bl->type == BL_ELEM ) {
- val = (status->max_hp * status->vit / 10000 + 1) * 6;
+ val = (st->max_hp * st->vit / 10000 + 1) * 6;
regen->hp = cap_value(val, 1, SHRT_MAX);
- val = (status->max_sp * (status->int_ + 10) / 750) + 1;
+ val = (st->max_sp * (st->int_ + 10) / 750) + 1;
regen->sp = cap_value(val, 1, SHRT_MAX);
}
}
@@ -3451,87 +3546,84 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
if (!sc || !sc->count)
return;
- if (
- (sc->data[SC_POISON] && !sc->data[SC_SLOWPOISON])
- || (sc->data[SC_DPOISON] && !sc->data[SC_SLOWPOISON])
- || sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]
- || sc->data[SC_TRICKDEAD]
- || sc->data[SC_BLOODING]
- || sc->data[SC_MAGICMUSHROOM]
- || sc->data[SC_RAISINGDRAGON]
- || sc->data[SC_SATURDAY_NIGHT_FEVER]
+ if ((sc->data[SC_POISON] && !sc->data[SC_SLOWPOISON])
+ || (sc->data[SC_DPOISON] && !sc->data[SC_SLOWPOISON])
+ || sc->data[SC_BERSERK]
+ || sc->data[SC_TRICKDEAD]
+ || sc->data[SC_BLOODING]
+ || sc->data[SC_MAGICMUSHROOM]
+ || sc->data[SC_RAISINGDRAGON]
+ || sc->data[SC_SATURDAY_NIGHT_FEVER]
) //No regen
regen->flag = 0;
- if (
- sc->data[SC_DANCING] || sc->data[SC_OBLIVIONCURSE] || sc->data[SC_MAXIMIZEPOWER] || sc->data[SC_REBOUND]
- || (
- (bl->type == BL_PC && ((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK &&
- (sc->data[SC_EXTREMITYFIST] || (sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SOULLINK] || sc->data[SC_SOULLINK]->val2 != SL_MONK)))
- )
- ) //No natural SP regen
- regen->flag &=~RGN_SP;
+ if ( sc->data[SC_DANCING] || sc->data[SC_OBLIVIONCURSE] || sc->data[SC_MAXIMIZEPOWER] || sc->data[SC_REBOUND]
+ || ( bl->type == BL_PC && (((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK
+ && (sc->data[SC_EXTREMITYFIST] || (sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SOULLINK] || sc->data[SC_SOULLINK]->val2 != SL_MONK)))
+ )
+ ) {
+ regen->flag &=~RGN_SP; //No natural SP regen
+ }
- if(
- sc->data[SC_TENSIONRELAX]
- ) {
+ if (sc->data[SC_TENSIONRELAX]) {
regen->rate.hp += 2;
if (regen->sregen)
regen->sregen->rate.hp += 3;
}
- if (sc->data[SC_MAGNIFICAT])
- {
+ if (sc->data[SC_MAGNIFICAT]) {
regen->rate.hp += 1;
regen->rate.sp += 1;
}
- if (sc->data[SC_GDSKILL_REGENERATION])
- {
+ if (sc->data[SC_GDSKILL_REGENERATION]) {
const struct status_change_entry *sce = sc->data[SC_GDSKILL_REGENERATION];
- if (!sce->val4)
- {
+ if (!sce->val4) {
regen->rate.hp += sce->val2;
regen->rate.sp += sce->val3;
} else
regen->flag&=~sce->val4; //Remove regen as specified by val4
}
- if(sc->data[SC_GENTLETOUCH_REVITALIZE]){
+ if(sc->data[SC_GENTLETOUCH_REVITALIZE]) {
regen->hp = cap_value(regen->hp*sc->data[SC_GENTLETOUCH_REVITALIZE]->val3/100, 1, SHRT_MAX);
regen->state.walk= 1;
}
- if ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1) //if insignia lvl 1
- || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1)
- || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1)
- || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1))
- regen->rate.hp *= 2;
-
+ if ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1) //if insignia lvl 1
+ || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1)
+ || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1)
+ || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1))
+ regen->rate.hp *= 2;
+ if( sc->data[SC_VITALITYACTIVATION] )
+ regen->flag &=~RGN_SP;
+ if(sc->data[SC_EXTRACT_WHITE_POTION_Z])
+ regen->rate.hp += regen->rate.hp * sc->data[SC_EXTRACT_WHITE_POTION_Z]->val1/100;
+ if(sc->data[SC_VITATA_500])
+ regen->rate.sp += regen->rate.sp * sc->data[SC_VITATA_500]->val1/100;
}
/// Recalculates parts of an object's battle status according to the specified flags.
/// @param flag bitfield of values from enum scb_flag
-void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
-{
- const struct status_data *b_status = status_get_base_status(bl);
- struct status_data *status = status_get_status_data(bl);
- struct status_change *sc = status_get_sc(bl);
+void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
+ const struct status_data *bst = status->get_base_status(bl);
+ struct status_data *st = status->get_status_data(bl);
+ struct status_change *sc = status->get_sc(bl);
TBL_PC *sd = BL_CAST(BL_PC,bl);
int temp;
- if (!b_status || !status)
+ if (!bst || !st)
return;
if((!(bl->type&BL_REGEN)) && (!sc || !sc->count)) { //No difference.
- status_cpy(status, b_status);
+ status_cpy(st, bst);
return;
}
if(flag&SCB_STR) {
- status->str = status_calc_str(bl, sc, b_status->str);
+ st->str = status->calc_str(bl, sc, bst->str);
flag|=SCB_BATK;
if( bl->type&BL_HOM )
flag |= SCB_WATK;
}
if(flag&SCB_AGI) {
- status->agi = status_calc_agi(bl, sc, b_status->agi);
+ st->agi = status->calc_agi(bl, sc, bst->agi);
flag|=SCB_FLEE
#ifdef RENEWAL
|SCB_DEF2
@@ -3542,7 +3634,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
}
if(flag&SCB_VIT) {
- status->vit = status_calc_vit(bl, sc, b_status->vit);
+ st->vit = status->calc_vit(bl, sc, bst->vit);
flag|=SCB_DEF2|SCB_MDEF2;
if( bl->type&(BL_PC|BL_HOM|BL_MER|BL_ELEM) )
flag |= SCB_MAXHP;
@@ -3551,7 +3643,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
}
if(flag&SCB_INT) {
- status->int_ = status_calc_int(bl, sc, b_status->int_);
+ st->int_ = status->calc_int(bl, sc, bst->int_);
flag|=SCB_MATK|SCB_MDEF2;
if( bl->type&(BL_PC|BL_HOM|BL_MER|BL_ELEM) )
flag |= SCB_MAXSP;
@@ -3560,7 +3652,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
}
if(flag&SCB_DEX) {
- status->dex = status_calc_dex(bl, sc, b_status->dex);
+ st->dex = status->calc_dex(bl, sc, bst->dex);
flag|=SCB_BATK|SCB_HIT
#ifdef RENEWAL
|SCB_MATK|SCB_MDEF2
@@ -3573,7 +3665,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
}
if(flag&SCB_LUK) {
- status->luk = status_calc_luk(bl, sc, b_status->luk);
+ st->luk = status->calc_luk(bl, sc, bst->luk);
flag|=SCB_BATK|SCB_CRI|SCB_FLEE2
#ifdef RENEWAL
|SCB_MATK|SCB_HIT|SCB_FLEE
@@ -3581,500 +3673,486 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
;
}
- if(flag&SCB_BATK && b_status->batk) {
- status->batk = status_base_atk(bl,status);
- temp = b_status->batk - status_base_atk(bl,b_status);
- if (temp)
- {
- temp += status->batk;
- status->batk = cap_value(temp, 0, USHRT_MAX);
+ if(flag&SCB_BATK && bst->batk) {
+ st->batk = status->base_atk(bl,st);
+ temp = bst->batk - status->base_atk(bl,bst);
+ if (temp) {
+ temp += st->batk;
+ st->batk = cap_value(temp, 0, USHRT_MAX);
}
- status->batk = status_calc_batk(bl, sc, status->batk, true);
+ st->batk = status->calc_batk(bl, sc, st->batk, true);
}
- if(flag&SCB_WATK) {
- status->rhw.atk = status_calc_watk(bl, sc, b_status->rhw.atk, true);
+ if(flag&SCB_WATK) {
+ st->rhw.atk = status->calc_watk(bl, sc, bst->rhw.atk, true);
if (!sd) //Should not affect weapon refine bonus
- status->rhw.atk2 = status_calc_watk(bl, sc, b_status->rhw.atk2, true);
+ st->rhw.atk2 = status->calc_watk(bl, sc, bst->rhw.atk2, true);
- if(b_status->lhw.atk) {
+ if(bst->lhw.atk) {
if (sd) {
sd->state.lr_flag = 1;
- status->lhw.atk = status_calc_watk(bl, sc, b_status->lhw.atk, true);
+ st->lhw.atk = status->calc_watk(bl, sc, bst->lhw.atk, true);
sd->state.lr_flag = 0;
} else {
- status->lhw.atk = status_calc_watk(bl, sc, b_status->lhw.atk, true);
- status->lhw.atk2 = status_calc_watk(bl, sc, b_status->lhw.atk2, true);
+ st->lhw.atk = status->calc_watk(bl, sc, bst->lhw.atk, true);
+ st->lhw.atk2 = status->calc_watk(bl, sc, bst->lhw.atk2, true);
}
}
- if( bl->type&BL_HOM )
- {
- status->rhw.atk += (status->dex - b_status->dex);
- status->rhw.atk2 += (status->str - b_status->str);
- if( status->rhw.atk2 < status->rhw.atk )
- status->rhw.atk2 = status->rhw.atk;
+ if( bl->type&BL_HOM ) {
+ st->rhw.atk += (st->dex - bst->dex);
+ st->rhw.atk2 += (st->str - bst->str);
+ if( st->rhw.atk2 < st->rhw.atk )
+ st->rhw.atk2 = st->rhw.atk;
}
}
if(flag&SCB_HIT) {
- if (status->dex == b_status->dex
+ if (st->dex == bst->dex
#ifdef RENEWAL
- && status->luk == b_status->luk
+ && st->luk == bst->luk
#endif
)
- status->hit = status_calc_hit(bl, sc, b_status->hit, true);
+ st->hit = status->calc_hit(bl, sc, bst->hit, true);
else
- status->hit = status_calc_hit(bl, sc, b_status->hit + (status->dex - b_status->dex)
+ st->hit = status->calc_hit(bl, sc, bst->hit + (st->dex - bst->dex)
#ifdef RENEWAL
- + (status->luk/3 - b_status->luk/3)
+ + (st->luk/3 - bst->luk/3)
#endif
- , true);
+ , true);
}
if(flag&SCB_FLEE) {
- if (status->agi == b_status->agi
+ if (st->agi == bst->agi
#ifdef RENEWAL
- && status->luk == b_status->luk
+ && st->luk == bst->luk
#endif
)
- status->flee = status_calc_flee(bl, sc, b_status->flee, true);
+ st->flee = status->calc_flee(bl, sc, bst->flee, true);
else
- status->flee = status_calc_flee(bl, sc, b_status->flee +(status->agi - b_status->agi)
+ st->flee = status->calc_flee(bl, sc, bst->flee +(st->agi - bst->agi)
#ifdef RENEWAL
- + (status->luk/5 - b_status->luk/5)
+ + (st->luk/5 - bst->luk/5)
#endif
, true);
}
- if(flag&SCB_DEF)
- {
- status->def = status_calc_def(bl, sc, b_status->def, true);
+ if(flag&SCB_DEF) {
+ st->def = status->calc_def(bl, sc, bst->def, true);
if( bl->type&BL_HOM )
- status->def += (status->vit/5 - b_status->vit/5);
+ st->def += (st->vit/5 - bst->vit/5);
}
if(flag&SCB_DEF2) {
- if (status->vit == b_status->vit
+ if (st->vit == bst->vit
#ifdef RENEWAL
- && status->agi == b_status->agi
+ && st->agi == bst->agi
#endif
)
- status->def2 = status_calc_def2(bl, sc, b_status->def2, true);
+ st->def2 = status->calc_def2(bl, sc, bst->def2, true);
else
- status->def2 = status_calc_def2(bl, sc, b_status->def2
+ st->def2 = status->calc_def2(bl, sc, bst->def2
#ifdef RENEWAL
- + (int)( ((float)status->vit/2 - (float)b_status->vit/2) + ((float)status->agi/5 - (float)b_status->agi/5) )
+ + (int)( ((float)st->vit/2 - (float)bst->vit/2) + ((float)st->agi/5 - (float)bst->agi/5) )
#else
- + (status->vit - b_status->vit)
+ + (st->vit - bst->vit)
#endif
- , true);
+ , true);
}
- if(flag&SCB_MDEF)
- {
- status->mdef = status_calc_mdef(bl, sc, b_status->mdef, true);
+ if(flag&SCB_MDEF) {
+ st->mdef = status->calc_mdef(bl, sc, bst->mdef, true);
if( bl->type&BL_HOM )
- status->mdef += (status->int_/5 - b_status->int_/5);
+ st->mdef += (st->int_/5 - bst->int_/5);
}
if(flag&SCB_MDEF2) {
- if (status->int_ == b_status->int_ && status->vit == b_status->vit
+ if (st->int_ == bst->int_ && st->vit == bst->vit
#ifdef RENEWAL
- && status->dex == b_status->dex
+ && st->dex == bst->dex
#endif
)
- status->mdef2 = status_calc_mdef2(bl, sc, b_status->mdef2, true);
+ st->mdef2 = status->calc_mdef2(bl, sc, bst->mdef2, true);
else
- status->mdef2 = status_calc_mdef2(bl, sc, b_status->mdef2 +(status->int_ - b_status->int_)
+ st->mdef2 = status->calc_mdef2(bl, sc, bst->mdef2 +(st->int_ - bst->int_)
#ifdef RENEWAL
- + (int)( ((float)status->dex/5 - (float)b_status->dex/5) + ((float)status->vit/5 - (float)b_status->vit/5) )
+ + (int)( ((float)st->dex/5 - (float)bst->dex/5) + ((float)st->vit/5 - (float)bst->vit/5) )
#else
- + ((status->vit - b_status->vit)>>1)
+ + ((st->vit - bst->vit)>>1)
#endif
, true);
}
if(flag&SCB_SPEED) {
- struct unit_data *ud = unit_bl2ud(bl);
- status->speed = status_calc_speed(bl, sc, b_status->speed);
+ struct unit_data *ud = unit->bl2ud(bl);
+
+ st->speed = status->calc_speed(bl, sc, bst->speed);
//Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER
//because if you step on something while walking, the moment this
//piece of code triggers the walk-timer is set on INVALID_TIMER) [Skotlex]
- if (ud)
+ if (ud)
ud->state.change_walk_target = ud->state.speed_changed = 1;
- if( bl->type&BL_PC && status->speed < battle_config.max_walk_speed )
- status->speed = battle_config.max_walk_speed;
+ if( bl->type&BL_PC && !(sd && sd->state.permanent_speed) && st->speed < battle_config.max_walk_speed )
+ st->speed = battle_config.max_walk_speed;
if( bl->type&BL_HOM && battle_config.hom_setting&0x8 && ((TBL_HOM*)bl)->master)
- status->speed = status_get_speed(&((TBL_HOM*)bl)->master->bl);
-
-
+ st->speed = status->get_speed(&((TBL_HOM*)bl)->master->bl);
}
- if(flag&SCB_CRI && b_status->cri) {
- if (status->luk == b_status->luk)
- status->cri = status_calc_critical(bl, sc, b_status->cri, true);
+ if(flag&SCB_CRI && bst->cri) {
+ if (st->luk == bst->luk)
+ st->cri = status->calc_critical(bl, sc, bst->cri, true);
else
- status->cri = status_calc_critical(bl, sc, b_status->cri + 3*(status->luk - b_status->luk), true);
+ st->cri = status->calc_critical(bl, sc, bst->cri + 3*(st->luk - bst->luk), true);
/**
- * after status_calc_critical so the bonus is applied despite if you have or not a sc bugreport:5240
- **/
+ * after status_calc_critical so the bonus is applied despite if you have or not a sc bugreport:5240
+ **/
if( bl->type == BL_PC && ((TBL_PC*)bl)->status.weapon == W_KATAR )
- status->cri <<= 1;
+ st->cri <<= 1;
}
- if(flag&SCB_FLEE2 && b_status->flee2) {
- if (status->luk == b_status->luk)
- status->flee2 = status_calc_flee2(bl, sc, b_status->flee2, true);
+ if(flag&SCB_FLEE2 && bst->flee2) {
+ if (st->luk == bst->luk)
+ st->flee2 = status->calc_flee2(bl, sc, bst->flee2, true);
else
- status->flee2 = status_calc_flee2(bl, sc, b_status->flee2 +(status->luk - b_status->luk), true);
+ st->flee2 = status->calc_flee2(bl, sc, bst->flee2 +(st->luk - bst->luk), true);
}
if(flag&SCB_ATK_ELE) {
- status->rhw.ele = status_calc_attack_element(bl, sc, b_status->rhw.ele);
+ st->rhw.ele = status->calc_attack_element(bl, sc, bst->rhw.ele);
if (sd) sd->state.lr_flag = 1;
- status->lhw.ele = status_calc_attack_element(bl, sc, b_status->lhw.ele);
+ st->lhw.ele = status->calc_attack_element(bl, sc, bst->lhw.ele);
if (sd) sd->state.lr_flag = 0;
}
if(flag&SCB_DEF_ELE) {
- status->def_ele = status_calc_element(bl, sc, b_status->def_ele);
- status->ele_lv = status_calc_element_lv(bl, sc, b_status->ele_lv);
+ st->def_ele = status->calc_element(bl, sc, bst->def_ele);
+ st->ele_lv = status->calc_element_lv(bl, sc, bst->ele_lv);
}
- if(flag&SCB_MODE)
- {
- status->mode = status_calc_mode(bl, sc, b_status->mode);
+ if(flag&SCB_MODE) {
+ st->mode = status->calc_mode(bl, sc, bst->mode);
//Since mode changed, reset their state.
- if (!(status->mode&MD_CANATTACK))
- unit_stop_attack(bl);
- if (!(status->mode&MD_CANMOVE))
- unit_stop_walking(bl,1);
+ if (!(st->mode&MD_CANATTACK))
+ unit->stop_attack(bl);
+ if (!(st->mode&MD_CANMOVE))
+ unit->stop_walking(bl,1);
}
-// No status changes alter these yet.
-// if(flag&SCB_SIZE)
-// if(flag&SCB_RACE)
-// if(flag&SCB_RANGE)
+ // No status changes alter these yet.
+ // if(flag&SCB_SIZE)
+ // if(flag&SCB_RACE)
+ // if(flag&SCB_RANGE)
if(flag&SCB_MAXHP) {
- if( bl->type&BL_PC )
- {
- status->max_hp = status_base_pc_maxhp(sd,status);
- status->max_hp += b_status->max_hp - sd->status.max_hp;
+ if( bl->type&BL_PC ) {
+ st->max_hp = status->base_pc_maxhp(sd,st);
+ st->max_hp += bst->max_hp - sd->status.max_hp;
- status->max_hp = status_calc_maxhp(bl, sc, status->max_hp);
+ st->max_hp = status->calc_maxhp(bl, sc, st->max_hp);
- if( status->max_hp > (unsigned int)battle_config.max_hp )
- status->max_hp = (unsigned int)battle_config.max_hp;
- }
- else
- {
- status->max_hp = status_calc_maxhp(bl, sc, b_status->max_hp);
+ if( st->max_hp > (unsigned int)battle_config.max_hp )
+ st->max_hp = (unsigned int)battle_config.max_hp;
+ } else {
+ st->max_hp = status->calc_maxhp(bl, sc, bst->max_hp);
}
- if( status->hp > status->max_hp ) //FIXME: Should perhaps a status_zap should be issued?
- {
- status->hp = status->max_hp;
+ if( st->hp > st->max_hp ) {
+ //FIXME: Should perhaps a status_zap should be issued?
+ st->hp = st->max_hp;
if( sd ) clif->updatestatus(sd,SP_HP);
}
}
if(flag&SCB_MAXSP) {
- if( bl->type&BL_PC )
- {
- status->max_sp = status_base_pc_maxsp(sd,status);
- status->max_sp += b_status->max_sp - sd->status.max_sp;
+ if( bl->type&BL_PC ) {
+ st->max_sp = status->base_pc_maxsp(sd,st);
+ st->max_sp += bst->max_sp - sd->status.max_sp;
- status->max_sp = status_calc_maxsp(&sd->bl, &sd->sc, status->max_sp);
+ st->max_sp = status->calc_maxsp(&sd->bl, &sd->sc, st->max_sp);
- if( status->max_sp > (unsigned int)battle_config.max_sp )
- status->max_sp = (unsigned int)battle_config.max_sp;
- }
- else
- {
- status->max_sp = status_calc_maxsp(bl, sc, b_status->max_sp);
+ if( st->max_sp > (unsigned int)battle_config.max_sp )
+ st->max_sp = (unsigned int)battle_config.max_sp;
+ } else {
+ st->max_sp = status->calc_maxsp(bl, sc, bst->max_sp);
}
- if( status->sp > status->max_sp )
- {
- status->sp = status->max_sp;
+ if( st->sp > st->max_sp ) {
+ st->sp = st->max_sp;
if( sd ) clif->updatestatus(sd,SP_SP);
}
}
- if(flag&SCB_MATK) {
- status_get_matk(bl, 0);
+ if(flag&SCB_MATK) {
+ status->update_matk(bl);
}
if(flag&SCB_ASPD) {
int amotion;
- if( bl->type&BL_PC )
- {
- amotion = status_base_amotion_pc(sd,status);
+ if( bl->type&BL_PC ) {
+ amotion = status->base_amotion_pc(sd,st);
#ifndef RENEWAL_ASPD
- status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate);
+ st->aspd_rate = status->calc_aspd_rate(bl, sc, bst->aspd_rate);
- if(status->aspd_rate != 1000)
- amotion = amotion*status->aspd_rate/1000;
+ if(st->aspd_rate != 1000)
+ amotion = amotion*st->aspd_rate/1000;
#else
// aspd = baseaspd + floor(sqrt((agi^2/2) + (dex^2/5))/4 + (potskillbonus*agi/200))
- amotion -= (int)(sqrt( (pow(status->agi, 2) / 2) + (pow(status->dex, 2) / 5) ) / 4 + ((float)status_calc_aspd(bl, sc, 1) * status->agi / 200)) * 10;
+ amotion -= (int)(sqrt( (pow(st->agi, 2) / 2) + (pow(st->dex, 2) / 5) ) / 4 + ((float)status->calc_aspd(bl, sc, 1) * st->agi / 200)) * 10;
- if( (status_calc_aspd(bl, sc, 2) + status->aspd_rate2) != 0 ) // RE ASPD percertage modifier
+ if( (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) != 0 ) // RE ASPD percertage modifier
amotion -= (( amotion - ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd) )
- * (status_calc_aspd(bl, sc, 2) + status->aspd_rate2) / 10 + 5) / 10;
+ * (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) / 10 + 5) / 10;
- if(status->aspd_rate != 1000) // absolute percentage modifier
- amotion = ( 200 - (200-amotion/10) * status->aspd_rate / 1000 ) * 10;
+ if(st->aspd_rate != 1000) // absolute percentage modifier
+ amotion = ( 200 - (200-amotion/10) * st->aspd_rate / 1000 ) * 10;
#endif
- amotion = status_calc_fix_aspd(bl, sc, amotion);
- status->amotion = cap_value(amotion,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000);
+ amotion = status->calc_fix_aspd(bl, sc, amotion);
+ st->amotion = cap_value(amotion,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000);
- status->adelay = 2*status->amotion;
- }
- else
- if( bl->type&BL_HOM )
- {
- amotion = (1000 -4*status->agi -status->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD/1000;
- status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate);
+ st->adelay = 2*st->amotion;
+ } else if( bl->type&BL_HOM ) {
+ amotion = (1000 - 4*st->agi - st->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD/1000;
+ st->aspd_rate = status->calc_aspd_rate(bl, sc, bst->aspd_rate);
- if(status->aspd_rate != 1000)
- amotion = amotion*status->aspd_rate/1000;
+ if(st->aspd_rate != 1000)
+ amotion = amotion*st->aspd_rate/1000;
- amotion = status_calc_fix_aspd(bl, sc, amotion);
- status->amotion = cap_value(amotion,battle_config.max_aspd,2000);
+ amotion = status->calc_fix_aspd(bl, sc, amotion);
+ st->amotion = cap_value(amotion,battle_config.max_aspd,2000);
- status->adelay = status->amotion;
- }
- else // mercenary and mobs
- {
- amotion = b_status->amotion;
- status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate);
+ st->adelay = st->amotion;
+ } else { // mercenary and mobs
+ amotion = bst->amotion;
+ st->aspd_rate = status->calc_aspd_rate(bl, sc, bst->aspd_rate);
- if(status->aspd_rate != 1000)
- amotion = amotion*status->aspd_rate/1000;
+ if(st->aspd_rate != 1000)
+ amotion = amotion*st->aspd_rate/1000;
- amotion = status_calc_fix_aspd(bl, sc, amotion);
- status->amotion = cap_value(amotion, battle_config.monster_max_aspd, 2000);
+ amotion = status->calc_fix_aspd(bl, sc, amotion);
+ st->amotion = cap_value(amotion, battle_config.monster_max_aspd, 2000);
- temp = b_status->adelay*status->aspd_rate/1000;
- status->adelay = cap_value(temp, battle_config.monster_max_aspd*2, 4000);
+ temp = bst->adelay*st->aspd_rate/1000;
+ st->adelay = cap_value(temp, battle_config.monster_max_aspd*2, 4000);
}
}
if(flag&SCB_DSPD) {
int dmotion;
- if( bl->type&BL_PC )
- {
- if (b_status->agi == status->agi)
- status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion);
+ if( bl->type&BL_PC ) {
+ if (bst->agi == st->agi)
+ st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion);
else {
- dmotion = 800-status->agi*4;
- status->dmotion = cap_value(dmotion, 400, 800);
+ dmotion = 800-st->agi*4;
+ st->dmotion = cap_value(dmotion, 400, 800);
if(battle_config.pc_damage_delay_rate != 100)
- status->dmotion = status->dmotion*battle_config.pc_damage_delay_rate/100;
- //It's safe to ignore b_status->dmotion since no bonus affects it.
- status->dmotion = status_calc_dmotion(bl, sc, status->dmotion);
+ st->dmotion = st->dmotion*battle_config.pc_damage_delay_rate/100;
+ //It's safe to ignore bst->dmotion since no bonus affects it.
+ st->dmotion = status->calc_dmotion(bl, sc, st->dmotion);
}
- }
- else
- if( bl->type&BL_HOM )
- {
- dmotion = 800-status->agi*4;
- status->dmotion = cap_value(dmotion, 400, 800);
- status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion);
- }
- else // mercenary and mobs
- {
- status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion);
+ } else if( bl->type&BL_HOM ) {
+ dmotion = 800-st->agi*4;
+ st->dmotion = cap_value(dmotion, 400, 800);
+ st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion);
+ } else { // mercenary and mobs
+ st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion);
}
}
if(flag&(SCB_VIT|SCB_MAXHP|SCB_INT|SCB_MAXSP) && bl->type&BL_REGEN)
- status_calc_regen(bl, status, status_get_regen_data(bl));
+ status->calc_regen(bl, st, status->get_regen_data(bl));
if(flag&SCB_REGEN && bl->type&BL_REGEN)
- status_calc_regen_rate(bl, status_get_regen_data(bl), sc);
+ status->calc_regen_rate(bl, status->get_regen_data(bl), sc);
}
/// Recalculates parts of an object's base status and battle status according to the specified flags.
/// Also sends updates to the client wherever applicable.
/// @param flag bitfield of values from enum scb_flag
/// @param first if true, will cause status_calc_* functions to run their base status initialization code
-void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first)
-{
- struct status_data b_status; // previous battle status
- struct status_data* status; // pointer to current battle status
+void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt) {
+ struct status_data bst; // previous battle status
+ struct status_data *st; // pointer to current battle status
+ if( bl->type == BL_PC && ((TBL_PC*)bl)->delayed_damage != 0 ) {
+ if( opt&SCO_FORCE )
+ ((TBL_PC*)bl)->state.hold_recalc = 0;/* clear and move on */
+ else {
+ ((TBL_PC*)bl)->state.hold_recalc = 1;/* flag and stop */
+ return;
+ }
+ }
+
// remember previous values
- status = status_get_status_data(bl);
- memcpy(&b_status, status, sizeof(struct status_data));
+ st = status->get_status_data(bl);
+ memcpy(&bst, st, sizeof(struct status_data));
if( flag&SCB_BASE ) {// calculate the object's base status too
switch( bl->type ) {
- case BL_PC: status_calc_pc_(BL_CAST(BL_PC,bl), first); break;
- case BL_MOB: status_calc_mob_(BL_CAST(BL_MOB,bl), first); break;
- case BL_PET: status_calc_pet_(BL_CAST(BL_PET,bl), first); break;
- case BL_HOM: status_calc_homunculus_(BL_CAST(BL_HOM,bl), first); break;
- case BL_MER: status_calc_mercenary_(BL_CAST(BL_MER,bl), first); break;
- case BL_ELEM: status_calc_elemental_(BL_CAST(BL_ELEM,bl), first); break;
- case BL_NPC: status_calc_npc_(BL_CAST(BL_NPC,bl), first); break;
+ case BL_PC: status->calc_pc_(BL_CAST(BL_PC,bl), opt); break;
+ case BL_MOB: status->calc_mob_(BL_CAST(BL_MOB,bl), opt); break;
+ case BL_PET: status->calc_pet_(BL_CAST(BL_PET,bl), opt); break;
+ case BL_HOM: status->calc_homunculus_(BL_CAST(BL_HOM,bl), opt); break;
+ case BL_MER: status->calc_mercenary_(BL_CAST(BL_MER,bl), opt); break;
+ case BL_ELEM: status->calc_elemental_(BL_CAST(BL_ELEM,bl), opt); break;
+ case BL_NPC: status->calc_npc_(BL_CAST(BL_NPC,bl), opt); break;
}
}
if( bl->type == BL_PET )
return; // pets are not affected by statuses
- if( first && bl->type == BL_MOB )
+ if( opt&SCO_FIRST && bl->type == BL_MOB )
return; // assume there will be no statuses active
- status_calc_bl_main(bl, flag);
+ status->calc_bl_main(bl, flag);
- if( first && bl->type == BL_HOM )
+ if( opt&SCO_FIRST && bl->type == BL_HOM )
return; // client update handled by caller
// compare against new values and send client updates
- if( bl->type == BL_PC )
- {
+ if( bl->type == BL_PC ) {
TBL_PC* sd = BL_CAST(BL_PC, bl);
- if(b_status.str != status->str)
+ if(bst.str != st->str)
clif->updatestatus(sd,SP_STR);
- if(b_status.agi != status->agi)
+ if(bst.agi != st->agi)
clif->updatestatus(sd,SP_AGI);
- if(b_status.vit != status->vit)
+ if(bst.vit != st->vit)
clif->updatestatus(sd,SP_VIT);
- if(b_status.int_ != status->int_)
+ if(bst.int_ != st->int_)
clif->updatestatus(sd,SP_INT);
- if(b_status.dex != status->dex)
+ if(bst.dex != st->dex)
clif->updatestatus(sd,SP_DEX);
- if(b_status.luk != status->luk)
+ if(bst.luk != st->luk)
clif->updatestatus(sd,SP_LUK);
- if(b_status.hit != status->hit)
+ if(bst.hit != st->hit)
clif->updatestatus(sd,SP_HIT);
- if(b_status.flee != status->flee)
+ if(bst.flee != st->flee)
clif->updatestatus(sd,SP_FLEE1);
- if(b_status.amotion != status->amotion)
+ if(bst.amotion != st->amotion)
clif->updatestatus(sd,SP_ASPD);
- if(b_status.speed != status->speed)
+ if(bst.speed != st->speed)
clif->updatestatus(sd,SP_SPEED);
- if(b_status.batk != status->batk
+ if(bst.batk != st->batk
#ifndef RENEWAL
- || b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk
+ || bst.rhw.atk != st->rhw.atk || bst.lhw.atk != st->lhw.atk
#endif
- )
+ )
clif->updatestatus(sd,SP_ATK1);
- if(b_status.def != status->def){
+ if(bst.def != st->def) {
clif->updatestatus(sd,SP_DEF1);
#ifdef RENEWAL
clif->updatestatus(sd,SP_DEF2);
#endif
}
- if(b_status.rhw.atk2 != status->rhw.atk2 || b_status.lhw.atk2 != status->lhw.atk2
+ if(bst.rhw.atk2 != st->rhw.atk2 || bst.lhw.atk2 != st->lhw.atk2
#ifdef RENEWAL
- || b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk
+ || bst.rhw.atk != st->rhw.atk || bst.lhw.atk != st->lhw.atk
#endif
)
clif->updatestatus(sd,SP_ATK2);
- if(b_status.def2 != status->def2){
+ if(bst.def2 != st->def2){
clif->updatestatus(sd,SP_DEF2);
#ifdef RENEWAL
clif->updatestatus(sd,SP_DEF1);
#endif
}
- if(b_status.flee2 != status->flee2)
+ if(bst.flee2 != st->flee2)
clif->updatestatus(sd,SP_FLEE2);
- if(b_status.cri != status->cri)
+ if(bst.cri != st->cri)
clif->updatestatus(sd,SP_CRITICAL);
#ifndef RENEWAL
- if(b_status.matk_max != status->matk_max)
+ if(bst.matk_max != st->matk_max)
clif->updatestatus(sd,SP_MATK1);
- if(b_status.matk_min != status->matk_min)
- clif->updatestatus(sd,SP_MATK2);
+ if(bst.matk_min != st->matk_min)
+ clif->updatestatus(sd,SP_MATK2);
#else
- if(b_status.matk_max != status->matk_max || b_status.matk_min != status->matk_min){
+ if(bst.matk_max != st->matk_max || bst.matk_min != st->matk_min){
clif->updatestatus(sd,SP_MATK2);
clif->updatestatus(sd,SP_MATK1);
}
#endif
- if(b_status.mdef != status->mdef){
+ if(bst.mdef != st->mdef) {
clif->updatestatus(sd,SP_MDEF1);
#ifdef RENEWAL
clif->updatestatus(sd,SP_MDEF2);
#endif
}
- if(b_status.mdef2 != status->mdef2){
+ if(bst.mdef2 != st->mdef2) {
clif->updatestatus(sd,SP_MDEF2);
#ifdef RENEWAL
clif->updatestatus(sd,SP_MDEF1);
#endif
}
- if(b_status.rhw.range != status->rhw.range)
+ if(bst.rhw.range != st->rhw.range)
clif->updatestatus(sd,SP_ATTACKRANGE);
- if(b_status.max_hp != status->max_hp)
+ if(bst.max_hp != st->max_hp)
clif->updatestatus(sd,SP_MAXHP);
- if(b_status.max_sp != status->max_sp)
+ if(bst.max_sp != st->max_sp)
clif->updatestatus(sd,SP_MAXSP);
- if(b_status.hp != status->hp)
+ if(bst.hp != st->hp)
clif->updatestatus(sd,SP_HP);
- if(b_status.sp != status->sp)
+ if(bst.sp != st->sp)
clif->updatestatus(sd,SP_SP);
+#ifdef RENEWAL
+ if(bst.equip_atk != st->equip_atk)
+ clif->updatestatus(sd,SP_ATK2);
+#endif
} else if( bl->type == BL_HOM ) {
TBL_HOM* hd = BL_CAST(BL_HOM, bl);
- if( hd->master && memcmp(&b_status, status, sizeof(struct status_data)) != 0 )
+ if( hd->master && memcmp(&bst, st, sizeof(struct status_data)) != 0 )
clif->hominfo(hd->master,hd,0);
} else if( bl->type == BL_MER ) {
TBL_MER* md = BL_CAST(BL_MER, bl);
- if( b_status.rhw.atk != status->rhw.atk || b_status.rhw.atk2 != status->rhw.atk2 )
+ if( bst.rhw.atk != st->rhw.atk || bst.rhw.atk2 != st->rhw.atk2 )
clif->mercenary_updatestatus(md->master, SP_ATK1);
- if( b_status.matk_max != status->matk_max )
+ if( bst.matk_max != st->matk_max )
clif->mercenary_updatestatus(md->master, SP_MATK1);
- if( b_status.hit != status->hit )
+ if( bst.hit != st->hit )
clif->mercenary_updatestatus(md->master, SP_HIT);
- if( b_status.cri != status->cri )
+ if( bst.cri != st->cri )
clif->mercenary_updatestatus(md->master, SP_CRITICAL);
- if( b_status.def != status->def )
+ if( bst.def != st->def )
clif->mercenary_updatestatus(md->master, SP_DEF1);
- if( b_status.mdef != status->mdef )
+ if( bst.mdef != st->mdef )
clif->mercenary_updatestatus(md->master, SP_MDEF1);
- if( b_status.flee != status->flee )
+ if( bst.flee != st->flee )
clif->mercenary_updatestatus(md->master, SP_MERCFLEE);
- if( b_status.amotion != status->amotion )
+ if( bst.amotion != st->amotion )
clif->mercenary_updatestatus(md->master, SP_ASPD);
- if( b_status.max_hp != status->max_hp )
+ if( bst.max_hp != st->max_hp )
clif->mercenary_updatestatus(md->master, SP_MAXHP);
- if( b_status.max_sp != status->max_sp )
+ if( bst.max_sp != st->max_sp )
clif->mercenary_updatestatus(md->master, SP_MAXSP);
- if( b_status.hp != status->hp )
+ if( bst.hp != st->hp )
clif->mercenary_updatestatus(md->master, SP_HP);
- if( b_status.sp != status->sp )
+ if( bst.sp != st->sp )
clif->mercenary_updatestatus(md->master, SP_SP);
} else if( bl->type == BL_ELEM ) {
TBL_ELEM* ed = BL_CAST(BL_ELEM, bl);
- if( b_status.max_hp != status->max_hp )
+ if( bst.max_hp != st->max_hp )
clif->elemental_updatestatus(ed->master, SP_MAXHP);
- if( b_status.max_sp != status->max_sp )
+ if( bst.max_sp != st->max_sp )
clif->elemental_updatestatus(ed->master, SP_MAXSP);
- if( b_status.hp != status->hp )
+ if( bst.hp != st->hp )
clif->elemental_updatestatus(ed->master, SP_HP);
- if( b_status.sp != status->sp )
+ if( bst.sp != st->sp )
clif->mercenary_updatestatus(ed->master, SP_SP);
}
}
/*==========================================
- * Apply shared stat mods from status changes [DracoRPG]
- *------------------------------------------*/
-static unsigned short status_calc_str(struct block_list *bl, struct status_change *sc, int str)
+* Apply shared stat mods from status changes [DracoRPG]
+*------------------------------------------*/
+unsigned short status_calc_str(struct block_list *bl, struct status_change *sc, int str)
{
if(!sc || !sc->count)
return cap_value(str,0,USHRT_MAX);
@@ -4083,6 +4161,8 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang
str -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(str,0,USHRT_MAX);
}
+ if(sc->data[SC_BEYOND_OF_WARCRY])
+ str += sc->data[SC_BEYOND_OF_WARCRY]->val3;
if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && str < 50)
return 50;
if(sc->data[SC_INCALLSTATUS])
@@ -4131,7 +4211,7 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang
return (unsigned short)cap_value(str,0,USHRT_MAX);
}
-static unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc, int agi)
+unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc, int agi)
{
if(!sc || !sc->count)
return cap_value(agi,0,USHRT_MAX);
@@ -4189,7 +4269,7 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang
return (unsigned short)cap_value(agi,0,USHRT_MAX);
}
-static unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc, int vit)
+unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc, int vit)
{
if(!sc || !sc->count)
return cap_value(vit,0,USHRT_MAX);
@@ -4237,7 +4317,7 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang
return (unsigned short)cap_value(vit,0,USHRT_MAX);
}
-static unsigned short status_calc_int(struct block_list *bl, struct status_change *sc, int int_)
+unsigned short status_calc_int(struct block_list *bl, struct status_change *sc, int int_)
{
if(!sc || !sc->count)
return cap_value(int_,0,USHRT_MAX);
@@ -4246,6 +4326,8 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang
int_ -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(int_,0,USHRT_MAX);
}
+ if(sc->data[SC_MELODYOFSINK])
+ int_ -= sc->data[SC_MELODYOFSINK]->val3;
if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && int_ < 50)
return 50;
if(sc->data[SC_INCALLSTATUS])
@@ -4275,7 +4357,7 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang
if(sc->data[SC_MARIONETTE])
int_ += ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF;
if(sc->data[SC_MANDRAGORA])
- int_ -= 5 + 5 * sc->data[SC_MANDRAGORA]->val1;
+ int_ -= 4 * sc->data[SC_MANDRAGORA]->val1;
if(sc->data[SC_COCKTAIL_WARG_BLOOD])
int_ += sc->data[SC_COCKTAIL_WARG_BLOOD]->val1;
if(sc->data[SC_INSPIRATION])
@@ -4285,17 +4367,19 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang
if(sc->data[SC_KYOUGAKU])
int_ -= sc->data[SC_KYOUGAKU]->val2;
- if(sc->data[SC_NOEQUIPHELM])
- int_ -= int_ * sc->data[SC_NOEQUIPHELM]->val2/100;
- if(sc->data[SC__STRIPACCESSARY])
- int_ -= int_ * sc->data[SC__STRIPACCESSARY]->val2 / 100;
+ if(bl->type != BL_PC){
+ if(sc->data[SC_NOEQUIPHELM])
+ int_ -= int_ * sc->data[SC_NOEQUIPHELM]->val2/100;
+ if(sc->data[SC__STRIPACCESSARY])
+ int_ -= int_ * sc->data[SC__STRIPACCESSARY]->val2 / 100;
+ }
if(sc->data[SC_FULL_THROTTLE])
int_ += int_ * 20 / 100;
return (unsigned short)cap_value(int_,0,USHRT_MAX);
}
-static unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc, int dex)
+unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc, int dex)
{
if(!sc || !sc->count)
return cap_value(dex,0,USHRT_MAX);
@@ -4347,7 +4431,7 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang
if(sc->data[SC_MARSHOFABYSS])
dex -= dex * sc->data[SC_MARSHOFABYSS]->val2 / 100;
- if(sc->data[SC__STRIPACCESSARY])
+ if(sc->data[SC__STRIPACCESSARY] && bl->type != BL_PC)
dex -= dex * sc->data[SC__STRIPACCESSARY]->val2 / 100;
if(sc->data[SC_FULL_THROTTLE])
dex += dex * 20 / 100;
@@ -4355,7 +4439,7 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang
return (unsigned short)cap_value(dex,0,USHRT_MAX);
}
-static unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc, int luk)
+unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc, int luk)
{
if(!sc || !sc->count)
return cap_value(luk,0,USHRT_MAX);
@@ -4395,7 +4479,7 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang
if(sc->data[SC_LAUDARAMUS])
luk += 4 + sc->data[SC_LAUDARAMUS]->val1;
- if(sc->data[SC__STRIPACCESSARY])
+ if(sc->data[SC__STRIPACCESSARY] && bl->type != BL_PC)
luk -= luk * sc->data[SC__STRIPACCESSARY]->val2 / 100;
if(sc->data[SC_BANANA_BOMB])
luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100;
@@ -4404,38 +4488,38 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang
return (unsigned short)cap_value(luk,0,USHRT_MAX);
}
-
-static unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, int batk, bool viewable)
+unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, int batk, bool viewable)
{
if(!sc || !sc->count)
return cap_value(batk,0,USHRT_MAX);
-
+
if( !viewable ){
/* some statuses that are hidden in the status window */
+ if(sc->data[SC_PLUSATTACKPOWER])
+ batk += sc->data[SC_PLUSATTACKPOWER]->val1;
return (unsigned short)cap_value(batk,0,USHRT_MAX);
}
-
+#ifndef RENEWAL
if(sc->data[SC_PLUSATTACKPOWER])
batk += sc->data[SC_PLUSATTACKPOWER]->val1;
- if(sc->data[SC_BATKFOOD])
- batk += sc->data[SC_BATKFOOD]->val1;
- if(sc->data[SC_GS_GATLINGFEVER])
- batk += sc->data[SC_GS_GATLINGFEVER]->val3;
if(sc->data[SC_GS_MADNESSCANCEL])
batk += 100;
+ if(sc->data[SC_GS_GATLINGFEVER])
+ batk += sc->data[SC_GS_GATLINGFEVER]->val3;
+#endif
+ if(sc->data[SC_BATKFOOD])
+ batk += sc->data[SC_BATKFOOD]->val1;
if(sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2)
batk += 50;
if(bl->type == BL_ELEM
- && ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1)
- || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1)
- || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1)
- || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1))
- )
+ && ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1)
+ || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1)
+ || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1)
+ || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1))
+ )
batk += batk / 5;
if(sc->data[SC_FULL_SWING_K])
batk += sc->data[SC_FULL_SWING_K]->val1;
- if(sc->data[SC_ODINS_POWER])
- batk += 70;
if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){
if(status_get_element(bl) == ELE_WATER) //water type
batk /= 2;
@@ -4463,45 +4547,40 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan
batk -= batk * 25/100;
if( sc->data[SC_ZANGETSU] )
batk += sc->data[SC_ZANGETSU]->val2;
-//Curse shouldn't effect on this? <- Curse OR Bleeding??
-// if(sc->data[SC_BLOODING])
-// batk -= batk * 25/100;
+ //Curse shouldn't effect on this? <- Curse OR Bleeding??
+ // if(sc->data[SC_BLOODING])
+ // batk -= batk * 25/100;
if(sc->data[SC_HLIF_FLEET])
batk += batk * sc->data[SC_HLIF_FLEET]->val3/100;
if(sc->data[SC__ENERVATION])
batk -= batk * sc->data[SC__ENERVATION]->val2 / 100;
- if(sc->data[SC_RUSH_WINDMILL])
- batk += batk * sc->data[SC_RUSH_WINDMILL]->val2/100;
if(sc->data[SC_SATURDAY_NIGHT_FEVER])
batk += 100 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1;
- if(sc->data[SC_MELODYOFSINK])
- batk -= batk * sc->data[SC_MELODYOFSINK]->val3/100;
- if(sc->data[SC_BEYOND_OF_WARCRY])
- batk += batk * sc->data[SC_BEYOND_OF_WARCRY]->val3/100;
return (unsigned short)cap_value(batk,0,USHRT_MAX);
}
-static unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, int watk, bool viewable)
+unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, int watk, bool viewable)
{
if(!sc || !sc->count)
return cap_value(watk,0,USHRT_MAX);
if( !viewable ){
/* some statuses that are hidden in the status window */
- if(sc->data[SC_STRIKING])
- watk += sc->data[SC_STRIKING]->val2;
+ if( sc->data[SC_WATER_BARRIER] )
+ watk -= sc->data[SC_WATER_BARRIER]->val3;
if(sc->data[SC_GENTLETOUCH_CHANGE] && sc->data[SC_GENTLETOUCH_CHANGE]->val2)
watk += sc->data[SC_GENTLETOUCH_CHANGE]->val2;
return (unsigned short)cap_value(watk,0,USHRT_MAX);
}
-
+#ifndef RENEWAL
if(sc->data[SC_IMPOSITIO])
watk += sc->data[SC_IMPOSITIO]->val2;
- if(sc->data[SC_WATKFOOD])
- watk += sc->data[SC_WATKFOOD]->val1;
if(sc->data[SC_DRUMBATTLE])
watk += sc->data[SC_DRUMBATTLE]->val2;
+#endif
+ if(sc->data[SC_WATKFOOD])
+ watk += sc->data[SC_WATKFOOD]->val1;
if(sc->data[SC_VOLCANO])
watk += sc->data[SC_VOLCANO]->val2;
if(sc->data[SC_MER_ATK])
@@ -4518,27 +4597,20 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
watk += sc->data[SC_TROPIC_OPTION]->val2;
if( sc->data[SC_HEATER_OPTION] )
watk += sc->data[SC_HEATER_OPTION]->val2;
- if( sc->data[SC_WATER_BARRIER] )
- watk -= sc->data[SC_WATER_BARRIER]->val3;
if( sc->data[SC_PYROTECHNIC_OPTION] )
watk += sc->data[SC_PYROTECHNIC_OPTION]->val2;
+
+#ifndef RENEWAL
if(sc->data[SC_NIBELUNGEN]) {
if (bl->type != BL_PC)
watk += sc->data[SC_NIBELUNGEN]->val2;
else {
- #ifndef RENEWAL
TBL_PC *sd = (TBL_PC*)bl;
int index = sd->equip_index[sd->state.lr_flag?EQI_HAND_L:EQI_HAND_R];
if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4)
- #endif
watk += sc->data[SC_NIBELUNGEN]->val2;
}
}
-#ifndef RENEWAL
- if(sc->data[SC_STRIKING])
- watk += sc->data[SC_STRIKING]->val2;
- if(sc->data[SC_GENTLETOUCH_CHANGE] && sc->data[SC_GENTLETOUCH_CHANGE]->val2)
- watk += sc->data[SC_GENTLETOUCH_CHANGE]->val2;
if(sc->data[SC_LKCONCENTRATION])
watk += watk * sc->data[SC_LKCONCENTRATION]->val2/100;
#endif
@@ -4548,106 +4620,111 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
watk += watk * sc->data[SC_PROVOKE]->val3/100;
if(sc->data[SC_SKE])
watk += watk * 3;
- if(sc->data[SC__ENERVATION])
- watk -= watk * sc->data[SC__ENERVATION]->val2 / 100;
if(sc->data[SC_HLIF_FLEET])
watk += watk * sc->data[SC_HLIF_FLEET]->val3/100;
if(sc->data[SC_CURSE])
watk -= watk * 25/100;
- if(sc->data[SC_NOEQUIPWEAPON])
+ if(sc->data[SC_NOEQUIPWEAPON] && bl->type != BL_PC)
watk -= watk * sc->data[SC_NOEQUIPWEAPON]->val2/100;
if(sc->data[SC__ENERVATION])
watk -= watk * sc->data[SC__ENERVATION]->val2 / 100;
+ if(sc->data[SC_RUSH_WINDMILL])
+ watk += sc->data[SC_RUSH_WINDMILL]->val2;
+ if (sc->data[SC_ODINS_POWER])
+ watk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1;
+ if(sc->data[SC_STRIKING])
+ watk += sc->data[SC_STRIKING]->val2;
if((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2)
- || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2)
- || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2)
- || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2)
- )
+ || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2)
+ || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2)
+ || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2)
+ )
watk += watk / 10;
if( sc && sc->data[SC_TIDAL_WEAPON] )
watk += watk * sc->data[SC_TIDAL_WEAPON]->val2 / 100;
if(sc->data[SC_ANGRIFFS_MODUS])
watk += watk * sc->data[SC_ANGRIFFS_MODUS]->val2/100;
+ if( sc->data[SC_FLASHCOMBO] )
+ watk += sc->data[SC_FLASHCOMBO]->val2;
return (unsigned short)cap_value(watk,0,USHRT_MAX);
}
+unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc, int matk) {
#ifdef RENEWAL
-static unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc, int matk)
-{
- if (!sc || !sc->count)
- return cap_value(matk,0,USHRT_MAX);
- if (sc->data[SC_PLUSMAGICPOWER])
- matk += sc->data[SC_PLUSMAGICPOWER]->val1;
- if (sc->data[SC_MATKFOOD])
- matk += sc->data[SC_MATKFOOD]->val1;
+ if (!sc || !sc->count)
+ return cap_value(matk,0,USHRT_MAX);
+ if (sc->data[SC_PLUSMAGICPOWER])
+ matk += sc->data[SC_PLUSMAGICPOWER]->val1;
+ if (sc->data[SC_MATKFOOD])
+ matk += sc->data[SC_MATKFOOD]->val1;
if(sc->data[SC_MANA_PLUS])
matk += sc->data[SC_MANA_PLUS]->val1;
if(sc->data[SC_AQUAPLAY_OPTION])
matk += sc->data[SC_AQUAPLAY_OPTION]->val2;
if(sc->data[SC_CHILLY_AIR_OPTION])
matk += sc->data[SC_CHILLY_AIR_OPTION]->val2;
- if(sc->data[SC_WATER_BARRIER])
- matk -= sc->data[SC_WATER_BARRIER]->val3;
+ if(sc->data[SC_COOLER_OPTION])
+ matk += sc->data[SC_COOLER_OPTION]->val2;
if(sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3)
matk += 50;
if(sc->data[SC_ODINS_POWER])
matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2
if(sc->data[SC_IZAYOI])
matk += 25 * sc->data[SC_IZAYOI]->val1;
- return (unsigned short)cap_value(matk,0,USHRT_MAX);
-}
+ return (unsigned short)cap_value(matk,0,USHRT_MAX);
+#else
+ return 0;
#endif
-static unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, int matk, bool viewable)
+}
+unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, int matk, bool viewable)
{
if(!sc || !sc->count)
return cap_value(matk,0,USHRT_MAX);
if( !viewable ){
/* some statuses that are hidden in the status window */
+ if (sc->data[SC_MINDBREAKER])
+ matk += matk * sc->data[SC_MINDBREAKER]->val2/100;
return (unsigned short)cap_value(matk,0,USHRT_MAX);
}
#ifndef RENEWAL
// take note fixed value first before % modifiers
- if (sc->data[SC_PLUSMAGICPOWER])
- matk += sc->data[SC_PLUSMAGICPOWER]->val1;
- if (sc->data[SC_MATKFOOD])
- matk += sc->data[SC_MATKFOOD]->val1;
- if (sc->data[SC_MANA_PLUS])
- matk += sc->data[SC_MANA_PLUS]->val1;
- if (sc->data[SC_AQUAPLAY_OPTION])
- matk += sc->data[SC_AQUAPLAY_OPTION]->val2;
- if (sc->data[SC_CHILLY_AIR_OPTION])
- matk += sc->data[SC_CHILLY_AIR_OPTION]->val2;
- if (sc->data[SC_WATER_BARRIER])
- matk -= sc->data[SC_WATER_BARRIER]->val3;
- if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3)
- matk += 50;
- if (sc->data[SC_ODINS_POWER])
- matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2
- if (sc->data[SC_IZAYOI])
- matk += 25 * sc->data[SC_IZAYOI]->val1;
+ if (sc->data[SC_PLUSMAGICPOWER])
+ matk += sc->data[SC_PLUSMAGICPOWER]->val1;
+ if (sc->data[SC_MATKFOOD])
+ matk += sc->data[SC_MATKFOOD]->val1;
+ if (sc->data[SC_MANA_PLUS])
+ matk += sc->data[SC_MANA_PLUS]->val1;
+ if (sc->data[SC_AQUAPLAY_OPTION])
+ matk += sc->data[SC_AQUAPLAY_OPTION]->val2;
+ if (sc->data[SC_CHILLY_AIR_OPTION])
+ matk += sc->data[SC_CHILLY_AIR_OPTION]->val2;
+ if(sc->data[SC_COOLER_OPTION])
+ matk += sc->data[SC_COOLER_OPTION]->val2;
+ if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3)
+ matk += 50;
+ if (sc->data[SC_ODINS_POWER])
+ matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2
+ if (sc->data[SC_IZAYOI])
+ matk += 25 * sc->data[SC_IZAYOI]->val1;
#endif
if( sc->data[SC_ZANGETSU] )
matk += sc->data[SC_ZANGETSU]->val3;
- if (sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4)
- matk += matk * sc->data[SC_MAGICPOWER]->val3/100;
- if (sc->data[SC_MINDBREAKER])
- matk += matk * sc->data[SC_MINDBREAKER]->val2/100;
- if (sc->data[SC_INCMATKRATE])
- matk += matk * sc->data[SC_INCMATKRATE]->val1/100;
- if (sc->data[SC_MOONLIT_SERENADE])
- matk += matk * sc->data[SC_MOONLIT_SERENADE]->val2/100;
- if (sc->data[SC_MELODYOFSINK])
- matk += matk * sc->data[SC_MELODYOFSINK]->val3/100;
- if (sc->data[SC_BEYOND_OF_WARCRY])
- matk -= matk * sc->data[SC_BEYOND_OF_WARCRY]->val3/100;
+ if (sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4)
+ matk += matk * sc->data[SC_MAGICPOWER]->val3/100;
+ if (sc->data[SC_INCMATKRATE])
+ matk += matk * sc->data[SC_INCMATKRATE]->val1/100;
+ if (sc->data[SC_MOONLIT_SERENADE])
+ matk += matk * sc->data[SC_MOONLIT_SERENADE]->val2/100;
+ if (sc->data[SC_MTF_MATK])
+ matk += matk * 25 / 100;
return (unsigned short)cap_value(matk,0,USHRT_MAX);
}
-static signed short status_calc_critical(struct block_list *bl, struct status_change *sc, int critical, bool viewable) {
+signed short status_calc_critical(struct block_list *bl, struct status_change *sc, int critical, bool viewable) {
if(!sc || !sc->count)
return cap_value(critical,10,SHRT_MAX);
@@ -4675,14 +4752,16 @@ static signed short status_calc_critical(struct block_list *bl, struct status_ch
#endif
if(sc->data[SC__INVISIBILITY])
- critical += critical * sc->data[SC__INVISIBILITY]->val3 / 100;
+ critical += sc->data[SC__INVISIBILITY]->val3;
if(sc->data[SC__UNLUCKY])
critical -= critical * sc->data[SC__UNLUCKY]->val2 / 100;
+ if(sc->data[SC_BEYOND_OF_WARCRY])
+ critical += 10 * sc->data[SC_BEYOND_OF_WARCRY]->val3;
return (short)cap_value(critical,10,SHRT_MAX);
}
-static signed short status_calc_hit(struct block_list *bl, struct status_change *sc, int hit, bool viewable)
+signed short status_calc_hit(struct block_list *bl, struct status_change *sc, int hit, bool viewable)
{
if(!sc || !sc->count)
@@ -4690,6 +4769,8 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change
if( !viewable ){
/* some statuses that are hidden in the status window */
+ if(sc->data[SC_MTF_ASPD])
+ hit += 5;
return (short)cap_value(hit,1,SHRT_MAX);
}
@@ -4704,7 +4785,7 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change
if(sc->data[SC_LKCONCENTRATION])
hit += sc->data[SC_LKCONCENTRATION]->val3;
if(sc->data[SC_INSPIRATION])
- hit += 5 * sc->data[SC_INSPIRATION]->val1;
+ hit += 5 * sc->data[SC_INSPIRATION]->val1 + 25;
if(sc->data[SC_GS_ADJUSTMENT])
hit -= 30;
if(sc->data[SC_GS_ACCURACY])
@@ -4722,17 +4803,17 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change
hit -= hit * 20 / 100;
if (sc->data[SC_VOLCANIC_ASH])
hit /= 2;
-
+ if(sc->data[SC_ILLUSIONDOPING])
+ hit -= hit * (5 + sc->data[SC_ILLUSIONDOPING]->val1) / 100; //custom
+
return (short)cap_value(hit,1,SHRT_MAX);
}
-static signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee, bool viewable)
-{
- if( bl->type == BL_PC )
- {
- if( map_flag_gvg(bl->m) )
+signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee, bool viewable) {
+ if( bl->type == BL_PC ) {
+ if( map_flag_gvg2(bl->m) )
flee -= flee * battle_config.gvg_flee_penalty/100;
- else if( map[bl->m].flag.battleground )
+ else if( map->list[bl->m].flag.battleground )
flee -= flee * battle_config.bg_flee_penalty/100;
}
@@ -4760,8 +4841,6 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
flee += 10;
if (sc->data[SC_ANGRIFFS_MODUS])
flee -= sc->data[SC_ANGRIFFS_MODUS]->val3;
- if (sc->data[SC_OVERED_BOOST])
- flee = max(flee,sc->data[SC_OVERED_BOOST]->val2);
if(sc->data[SC_GS_ADJUSTMENT])
flee += 30;
if(sc->data[SC_HLIF_SPEED])
@@ -4785,35 +4864,38 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
flee += flee * sc->data[SC_INCFLEERATE]->val1/100;
if(sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1)
flee -= flee * 50/100;
- if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
+ if (sc->data[SC_BERSERK])
flee -= flee * 50/100;
if(sc->data[SC_BLIND])
flee -= flee * 25/100;
if(sc->data[SC_FEAR])
flee -= flee * 20 / 100;
if(sc->data[SC_PARALYSE])
- flee -= flee * 10 / 100; // 10% Flee reduction
+ flee -= flee / 10; // 10% Flee reduction
if(sc->data[SC_INFRAREDSCAN])
flee -= flee * 30 / 100;
if( sc->data[SC__LAZINESS] )
flee -= flee * sc->data[SC__LAZINESS]->val3 / 100;
if( sc->data[SC_GLOOMYDAY] )
- flee -= flee * sc->data[SC_GLOOMYDAY]->val2 / 100;
+ flee -= flee * ( 20 + 5 * sc->data[SC_GLOOMYDAY]->val1 ) / 100;
if( sc->data[SC_SATURDAY_NIGHT_FEVER] )
flee -= flee * (40 + 10 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1) / 100;
if( sc->data[SC_WIND_STEP_OPTION] )
flee += flee * sc->data[SC_WIND_STEP_OPTION]->val2 / 100;
if( sc->data[SC_ZEPHYR] )
- flee += flee * sc->data[SC_ZEPHYR]->val2 / 100;
+ flee += sc->data[SC_ZEPHYR]->val2;
if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){ //mob
if(status_get_element(bl) == ELE_WATER) //water type
flee /= 2;
}
+
+ if( sc->data[SC_OVERED_BOOST] ) // should be final and unmodifiable by any means
+ flee = sc->data[SC_OVERED_BOOST]->val2;
return (short)cap_value(flee,1,SHRT_MAX);
}
-static signed short status_calc_flee2(struct block_list *bl, struct status_change *sc, int flee2, bool viewable)
+signed short status_calc_flee2(struct block_list *bl, struct status_change *sc, int flee2, bool viewable)
{
if(!sc || !sc->count)
return cap_value(flee2,10,SHRT_MAX);
@@ -4841,12 +4923,20 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
/* some statuses that are hidden in the status window */
if( sc && sc->data[SC_CAMOUFLAGE] )
def -= def * 5 * (10-sc->data[SC_CAMOUFLAGE]->val4) / 100;
+ if( sc->data[SC_OVERED_BOOST] && bl->type == BL_PC )
+ def -= def * 50 / 100;
+ if( sc->data[SC_NEUTRALBARRIER] )
+ def += def * (10 + 5*sc->data[SC_NEUTRALBARRIER]->val1) / 100;
if( sc && sc->data[SC_GENTLETOUCH_REVITALIZE] && sc->data[SC_GENTLETOUCH_REVITALIZE]->val4 )
def += 2 * sc->data[SC_GENTLETOUCH_REVITALIZE]->val4;
+ if( sc->data[SC_FORCEOFVANGUARD] )
+ def += def * 2 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100;
+ if(sc->data[SC_DEFSET])
+ return sc->data[SC_DEFSET]->val1;
return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);
}
- if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
+ if (sc->data[SC_BERSERK])
return 0;
if(sc->data[SC_SKA])
return sc->data[SC_SKA]->val3;
@@ -4858,27 +4948,32 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
if(sc->data[SC_STEELBODY])
return 90;
#endif
+
+ if(sc->data[SC_STONEHARDSKIN])
+ def += sc->data[SC_STONEHARDSKIN]->val1;
+ if(sc->data[SC_DRUMBATTLE])
+ def += sc->data[SC_DRUMBATTLE]->val3;
if(sc->data[SC_STONESKIN])
def += sc->data[SC_STONESKIN]->val2;
- if(sc->data[SC_DRUMBATTLE])
- def += sc->data[SC_DRUMBATTLE]->val3;
if(sc->data[SC_HAMI_DEFENCE]) //[orn]
- def += sc->data[SC_HAMI_DEFENCE]->val2 ;
- if(sc->data[SC_INCDEFRATE])
- def += def * sc->data[SC_INCDEFRATE]->val1/100;
+ def += sc->data[SC_HAMI_DEFENCE]->val2;
+
if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2)
def += 50;
if(sc->data[SC_ODINS_POWER])
def -= 20;
- if( sc->data[SC_ANGRIFFS_MODUS] )
- def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1;
- if(sc->data[SC_STONEHARDSKIN])
- def += sc->data[SC_STONEHARDSKIN]->val1;
+
+#ifndef RENEWAL
if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
def >>=1;
if(sc->data[SC_FREEZE])
def >>=1;
+ if(sc->data[SC_INCDEFRATE])
+ def += def * sc->data[SC_INCDEFRATE]->val1/100;
+#endif
+ if( sc->data[SC_ANGRIFFS_MODUS] )
+ def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1;
if(sc->data[SC_CRUCIS])
def -= def * sc->data[SC_CRUCIS]->val2/100;
if(sc->data[SC_LKCONCENTRATION])
@@ -4893,24 +4988,29 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
def -= def * (sc->data[SC_FLING]->val2)/100;
if( sc->data[SC_ANALYZE] )
def -= def * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100;
- if( sc->data[SC_FORCEOFVANGUARD] )
- def += def * 2 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100;
if(sc->data[SC_SATURDAY_NIGHT_FEVER])
def -= def * (10 + 10 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1) / 100;
if(sc->data[SC_EARTHDRIVE])
def -= def * 25 / 100;
if( sc->data[SC_ROCK_CRUSHER] )
def -= def * sc->data[SC_ROCK_CRUSHER]->val2 / 100;
+ if( sc->data[SC_FROSTMISTY] )
+ def -= def * 10 / 100;
+ if( sc->data[SC_OVERED_BOOST] && bl->type == BL_HOM )
+ def -= def * 50 / 100;
+
if( sc->data[SC_POWER_OF_GAIA] )
def += def * sc->data[SC_POWER_OF_GAIA]->val2 / 100;
+ if( sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 2 )
+ def += sc->data[SC_SHIELDSPELL_REF]->val2;
if( sc->data[SC_PRESTIGE] )
def += def * sc->data[SC_PRESTIGE]->val1 / 100;
- if( sc->data[SC_FROSTMISTY] )
- def -= def * 10 / 100;
if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){
if(status_get_race(bl)==RC_PLANT)
def /= 2;
}
+ if(sc->data[SC_UNLIMIT])
+ return 1;
return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);
}
@@ -4929,9 +5029,11 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i
#ifdef RENEWAL
if( sc && sc->data[SC_ASSUMPTIO] )
def2 <<= 1;
-#endif
+#endif
if( sc && sc->data[SC_CAMOUFLAGE] )
def2 -= def2 * 5 * (10-sc->data[SC_CAMOUFLAGE]->val4) / 100;
+ if(sc->data[SC_DEFSET])
+ return sc->data[SC_DEFSET]->val1;
#ifdef RENEWAL
return (short)cap_value(def2,SHRT_MIN,SHRT_MAX);
#else
@@ -4939,17 +5041,14 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i
#endif
}
- if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
+ if (sc->data[SC_BERSERK])
return 0;
if(sc->data[SC_ETERNALCHAOS])
return 0;
if(sc->data[SC_SUN_COMFORT])
def2 += sc->data[SC_SUN_COMFORT]->val2;
- if( sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 )
- def2 += sc->data[SC_SHIELDSPELL_REF]->val2;
if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 )
def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2);
-
if(sc->data[SC_ANGELUS])
#ifdef RENEWAL //in renewal only the VIT stat bonus is boosted by angelus
def2 += status_get_vit(bl) / 2 * sc->data[SC_ANGELUS]->val2/100;
@@ -4968,20 +5067,21 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i
def2 -= def2 * sc->data[SC_PROVOKE]->val4/100;
if(sc->data[SC_JOINTBEAT])
def2 -= def2 * ( sc->data[SC_JOINTBEAT]->val2&BREAK_SHOULDER ? 50 : 0 ) / 100
- + def2 * ( sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST ? 25 : 0 ) / 100;
+ + def2 * ( sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST ? 25 : 0 ) / 100;
if(sc->data[SC_FLING])
def2 -= def2 * (sc->data[SC_FLING]->val3)/100;
if(sc->data[SC_ANALYZE])
def2 -= def2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100;
if( sc->data[SC_ECHOSONG] )
- def2 += def2 * sc->data[SC_ECHOSONG]->val2/100;
+ def2 += def2 * sc->data[SC_ECHOSONG]->val3/100;
if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){
if(status_get_race(bl)==RC_PLANT)
def2 /= 2;
}
if (sc->data[SC_NEEDLE_OF_PARALYZE])
def2 -= def2 * sc->data[SC_NEEDLE_OF_PARALYZE]->val2 / 100;
-
+ if (sc->data[SC_UNLIMIT])
+ return 1;
#ifdef RENEWAL
return (short)cap_value(def2,SHRT_MIN,SHRT_MAX);
#else
@@ -4997,10 +5097,14 @@ defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int md
if( !viewable ){
/* some statuses that are hidden in the status window */
+ if(sc->data[SC_NEUTRALBARRIER] )
+ mdef += mdef * (5 * sc->data[SC_NEUTRALBARRIER]->val1 + 10) / 100;
+ if(sc->data[SC_MDEFSET])
+ return sc->data[SC_MDEFSET]->val1;
return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX);
}
- if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
+ if (sc->data[SC_BERSERK])
return 0;
if(sc->data[SC_BARRIER])
return 100;
@@ -5018,8 +5122,6 @@ defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int md
mdef += (sc->data[SC_ENDURE]->val4 == 0) ? sc->data[SC_ENDURE]->val1 : 1;
if(sc->data[SC_STONEHARDSKIN])// Final MDEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech]
mdef += sc->data[SC_STONEHARDSKIN]->val1;
- if(sc->data[SC_WATER_BARRIER])
- mdef += sc->data[SC_WATER_BARRIER]->val2;
if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
mdef += 25*mdef/100;
if(sc->data[SC_FREEZE])
@@ -5031,9 +5133,11 @@ defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int md
if(sc->data[SC_GENTLETOUCH_CHANGE] && sc->data[SC_GENTLETOUCH_CHANGE]->val4)
mdef -= mdef * sc->data[SC_GENTLETOUCH_CHANGE]->val4 / 100;
if (sc->data[SC_ODINS_POWER])
- mdef -= 20 * sc->data[SC_ODINS_POWER]->val1;
+ mdef -= 20;
if(sc->data[SC_BURNING])
mdef -= mdef *25 / 100;
+ if (sc->data[SC_UNLIMIT])
+ return 1;
return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX);
}
@@ -5049,6 +5153,10 @@ signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc,
if( !viewable ){
/* some statuses that are hidden in the status window */
+ if(sc->data[SC_MDEFSET])
+ return sc->data[SC_MDEFSET]->val1;
+ if(sc->data[SC_MINDBREAKER])
+ mdef2 -= mdef2 * sc->data[SC_MINDBREAKER]->val3/100;
#ifdef RENEWAL
if(sc && sc->data[SC_ASSUMPTIO])
mdef2 <<= 1;
@@ -5058,15 +5166,14 @@ signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc,
#endif
}
- if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
+ if (sc->data[SC_BERSERK])
return 0;
if(sc->data[SC_SKA])
return 90;
- if(sc->data[SC_MINDBREAKER])
- mdef2 -= mdef2 * sc->data[SC_MINDBREAKER]->val3/100;
if(sc->data[SC_ANALYZE])
mdef2 -= mdef2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100;
-
+ if (sc->data[SC_UNLIMIT])
+ return 1;
#ifdef RENEWAL
return (short)cap_value(mdef2,SHRT_MIN,SHRT_MAX);
#else
@@ -5074,21 +5181,18 @@ signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc,
#endif
}
-static unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed)
+unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed)
{
TBL_PC* sd = BL_CAST(BL_PC, bl);
int speed_rate;
- if( sc == NULL )
- return cap_value(speed,10,USHRT_MAX);
-
- if (sd && sd->state.permanent_speed)
- return (short)cap_value(speed,10,USHRT_MAX);
+ if( sc == NULL || ( sd && sd->state.permanent_speed ) )
+ return (unsigned short)cap_value(speed,MIN_WALK_SPEED,MAX_WALK_SPEED);
if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || sd->ud.skill_id == LG_EXEEDBREAK) )
{
if( sd->ud.skill_id == LG_EXEEDBREAK )
- speed_rate = 100 + 60 - (sd->ud.skill_lv * 10);
+ speed_rate = 160 - 10 * sd->ud.skill_lv;
else
speed_rate = 175 - 5 * pc->checkskill(sd,SA_FREECAST);
}
@@ -5124,68 +5228,70 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
if( sd && sc->data[SC_HIDING] && pc->checkskill(sd,RG_TUNNELDRIVE) > 0 )
val = 120 - 6 * pc->checkskill(sd,RG_TUNNELDRIVE);
else
- if( sd && sc->data[SC_CHASEWALK] && sc->data[SC_CHASEWALK]->val3 < 0 )
- val = sc->data[SC_CHASEWALK]->val3;
- else
- {
- // Longing for Freedom cancels song/dance penalty
- if( sc->data[SC_LONGING] )
- val = max( val, 50 - 10 * sc->data[SC_LONGING]->val1 );
+ if( sd && sc->data[SC_CHASEWALK] && sc->data[SC_CHASEWALK]->val3 < 0 )
+ val = sc->data[SC_CHASEWALK]->val3;
else
- if( sd && sc->data[SC_DANCING] )
- val = max( val, 500 - (40 + 10 * (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) * pc->checkskill(sd,(sd->status.sex?BA_MUSICALLESSON:DC_DANCINGLESSON)) );
-
- if( sc->data[SC_DEC_AGI] )
- val = max( val, 25 );
- if( sc->data[SC_QUAGMIRE] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY] || (sc->data[SC_GLOOMYDAY] && sc->data[SC_GLOOMYDAY]->val4) )
- val = max( val, 50 );
- if( sc->data[SC_DONTFORGETME] )
- val = max( val, sc->data[SC_DONTFORGETME]->val3 );
- if( sc->data[SC_CURSE] )
- val = max( val, 300 );
- if( sc->data[SC_CHASEWALK] )
- val = max( val, sc->data[SC_CHASEWALK]->val3 );
- if( sc->data[SC_WEDDING] )
- val = max( val, 100 );
- if( sc->data[SC_JOINTBEAT] && sc->data[SC_JOINTBEAT]->val2&(BREAK_ANKLE|BREAK_KNEE) )
- val = max( val, (sc->data[SC_JOINTBEAT]->val2&BREAK_ANKLE ? 50 : 0) + (sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE ? 30 : 0) );
- if( sc->data[SC_CLOAKING] && (sc->data[SC_CLOAKING]->val4&1) == 0 )
- val = max( val, sc->data[SC_CLOAKING]->val1 < 3 ? 300 : 30 - 3 * sc->data[SC_CLOAKING]->val1 );
- if( sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY )
- val = max( val, 75 );
- if( sc->data[SC_SLOWDOWN] ) // Slow Potion
- val = max( val, 100 );
- if( sc->data[SC_GS_GATLINGFEVER] )
- val = max( val, 100 );
- if( sc->data[SC_NJ_SUITON] )
- val = max( val, sc->data[SC_NJ_SUITON]->val3 );
- if( sc->data[SC_SWOO] )
- val = max( val, 300 );
- if( sc->data[SC_FROSTMISTY] )
- val = max( val, 50 );
- if( sc->data[SC_CAMOUFLAGE] && (sc->data[SC_CAMOUFLAGE]->val3&1) == 0 )
- val = max( val, sc->data[SC_CAMOUFLAGE]->val1 < 3 ? 0 : 25 * (5 - sc->data[SC_CAMOUFLAGE]->val1) );
- if( sc->data[SC__GROOMY] )
- val = max( val, sc->data[SC__GROOMY]->val2);
- if( sc->data[SC_STEALTHFIELD_MASTER] )
- val = max( val, 30 );
- if( sc->data[SC_BANDING_DEFENCE] )
- val = max( val, sc->data[SC_BANDING_DEFENCE]->val1 );//+90% walking speed.
- if( sc->data[SC_ROCK_CRUSHER_ATK] )
- val = max( val, sc->data[SC_ROCK_CRUSHER_ATK]->val2 );
- if( sc->data[SC_POWER_OF_GAIA] )
- val = max( val, sc->data[SC_POWER_OF_GAIA]->val2 );
- if( sc->data[SC_MELON_BOMB] )
- val = max( val, sc->data[SC_MELON_BOMB]->val1 );
-
- if( sc->data[SC_MARSHOFABYSS] ) // It stacks to other statuses so always put this at the end.
- val = max( 50, val + 10 * sc->data[SC_MARSHOFABYSS]->val1 );
-
- if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate > 0 ) // permanent item-based speedup
- val = max( val, sd->bonus.speed_rate + sd->bonus.speed_add_rate );
- }
+ {
+ // Longing for Freedom cancels song/dance penalty
+ if( sc->data[SC_LONGING] )
+ val = max( val, 50 - 10 * sc->data[SC_LONGING]->val1 );
+ else
+ if( sd && sc->data[SC_DANCING] )
+ val = max( val, 500 - (40 + 10 * (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) * pc->checkskill(sd,(sd->status.sex?BA_MUSICALLESSON:DC_DANCINGLESSON)) );
+
+ if( sc->data[SC_DEC_AGI] )
+ val = max( val, 25 );
+ if( sc->data[SC_QUAGMIRE] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY] )
+ val = max( val, 50 );
+ if( sc->data[SC_DONTFORGETME] )
+ val = max( val, sc->data[SC_DONTFORGETME]->val3 );
+ if( sc->data[SC_CURSE] )
+ val = max( val, 300 );
+ if( sc->data[SC_CHASEWALK] )
+ val = max( val, sc->data[SC_CHASEWALK]->val3 );
+ if( sc->data[SC_WEDDING] )
+ val = max( val, 100 );
+ if( sc->data[SC_JOINTBEAT] && sc->data[SC_JOINTBEAT]->val2&(BREAK_ANKLE|BREAK_KNEE) )
+ val = max( val, (sc->data[SC_JOINTBEAT]->val2&BREAK_ANKLE ? 50 : 0) + (sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE ? 30 : 0) );
+ if( sc->data[SC_CLOAKING] && (sc->data[SC_CLOAKING]->val4&1) == 0 )
+ val = max( val, sc->data[SC_CLOAKING]->val1 < 3 ? 300 : 30 - 3 * sc->data[SC_CLOAKING]->val1 );
+ if( sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY )
+ val = max( val, 75 );
+ if( sc->data[SC_SLOWDOWN] ) // Slow Potion
+ val = max( val, 100 );
+ if( sc->data[SC_GS_GATLINGFEVER] )
+ val = max( val, 100 );
+ if( sc->data[SC_NJ_SUITON] )
+ val = max( val, sc->data[SC_NJ_SUITON]->val3 );
+ if( sc->data[SC_SWOO] )
+ val = max( val, 300 );
+ if( sc->data[SC_FROSTMISTY] )
+ val = max( val, 50 );
+ if( sc->data[SC_CAMOUFLAGE] && (sc->data[SC_CAMOUFLAGE]->val3&1) == 0 )
+ val = max( val, sc->data[SC_CAMOUFLAGE]->val1 < 3 ? 0 : 25 * (5 - sc->data[SC_CAMOUFLAGE]->val1) );
+ if( sc->data[SC__GROOMY] )
+ val = max( val, sc->data[SC__GROOMY]->val2);
+ if( sc->data[SC_GLOOMYDAY] )
+ val = max( val, sc->data[SC_GLOOMYDAY]->val3 ); // Should be 50 (-50% speed)
+ if( sc->data[SC_STEALTHFIELD_MASTER] )
+ val = max( val, 30 );
+ if( sc->data[SC_BANDING_DEFENCE] )
+ val = max( val, sc->data[SC_BANDING_DEFENCE]->val1 );//+90% walking speed.
+ if( sc->data[SC_ROCK_CRUSHER_ATK] )
+ val = max( val, sc->data[SC_ROCK_CRUSHER_ATK]->val2 );
+ if( sc->data[SC_POWER_OF_GAIA] )
+ val = max( val, sc->data[SC_POWER_OF_GAIA]->val2 );
+ if( sc->data[SC_MELON_BOMB] )
+ val = max( val, sc->data[SC_MELON_BOMB]->val1 );
+
+ if( sc->data[SC_MARSHOFABYSS] ) // It stacks to other statuses so always put this at the end.
+ val = max( 50, val + 10 * sc->data[SC_MARSHOFABYSS]->val1 );
+
+ if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate > 0 ) // permanent item-based speedup
+ val = max( val, sd->bonus.speed_rate + sd->bonus.speed_add_rate );
+ }
- speed_rate += val;
+ speed_rate += val;
}
//GetMoveHasteValue1()
@@ -5204,7 +5310,7 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
val = max( val, 1 * pc->checkskill(sd,TF_MISS) );
if( sc->data[SC_CLOAKING] && (sc->data[SC_CLOAKING]->val4&1) == 1 )
val = max( val, sc->data[SC_CLOAKING]->val1 >= 10 ? 25 : 3 * sc->data[SC_CLOAKING]->val1 - 3 );
- if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
+ if (sc->data[SC_BERSERK])
val = max( val, 25 );
if( sc->data[SC_RUN] )
val = max( val, 55 );
@@ -5219,7 +5325,7 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
if( sc->data[SC_GN_CARTBOOST] )
val = max( val, sc->data[SC_GN_CARTBOOST]->val2 );
if( sc->data[SC_SWING] )
- val = max( val, sc->data[SC_SWING]->val2 );
+ val = max( val, sc->data[SC_SWING]->val3 );
if( sc->data[SC_WIND_STEP_OPTION] )
val = max( val, sc->data[SC_WIND_STEP_OPTION]->val2 );
if( sc->data[SC_FULL_THROTTLE] )
@@ -5256,14 +5362,13 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
}
- return (short)cap_value(speed,10,USHRT_MAX);
+ return (unsigned short)cap_value(speed,MIN_WALK_SPEED,MAX_WALK_SPEED);
}
-#ifdef RENEWAL_ASPD
// flag&1 - fixed value [malufett]
// flag&2 - percentage value
-static short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag)
-{
+short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag) {
+#ifdef RENEWAL_ASPD
int i, pots = 0, skills1 = 0, skills2 = 0;
if(!sc || !sc->count)
@@ -5297,7 +5402,7 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s
skills1 = 5;
}
- if((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) && skills1 < 15)
+ if((sc->data[SC_BERSERK]) && skills1 < 15)
skills1 = 15;
else if(sc->data[SC_GS_MADNESSCANCEL] && skills1 < 20)
skills1 = 20;
@@ -5329,20 +5434,22 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s
if( sc->data[SC_PARALYSE] )
skills2 -= 10;
if( sc->data[SC__BODYPAINT] )
- skills2 -= 2 + 5 * sc->data[SC__BODYPAINT]->val1;
+ skills2 -= sc->data[SC__BODYPAINT]->val1;
if( sc->data[SC__INVISIBILITY] )
skills2 -= sc->data[SC__INVISIBILITY]->val2 ;
if( sc->data[SC__GROOMY] )
skills2 -= sc->data[SC__GROOMY]->val2;
if( sc->data[SC_GLOOMYDAY] )
- skills2 -= sc->data[SC_GLOOMYDAY]->val3;
+ skills2 -= ( 15 + 5 * sc->data[SC_GLOOMYDAY]->val1 );
if( sc->data[SC_EARTHDRIVE] )
skills2 -= 25;
if( sc->data[SC_MELON_BOMB] )
skills2 -= sc->data[SC_MELON_BOMB]->val1;
+ if( sc->data[SC_PAIN_KILLER] )
+ skills2 -= sc->data[SC_PAIN_KILLER]->val2;
if( sc->data[SC_SWING] )
- skills2 += sc->data[SC_SWING]->val2;
+ skills2 += sc->data[SC_SWING]->val3;
if( sc->data[SC_DANCE_WITH_WUG] )
skills2 += sc->data[SC_DANCE_WITH_WUG]->val3;
if( sc->data[SC_GENTLETOUCH_CHANGE] )
@@ -5361,7 +5468,7 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s
if (bl->type!=BL_PC)
skills2 += sc->data[SC_ASSNCROS]->val2;
else
- switch(((TBL_PC*)bl)->status.weapon)
+ switch(((TBL_PC*)bl)->status.weapon)
{
case W_BOW:
case W_REVOLVER:
@@ -5375,30 +5482,31 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s
}
}
return ( flag&1? (skills1 + pots) : skills2 );
-}
+#else
+ return 0;
#endif
+}
-static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) {
- if (!sc || !sc->count)
- return cap_value(aspd, 0, 2000);
-
- if (!sc->data[SC_QUAGMIRE]) {
- if (sc->data[SC_OVERED_BOOST])
- aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3*10;
- }
+short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) {
+ if (!sc || !sc->count)
+ return cap_value(aspd, 0, 2000);
if ((sc->data[SC_GUST_OPTION] || sc->data[SC_BLAST_OPTION]
- || sc->data[SC_WILD_STORM_OPTION]))
+ || sc->data[SC_WILD_STORM_OPTION]))
aspd -= 50; // +5 ASPD
if( sc && sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 )
aspd -= (bl->type==BL_PC?pc->checkskill((TBL_PC *)bl, RK_RUNEMASTERY):10) / 10 * 40;
+ if( sc && sc->data[SC_MTF_ASPD] )
+ aspd -= 10;
- return cap_value(aspd, 0, 2000); // will be recap for proper bl anyway
+ if (sc->data[SC_OVERED_BOOST]) // should be final and unmodifiable by any means
+ aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3 * 10;
+ return cap_value(aspd, 0, 2000); // will be recap for proper bl anyway
}
/// Calculates an object's ASPD modifier (alters the base amotion value).
/// Note that the scale of aspd_rate is 1000 = 100%.
-static short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate)
+short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate)
{
int i;
@@ -5448,7 +5556,7 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
if (bl->type!=BL_PC)
max = sc->data[SC_ASSNCROS]->val2;
else
- switch(((TBL_PC*)bl)->status.weapon)
+ switch(((TBL_PC*)bl)->status.weapon)
{
case W_BOW:
case W_REVOLVER:
@@ -5463,7 +5571,7 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
}
aspd_rate -= max;
- if((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]))
+ if(sc->data[SC_BERSERK])
aspd_rate -= 300;
else if(sc->data[SC_GS_MADNESSCANCEL])
aspd_rate -= 200;
@@ -5504,17 +5612,17 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
if( sc->data[SC_PARALYSE] )
aspd_rate += 100;
if( sc->data[SC__BODYPAINT] )
- aspd_rate += 200 + 50 * sc->data[SC__BODYPAINT]->val1;
+ aspd_rate += 10 * 5 * sc->data[SC__BODYPAINT]->val1;
if( sc->data[SC__INVISIBILITY] )
aspd_rate += sc->data[SC__INVISIBILITY]->val2 * 10 ;
if( sc->data[SC__GROOMY] )
aspd_rate += sc->data[SC__GROOMY]->val2 * 10;
if( sc->data[SC_SWING] )
- aspd_rate -= sc->data[SC_SWING]->val2 * 10;
+ aspd_rate -= sc->data[SC_SWING]->val3 * 10;
if( sc->data[SC_DANCE_WITH_WUG] )
aspd_rate -= sc->data[SC_DANCE_WITH_WUG]->val3 * 10;
if( sc->data[SC_GLOOMYDAY] )
- aspd_rate += sc->data[SC_GLOOMYDAY]->val3 * 10;
+ aspd_rate += ( 15 + 5 * sc->data[SC_GLOOMYDAY]->val1 );
if( sc->data[SC_EARTHDRIVE] )
aspd_rate += 250;
if( sc->data[SC_GENTLETOUCH_CHANGE] )
@@ -5535,14 +5643,15 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
return (short)cap_value(aspd_rate,0,SHRT_MAX);
}
-static unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion)
-{
- if( !sc || !sc->count || map_flag_gvg(bl->m) || map[bl->m].flag.battleground )
+unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion) {
+ // It has been confirmed on official servers that MvP mobs have no dmotion even without endure
+ if( bl->type == BL_MOB && (((TBL_MOB*)bl)->status.mode&MD_BOSS) )
+ return 0;
+
+ if( !sc || !sc->count || map_flag_gvg2(bl->m) || map->list[bl->m].flag.battleground )
return cap_value(dmotion,0,USHRT_MAX);
- /**
- * It has been confirmed on official servers that MvP mobs have no dmotion even without endure
- **/
- if( sc->data[SC_ENDURE] || ( bl->type == BL_MOB && (((TBL_MOB*)bl)->status.mode&MD_BOSS) ) )
+
+ if( sc->data[SC_ENDURE] )
return 0;
if( sc->data[SC_RUN] || sc->data[SC_WUGDASH] )
return 0;
@@ -5550,7 +5659,7 @@ static unsigned short status_calc_dmotion(struct block_list *bl, struct status_c
return (unsigned short)cap_value(dmotion,0,USHRT_MAX);
}
-static unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, uint64 maxhp)
+unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, uint64 maxhp)
{
if(!sc || !sc->count)
return (unsigned int)cap_value(maxhp,1,UINT_MAX);
@@ -5563,7 +5672,7 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang
maxhp += maxhp * sc->data[SC_APPLEIDUN]->val2/100;
if(sc->data[SC_DELUGE])
maxhp += maxhp * sc->data[SC_DELUGE]->val2/100;
- if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
+ if(sc->data[SC_BERSERK])
maxhp += maxhp * 2;
if(sc->data[SC_MARIONETTE_MASTER])
maxhp -= 1000;
@@ -5584,11 +5693,13 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang
if(sc->data[SC__WEAKNESS])
maxhp -= maxhp * sc->data[SC__WEAKNESS]->val2 / 100;
if(sc->data[SC_LERADS_DEW])
- maxhp += maxhp * sc->data[SC_LERADS_DEW]->val3 / 100;
+ maxhp += sc->data[SC_LERADS_DEW]->val3;
+ if(sc->data[SC_BEYOND_OF_WARCRY])
+ maxhp -= maxhp * sc->data[SC_BEYOND_OF_WARCRY]->val4 / 100;
if(sc->data[SC_FORCEOFVANGUARD])
maxhp += maxhp * 3 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100;
- if(sc->data[SC_INSPIRATION]) //Custom value.
- maxhp += maxhp * 3 * sc->data[SC_INSPIRATION]->val1 / 100;
+ if(sc->data[SC_INSPIRATION])
+ maxhp += maxhp * 5 * sc->data[SC_INSPIRATION]->val1 / 100 + 600 * sc->data[SC_INSPIRATION]->val1;
if(sc->data[SC_RAISINGDRAGON])
maxhp += maxhp * (2 + sc->data[SC_RAISINGDRAGON]->val1) / 100;
if(sc->data[SC_GENTLETOUCH_CHANGE]) // Max HP decrease: [Skill Level x 4] %
@@ -5601,6 +5712,10 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang
maxhp -= sc->data[SC_MYSTERIOUS_POWDER]->val1 / 100;
if(sc->data[SC_PETROLOGY_OPTION])
maxhp += maxhp * sc->data[SC_PETROLOGY_OPTION]->val2 / 100;
+ if(sc->data[SC_CURSED_SOIL_OPTION])
+ maxhp += maxhp * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100;
+ if(sc->data[SC_UPHEAVAL_OPTION])
+ maxhp += maxhp * sc->data[SC_UPHEAVAL_OPTION]->val3 / 100;
if (sc->data[SC_ANGRIFFS_MODUS])
maxhp += maxhp * 5 * sc->data[SC_ANGRIFFS_MODUS]->val1 /100;
if (sc->data[SC_GOLDENE_FERSE])
@@ -5611,7 +5726,7 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang
return (unsigned int)cap_value(maxhp,1,UINT_MAX);
}
-static unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, unsigned int maxsp)
+unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, unsigned int maxsp)
{
if(!sc || !sc->count)
return cap_value(maxsp,1,UINT_MAX);
@@ -5634,7 +5749,7 @@ static unsigned int status_calc_maxsp(struct block_list *bl, struct status_chang
return cap_value(maxsp,1,UINT_MAX);
}
-static unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element)
+unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element)
{
if(!sc || !sc->count)
return element;
@@ -5655,7 +5770,7 @@ static unsigned char status_calc_element(struct block_list *bl, struct status_ch
return (unsigned char)cap_value(element,0,UCHAR_MAX);
}
-static unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv)
+unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv)
{
if(!sc || !sc->count)
return lv;
@@ -5686,16 +5801,16 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch
if(sc->data[SC_ENCHANTARMS])
return sc->data[SC_ENCHANTARMS]->val2;
if(sc->data[SC_PROPERTYWATER]
- || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) )
+ || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) )
return ELE_WATER;
if(sc->data[SC_PROPERTYGROUND]
- || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) )
+ || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) )
return ELE_EARTH;
if(sc->data[SC_PROPERTYFIRE]
- || (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) )
+ || (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) )
return ELE_FIRE;
if(sc->data[SC_PROPERTYWIND]
- || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2) )
+ || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2) )
return ELE_WIND;
if(sc->data[SC_ENCHANTPOISON])
return ELE_POISON;
@@ -5707,12 +5822,12 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch
return ELE_GHOST;
if(sc->data[SC_TIDAL_WEAPON_OPTION] || sc->data[SC_TIDAL_WEAPON] )
return ELE_WATER;
- if(sc->data[SC_PYROCLASTIC])
- return ELE_FIRE;
+ if(sc->data[SC_PYROCLASTIC])
+ return ELE_FIRE;
return (unsigned char)cap_value(element,0,UCHAR_MAX);
}
-static unsigned short status_calc_mode(struct block_list *bl, struct status_change *sc, int mode)
+unsigned short status_calc_mode(struct block_list *bl, struct status_change *sc, int mode)
{
if(!sc || !sc->count)
return mode;
@@ -5730,21 +5845,21 @@ static unsigned short status_calc_mode(struct block_list *bl, struct status_chan
const char* status_get_name(struct block_list *bl) {
nullpo_ret(bl);
switch (bl->type) {
- case BL_PC: return ((TBL_PC *)bl)->fakename[0] != '\0' ? ((TBL_PC*)bl)->fakename : ((TBL_PC*)bl)->status.name;
- case BL_MOB: return ((TBL_MOB*)bl)->name;
- case BL_PET: return ((TBL_PET*)bl)->pet.name;
- case BL_HOM: return ((TBL_HOM*)bl)->homunculus.name;
- case BL_NPC: return ((TBL_NPC*)bl)->name;
+ case BL_PC: return ((TBL_PC *)bl)->fakename[0] != '\0' ? ((TBL_PC*)bl)->fakename : ((TBL_PC*)bl)->status.name;
+ case BL_MOB: return ((TBL_MOB*)bl)->name;
+ case BL_PET: return ((TBL_PET*)bl)->pet.name;
+ case BL_HOM: return ((TBL_HOM*)bl)->homunculus.name;
+ case BL_NPC: return ((TBL_NPC*)bl)->name;
}
return "Unknown";
}
/*==========================================
- * Get the class of the current bl
- * return
- * 0 = fail
- * class_id = success
- *------------------------------------------*/
+* Get the class of the current bl
+* return
+* 0 = fail
+* class_id = success
+*------------------------------------------*/
int status_get_class(struct block_list *bl) {
nullpo_ret(bl);
switch( bl->type ) {
@@ -5759,11 +5874,11 @@ int status_get_class(struct block_list *bl) {
return 0;
}
/*==========================================
- * Get the base level of the current bl
- * return
- * 1 = fail
- * level = success
- *------------------------------------------*/
+* Get the base level of the current bl
+* return
+* 1 = fail
+* level = success
+*------------------------------------------*/
int status_get_lv(struct block_list *bl) {
nullpo_ret(bl);
switch (bl->type) {
@@ -5793,7 +5908,7 @@ struct regen_data *status_get_regen_data(struct block_list *bl)
struct status_data *status_get_status_data(struct block_list *bl)
{
- nullpo_retr(&dummy_status, bl);
+ nullpo_retr(&status->dummy, bl);
switch (bl->type) {
case BL_PC: return &((TBL_PC*)bl)->battle_status;
@@ -5802,9 +5917,9 @@ struct status_data *status_get_status_data(struct block_list *bl)
case BL_HOM: return &((TBL_HOM*)bl)->battle_status;
case BL_MER: return &((TBL_MER*)bl)->battle_status;
case BL_ELEM: return &((TBL_ELEM*)bl)->battle_status;
- case BL_NPC: return ((mobdb_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : &dummy_status);
+ case BL_NPC: return ((mob->db_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : &status->dummy);
default:
- return &dummy_status;
+ return &status->dummy;
}
}
@@ -5818,62 +5933,61 @@ struct status_data *status_get_base_status(struct block_list *bl)
case BL_HOM: return &((TBL_HOM*)bl)->base_status;
case BL_MER: return &((TBL_MER*)bl)->base_status;
case BL_ELEM: return &((TBL_ELEM*)bl)->base_status;
- case BL_NPC: return ((mobdb_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : NULL);
+ case BL_NPC: return ((mob->db_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : NULL);
default:
return NULL;
}
}
defType status_get_def(struct block_list *bl) {
struct unit_data *ud;
- struct status_data *status = status_get_status_data(bl);
- int def = status?status->def:0;
- ud = unit_bl2ud(bl);
+ struct status_data *st = status->get_status_data(bl);
+ int def = st ? st->def : 0;
+ ud = unit->bl2ud(bl);
if (ud && ud->skilltimer != INVALID_TIMER)
def -= def * skill->get_castdef(ud->skill_id)/100;
return cap_value(def, DEFTYPE_MIN, DEFTYPE_MAX);
}
-unsigned short status_get_speed(struct block_list *bl)
-{
- if(bl->type==BL_NPC)//Only BL with speed data but no status_data [Skotlex]
- return ((struct npc_data *)bl)->speed;
- return status_get_status_data(bl)->speed;
+unsigned short status_get_speed(struct block_list *bl) {
+ if(bl->type==BL_NPC)//Only BL with speed data but no status_data [Skotlex]
+ return ((struct npc_data *)bl)->speed;
+ return status->get_status_data(bl)->speed;
}
int status_get_party_id(struct block_list *bl) {
nullpo_ret(bl);
switch (bl->type) {
- case BL_PC:
- return ((TBL_PC*)bl)->status.party_id;
- case BL_PET:
- if (((TBL_PET*)bl)->msd)
- return ((TBL_PET*)bl)->msd->status.party_id;
- break;
- case BL_MOB: {
- struct mob_data *md=(TBL_MOB*)bl;
- if( md->master_id > 0 ) {
- struct map_session_data *msd;
- if (md->special_state.ai && (msd = iMap->id2sd(md->master_id)) != NULL)
- return msd->status.party_id;
- return -md->master_id;
- }
- }
- break;
- case BL_HOM:
- if (((TBL_HOM*)bl)->master)
- return ((TBL_HOM*)bl)->master->status.party_id;
- break;
- case BL_MER:
- if (((TBL_MER*)bl)->master)
- return ((TBL_MER*)bl)->master->status.party_id;
- break;
- case BL_SKILL:
- return ((TBL_SKILL*)bl)->group->party_id;
- case BL_ELEM:
- if (((TBL_ELEM*)bl)->master)
- return ((TBL_ELEM*)bl)->master->status.party_id;
- break;
+ case BL_PC:
+ return ((TBL_PC*)bl)->status.party_id;
+ case BL_PET:
+ if (((TBL_PET*)bl)->msd)
+ return ((TBL_PET*)bl)->msd->status.party_id;
+ break;
+ case BL_MOB: {
+ struct mob_data *md=(TBL_MOB*)bl;
+ if( md->master_id > 0 ) {
+ struct map_session_data *msd;
+ if (md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL)
+ return msd->status.party_id;
+ return -md->master_id;
+ }
+ }
+ break;
+ case BL_HOM:
+ if (((TBL_HOM*)bl)->master)
+ return ((TBL_HOM*)bl)->master->status.party_id;
+ break;
+ case BL_MER:
+ if (((TBL_MER*)bl)->master)
+ return ((TBL_MER*)bl)->master->status.party_id;
+ break;
+ case BL_SKILL:
+ return ((TBL_SKILL*)bl)->group->party_id;
+ case BL_ELEM:
+ if (((TBL_ELEM*)bl)->master)
+ return ((TBL_ELEM*)bl)->master->status.party_id;
+ break;
}
return 0;
}
@@ -5881,39 +5995,42 @@ int status_get_party_id(struct block_list *bl) {
int status_get_guild_id(struct block_list *bl) {
nullpo_ret(bl);
switch (bl->type) {
- case BL_PC:
- return ((TBL_PC*)bl)->status.guild_id;
- case BL_PET:
- if (((TBL_PET*)bl)->msd)
- return ((TBL_PET*)bl)->msd->status.guild_id;
- break;
- case BL_MOB: {
- struct map_session_data *msd;
- struct mob_data *md = (struct mob_data *)bl;
- if (md->guardian_data) //Guardian's guild [Skotlex]
- return md->guardian_data->guild_id;
- if (md->special_state.ai && (msd = iMap->id2sd(md->master_id)) != NULL)
- return msd->status.guild_id; //Alchemist's mobs [Skotlex]
- }
- break;
- case BL_HOM:
- if (((TBL_HOM*)bl)->master)
- return ((TBL_HOM*)bl)->master->status.guild_id;
- break;
- case BL_MER:
- if (((TBL_MER*)bl)->master)
- return ((TBL_MER*)bl)->master->status.guild_id;
- break;
- case BL_NPC:
- if (((TBL_NPC*)bl)->subtype == SCRIPT)
- return ((TBL_NPC*)bl)->u.scr.guild_id;
- break;
- case BL_SKILL:
- return ((TBL_SKILL*)bl)->group->guild_id;
- case BL_ELEM:
- if (((TBL_ELEM*)bl)->master)
- return ((TBL_ELEM*)bl)->master->status.guild_id;
- break;
+ case BL_PC:
+ return ((TBL_PC*)bl)->status.guild_id;
+ case BL_PET:
+ if (((TBL_PET*)bl)->msd)
+ return ((TBL_PET*)bl)->msd->status.guild_id;
+ break;
+ case BL_MOB:
+ {
+ struct map_session_data *msd;
+ struct mob_data *md = (struct mob_data *)bl;
+ if( md->guardian_data ) { //Guardian's guild [Skotlex]
+ // Guardian guild data may not been available yet, castle data is always set
+ return (md->guardian_data->g)?md->guardian_data->g->guild_id:md->guardian_data->castle->guild_id;
+ }
+ if( md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL )
+ return msd->status.guild_id; //Alchemist's mobs [Skotlex]
+ break;
+ }
+ case BL_HOM:
+ if (((TBL_HOM*)bl)->master)
+ return ((TBL_HOM*)bl)->master->status.guild_id;
+ break;
+ case BL_MER:
+ if (((TBL_MER*)bl)->master)
+ return ((TBL_MER*)bl)->master->status.guild_id;
+ break;
+ case BL_NPC:
+ if (((TBL_NPC*)bl)->subtype == SCRIPT)
+ return ((TBL_NPC*)bl)->u.scr.guild_id;
+ break;
+ case BL_SKILL:
+ return ((TBL_SKILL*)bl)->group->guild_id;
+ case BL_ELEM:
+ if (((TBL_ELEM*)bl)->master)
+ return ((TBL_ELEM*)bl)->master->status.guild_id;
+ break;
}
return 0;
}
@@ -5921,40 +6038,40 @@ int status_get_guild_id(struct block_list *bl) {
int status_get_emblem_id(struct block_list *bl) {
nullpo_ret(bl);
switch (bl->type) {
- case BL_PC:
- return ((TBL_PC*)bl)->guild_emblem_id;
- case BL_PET:
- if (((TBL_PET*)bl)->msd)
- return ((TBL_PET*)bl)->msd->guild_emblem_id;
- break;
- case BL_MOB: {
- struct map_session_data *msd;
- struct mob_data *md = (struct mob_data *)bl;
- if (md->guardian_data) //Guardian's guild [Skotlex]
- return md->guardian_data->emblem_id;
- if (md->special_state.ai && (msd = iMap->id2sd(md->master_id)) != NULL)
- return msd->guild_emblem_id; //Alchemist's mobs [Skotlex]
- }
- break;
- case BL_HOM:
- if (((TBL_HOM*)bl)->master)
- return ((TBL_HOM*)bl)->master->guild_emblem_id;
- break;
- case BL_MER:
- if (((TBL_MER*)bl)->master)
- return ((TBL_MER*)bl)->master->guild_emblem_id;
- break;
- case BL_NPC:
- if (((TBL_NPC*)bl)->subtype == SCRIPT && ((TBL_NPC*)bl)->u.scr.guild_id > 0) {
- struct guild *g = guild->search(((TBL_NPC*)bl)->u.scr.guild_id);
- if (g)
- return g->emblem_id;
- }
- break;
- case BL_ELEM:
- if (((TBL_ELEM*)bl)->master)
- return ((TBL_ELEM*)bl)->master->guild_emblem_id;
- break;
+ case BL_PC:
+ return ((TBL_PC*)bl)->guild_emblem_id;
+ case BL_PET:
+ if (((TBL_PET*)bl)->msd)
+ return ((TBL_PET*)bl)->msd->guild_emblem_id;
+ break;
+ case BL_MOB: {
+ struct map_session_data *msd;
+ struct mob_data *md = (struct mob_data *)bl;
+ if (md->guardian_data) //Guardian's guild [Skotlex]
+ return (md->guardian_data->g) ? md->guardian_data->g->emblem_id:0;
+ if (md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL)
+ return msd->guild_emblem_id; //Alchemist's mobs [Skotlex]
+ }
+ break;
+ case BL_HOM:
+ if (((TBL_HOM*)bl)->master)
+ return ((TBL_HOM*)bl)->master->guild_emblem_id;
+ break;
+ case BL_MER:
+ if (((TBL_MER*)bl)->master)
+ return ((TBL_MER*)bl)->master->guild_emblem_id;
+ break;
+ case BL_NPC:
+ if (((TBL_NPC*)bl)->subtype == SCRIPT && ((TBL_NPC*)bl)->u.scr.guild_id > 0) {
+ struct guild *g = guild->search(((TBL_NPC*)bl)->u.scr.guild_id);
+ if (g)
+ return g->emblem_id;
+ }
+ break;
+ case BL_ELEM:
+ if (((TBL_ELEM*)bl)->master)
+ return ((TBL_ELEM*)bl)->master->guild_emblem_id;
+ break;
}
return 0;
}
@@ -5978,15 +6095,13 @@ int status_get_race2(struct block_list *bl)
return 0;
}
-int status_isdead(struct block_list *bl)
-{
+int status_isdead(struct block_list *bl) {
nullpo_ret(bl);
- return status_get_status_data(bl)->hp == 0;
+ return status->get_status_data(bl)->hp == 0;
}
-int status_isimmune(struct block_list *bl)
-{
- struct status_change *sc =status_get_sc(bl);
+int status_isimmune(struct block_list *bl) {
+ struct status_change *sc = status->get_sc(bl);
if (sc && sc->data[SC_HERMODE])
return 100;
@@ -6015,135 +6130,137 @@ void status_set_viewdata(struct block_list *bl, int class_)
{
struct view_data* vd;
nullpo_retv(bl);
- if (mobdb_checkid(class_) || mob_is_clone(class_))
- vd = mob_get_viewdata(class_);
+ if (mob->db_checkid(class_) || mob->is_clone(class_))
+ vd = mob->get_viewdata(class_);
else if (npcdb_checkid(class_) || (bl->type == BL_NPC && class_ == WARP_CLASS))
- vd = npc_get_viewdata(class_);
+ vd = npc->get_viewdata(class_);
else if (homdb_checkid(class_))
vd = homun->get_viewdata(class_);
- else if (merc_class(class_))
- vd = merc_get_viewdata(class_);
- else if (elemental_class(class_))
- vd = elemental_get_viewdata(class_);
+ else if (mercenary->class(class_))
+ vd = mercenary->get_viewdata(class_);
+ else if (elemental->class(class_))
+ vd = elemental->get_viewdata(class_);
else
vd = NULL;
switch (bl->type) {
- case BL_PC:
- {
- TBL_PC* sd = (TBL_PC*)bl;
- if (pcdb_checkid(class_)) {
- if (sd->sc.option&OPTION_RIDING) {
- switch (class_) { //Adapt class to a Mounted one.
- case JOB_KNIGHT:
- class_ = JOB_KNIGHT2;
- break;
- case JOB_CRUSADER:
- class_ = JOB_CRUSADER2;
- break;
- case JOB_LORD_KNIGHT:
- class_ = JOB_LORD_KNIGHT2;
- break;
- case JOB_PALADIN:
- class_ = JOB_PALADIN2;
- break;
- case JOB_BABY_KNIGHT:
- class_ = JOB_BABY_KNIGHT2;
- break;
- case JOB_BABY_CRUSADER:
- class_ = JOB_BABY_CRUSADER2;
- break;
- }
- }
- sd->vd.class_ = class_;
- clif->get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield);
- sd->vd.head_top = sd->status.head_top;
- sd->vd.head_mid = sd->status.head_mid;
- sd->vd.head_bottom = sd->status.head_bottom;
- sd->vd.hair_style = cap_value(sd->status.hair,0,battle_config.max_hair_style);
- sd->vd.hair_color = cap_value(sd->status.hair_color,0,battle_config.max_hair_color);
- sd->vd.cloth_color = cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color);
- sd->vd.robe = sd->status.robe;
- sd->vd.sex = sd->status.sex;
-
- if ( sd->vd.cloth_color ) {
- if( sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette )
- sd->vd.cloth_color = 0;
- if( sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette )
- sd->vd.cloth_color = 0;
- if( sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette )
- sd->vd.cloth_color = 0;
- if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette )
- sd->vd.cloth_color = 0;
+ case BL_PC:
+ {
+ TBL_PC* sd = (TBL_PC*)bl;
+ if (pcdb_checkid(class_)) {
+ if (sd->sc.option&OPTION_RIDING) {
+ switch (class_) { //Adapt class to a Mounted one.
+ case JOB_KNIGHT:
+ class_ = JOB_KNIGHT2;
+ break;
+ case JOB_CRUSADER:
+ class_ = JOB_CRUSADER2;
+ break;
+ case JOB_LORD_KNIGHT:
+ class_ = JOB_LORD_KNIGHT2;
+ break;
+ case JOB_PALADIN:
+ class_ = JOB_PALADIN2;
+ break;
+ case JOB_BABY_KNIGHT:
+ class_ = JOB_BABY_KNIGHT2;
+ break;
+ case JOB_BABY_CRUSADER:
+ class_ = JOB_BABY_CRUSADER2;
+ break;
}
- } else if (vd)
- memcpy(&sd->vd, vd, sizeof(struct view_data));
- else
- ShowError("status_set_viewdata (PC): No view data for class %d\n", class_);
- }
+ }
+ sd->vd.class_ = class_;
+ clif->get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield);
+ sd->vd.head_top = sd->status.head_top;
+ sd->vd.head_mid = sd->status.head_mid;
+ sd->vd.head_bottom = sd->status.head_bottom;
+ sd->vd.hair_style = cap_value(sd->status.hair,0,battle_config.max_hair_style);
+ sd->vd.hair_color = cap_value(sd->status.hair_color,0,battle_config.max_hair_color);
+ sd->vd.cloth_color = cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color);
+ sd->vd.robe = sd->status.robe;
+ sd->vd.sex = sd->status.sex;
+
+ if ( sd->vd.cloth_color ) {
+ if( sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette )
+ sd->vd.cloth_color = 0;
+ if( sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette )
+ sd->vd.cloth_color = 0;
+ if( sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette )
+ sd->vd.cloth_color = 0;
+ if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette )
+ sd->vd.cloth_color = 0;
+ if( sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */ )
+ sd->vd.cloth_color = 0;
+ }
+ } else if (vd)
+ memcpy(&sd->vd, vd, sizeof(struct view_data));
+ else
+ ShowError("status_set_viewdata (PC): No view data for class %d\n", class_);
+ }
break;
- case BL_MOB:
- {
- TBL_MOB* md = (TBL_MOB*)bl;
- if (vd)
- md->vd = vd;
- else
- ShowError("status_set_viewdata (MOB): No view data for class %d\n", class_);
- }
+ case BL_MOB:
+ {
+ TBL_MOB* md = (TBL_MOB*)bl;
+ if (vd)
+ md->vd = vd;
+ else
+ ShowError("status_set_viewdata (MOB): No view data for class %d\n", class_);
+ }
break;
- case BL_PET:
- {
- TBL_PET* pd = (TBL_PET*)bl;
- if (vd) {
- memcpy(&pd->vd, vd, sizeof(struct view_data));
- if (!pcdb_checkid(vd->class_)) {
- pd->vd.hair_style = battle_config.pet_hair_style;
- if(pd->pet.equip) {
- pd->vd.head_bottom = itemdb_viewid(pd->pet.equip);
- if (!pd->vd.head_bottom)
- pd->vd.head_bottom = pd->pet.equip;
- }
+ case BL_PET:
+ {
+ TBL_PET* pd = (TBL_PET*)bl;
+ if (vd) {
+ memcpy(&pd->vd, vd, sizeof(struct view_data));
+ if (!pcdb_checkid(vd->class_)) {
+ pd->vd.hair_style = battle_config.pet_hair_style;
+ if(pd->pet.equip) {
+ pd->vd.head_bottom = itemdb_viewid(pd->pet.equip);
+ if (!pd->vd.head_bottom)
+ pd->vd.head_bottom = pd->pet.equip;
}
- } else
- ShowError("status_set_viewdata (PET): No view data for class %d\n", class_);
- }
+ }
+ } else
+ ShowError("status_set_viewdata (PET): No view data for class %d\n", class_);
+ }
break;
- case BL_NPC:
- {
- TBL_NPC* nd = (TBL_NPC*)bl;
- if (vd)
- nd->vd = vd;
- else
- ShowError("status_set_viewdata (NPC): No view data for class %d\n", class_);
- }
+ case BL_NPC:
+ {
+ TBL_NPC* nd = (TBL_NPC*)bl;
+ if (vd)
+ nd->vd = vd;
+ else
+ ShowError("status_set_viewdata (NPC): No view data for class %d\n", class_);
+ }
+ break;
+ case BL_HOM: //[blackhole89]
+ {
+ struct homun_data *hd = (struct homun_data*)bl;
+ if (vd)
+ hd->vd = vd;
+ else
+ ShowError("status_set_viewdata (HOMUNCULUS): No view data for class %d\n", class_);
+ }
+ break;
+ case BL_MER:
+ {
+ struct mercenary_data *md = (struct mercenary_data*)bl;
+ if (vd)
+ md->vd = vd;
+ else
+ ShowError("status_set_viewdata (MERCENARY): No view data for class %d\n", class_);
+ }
+ break;
+ case BL_ELEM:
+ {
+ struct elemental_data *ed = (struct elemental_data*)bl;
+ if (vd)
+ ed->vd = vd;
+ else
+ ShowError("status_set_viewdata (ELEMENTAL): No view data for class %d\n", class_);
+ }
break;
- case BL_HOM: //[blackhole89]
- {
- struct homun_data *hd = (struct homun_data*)bl;
- if (vd)
- hd->vd = vd;
- else
- ShowError("status_set_viewdata (HOMUNCULUS): No view data for class %d\n", class_);
- }
- break;
- case BL_MER:
- {
- struct mercenary_data *md = (struct mercenary_data*)bl;
- if (vd)
- md->vd = vd;
- else
- ShowError("status_set_viewdata (MERCENARY): No view data for class %d\n", class_);
- }
- break;
- case BL_ELEM:
- {
- struct elemental_data *ed = (struct elemental_data*)bl;
- if (vd)
- ed->vd = vd;
- else
- ShowError("status_set_viewdata (ELEMENTAL): No view data for class %d\n", class_);
- }
- break;
}
}
@@ -6151,192 +6268,308 @@ void status_set_viewdata(struct block_list *bl, int class_)
struct status_change *status_get_sc(struct block_list *bl) {
if( bl ) {
switch (bl->type) {
- case BL_PC: return &((TBL_PC*)bl)->sc;
- case BL_MOB: return &((TBL_MOB*)bl)->sc;
- case BL_NPC: return NULL;
- case BL_HOM: return &((TBL_HOM*)bl)->sc;
- case BL_MER: return &((TBL_MER*)bl)->sc;
- case BL_ELEM: return &((TBL_ELEM*)bl)->sc;
+ case BL_PC: return &((TBL_PC*)bl)->sc;
+ case BL_MOB: return &((TBL_MOB*)bl)->sc;
+ case BL_NPC: return NULL;
+ case BL_HOM: return &((TBL_HOM*)bl)->sc;
+ case BL_MER: return &((TBL_MER*)bl)->sc;
+ case BL_ELEM: return &((TBL_ELEM*)bl)->sc;
}
}
return NULL;
}
-void status_change_init(struct block_list *bl)
-{
- struct status_change *sc = status_get_sc(bl);
+void status_change_init(struct block_list *bl) {
+ struct status_change *sc = status->get_sc(bl);
nullpo_retv(sc);
memset(sc, 0, sizeof (struct status_change));
}
//Applies SC defense to a given status change.
//Returns the adjusted duration based on flag values.
-//the flag values are the same as in status_change_start.
-int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int tick, int flag)
-{
+//the flag values are the same as in status->change_start.
+int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag) {
//Percentual resistance: 10000 = 100% Resist
//Example: 50% -> sc_def=5000 -> 25%; 5000ms -> tick_def=5000 -> 2500ms
int sc_def = 0, tick_def = -1; //-1 = use sc_def
//Linear resistance substracted from rate and tick after percentual resistance was applied
//Example: 25% -> sc_def2=2000 -> 5%; 2500ms -> tick_def2=2000 -> 500ms
- int sc_def2 = 0, tick_def2 = -1; //-1 = use sc_def2
- struct status_data* status;
- struct status_change* sc;
+ int sc_def2 = 0, tick_def2 = -1; //-1 = use sc_def2 (pre-re only)
+
+ struct status_data *st;
+ struct status_change *sc;
struct map_session_data *sd;
nullpo_ret(bl);
+
+ if(!src)
+ return tick ? tick : 1; // If no source, it can't be resisted (NPC given)
+
+/// Returns the 'bl's level, capped to 'cap'
+#define SCDEF_LVL_CAP(bl, cap) ( (bl) ? (status->get_lv(bl) > (cap) ? (cap) : status->get_lv(bl)) : 0 )
+/// Renewal level modifier.
+/// In renewal, returns the difference between the levels of 'bl' and 'src', both capped to 'maxlv', multiplied by 'factor'
+/// In pre-renewal, returns zero.
+#ifdef RENEWAL
+#define SCDEF_LVL_DIFF(bl, src, maxlv, factor) ( ( SCDEF_LVL_CAP((bl), (maxlv)) - SCDEF_LVL_CAP((src), (maxlv)) ) * (factor) )
+#else
+#define SCDEF_LVL_DIFF(bl, src, maxlv, factor) 0
+#endif
//Status that are blocked by Golden Thief Bug card or Wand of Hermod
- if (status_isimmune(bl))
+ if (status->isimmune(bl))
switch (type) {
- case SC_DEC_AGI:
- case SC_SILENCE:
- case SC_COMA:
- case SC_INC_AGI:
- case SC_BLESSING:
- case SC_SLOWPOISON:
- case SC_IMPOSITIO:
- case SC_LEXAETERNA:
- case SC_SUFFRAGIUM:
- case SC_BENEDICTIO:
- case SC_PROVIDENCE:
- case SC_KYRIE:
- case SC_ASSUMPTIO:
- case SC_ANGELUS:
- case SC_MAGNIFICAT:
- case SC_GLORIA:
- case SC_WINDWALK:
- case SC_MAGICROD:
- case SC_ILLUSION:
- case SC_STONE:
- case SC_QUAGMIRE:
- case SC_NJ_SUITON:
- case SC_SWING:
- case SC__ENERVATION:
- case SC__GROOMY:
- case SC__IGNORANCE:
- case SC__LAZINESS:
- case SC__UNLUCKY:
- case SC__WEAKNESS:
- case SC__BLOODYLUST:
- return 0;
+ case SC_DEC_AGI:
+ case SC_SILENCE:
+ case SC_COMA:
+ case SC_INC_AGI:
+ case SC_BLESSING:
+ case SC_SLOWPOISON:
+ case SC_IMPOSITIO:
+ case SC_LEXAETERNA:
+ case SC_SUFFRAGIUM:
+ case SC_BENEDICTIO:
+ case SC_PROVIDENCE:
+ case SC_KYRIE:
+ case SC_ASSUMPTIO:
+ case SC_ANGELUS:
+ case SC_MAGNIFICAT:
+ case SC_GLORIA:
+ case SC_WINDWALK:
+ case SC_MAGICROD:
+ case SC_ILLUSION:
+ case SC_STONE:
+ case SC_QUAGMIRE:
+ case SC_NJ_SUITON:
+ case SC_SWING:
+ case SC__ENERVATION:
+ case SC__GROOMY:
+ case SC__IGNORANCE:
+ case SC__LAZINESS:
+ case SC__UNLUCKY:
+ case SC__WEAKNESS:
+ return 0;
}
sd = BL_CAST(BL_PC,bl);
- status = status_get_status_data(bl);
- sc = status_get_sc(bl);
+ st = status->get_status_data(bl);
+ sc = status->get_sc(bl);
if( sc && !sc->count )
sc = NULL;
- switch (type) {
- case SC_STUN:
- case SC_POISON:
- if( sc && sc->data[SC__UNLUCKY] )
- return tick;
- case SC_DPOISON:
- case SC_SILENCE:
- case SC_BLOODING:
- sc_def = status->vit*100;
- sc_def2 = status->luk*10;
- break;
- case SC_SLEEP:
- sc_def = status->int_*100;
- sc_def2 = status->luk*10;
- break;
- case SC_DEEP_SLEEP:
- sc_def = status->int_*50;
- tick_def = status->int_*10 + status_get_lv(bl) * 65 / 10; //Seems to be -1 sec every 10 int and -5% chance every 10 int.
- break;
- case SC_DEC_AGI:
- case SC_ADORAMUS: //Arch Bishop
- if (sd) tick>>=1; //Half duration for players.
- case SC_STONE:
- //Impossible to reduce duration with stats
- tick_def = 0;
- tick_def2 = 0;
- case SC_FREEZE:
- sc_def = status->mdef*100;
- sc_def2 = status->luk*10;
- break;
- case SC_CURSE:
- //Special property: inmunity when luk is greater than level or zero
- if (status->luk > status_get_lv(bl) || status->luk == 0)
+
+ if (sc && sc->data[SC_KINGS_GRACE]) {
+ // Protects against status effects
+ switch (type) {
+ case SC_POISON:
+ case SC_BLIND:
+ case SC_FREEZE:
+ case SC_STONE:
+ case SC_STUN:
+ case SC_SLEEP:
+ case SC_BLOODING:
+ case SC_CURSE:
+ case SC_CONFUSION:
+ case SC_ILLUSION:
+ case SC_SILENCE:
+ case SC_BURNING:
+ case SC_COLD:
+ case SC_FROSTMISTY:
+ case SC_DEEP_SLEEP:
+ case SC_FEAR:
+ case SC_MANDRAGORA:
+ case SC__CHAOS:
return 0;
- sc_def = status->luk*100;
- sc_def2 = status->luk*10;
- tick_def = status->vit*100;
- break;
- case SC_BLIND:
- if( sc && sc->data[SC__UNLUCKY] )
- return tick;
- sc_def = (status->vit + status->int_)*50;
- sc_def2 = status->luk*10;
- break;
- case SC_CONFUSION:
- sc_def = (status->str + status->int_)*50;
- sc_def2 = status->luk*10;
- break;
- case SC_ANKLESNARE:
- if(status->mode&MD_BOSS) // Lasts 5 times less on bosses
- tick /= 5;
- sc_def = status->agi*50;
- break;
- case SC_MAGICMIRROR:
- case SC_STONESKIN:
- if (sd) //Duration greatly reduced for players.
- tick /= 15;
- sc_def2 = status_get_lv(bl)*20 + status->vit*25 + status->agi*10; // Lineal Reduction of Rate
- tick_def2 = 0; //No duration reduction
- break;
- case SC_MARSHOFABYSS:
- //5 second (Fixed) + 25 second - {( INT + LUK ) / 20 second }
- tick_def2 = (status->int_ + status->luk)*50;
- break;
- case SC_STASIS:
- //5 second (fixed) + { Stasis Skill level * 5 - (Target's VIT + DEX) / 20 }
- tick_def2 = (status->vit + status->dex)*50;
+ }
+ }
+
+ switch (type) {
+ case SC_STUN:
+ sc_def = st->vit*100;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#ifdef RENEWAL
+ tick_def2 = st->luk*10;
+#endif
+ break;
+ case SC_POISON:
+ case SC_DPOISON:
+ sc_def = st->vit*100;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#ifdef RENEWAL
+ if (sd) {
+ //For players: 60000 - 450*vit - 100*luk
+ tick_def = st->vit*75;
+ tick_def2 = st->luk*100;
+ } else {
+ //For monsters: 30000 - 200*vit
+ tick>>=1;
+ tick_def = (st->vit*200)/3;
+ }
+#endif
+ break;
+ case SC_SILENCE:
+#ifdef RENEWAL
+ sc_def = st->int_*100;
+ sc_def2 = (st->vit + st->luk) * 5 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+ tick_def2 = st->luk * 10;
+#else
+ sc_def = st->vit*100;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#endif
+ break;
+ case SC_BLOODING:
+#ifdef RENEWAL
+ sc_def = st->agi*100;
+ tick_def2 = st->luk*10;
+#else
+ sc_def = st->vit*100;
+#endif
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+ break;
+ case SC_SLEEP:
+ sc_def = st->int_*100;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#ifdef RENEWAL
+ tick_def2 = st->luk*10;
+#endif
+ break;
+ case SC_DEEP_SLEEP:
+ sc_def = st->int_*50;
+ tick_def = 0; // Linear reduction instead
+ tick_def2 = st->int_ * 50 + SCDEF_LVL_CAP(bl, 150) * 50; // kRO balance update lists this formula
+ break;
+ case SC_DEC_AGI:
+ case SC_ADORAMUS:
+ if (sd) tick >>= 1; //Half duration for players.
+ sc_def = st->mdef*100;
+#ifndef RENEWAL
+ sc_def2 = st->luk*10;
+ tick_def2 = 0; //No duration reduction
+#endif
+ tick_def = 0; //No duration reduction
+ break;
+ case SC_STONE:
+ sc_def = st->mdef*100;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+ tick_def = 0; //No duration reduction
+#ifndef RENEWAL
+ tick_def2 = 0; //No duration reduction
+#endif
+ break;
+ case SC_FREEZE:
+ sc_def = st->mdef*100;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+ tick_def = 0; //No duration reduction
+#ifdef RENEWAL
+ tick_def2 = status_get_luk(src) * -10; //Caster can increase final duration with luk
+#else
+ tick_def2 = 0; //No duration reduction
+#endif
+ break;
+ case SC_CURSE:
+ // Special property: immunity when luk is zero
+ if (st->luk == 0)
+ return 0;
+#ifndef RENEWAL
+ // Special property: immunity when luk is greater than level
+ if (st->luk > status->get_lv(bl))
+ return 0;
+#endif
+ sc_def = st->luk*100;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(NULL, src, 99, 10); // Curse only has a level penalty and no resistance
+ tick_def = st->vit*100;
+#ifdef RENEWAL
+ tick_def2 = st->luk*10;
+#endif
+ break;
+ case SC_BLIND:
+ sc_def = (st->vit + st->int_)*50;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#ifdef RENEWAL
+ tick_def2 = st->luk*10;
+#endif
+ break;
+ case SC_CONFUSION:
+ sc_def = (st->str + st->int_)*50;
+ sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#ifdef RENEWAL
+ sc_def2 = -sc_def2; // Reversed sc_def2
+ tick_def2 = st->luk*10;
+#endif
+ break;
+ case SC_ANKLESNARE:
+ if(st->mode&MD_BOSS) // Lasts 5 times less on bosses
+ tick /= 5;
+ sc_def = st->agi*50;
+ break;
+ case SC_MAGICMIRROR:
+ case SC_STONESKIN:
+ if (sd) //Duration greatly reduced for players.
+ tick /= 15;
+ sc_def2 = st->vit*25 + st->agi*10 + SCDEF_LVL_CAP(bl, 99) * 20; // Linear Reduction of Rate
+ tick_def2 = 0; //No duration reduction
+ break;
+ case SC_MARSHOFABYSS:
+ //5 second (Fixed) + 25 second - {( INT + LUK ) / 20 second }
+ tick_def2 = (st->int_ + st->luk)*50;
+ break;
+ case SC_STASIS:
+ //5 second (fixed) + { Stasis Skill level * 5 - (Target's VIT + DEX) / 20 }
+ tick_def2 = (st->vit + st->dex)*50;
+ break;
+ case SC_WHITEIMPRISON:
+ if( tick == 5000 ) // 100% on caster
break;
- if( bl->type == BL_PC )
- tick -= (status_get_lv(bl) / 5 + status->vit / 4 + status->agi / 10)*100;
+ if (bl->type == BL_PC)
+ tick_def2 = st->vit*25 + st->agi*10 + SCDEF_LVL_CAP(bl, 150) * 20;
else
- tick -= (status->vit + status->luk) / 20 * 1000;
+ tick_def2 = (st->vit + st->luk)*50;
break;
case SC_BURNING:
- tick -= 75 * status->luk + 125 * status->agi;
- tick = max(tick,5000); // Minimum Duration 5s.
+ tick_def2 = 75*st->luk + 125*st->agi;
break;
case SC_FROSTMISTY:
- tick -= 1000 * ((status->vit + status->dex) / 20);
- tick = max(tick,6000); // Minimum Duration 10s.
+ tick_def2 = (st->vit + st->dex)*50;
break;
case SC_OBLIVIONCURSE: // 100% - (100 - 0.8 x INT)
- sc_def = 100 - ( 100 - status->int_* 8 / 10 );
- sc_def = max(sc_def, 5); // minimum of 5%
+ sc_def = st->int_*80;
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_LEECHESEND:
+ tick_def2 = (st->vit + st->luk) * 500;
break;
case SC_WUGBITE: // {(Base Success chance) - (Target's AGI / 4)}
- rate -= status->agi*100/4;
- rate = max(rate,5000); // minimum of 50%
+ sc_def2 = st->agi*25;
break;
case SC_ELECTRICSHOCKER:
- if( bl->type == BL_MOB )
- tick -= 1000 * (status->agi/10);
+ tick_def2 = (st->vit + st->agi) * 70;
+ break;
+ case SC_COLD:
+ tick_def2 = st->vit*100 + status->get_lv(bl)*20;
break;
- case SC_CRYSTALIZE:
- tick -= (1000*(status->vit/10))+(status_get_lv(bl)/50);
+ case SC_VACUUM_EXTREME:
+ tick_def2 = st->str*50;
break;
case SC_MANDRAGORA:
- sc_def = (status->vit+status->luk)/5;
+ sc_def = (st->vit + st->luk)*20;
+ break;
+ case SC_SIREN:
+ tick_def2 = (status->get_lv(bl) * 100) + ((bl->type == BL_PC)?((TBL_PC*)bl)->status.job_level : 0);
break;
case SC_KYOUGAKU:
- tick -= 1000 * status_get_int(bl) / 20;
+ tick_def2 = st->int_ * 50;
+ break;
+ case SC_NEEDLE_OF_PARALYZE:
+ tick_def2 = (st->vit + st->luk) * 50;
break;
- case SC_NEEDLE_OF_PARALYZE:
- tick -= 50 * (status->vit + status->luk); //(1000/20);
- break;
default:
//Effect that cannot be reduced? Likely a buff.
if (!(rnd()%10000 < rate))
return 0;
- return tick?tick:1;
+ return tick ? tick : 1;
}
if (sd) {
@@ -6376,11 +6609,16 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
sc_def += sc->data[SC_SIEGFRIED]->val3*100; //Status resistance.
}
- //When no tick def, reduction is the same for both.
- if(tick_def < 0)
+ //When tick def not set, reduction is the same for both.
+ if(tick_def == -1)
tick_def = sc_def;
- if(tick_def2 < 0)
+ if(tick_def2 == -1) {
+#ifdef RENEWAL
+ tick_def2 = 0;
+#else
tick_def2 = sc_def2;
+#endif
+ }
//Natural resistance
if (!(flag&8)) {
@@ -6389,9 +6627,12 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
//Minimum chances
switch (type) {
- case SC_WUGBITE:
- rate = max(rate, 5000); //Minimum of 50%
- break;
+ case SC_OBLIVIONCURSE:
+ rate = max(rate,500); //Minimum of 5%
+ break;
+ case SC_WUGBITE:
+ rate = max(rate,5000); //Minimum of 50%
+ break;
}
//Item resistance (only applies to rate%)
@@ -6402,6 +6643,9 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
if( sd->sc.data[SC_TARGET_BLOOD] )
rate -= rate*sd->sc.data[SC_TARGET_BLOOD]->val1/100;
}
+
+ //Aegis accuracy
+ if(rate > 0 && rate%10 != 0) rate += (10 - rate%10);
}
if (!(rnd()%10000 < rate))
@@ -6419,61 +6663,79 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
//Minimum durations
switch (type) {
- case SC_ANKLESNARE:
- case SC_MARSHOFABYSS:
- case SC_STASIS:
- tick = max(tick, 5000); //Minimum duration 5s
- break;
- case SC_BURNING:
- case SC_FROSTMISTY:
- tick = max(tick, 10000); //Minimum duration 10s
- break;
- default:
- //Skills need to trigger even if the duration is reduced below 1ms
- tick = max(tick, 1);
- break;
+ case SC_ANKLESNARE:
+ case SC_BURNING:
+ case SC_MARSHOFABYSS:
+ case SC_STASIS:
+ case SC_DEEP_SLEEP:
+ tick = max(tick, 5000); //Minimum duration 5s
+ break;
+ case SC_FROSTMISTY:
+ tick = max(tick, 6000);
+ break;
+ default:
+ //Skills need to trigger even if the duration is reduced below 1ms
+ tick = max(tick, 1);
+ break;
}
return tick;
+#undef SCDEF_LVL_CAP
+#undef SCDEF_LVL_DIFF
}
/* [Ind/Hercules] fast-checkin sc-display array */
void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) {
- struct sc_display_entry *entry = ers_alloc(pc_sc_display_ers, struct sc_display_entry);
+ struct sc_display_entry *entry;
+ int i;
+
+ for( i = 0; i < sd->sc_display_count; i++ ) {
+ if( sd->sc_display[i]->type == type )
+ break;
+ }
+ if( i != sd->sc_display_count ) {
+ sd->sc_display[i]->val1 = dval1;
+ sd->sc_display[i]->val2 = dval2;
+ sd->sc_display[i]->val3 = dval3;
+ return;
+ }
+
+ entry = ers_alloc(pc->sc_display_ers, struct sc_display_entry);
+
entry->type = type;
entry->val1 = dval1;
entry->val2 = dval2;
entry->val3 = dval3;
-
+
RECREATE(sd->sc_display, struct sc_display_entry *, ++sd->sc_display_count);
sd->sc_display[ sd->sc_display_count - 1 ] = entry;
}
void status_display_remove(struct map_session_data *sd, enum sc_type type) {
int i;
-
+
for( i = 0; i < sd->sc_display_count; i++ ) {
if( sd->sc_display[i]->type == type )
break;
}
-
+
if( i != sd->sc_display_count ) {
int cursor;
-
- ers_free(pc_sc_display_ers, sd->sc_display[i]);
+
+ ers_free(pc->sc_display_ers, sd->sc_display[i]);
sd->sc_display[i] = NULL;
-
+
/* the all-mighty compact-o-matic */
for( i = 0, cursor = 0; i < sd->sc_display_count; i++ ) {
if( sd->sc_display[i] == NULL )
continue;
-
+
if( i != cursor ) {
sd->sc_display[cursor] = sd->sc_display[i];
}
-
+
cursor++;
}
-
+
if( !(sd->sc_display_count = cursor) ) {
aFree(sd->sc_display);
sd->sc_display = NULL;
@@ -6481,30 +6743,29 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) {
}
}
/*==========================================
- * Starts a status change.
- * 'type' = type, 'val1~4' depend on the type.
- * 'rate' = base success rate. 10000 = 100%
- * 'tick' is base duration
- * 'flag':
- * &1: Cannot be avoided (it has to start)
- * &2: Tick should not be reduced (by vit, luk, lv, etc)
- * &4: sc_data loaded, no value has to be altered.
- * &8: rate should not be reduced
- *------------------------------------------*/
-int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag) {
+* Starts a status change.
+* 'type' = type, 'val1~4' depend on the type.
+* 'rate' = base success rate. 10000 = 100%
+* 'tick' is base duration
+* 'flag':
+* &1: Cannot be avoided (it has to start)
+* &2: Tick should not be reduced (by vit, luk, lv, etc)
+* &4: sc_data loaded, no value has to be altered.
+* &8: rate should not be reduced
+*------------------------------------------*/
+int status_change_start(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag) {
struct map_session_data *sd = NULL;
struct status_change* sc;
struct status_change_entry* sce;
- struct status_data *status;
+ struct status_data *st;
struct view_data *vd;
int opt_flag, calc_flag, undead_flag, val_flag = 0, tick_time = 0;
nullpo_ret(bl);
- sc = status_get_sc(bl);
- status = status_get_status_data(bl);
+ sc = status->get_sc(bl);
+ st = status->get_status_data(bl);
- if( type <= SC_NONE || type >= SC_MAX )
- {
+ if( type <= SC_NONE || type >= SC_MAX ) {
ShowError("status_change_start: invalid status change (%d)!\n", type);
return 0;
}
@@ -6512,62 +6773,81 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if( !sc )
return 0; //Unable to receive status changes
- if( status_isdead(bl) && type != SC_NOCHAT ) // SC_NOCHAT should work even on dead characters
+ if( status->isdead(bl) && type != SC_NOCHAT ) // SC_NOCHAT should work even on dead characters
return 0;
- if( bl->type == BL_MOB)
- {
+ if( bl->type == BL_MOB) {
struct mob_data *md = BL_CAST(BL_MOB,bl);
if(md && (md->class_ == MOBID_EMPERIUM || mob_is_battleground(md)) && type != SC_SAFETYWALL && type != SC_PNEUMA)
return 0; //Emperium/BG Monsters can't be afflicted by status changes
- // if(md && mob_is_gvg(md) && status_sc2scb_flag(type)&SCB_MAXHP)
- // return 0; //prevent status addinh hp to gvg mob (like bloodylust=hp*3 etc...
+ //if(md && mob_is_gvg(md) && status->sc2scb_flag(type)&SCB_MAXHP)
+ // return 0; //prevent status addinh hp to gvg mob (like bloodylust=hp*3 etc...
}
if( sc->data[SC_REFRESH] ) {
if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed.
return 0; // Immune to status ailements
switch( type ) {
- case SC_QUAGMIRE://Tester said it protects against this and decrease agi.
- case SC_DEC_AGI:
- case SC_BURNING:
- case SC_FROSTMISTY:
- //case SC_WHITEIMPRISON://Need confirm. Protected against this in the past. [Rytech]
- case SC_MARSHOFABYSS:
- case SC_TOXIN:
- case SC_PARALYSE:
- case SC_VENOMBLEED:
- case SC_MAGICMUSHROOM:
- case SC_DEATHHURT:
- case SC_PYREXIA:
- case SC_OBLIVIONCURSE:
- case SC_LEECHESEND:
- case SC_CRYSTALIZE: ////08/31/2011 - Class Balance Changes
- case SC_DEEP_SLEEP:
- case SC_MANDRAGORA:
- return 0;
+ case SC_DEEP_SLEEP:
+ case SC__CHAOS:
+ case SC_BURNING:
+ case SC_STUN:
+ case SC_SLEEP:
+ case SC_CURSE:
+ case SC_STONE:
+ case SC_POISON:
+ case SC_BLIND:
+ case SC_SILENCE:
+ case SC_BLOODING:
+ case SC_FREEZE:
+ case SC_FROSTMISTY:
+ case SC_COLD:
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_OBLIVIONCURSE:
+ case SC_MARSHOFABYSS:
+ case SC_MANDRAGORA:
+ return 0;
}
- }
- else if( sc->data[SC_INSPIRATION] ) {
+ } else if( sc->data[SC_INSPIRATION] ) {
if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX )
return 0; // Immune to status ailements
switch( type ) {
- case SC_DEEP_SLEEP:
- case SC_SATURDAY_NIGHT_FEVER:
- case SC_PYREXIA:
- case SC_DEATHHURT:
- case SC_MAGICMUSHROOM:
- case SC_VENOMBLEED:
+ case SC_POISON:
+ case SC_BLIND:
+ case SC_STUN:
+ case SC_SILENCE:
+ case SC__CHAOS:
+ case SC_STONE:
+ case SC_SLEEP:
+ case SC_BLOODING:
+ case SC_CURSE:
+ case SC_BURNING:
+ case SC_FROSTMISTY:
+ case SC_FREEZE:
+ case SC_COLD:
+ case SC_FEAR:
case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
case SC_OBLIVIONCURSE:
case SC_LEECHESEND:
+ case SC_DEEP_SLEEP:
+ case SC_SATURDAY_NIGHT_FEVER:
+ case SC__BODYPAINT:
case SC__ENERVATION:
case SC__GROOMY:
+ case SC__IGNORANCE:
case SC__LAZINESS:
case SC__UNLUCKY:
case SC__WEAKNESS:
- case SC__BODYPAINT:
- case SC__IGNORANCE:
return 0;
}
}
@@ -6575,308 +6855,304 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
sd = BL_CAST(BL_PC, bl);
//Adjust tick according to status resistances
- if( !(flag&(1|4)) )
- {
- tick = status_get_sc_def(bl, type, rate, tick, flag);
+ if( !(flag&(1|4)) ) {
+ tick = status->get_sc_def(src, bl, type, rate, tick, flag);
if( !tick ) return 0;
}
- undead_flag = battle->check_undead(status->race,status->def_ele);
+ undead_flag = battle->check_undead(st->race,st->def_ele);
//Check for inmunities / sc fails
switch (type) {
- case SC_ANGRIFFS_MODUS:
- case SC_GOLDENE_FERSE:
- if ((type==SC_GOLDENE_FERSE && sc->data[SC_ANGRIFFS_MODUS])
- || (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE])
- )
- return 0;
- case SC_STONE:
- if(sc->data[SC_POWER_OF_GAIA])
- return 0;
- case SC_FREEZE:
- //Undead are immune to Freeze/Stone
- if (undead_flag && !(flag&1))
- return 0;
- case SC_DEEP_SLEEP:
- case SC_SLEEP:
- case SC_STUN:
- case SC_FROSTMISTY:
- case SC_CRYSTALIZE:
- if (sc->opt1)
- return 0; //Cannot override other opt1 status changes. [Skotlex]
- if((type == SC_FREEZE || type == SC_FROSTMISTY || type == SC_CRYSTALIZE) && sc->data[SC_WARMER])
- return 0; //Immune to Frozen and Freezing status if under Warmer status. [Jobbie]
- break;
-
- //There all like berserk, do not everlap each other
- case SC__BLOODYLUST:
- if(!sd) return 0; //should only affect player
- case SC_BERSERK:
- if (((type == SC_BERSERK) && (sc->data[SC_SATURDAY_NIGHT_FEVER] || sc->data[SC__BLOODYLUST]))
- || ((type == SC__BLOODYLUST) && (sc->data[SC_SATURDAY_NIGHT_FEVER] || sc->data[SC_BERSERK]))
- )
- return 0;
- break;
+ case SC_DRUMBATTLE:
+ case SC_NIBELUNGEN:
+ case SC_INTOABYSS:
+ case SC_SIEGFRIED:
+ if( sd && !sd->status.party_id )
+ return 0;
+ break;
+ case SC_ANGRIFFS_MODUS:
+ case SC_GOLDENE_FERSE:
+ if ((type==SC_GOLDENE_FERSE && sc->data[SC_ANGRIFFS_MODUS])
+ || (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE])
+ )
+ return 0;
+ case SC_VACUUM_EXTREME:
+ if(sc->data[SC_HALLUCINATIONWALK] || sc->data[SC_HOVERING])
+ return 0;
+ break;
+ case SC_STONE:
+ if(sc->data[SC_POWER_OF_GAIA])
+ return 0;
+ case SC_FREEZE:
+ //Undead are immune to Freeze/Stone
+ if (undead_flag && !(flag&1))
+ return 0;
+ case SC_SLEEP:
+ case SC_STUN:
+ case SC_FROSTMISTY:
+ case SC_COLD:
+ if (sc->opt1)
+ return 0; //Cannot override other opt1 status changes. [Skotlex]
+ if((type == SC_FREEZE || type == SC_FROSTMISTY || type == SC_COLD) && sc->data[SC_WARMER])
+ return 0; //Immune to Frozen and Freezing status if under Warmer status. [Jobbie]
+ break;
- case SC_BURNING:
- if(sc->opt1 || sc->data[SC_FROSTMISTY])
- return 0;
- break;
+ //There all like berserk, do not everlap each other
+ case SC_BERSERK:
+ if( sc->data[SC__BLOODYLUST] )
+ return 0;
+ break;
- case SC_CRUCIS:
- //Only affects demons and undead element (but not players)
- if((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC)
- return 0;
- break;
- case SC_LEXAETERNA:
- if( (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) || sc->data[SC_FREEZE] )
- return 0;
- break;
- case SC_KYRIE:
- if (bl->type == BL_MOB)
- return 0;
- break;
- case SC_OVERTHRUST:
- if (sc->data[SC_OVERTHRUSTMAX])
- return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex]
- case SC_OVERTHRUSTMAX:
- if( sc->option&OPTION_MADOGEAR )
- return 0;//Overthrust and Overthrust Max cannot be used on Mado Gear [Ind]
- break;
- case SC_ADRENALINE:
- if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE)))
- return 0;
- if (sc->data[SC_QUAGMIRE] ||
- sc->data[SC_DEC_AGI] ||
- sc->option&OPTION_MADOGEAR //Adrenaline doesn't affect Mado Gear [Ind]
- )
- return 0;
- break;
- case SC_ADRENALINE2:
- if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE2)))
- return 0;
- if (sc->data[SC_QUAGMIRE] ||
- sc->data[SC_DEC_AGI]
- )
- return 0;
- break;
- case SC_MAGNIFICAT:
- if( sc->data[SC_OFFERTORIUM] || sc->option&OPTION_MADOGEAR ) //Mado is immune to magnificat
- return 0;
- break;
- case SC_ONEHANDQUICKEN:
- case SC_MER_QUICKEN:
- case SC_TWOHANDQUICKEN:
- if(sc->data[SC_DEC_AGI])
- return 0;
+ case SC_BURNING:
+ if(sc->opt1 || sc->data[SC_FROSTMISTY])
+ return 0;
+ break;
- case SC_INC_AGI:
- if(sd && pc_issit(sd)){
- pc->setstand(sd);
- clif->standing(&sd->bl);
- }
-
- case SC_CONCENTRATION:
- case SC_SPEARQUICKEN:
- case SC_TRUESIGHT:
- case SC_WINDWALK:
- case SC_CARTBOOST:
- case SC_ASSNCROS:
- if (sc->data[SC_QUAGMIRE])
- return 0;
- if(sc->option&OPTION_MADOGEAR)
- return 0;//Mado is immune to increase agi, wind walk, cart boost, etc (others above) [Ind]
- break;
- case SC_CLOAKING:
- //Avoid cloaking with no wall and low skill level. [Skotlex]
- //Due to the cloaking card, we have to check the wall versus to known
- //skill level rather than the used one. [Skotlex]
- //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL))
- if( sd && pc->checkskill(sd, AS_CLOAKING) < 3 && !skill->check_cloaking(bl,NULL) )
- return 0;
- break;
- case SC_MODECHANGE:
- {
- int mode;
- struct status_data *bstatus = status_get_base_status(bl);
- if (!bstatus) return 0;
- if (sc->data[type])
- { //Pile up with previous values.
- if(!val2) val2 = sc->data[type]->val2;
- val3 |= sc->data[type]->val3;
- val4 |= sc->data[type]->val4;
- }
- mode = val2?val2:bstatus->mode; //Base mode
- if (val4) mode&=~val4; //Del mode
- if (val3) mode|= val3; //Add mode
- if (mode == bstatus->mode) { //No change.
- if (sc->data[type]) //Abort previous status
- return status_change_end(bl, type, INVALID_TIMER);
- return 0;
- }
- }
- break;
- //Strip skills, need to divest something or it fails.
- case SC_NOEQUIPWEAPON:
- if (sd && !(flag&4)) { //apply sc anyway if loading saved sc_data
- int i;
- opt_flag = 0; //Reuse to check success condition.
- if(sd->bonus.unstripable_equip&EQP_WEAPON)
+ case SC_CRUCIS:
+ //Only affects demons and undead element (but not players)
+ if((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC)
+ return 0;
+ break;
+ case SC_LEXAETERNA:
+ if( (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) || sc->data[SC_FREEZE] )
+ return 0;
+ break;
+ case SC_KYRIE:
+ if (bl->type == BL_MOB)
+ return 0;
+ break;
+ case SC_OVERTHRUST:
+ if (sc->data[SC_OVERTHRUSTMAX])
+ return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex]
+ case SC_OVERTHRUSTMAX:
+ if( sc->option&OPTION_MADOGEAR )
+ return 0;//Overthrust and Overthrust Max cannot be used on Mado Gear [Ind]
+ break;
+ case SC_ADRENALINE:
+ if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE)))
+ return 0;
+ if (sc->data[SC_QUAGMIRE] ||
+ sc->data[SC_DEC_AGI] ||
+ sc->option&OPTION_MADOGEAR //Adrenaline doesn't affect Mado Gear [Ind]
+ )
+ return 0;
+ break;
+ case SC_ADRENALINE2:
+ if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE2)))
+ return 0;
+ if (sc->data[SC_QUAGMIRE] ||
+ sc->data[SC_DEC_AGI]
+ )
+ return 0;
+ break;
+ case SC_MAGNIFICAT:
+ if( sc->data[SC_OFFERTORIUM] || sc->option&OPTION_MADOGEAR ) //Mado is immune to magnificat
+ return 0;
+ break;
+ case SC_ONEHANDQUICKEN:
+ case SC_MER_QUICKEN:
+ case SC_TWOHANDQUICKEN:
+ if(sc->data[SC_DEC_AGI])
return 0;
- i = sd->equip_index[EQI_HAND_R];
- if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) {
- opt_flag|=2;
- pc->unequipitem(sd,i,3);
+ case SC_CONCENTRATION:
+ case SC_SPEARQUICKEN:
+ case SC_TRUESIGHT:
+ case SC_WINDWALK:
+ case SC_CARTBOOST:
+ case SC_ASSNCROS:
+ if(sc->option&OPTION_MADOGEAR)
+ return 0;//Mado is immune to wind walk, cart boost, etc (others above) [Ind]
+ case SC_INC_AGI:
+ if (sc->data[SC_QUAGMIRE])
+ return 0;
+ break;
+ case SC_CLOAKING:
+ if (sd && !skill->can_cloak(sd))
+ return 0;
+ break;
+ case SC_MODECHANGE:
+ {
+ int mode;
+ struct status_data *bst = status->get_base_status(bl);
+ if (!bst) return 0;
+ if (sc->data[type]) {
+ //Pile up with previous values.
+ if(!val2) val2 = sc->data[type]->val2;
+ val3 |= sc->data[type]->val3;
+ val4 |= sc->data[type]->val4;
+ }
+ mode = val2 ? val2 : bst->mode; //Base mode
+ if (val4) mode&=~val4; //Del mode
+ if (val3) mode|= val3; //Add mode
+ if (mode == bst->mode) { //No change.
+ if (sc->data[type]) //Abort previous status
+ return status_change_end(bl, type, INVALID_TIMER);
+ return 0;
}
- if (!opt_flag) return 0;
}
- if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
- break;
- case SC_NOEQUIPSHIELD:
- if( val2 == 1 ) val2 = 0; //GX effect. Do not take shield off..
- else
- if (sd && !(flag&4)) {
- int i;
- if(sd->bonus.unstripable_equip&EQP_SHIELD)
+ break;
+ //Strip skills, need to divest something or it fails.
+ case SC_NOEQUIPWEAPON:
+ if (sd && !(flag&4)) { //apply sc anyway if loading saved sc_data
+ int i;
+ opt_flag = 0; //Reuse to check success condition.
+ if(sd->bonus.unstripable_equip&EQP_WEAPON)
+ return 0;
+
+ i = sd->equip_index[EQI_HAND_R];
+ if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) {
+ opt_flag|=2;
+ pc->unequipitem(sd,i,3);
+ }
+ if (!opt_flag) return 0;
+ }
+ if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
+ break;
+ case SC_NOEQUIPSHIELD:
+ if( val2 == 1 ) val2 = 0; //GX effect. Do not take shield off..
+ else
+ if (sd && !(flag&4)) {
+ int i;
+ if(sd->bonus.unstripable_equip&EQP_SHIELD)
+ return 0;
+ i = sd->equip_index[EQI_HAND_L];
+ if ( i < 0 || !sd->inventory_data[i] || sd->inventory_data[i]->type != IT_ARMOR )
+ return 0;
+ pc->unequipitem(sd,i,3);
+ }
+ if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
+ break;
+ case SC_NOEQUIPARMOR:
+ if (sd && !(flag&4)) {
+ int i;
+ if(sd->bonus.unstripable_equip&EQP_ARMOR)
+ return 0;
+ i = sd->equip_index[EQI_ARMOR];
+ if ( i < 0 || !sd->inventory_data[i] )
+ return 0;
+ pc->unequipitem(sd,i,3);
+ }
+ if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
+ break;
+ case SC_NOEQUIPHELM:
+ if (sd && !(flag&4)) {
+ int i;
+ if(sd->bonus.unstripable_equip&EQP_HELM)
+ return 0;
+ i = sd->equip_index[EQI_HEAD_TOP];
+ if ( i < 0 || !sd->inventory_data[i] )
+ return 0;
+ pc->unequipitem(sd,i,3);
+ }
+ if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
+ break;
+ case SC_MER_FLEE:
+ case SC_MER_ATK:
+ case SC_MER_HP:
+ case SC_MER_SP:
+ case SC_MER_HIT:
+ if( bl->type != BL_MER )
+ return 0; // Stats only for Mercenaries
+ break;
+ case SC_FOOD_STR:
+ if (sc->data[SC_FOOD_STR_CASH] && sc->data[SC_FOOD_STR_CASH]->val1 > val1)
return 0;
- i = sd->equip_index[EQI_HAND_L];
- if ( i < 0 || !sd->inventory_data[i] || sd->inventory_data[i]->type != IT_ARMOR )
+ break;
+ case SC_FOOD_AGI:
+ if (sc->data[SC_FOOD_AGI_CASH] && sc->data[SC_FOOD_AGI_CASH]->val1 > val1)
return 0;
- pc->unequipitem(sd,i,3);
- }
- if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
- break;
- case SC_NOEQUIPARMOR:
- if (sd && !(flag&4)) {
- int i;
- if(sd->bonus.unstripable_equip&EQP_ARMOR)
+ break;
+ case SC_FOOD_VIT:
+ if (sc->data[SC_FOOD_VIT_CASH] && sc->data[SC_FOOD_VIT_CASH]->val1 > val1)
return 0;
- i = sd->equip_index[EQI_ARMOR];
- if ( i < 0 || !sd->inventory_data[i] )
+ break;
+ case SC_FOOD_INT:
+ if (sc->data[SC_FOOD_INT_CASH] && sc->data[SC_FOOD_INT_CASH]->val1 > val1)
return 0;
- pc->unequipitem(sd,i,3);
- }
- if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
- break;
- case SC_NOEQUIPHELM:
- if (sd && !(flag&4)) {
- int i;
- if(sd->bonus.unstripable_equip&EQP_HELM)
+ break;
+ case SC_FOOD_DEX:
+ if (sc->data[SC_FOOD_DEX_CASH] && sc->data[SC_FOOD_DEX_CASH]->val1 > val1)
return 0;
- i = sd->equip_index[EQI_HEAD_TOP];
- if ( i < 0 || !sd->inventory_data[i] )
+ break;
+ case SC_FOOD_LUK:
+ if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > val1)
return 0;
- pc->unequipitem(sd,i,3);
- }
- if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
- break;
- case SC_MER_FLEE:
- case SC_MER_ATK:
- case SC_MER_HP:
- case SC_MER_SP:
- case SC_MER_HIT:
- if( bl->type != BL_MER )
- return 0; // Stats only for Mercenaries
- break;
- case SC_FOOD_STR:
- if (sc->data[SC_FOOD_STR_CASH] && sc->data[SC_FOOD_STR_CASH]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_AGI:
- if (sc->data[SC_FOOD_AGI_CASH] && sc->data[SC_FOOD_AGI_CASH]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_VIT:
- if (sc->data[SC_FOOD_VIT_CASH] && sc->data[SC_FOOD_VIT_CASH]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_INT:
- if (sc->data[SC_FOOD_INT_CASH] && sc->data[SC_FOOD_INT_CASH]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_DEX:
- if (sc->data[SC_FOOD_DEX_CASH] && sc->data[SC_FOOD_DEX_CASH]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_LUK:
- if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_STR_CASH:
- if (sc->data[SC_FOOD_STR] && sc->data[SC_FOOD_STR]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_AGI_CASH:
- if (sc->data[SC_FOOD_AGI] && sc->data[SC_FOOD_AGI]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_VIT_CASH:
- if (sc->data[SC_FOOD_VIT] && sc->data[SC_FOOD_VIT]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_INT_CASH:
- if (sc->data[SC_FOOD_INT] && sc->data[SC_FOOD_INT]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_DEX_CASH:
- if (sc->data[SC_FOOD_DEX] && sc->data[SC_FOOD_DEX]->val1 > val1)
- return 0;
- break;
- case SC_FOOD_LUK_CASH:
- if (sc->data[SC_FOOD_LUK] && sc->data[SC_FOOD_LUK]->val1 > val1)
- return 0;
- break;
- case SC_CAMOUFLAGE:
- if( sd && pc->checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill->check_camouflage(bl,NULL) )
- return 0;
- break;
- case SC__STRIPACCESSARY:
- if( sd ) {
- int i = -1;
- if( !(sd->bonus.unstripable_equip&EQI_ACC_L) ) {
- i = sd->equip_index[EQI_ACC_L];
- if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR )
- pc->unequipitem(sd,i,3); //L-Accessory
- } if( !(sd->bonus.unstripable_equip&EQI_ACC_R) ) {
- i = sd->equip_index[EQI_ACC_R];
- if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR )
- pc->unequipitem(sd,i,3); //R-Accessory
- }
- if( i < 0 )
+ break;
+ case SC_FOOD_STR_CASH:
+ if (sc->data[SC_FOOD_STR] && sc->data[SC_FOOD_STR]->val1 > val1)
return 0;
- }
- if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
- break;
- case SC_TOXIN:
- case SC_PARALYSE:
- case SC_VENOMBLEED:
- case SC_MAGICMUSHROOM:
- case SC_DEATHHURT:
- case SC_PYREXIA:
- case SC_OBLIVIONCURSE:
- case SC_LEECHESEND:
- { // it doesn't stack or even renewed
- int i = SC_TOXIN;
- for(; i<= SC_LEECHESEND; i++)
- if(sc->data[i]) return 0;
- }
- break;
- case SC_SATURDAY_NIGHT_FEVER:
- if (sc->data[SC_BERSERK] || sc->data[SC_INSPIRATION] || sc->data[SC__BLOODYLUST])
- return 0;
- break;
- case SC_OFFERTORIUM:
- if (sc->data[SC_MAGNIFICAT])
- return 0;
- break;
+ break;
+ case SC_FOOD_AGI_CASH:
+ if (sc->data[SC_FOOD_AGI] && sc->data[SC_FOOD_AGI]->val1 > val1)
+ return 0;
+ break;
+ case SC_FOOD_VIT_CASH:
+ if (sc->data[SC_FOOD_VIT] && sc->data[SC_FOOD_VIT]->val1 > val1)
+ return 0;
+ break;
+ case SC_FOOD_INT_CASH:
+ if (sc->data[SC_FOOD_INT] && sc->data[SC_FOOD_INT]->val1 > val1)
+ return 0;
+ break;
+ case SC_FOOD_DEX_CASH:
+ if (sc->data[SC_FOOD_DEX] && sc->data[SC_FOOD_DEX]->val1 > val1)
+ return 0;
+ break;
+ case SC_FOOD_LUK_CASH:
+ if (sc->data[SC_FOOD_LUK] && sc->data[SC_FOOD_LUK]->val1 > val1)
+ return 0;
+ break;
+ case SC_CAMOUFLAGE:
+ if( sd && pc->checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill->check_camouflage(bl,NULL) )
+ return 0;
+ break;
+ case SC__STRIPACCESSARY:
+ if( sd ) {
+ int i = -1;
+ if( !(sd->bonus.unstripable_equip&EQP_ACC_L) ) {
+ i = sd->equip_index[EQI_ACC_L];
+ if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR )
+ pc->unequipitem(sd,i,3); //L-Accessory
+ } if( !(sd->bonus.unstripable_equip&EQP_ACC_R) ) {
+ i = sd->equip_index[EQI_ACC_R];
+ if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR )
+ pc->unequipitem(sd,i,3); //R-Accessory
+ }
+ if( i < 0 )
+ return 0;
+ }
+ if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
+ break;
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_OBLIVIONCURSE:
+ case SC_LEECHESEND:
+ { // it doesn't stack or even renewed
+ int i = SC_TOXIN;
+ for(; i<= SC_LEECHESEND; i++)
+ if(sc->data[i]) return 0;
+ }
+ break;
+ case SC_MAGNETICFIELD:
+ if(sc->data[SC_HOVERING])
+ return 0;
+ break;
+ case SC_OFFERTORIUM:
+ if (sc->data[SC_MAGNIFICAT])
+ return 0;
+ break;
}
//Check for BOSS resistances
- if(status->mode&MD_BOSS && !(flag&1)) {
- if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX)
- return 0;
- switch (type) {
+ if(st->mode&MD_BOSS && !(flag&1)) {
+ if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX)
+ return 0;
+ switch (type) {
case SC_BLESSING:
case SC_DEC_AGI:
case SC_PROVOKE:
@@ -6887,14 +7163,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_ROKISWEIL:
case SC_FOGWALL:
case SC_FROSTMISTY:
- case SC_BURNING:
+ case SC_BURNING:
case SC_MARSHOFABYSS:
case SC_ADORAMUS:
case SC_NEEDLE_OF_PARALYZE:
case SC_DEEP_SLEEP:
- case SC_CRYSTALIZE:
+ case SC_COLD:
- // Exploit prevention - kRO Fix
+ // Exploit prevention - kRO Fix
case SC_PYREXIA:
case SC_DEATHHURT:
case SC_TOXIN:
@@ -6904,247 +7180,255 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_OBLIVIONCURSE:
case SC_LEECHESEND:
- // Ranger Effects
+ // Ranger Effects
case SC_WUGBITE:
case SC_ELECTRICSHOCKER:
case SC_MAGNETICFIELD:
+ // Masquerades
+ case SC__ENERVATION:
+ case SC__GROOMY:
+ case SC__LAZINESS:
+ case SC__UNLUCKY:
+ case SC__WEAKNESS:
+ case SC__IGNORANCE:
+
+ // Other Effects
+ case SC_VACUUM_EXTREME:
+
return 0;
}
}
//Before overlapping fail, one must check for status cured.
switch (type) {
- case SC_BLESSING:
- //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM
- //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm]
- if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) {
- status_change_end(bl, SC_CURSE, INVALID_TIMER);
- if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
- status_change_end(bl, SC_STONE, INVALID_TIMER);
- }
- break;
- case SC_INC_AGI:
- status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
- break;
- case SC_QUAGMIRE:
- status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER);
- status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER);
- status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
- //Also blocks the ones below...
- case SC_DEC_AGI:
- status_change_end(bl, SC_CARTBOOST, INVALID_TIMER);
- //Also blocks the ones below...
- case SC_DONTFORGETME:
- status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
- status_change_end(bl, SC_ADRENALINE, INVALID_TIMER);
- status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER);
- status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_ACCELERATION, INVALID_TIMER);
- break;
- case SC_ONEHANDQUICKEN:
- //Removes the Aspd potion effect, as reported by Vicious. [Skotlex]
- status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
- break;
- case SC_OVERTHRUSTMAX:
- //Cancels Normal Overthrust. [Skotlex]
- status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER);
- break;
- case SC_KYRIE:
- //Cancels Assumptio
- status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
- break;
- case SC_DELUGE:
- if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND])
- status_change_end(bl, SC_BLIND, INVALID_TIMER);
- break;
- case SC_SILENCE:
- if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF)
- status_change_end(bl, SC_GOSPEL, INVALID_TIMER);
- break;
- case SC_HIDING:
- status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER);
- status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
- break;
- case SC__BLOODYLUST:
- case SC_BERSERK:
- if(battle_config.berserk_cancels_buffs) {
- status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
+ case SC_BLESSING:
+ //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM
+ //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm]
+ if ((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC) {
+ status_change_end(bl, SC_CURSE, INVALID_TIMER);
+ if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
+ status_change_end(bl, SC_STONE, INVALID_TIMER);
+ }
+ break;
+ case SC_INC_AGI:
+ status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
+ break;
+ case SC_QUAGMIRE:
+ status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER);
+ status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER);
+ status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
+ //Also blocks the ones below...
+ case SC_DEC_AGI:
+ case SC_ADORAMUS:
+ status_change_end(bl, SC_CARTBOOST, INVALID_TIMER);
+ //Also blocks the ones below...
+ case SC_DONTFORGETME:
+ status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
+ status_change_end(bl, SC_ADRENALINE, INVALID_TIMER);
+ status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER);
+ status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER);
status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
- status_change_end(bl, SC_PARRYING, INVALID_TIMER);
- status_change_end(bl, SC_AURABLADE, INVALID_TIMER);
+ status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER);
- }
-#ifdef RENEWAL
- else {
- status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
- }
-#endif
- break;
- case SC_ASSUMPTIO:
- status_change_end(bl, SC_KYRIE, INVALID_TIMER);
- status_change_end(bl, SC_KAITE, INVALID_TIMER);
- break;
- case SC_KAITE:
- status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
- break;
- case SC_CARTBOOST:
- if(sc->data[SC_DEC_AGI])
- { //Cancel Decrease Agi, but take no further effect [Skotlex]
- status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
- return 0;
- }
- break;
- case SC_FUSION:
- status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
- break;
- case SC_GS_ADJUSTMENT:
- status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER);
- break;
- case SC_GS_MADNESSCANCEL:
- status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER);
- break;
- //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up
- case SC_PROPERTYUNDEAD:
- status_change_end(bl, SC_BLESSING, INVALID_TIMER);
- status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
- break;
- case SC_FOOD_STR:
- status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_AGI:
- status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_VIT:
- status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_INT:
- status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_DEX:
- status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_LUK:
- status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_STR_CASH:
- status_change_end(bl, SC_FOOD_STR, INVALID_TIMER);
- break;
- case SC_FOOD_AGI_CASH:
- status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER);
- break;
- case SC_FOOD_VIT_CASH:
- status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER);
- break;
- case SC_FOOD_INT_CASH:
- status_change_end(bl, SC_FOOD_INT, INVALID_TIMER);
- break;
- case SC_FOOD_DEX_CASH:
- status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER);
- break;
- case SC_FOOD_LUK_CASH:
- status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER);
- break;
- case SC_ENDURE:
- if( val4 )
- status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
- break;
- case SC_FIGHTINGSPIRIT:
- status_change_end(bl, type, INVALID_TIMER); // Remove previous one.
- break;
- case SC_MARSHOFABYSS:
- status_change_end(bl, SC_INCAGI, INVALID_TIMER);
- status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
- break;
- case SC_SWING:
- case SC_SYMPHONY_LOVE:
- case SC_MOONLIT_SERENADE:
- case SC_RUSH_WINDMILL:
- case SC_ECHOSONG:
- case SC_HARMONIZE: //group A doesn't overlap
- if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER);
- if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
- if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
- if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
- if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
- if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
- break;
- case SC_SIREN:
- case SC_DEEP_SLEEP:
- case SC_GLOOMYDAY:
- case SC_SONG_OF_MANA:
- case SC_DANCE_WITH_WUG:
- case SC_SATURDAY_NIGHT_FEVER:
- case SC_LERADS_DEW:
- case SC_MELODYOFSINK:
- case SC_BEYOND_OF_WARCRY:
- case SC_UNLIMITED_HUMMING_VOICE: //group B
- if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER);
- if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
- if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
- if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
- if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
- if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER);
- if (type != SC_GLOOMYDAY) {
- status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
- status_change_end(bl, SC_GLOOMYDAY_SK, INVALID_TIMER);
- }
- if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
- if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
- if (type != SC_SATURDAY_NIGHT_FEVER) {
- if (sc->data[SC_SATURDAY_NIGHT_FEVER]) {
- sc->data[SC_SATURDAY_NIGHT_FEVER]->val2 = 0; //mark to not lose hp
- status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER);
- }
- }
- break;
- case SC_REFLECTSHIELD:
- status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER);
- break;
- case SC_LG_REFLECTDAMAGE:
- status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER);
- break;
- case SC_SHIELDSPELL_DEF:
- case SC_SHIELDSPELL_MDEF:
- case SC_SHIELDSPELL_REF:
- status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER);
- if( type != SC_SHIELDSPELL_DEF )
+ status_change_end(bl, SC_ACCELERATION, INVALID_TIMER);
+ break;
+ case SC_ONEHANDQUICKEN:
+ //Removes the Aspd potion effect, as reported by Vicious. [Skotlex]
+ status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
+ break;
+ case SC_OVERTHRUSTMAX:
+ //Cancels Normal Overthrust. [Skotlex]
+ status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER);
+ break;
+ case SC_KYRIE:
+ //Cancels Assumptio
+ status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
+ break;
+ case SC_DELUGE:
+ if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND])
+ status_change_end(bl, SC_BLIND, INVALID_TIMER);
+ break;
+ case SC_SILENCE:
+ if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF)
+ status_change_end(bl, SC_GOSPEL, INVALID_TIMER);
+ break;
+ case SC_HIDING:
+ status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER);
+ status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
+ break;
+ case SC_BERSERK:
+ if( val3 == SC__BLOODYLUST )
+ break;
+ if(battle_config.berserk_cancels_buffs) {
+ status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
+ status_change_end(bl, SC_PARRYING, INVALID_TIMER);
+ status_change_end(bl, SC_AURABLADE, INVALID_TIMER);
+ status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER);
+ }
+ #ifdef RENEWAL
+ else {
+ status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
+ }
+ #endif
+ break;
+ case SC_ASSUMPTIO:
+ status_change_end(bl, SC_KYRIE, INVALID_TIMER);
+ status_change_end(bl, SC_KAITE, INVALID_TIMER);
+ break;
+ case SC_KAITE:
+ status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
+ break;
+ case SC_CARTBOOST:
+ if(sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS])
+ { //Cancel Decrease Agi, but take no further effect [Skotlex]
+ status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
+ status_change_end(bl, SC_ADORAMUS, INVALID_TIMER);
+ return 0;
+ }
+ break;
+ case SC_FUSION:
+ status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
+ break;
+ case SC_GS_ADJUSTMENT:
+ status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER);
+ break;
+ case SC_GS_MADNESSCANCEL:
+ status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER);
+ break;
+ //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up
+ case SC_PROPERTYUNDEAD:
+ status_change_end(bl, SC_BLESSING, INVALID_TIMER);
+ status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
+ break;
+ case SC_FOOD_STR:
+ status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_AGI:
+ status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_VIT:
+ status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_INT:
+ status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_DEX:
+ status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_LUK:
+ status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_STR_CASH:
+ status_change_end(bl, SC_FOOD_STR, INVALID_TIMER);
+ break;
+ case SC_FOOD_AGI_CASH:
+ status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER);
+ break;
+ case SC_FOOD_VIT_CASH:
+ status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER);
+ break;
+ case SC_FOOD_INT_CASH:
+ status_change_end(bl, SC_FOOD_INT, INVALID_TIMER);
+ break;
+ case SC_FOOD_DEX_CASH:
+ status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER);
+ break;
+ case SC_FOOD_LUK_CASH:
+ status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER);
+ break;
+ case SC_ENDURE:
+ if( val4 )
+ status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
+ break;
+ case SC_FIGHTINGSPIRIT:
+ case SC_OVERED_BOOST:
+ status_change_end(bl, type, INVALID_TIMER); // Remove previous one.
+ break;
+ case SC_MARSHOFABYSS:
+ status_change_end(bl, SC_INCAGI, INVALID_TIMER);
+ status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
+ break;
+ //Group A Status (doesn't overlap)
+ case SC_SWING:
+ case SC_SYMPHONY_LOVE:
+ case SC_MOONLIT_SERENADE:
+ case SC_RUSH_WINDMILL:
+ case SC_ECHOSONG:
+ case SC_HARMONIZE:
+ case SC_FRIGG_SONG:
+ if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER);
+ if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
+ if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
+ if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
+ if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
+ if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
+ if (type != SC_FRIGG_SONG) status_change_end(bl, SC_FRIGG_SONG, INVALID_TIMER);
+ break;
+ //Group B Status
+ case SC_SIREN:
+ case SC_DEEP_SLEEP:
+ case SC_SIRCLEOFNATURE:
+ case SC_LERADS_DEW:
+ case SC_MELODYOFSINK:
+ case SC_BEYOND_OF_WARCRY:
+ case SC_UNLIMITED_HUMMING_VOICE:
+ case SC_GLOOMYDAY:
+ case SC_SONG_OF_MANA:
+ case SC_DANCE_WITH_WUG:
+ if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER);
+ if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
+ if (type != SC_SIRCLEOFNATURE) status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER);
+ if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
+ if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
+ if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
+ if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER);
+ if (type != SC_GLOOMYDAY) status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
+ if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
+ if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
+ break;
+ case SC_REFLECTSHIELD:
+ status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER);
+ break;
+ case SC_LG_REFLECTDAMAGE:
+ status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER);
+ break;
+ case SC_SHIELDSPELL_DEF:
+ case SC_SHIELDSPELL_MDEF:
+ case SC_SHIELDSPELL_REF:
+ status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER);
status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER);
- if( type != SC_SHIELDSPELL_MDEF )
status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER);
- if( type != SC_SHIELDSPELL_REF )
status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER);
- break;
- case SC_GENTLETOUCH_ENERGYGAIN:
- case SC_GENTLETOUCH_CHANGE:
- case SC_GENTLETOUCH_REVITALIZE:
- if( type != SC_GENTLETOUCH_REVITALIZE )
- status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER);
- if( type != SC_GENTLETOUCH_ENERGYGAIN )
- status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER);
- if( type != SC_GENTLETOUCH_CHANGE )
- status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER);
- break;
- case SC_INVINCIBLE:
- status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER);
- break;
- case SC_INVINCIBLEOFF:
- status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER);
- break;
- case SC_MAGICPOWER:
- status_change_end(bl, type, INVALID_TIMER);
- break;
+ break;
+ case SC_GENTLETOUCH_ENERGYGAIN:
+ case SC_GENTLETOUCH_CHANGE:
+ case SC_GENTLETOUCH_REVITALIZE:
+ if( type != SC_GENTLETOUCH_REVITALIZE )
+ status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER);
+ if( type != SC_GENTLETOUCH_ENERGYGAIN )
+ status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER);
+ if( type != SC_GENTLETOUCH_CHANGE )
+ status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER);
+ break;
+ case SC_INVINCIBLE:
+ status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER);
+ break;
+ case SC_INVINCIBLEOFF:
+ status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER);
+ break;
+ case SC_MAGICPOWER:
+ status_change_end(bl, type, INVALID_TIMER);
+ break;
}
//Check for overlapping fails
@@ -7182,6 +7466,15 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_MARIONETTE:
case SC_NOCHAT:
case SC_HLIF_CHANGE: //Otherwise your Hp/Sp would get refilled while still within effect of the last invocation.
+ case SC_ABUNDANCE:
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_OBLIVIONCURSE:
+ case SC_LEECHESEND:
case SC__INVISIBILITY:
case SC__ENERVATION:
case SC__GROOMY:
@@ -7189,6 +7482,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC__LAZINESS:
case SC__WEAKNESS:
case SC__UNLUCKY:
+ case SC__CHAOS:
return 0;
case SC_COMBOATTACK:
case SC_DANCING:
@@ -7204,7 +7498,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_ARMOR_RESIST:
break;
case SC_GOSPEL:
- //Must not override a casting gospel char.
+ //Must not override a casting gospel char.
if(sce->val4 == BCT_SELF)
return 0;
if(sce->val1 > val1)
@@ -7220,7 +7514,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
//Kaahi overwrites previous level regardless of existing level.
//Delete timer if it exists.
if (sce->val4 != INVALID_TIMER) {
- iTimer->delete_timer(sce->val4,kaahi_heal_timer);
+ timer->delete(sce->val4,status->kaahi_heal_timer);
sce->val4 = INVALID_TIMER;
}
break;
@@ -7231,7 +7525,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val4 = sce->val4;
break;
case SC_LERADS_DEW:
- if (sc && (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]))
+ if (sc && sc->data[SC_BERSERK])
return 0;
case SC_SHAPESHIFT:
case SC_PROPERTYWALK:
@@ -7251,39 +7545,38 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
}
}
- vd = status_get_viewdata(bl);
- calc_flag = StatusChangeFlagTable[type];
+ vd = status->get_viewdata(bl);
+ calc_flag = status->ChangeFlagTable[type];
if(!(flag&4)) { //&4 - Do not parse val settings when loading SCs
switch(type) {
+ case SC_ADORAMUS:
+ sc_start(src,bl,SC_BLIND,100,val1,skill->get_time(status->sc2skill(type),val1));
+ // Fall through to SC_INC_AGI
case SC_DEC_AGI:
case SC_INC_AGI:
val2 = 2 + val1; //Agi change
break;
case SC_ENDURE:
val2 = 7; // Hit-count [Celest]
- if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && !val4 )
- {
+ if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground && !val4 ) {
struct map_session_data *tsd;
- if( sd )
- {
+ if( sd ) {
int i;
- for( i = 0; i < 5; i++ )
- {
- if( sd->devotion[i] && (tsd = iMap->id2sd(sd->devotion[i])) )
- status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1);
+ for( i = 0; i < 5; i++ ) {
+ if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) )
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1);
}
- }
- else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
- status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1);
+ } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1);
}
//val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk)
if( val4 )
tick = -1;
break;
case SC_AUTOBERSERK:
- if (status->hp < status->max_hp>>2 &&
+ if (st->hp < st->max_hp>>2 &&
(!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0))
- sc_start4(bl,SC_PROVOKE,100,10,1,0,0,60000);
+ sc_start4(src,bl,SC_PROVOKE,100,10,1,0,0,60000);
tick = -1;
break;
case SC_CRUCIS:
@@ -7297,11 +7590,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_EDP: // [Celest]
val2 = val1 + 2; //Chance to Poison enemies.
+ val3 = 50*(val1+1); //Damage increase (+50 +50*lv%)
#ifdef RENEWAL_EDP
- val3 = 50*(val1+3);
val4 = 100 * ((val1 + 1)/2 + 2);
- #else
- val3 = 50*(val1+1); //Damage increase (+50 +50*lv%)
#endif
if( sd )//[Ind] - iROwiki says each level increases its duration by 3 seconds
tick += pc->checkskill(sd,GC_RESEARCHNEWPOISON)*3000;
@@ -7314,8 +7605,17 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val2 = val1*20; //SP gained
break;
case SC_KYRIE:
- val2 = (int64)status->max_hp * (val1 * 2 + 10) / 100; //%Max HP to absorb
- val3 = (val1 / 2 + 5); //Hits
+ val2 = APPLY_RATE(st->max_hp, (val1 * 2 + 10)); //%Max HP to absorb
+ // val4 holds current about of party memebers when casting AB_PRAEFATIO,
+ // as Praefatio's barrier has more health and blocks more hits than Kyrie Elesion.
+ if( val4 < 1 ) //== PR_KYRIE
+ val3 = (val1 / 2 + 5); // Hits
+ else { //== AB_PRAEFATIO
+ val2 += val4 * 2; //Increase barrier strength per party member.
+ val3 = 6 + val1;
+ }
+ if( sd )
+ val1 = min(val1,pc->checkskill(sd,PR_KYRIE)); // use skill level to determine barrier health.
break;
case SC_MAGICPOWER:
//val1: Skill lv
@@ -7355,20 +7655,16 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_REFLECTSHIELD:
val2=10+val1*3; // %Dmg reflected
- if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) )
- {
+ if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) ) {
struct map_session_data *tsd;
- if( sd )
- {
+ if( sd ) {
int i;
- for( i = 0; i < 5; i++ )
- {
- if( sd->devotion[i] && (tsd = iMap->id2sd(sd->devotion[i])) )
- status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
+ for( i = 0; i < 5; i++ ) {
+ if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) )
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
}
- }
- else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
- status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
+ } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
}
break;
case SC_NOEQUIPWEAPON:
@@ -7396,21 +7692,21 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_VOLCANO:
val2 = val1*10; //Watk increase
#ifndef RENEWAL
- if (status->def_ele != ELE_FIRE)
+ if (st->def_ele != ELE_FIRE)
val2 = 0;
#endif
break;
case SC_VIOLENTGALE:
val2 = val1*3; //Flee increase
- #ifndef RENEWAL
- if (status->def_ele != ELE_WIND)
+ #ifndef RENEWAL
+ if (st->def_ele != ELE_WIND)
val2 = 0;
- #endif
+ #endif
break;
case SC_DELUGE:
- val2 = deluge_eff[val1-1]; //HP increase
+ val2 = skill->deluge_eff[val1-1]; //HP increase
#ifndef RENEWAL
- if(status->def_ele != ELE_WATER)
+ if(st->def_ele != ELE_WATER)
val2 = 0;
#endif
break;
@@ -7466,18 +7762,22 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_ATTHASTE_POTION3:
case SC_ATTHASTE_INFINITY:
val2 = 50*(2+type-SC_ATTHASTE_POTION1);
- break;
+ break;
case SC_WEDDING:
case SC_XMAS:
case SC_SUMMER:
case SC_HANBOK:
+ case SC_OKTOBERFEST:
if (!vd) return 0;
//Store previous values as they could be removed.
- unit_stop_attack(bl);
+ unit->stop_attack(bl);
break;
case SC_NOCHAT:
- // [GodLesZ] FIXME: is this correct? a hardcoded interval of 60sec? what about configuration ?_?
+ // A hardcoded interval of 60 seconds is expected, as the time that SC_NOCHAT uses is defined by
+ // mmocharstatus.manner, each negative point results in 1 minute with this status activated
+ // This is done this way because the message that the client displays is hardcoded, and only
+ // shows how many minutes are remaining. [Panikon]
tick = 60000;
val1 = battle_config.manner_system; //Mute filters.
if (sd)
@@ -7497,30 +7797,30 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_DPOISON:
- //Lose 10/15% of your life as long as it doesn't brings life below 25%
- if (status->hp > status->max_hp>>2) {
- int diff = status->max_hp*(bl->type==BL_PC?10:15)/100;
- if (status->hp - diff < status->max_hp>>2)
- diff = status->hp - (status->max_hp>>2);
- if( val2 && bl->type == BL_MOB ) {
- struct block_list* src = iMap->id2bl(val2);
- if( src )
- mob_log_damage((TBL_MOB*)bl,src,diff);
+ //Lose 10/15% of your life as long as it doesn't brings life below 25%
+ if (st->hp > st->max_hp>>2) {
+ int diff = st->max_hp*(bl->type==BL_PC?10:15)/100;
+ if (st->hp - diff < st->max_hp>>2)
+ diff = st->hp - (st->max_hp>>2);
+ if( val2 && bl->type == BL_MOB ) {
+ struct block_list* src2 = map->id2bl(val2);
+ if( src2 )
+ mob->log_damage((TBL_MOB*)bl,src2,diff);
+ }
+ status_zap(bl, diff, 0);
}
- status_zap(bl, diff, 0);
- }
- // fall through
+ // fall through
case SC_POISON:
- val3 = tick/1000; //Damage iterations
- if(val3 < 1) val3 = 1;
- tick_time = 1000; // [GodLesZ] tick time
- //val4: HP damage
- if (bl->type == BL_PC)
- val4 = (type == SC_DPOISON) ? 3 + status->max_hp/50 : 3 + status->max_hp*3/200;
- else
- val4 = (type == SC_DPOISON) ? 3 + status->max_hp/100 : 3 + status->max_hp/200;
+ val3 = tick/1000; //Damage iterations
+ if(val3 < 1) val3 = 1;
+ tick_time = 1000; // [GodLesZ] tick time
+ //val4: HP damage
+ if (bl->type == BL_PC)
+ val4 = (type == SC_DPOISON) ? 3 + st->max_hp/50 : 3 + st->max_hp*3/200;
+ else
+ val4 = (type == SC_DPOISON) ? 3 + st->max_hp/100 : 3 + st->max_hp/200;
- break;
+ break;
case SC_CONFUSION:
clif->emotion(bl,E_WHAT);
break;
@@ -7541,11 +7841,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
tick_time = val2 * 1000; // [GodLesZ] tick time
break;
case SC_CASH_BOSS_ALARM:
- if( sd != NULL )
- {
- struct mob_data *boss_md = iMap->getmob_boss(bl->m); // Search for Boss on this Map
- if( boss_md == NULL || boss_md->bl.prev == NULL )
- { // No MVP on this map - MVP is dead
+ if( sd != NULL ) {
+ struct mob_data *boss_md = map->getmob_boss(bl->m); // Search for Boss on this Map
+ if( boss_md == NULL || boss_md->bl.prev == NULL ) {
+ // No MVP on this map - MVP is dead
clif->bossmapinfo(sd->fd, boss_md, 1);
return 0; // No need to start SC
}
@@ -7567,7 +7866,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_ROGUE)
val3 -= 40;
val4 = 10+val1*2; //SP cost.
- if (map_flag_gvg(bl->m) || map[bl->m].flag.battleground) val4 *= 5;
+ if (map_flag_gvg(bl->m) || map->list[bl->m].flag.battleground) val4 *= 5;
break;
case SC_CLOAKING:
if (!sd) //Monsters should be able to walk with no penalties. [Skotlex]
@@ -7591,7 +7890,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
tick_time = 10; // [GodLesZ] tick time
break;
- //Permanent effects.
+ //Permanent effects.
case SC_LEXAETERNA:
case SC_MODECHANGE:
case SC_WEIGHTOVER50:
@@ -7604,52 +7903,44 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_TURNKICK_READY:
case SC_DODGE_READY:
case SC_PUSH_CART:
- case SC_ALL_RIDING:
tick = -1;
break;
case SC_AUTOGUARD:
- if( !(flag&1) )
- {
+ if( !(flag&1) ) {
struct map_session_data *tsd;
int i,t;
- for( i = val2 = 0; i < val1; i++)
- {
+ for( i = val2 = 0; i < val1; i++) {
t = 5-(i>>1);
val2 += (t < 0)? 1:t;
}
- if( bl->type&(BL_PC|BL_MER) )
- {
- if( sd )
- {
- for( i = 0; i < 5; i++ )
- {
- if( sd->devotion[i] && (tsd = iMap->id2sd(sd->devotion[i])) )
- status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
+ if( bl->type&(BL_PC|BL_MER) ) {
+ if( sd ) {
+ for( i = 0; i < 5; i++ ) {
+ if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) )
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
}
}
else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
- status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
}
}
break;
case SC_DEFENDER:
- if (!(flag&1))
- {
+ if (!(flag&1)) {
val2 = 5 + 15*val1; //Damage reduction
val3 = 0; // unused, previously speed adjustment
val4 = 250 - 50*val1; //Aspd adjustment
- if (sd)
- {
+ if (sd) {
struct map_session_data *tsd;
int i;
- for (i = 0; i < 5; i++)
- { //See if there are devoted characters, and pass the status to them. [Skotlex]
- if (sd->devotion[i] && (tsd = iMap->id2sd(sd->devotion[i])))
- status_change_start(&tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1);
+ for (i = 0; i < 5; i++) {
+ //See if there are devoted characters, and pass the status to them. [Skotlex]
+ if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])))
+ status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1);
}
}
}
@@ -7676,26 +7967,28 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_JOINTBEAT:
if( val2&BREAK_NECK )
- sc_start2(bl,SC_BLOODING,100,val1,val3,skill->get_time2(status_sc2skill(type),val1));
+ sc_start2(src,bl,SC_BLOODING,100,val1,val3,skill->get_time2(status->sc2skill(type),val1));
break;
case SC_BERSERK:
- if (!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4)
- sc_start4(bl, SC_ENDURE, 100,10,0,0,2, tick);
- case SC__BLOODYLUST:
+ if( val3 == SC__BLOODYLUST )
+ sc_start(src,bl,(sc_type)val3,100,val1,tick);
+ if( !val3 && !(!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4) )
+ sc_start4(src, bl, SC_ENDURE, 100,10,0,0,2, tick);
//HP healing is performing after the calc_status call.
//Val2 holds HP penalty
- if (!val4) val4 = skill->get_time2(status_sc2skill(type),val1);
+ if (!val4) val4 = skill->get_time2(status->sc2skill(type),val1);
if (!val4) val4 = 10000; //Val4 holds damage interval
val3 = tick/val4; //val3 holds skill duration
tick_time = val4; // [GodLesZ] tick time
break;
case SC_GOSPEL:
- if(val4 == BCT_SELF) { // self effect
+ if(val4 == BCT_SELF) {
+ // self effect
val2 = tick/10000;
tick_time = 10000; // [GodLesZ] tick time
- status_change_clear_buffs(bl,3); //Remove buffs/debuffs
+ status->change_clear_buffs(bl,3); //Remove buffs/debuffs
}
break;
@@ -7705,23 +7998,23 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val3 = 0;
val4 = 0;
- stat = ( sd ? sd->status.str : status_get_base_status(bl)->str ) / 2; val3 |= cap_value(stat,0,0xFF)<<16;
- stat = ( sd ? sd->status.agi : status_get_base_status(bl)->agi ) / 2; val3 |= cap_value(stat,0,0xFF)<<8;
- stat = ( sd ? sd->status.vit : status_get_base_status(bl)->vit ) / 2; val3 |= cap_value(stat,0,0xFF);
- stat = ( sd ? sd->status.int_: status_get_base_status(bl)->int_) / 2; val4 |= cap_value(stat,0,0xFF)<<16;
- stat = ( sd ? sd->status.dex : status_get_base_status(bl)->dex ) / 2; val4 |= cap_value(stat,0,0xFF)<<8;
- stat = ( sd ? sd->status.luk : status_get_base_status(bl)->luk ) / 2; val4 |= cap_value(stat,0,0xFF);
- break;
+ stat = ( sd ? sd->status.str : status->get_base_status(bl)->str ) / 2; val3 |= cap_value(stat,0,0xFF)<<16;
+ stat = ( sd ? sd->status.agi : status->get_base_status(bl)->agi ) / 2; val3 |= cap_value(stat,0,0xFF)<<8;
+ stat = ( sd ? sd->status.vit : status->get_base_status(bl)->vit ) / 2; val3 |= cap_value(stat,0,0xFF);
+ stat = ( sd ? sd->status.int_: status->get_base_status(bl)->int_) / 2; val4 |= cap_value(stat,0,0xFF)<<16;
+ stat = ( sd ? sd->status.dex : status->get_base_status(bl)->dex ) / 2; val4 |= cap_value(stat,0,0xFF)<<8;
+ stat = ( sd ? sd->status.luk : status->get_base_status(bl)->luk ) / 2; val4 |= cap_value(stat,0,0xFF);
}
+ break;
case SC_MARIONETTE:
{
int stat,max_stat;
// fetch caster information
- struct block_list *pbl = iMap->id2bl(val1);
- struct status_change *psc = pbl?status_get_sc(pbl):NULL;
- struct status_change_entry *psce = psc?psc->data[SC_MARIONETTE_MASTER]:NULL;
+ struct block_list *pbl = map->id2bl(val1);
+ struct status_change *psc = pbl ? status->get_sc(pbl) : NULL;
+ struct status_change_entry *psce = psc ? psc->data[SC_MARIONETTE_MASTER] : NULL;
// fetch target's stats
- struct status_data* status = status_get_status_data(bl); // battle status
+ struct status_data* tst = status->get_status_data(bl); // battle status
if (!psce)
return 0;
@@ -7729,14 +8022,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val3 = 0;
val4 = 0;
max_stat = battle_config.max_parameter; //Cap to 99 (default)
- stat = (psce->val3 >>16)&0xFF; stat = min(stat, max_stat - status->str ); val3 |= cap_value(stat,0,0xFF)<<16;
- stat = (psce->val3 >> 8)&0xFF; stat = min(stat, max_stat - status->agi ); val3 |= cap_value(stat,0,0xFF)<<8;
- stat = (psce->val3 >> 0)&0xFF; stat = min(stat, max_stat - status->vit ); val3 |= cap_value(stat,0,0xFF);
- stat = (psce->val4 >>16)&0xFF; stat = min(stat, max_stat - status->int_); val4 |= cap_value(stat,0,0xFF)<<16;
- stat = (psce->val4 >> 8)&0xFF; stat = min(stat, max_stat - status->dex ); val4 |= cap_value(stat,0,0xFF)<<8;
- stat = (psce->val4 >> 0)&0xFF; stat = min(stat, max_stat - status->luk ); val4 |= cap_value(stat,0,0xFF);
- break;
+ stat = (psce->val3 >>16)&0xFF; stat = min(stat, max_stat - tst->str ); val3 |= cap_value(stat,0,0xFF)<<16;
+ stat = (psce->val3 >> 8)&0xFF; stat = min(stat, max_stat - tst->agi ); val3 |= cap_value(stat,0,0xFF)<<8;
+ stat = (psce->val3 >> 0)&0xFF; stat = min(stat, max_stat - tst->vit ); val3 |= cap_value(stat,0,0xFF);
+ stat = (psce->val4 >>16)&0xFF; stat = min(stat, max_stat - tst->int_); val4 |= cap_value(stat,0,0xFF)<<16;
+ stat = (psce->val4 >> 8)&0xFF; stat = min(stat, max_stat - tst->dex ); val4 |= cap_value(stat,0,0xFF)<<8;
+ stat = (psce->val4 >> 0)&0xFF; stat = min(stat, max_stat - tst->luk ); val4 |= cap_value(stat,0,0xFF);
}
+ break;
case SC_SWORDREJECT:
val2 = 15*val1; //Reflect chance
val3 = 3; //Reflections
@@ -7766,16 +8059,15 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
struct block_list *d_bl;
struct status_change *d_sc;
- if( (d_bl = iMap->id2bl(val1)) && (d_sc = status_get_sc(d_bl)) && d_sc->count )
- { // Inherits Status From Source
+ if( (d_bl = map->id2bl(val1)) && (d_sc = status->get_sc(d_bl)) && d_sc->count ) {
+ // Inherits Status From Source
const enum sc_type types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE };
enum sc_type type2;
- int i = (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)?2:3;
- while( i >= 0 )
- {
+ int i = (map_flag_gvg(bl->m) || map->list[bl->m].flag.battleground)?2:3;
+ while( i >= 0 ) {
type2 = types[i];
if( d_sc->data[type2] )
- sc_start(bl, type2, 100, d_sc->data[type2]->val1, skill->get_time(status_sc2skill(type2),d_sc->data[type2]->val1));
+ sc_start(bl, bl, type2, 100, d_sc->data[type2]->val1, skill->get_time(status->sc2skill(type2),d_sc->data[type2]->val1));
i--;
}
}
@@ -7784,25 +8076,25 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_COMA: //Coma. Sends a char to 1HP. If val2, do not zap sp
if( val3 && bl->type == BL_MOB ) {
- struct block_list* src = iMap->id2bl(val3);
- if( src )
- mob_log_damage((TBL_MOB*)bl,src,status->hp - 1);
+ struct block_list* src2 = map->id2bl(val3);
+ if( src2 )
+ mob->log_damage((TBL_MOB*)bl,src2,st->hp - 1);
}
- status_zap(bl, status->hp-1, val2?0:status->sp);
+ status_zap(bl, st->hp-1, val2 ? 0 : st->sp);
return 1;
break;
case SC_RG_CCONFINE_S:
{
- struct block_list *src = val2?iMap->id2bl(val2):NULL;
- struct status_change *sc2 = src?status_get_sc(src):NULL;
- struct status_change_entry *sce2 = sc2?sc2->data[SC_RG_CCONFINE_M]:NULL;
- if (src && sc2) {
+ struct block_list *src2 = val2 ? map->id2bl(val2) : NULL;
+ struct status_change *sc2 = src ? status->get_sc(src2) : NULL;
+ struct status_change_entry *sce2 = sc2 ? sc2->data[SC_RG_CCONFINE_M] : NULL;
+ if (src2 && sc2) {
if (!sce2) //Start lock on caster.
- sc_start4(src,SC_RG_CCONFINE_M,100,val1,1,0,0,tick+1000);
+ sc_start4(src,src2,SC_RG_CCONFINE_M,100,val1,1,0,0,tick+1000);
else { //Increase count of locked enemies and refresh time.
(sce2->val2)++;
- iTimer->delete_timer(sce2->timer, status_change_timer);
- sce2->timer = iTimer->add_timer(iTimer->gettick()+tick+1000, status_change_timer, src->id, SC_RG_CCONFINE_M);
+ timer->delete(sce2->timer, status->change_timer);
+ sce2->timer = timer->add(timer->gettick()+tick+1000, status->change_timer, src2->id, SC_RG_CCONFINE_M);
}
} else //Status failed.
return 0;
@@ -7813,41 +8105,50 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_KAUPE:
switch (val1) {
- case 3: //33*3 + 1 -> 100%
- val2++;
- case 1:
- case 2: //33, 66%
- val2 += 33*val1;
- val3 = 1; //Dodge 1 attack total.
- break;
- default: //Custom. For high level mob usage, higher level means more blocks. [Skotlex]
- val2 = 100;
- val3 = val1-2;
- break;
+ case 3: //33*3 + 1 -> 100%
+ val2++;
+ case 1:
+ case 2: //33, 66%
+ val2 += 33*val1;
+ val3 = 1; //Dodge 1 attack total.
+ break;
+ default: //Custom. For high level mob usage, higher level means more blocks. [Skotlex]
+ val2 = 100;
+ val3 = val1-2;
+ break;
}
break;
- case SC_COMBOATTACK: {
- //val1: Skill ID
- //val2: When given, target (for autotargetting skills)
- //val3: When set, this combo time should NOT delay attack/movement
- //val3: TK: Last used kick
- //val4: TK: Combo time
- struct unit_data *ud = unit_bl2ud(bl);
- if (ud && !val3) {
- tick += 300 * battle_config.combo_delay_rate/100;
- ud->attackabletime = iTimer->gettick()+tick;
- unit_set_walkdelay(bl, iTimer->gettick(), tick, 1);
- }
- val3 = 0;
- val4 = tick;
+ case SC_COMBOATTACK:
+ {
+ //val1: Skill ID
+ //val2: When given, target (for autotargetting skills)
+ //val3: When set, this combo time should NOT delay attack/movement
+ //val3: If set to 2 this combo will delay ONLY attack
+ //val3: TK: Last used kick
+ //val4: TK: Combo time
+ struct unit_data *ud = unit->bl2ud(bl);
+ if( ud && (!val3 || val3 == 2) ) {
+ tick += 300 * battle_config.combo_delay_rate/100;
+ ud->attackabletime = timer->gettick()+tick;
+ if( !val3 )
+ unit->set_walkdelay(bl, timer->gettick(), tick, 1);
}
+ val3 = 0;
+ val4 = tick;
break;
+ }
case SC_EARTHSCROLL:
val2 = 11-val1; //Chance to consume: 11-skill_lv%
break;
case SC_RUN:
- val4 = iTimer->gettick(); //Store time at which you started running.
+ {
+ //Store time at which you started running.
+ int64 currenttick = timer->gettick();
+ // Note: this int64 value is stored in two separate int32 variables (FIXME)
+ val3 = (int)(currenttick&0x00000000ffffffffLL);
+ val4 = (int)((currenttick&0xffffffff00000000LL)>>32);
+ }
tick = -1;
break;
case SC_KAAHI:
@@ -7856,7 +8157,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val4 = INVALID_TIMER; //Kaahi Timer.
break;
case SC_BLESSING:
- if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC)
+ if ((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC)
val2 = val1;
else
val2 = 0; //0 -> Half stat.
@@ -7894,7 +8195,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val2 = 5*val1; //Batk/Watk Increase
val3 = 10*val1; //Hit Increase
val4 = 5*val1; //Def reduction
- sc_start(bl, SC_ENDURE, 100, 1, tick); //Endure effect
+ sc_start(src, bl, SC_ENDURE, 100, 1, tick); //Endure effect
break;
case SC_ANGELUS:
val2 = 5*val1; //def increase
@@ -7911,23 +8212,25 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val3 = 3*val1; //Hit increase
break;
case SC_SUN_COMFORT:
- val2 = (status_get_lv(bl) + status->dex + status->luk)/2; //def increase
+ val2 = (status->get_lv(bl) + st->dex + st->luk)/2; //def increase
break;
case SC_MOON_COMFORT:
- val2 = (status_get_lv(bl) + status->dex + status->luk)/10; //flee increase
+ val2 = (status->get_lv(bl) + st->dex + st->luk)/10; //flee increase
break;
case SC_STAR_COMFORT:
- val2 = (status_get_lv(bl) + status->dex + status->luk); //Aspd increase
+ val2 = (status->get_lv(bl) + st->dex + st->luk); //Aspd increase
break;
case SC_QUAGMIRE:
val2 = (sd?5:10)*val1; //Agi/Dex decrease.
break;
- // gs_something1 [Vicious]
+ // gs_something1 [Vicious]
case SC_GS_GATLINGFEVER:
val2 = 20*val1; //Aspd increase
- val3 = 20+10*val1; //Batk increase
val4 = 5*val1; //Flee decrease
+ #ifndef RENEWAL
+ val3 = 20+10*val1; //Batk increase
+ #endif
break;
case SC_FLING:
@@ -7967,20 +8270,30 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_JAILED:
- //Val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time.
+ // val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time.
+ // When first called:
+ // val2 Jail map_index
+ // val3 x
+ // val4 y
+ // When renewing status' information
+ // val3 Return map_index
+ // val4 return coordinates
tick = val1>0?1000:250;
if (sd)
{
if (sd->mapindex != val2)
{
- int pos = (bl->x&0xFFFF)|(bl->y<<16), //Current Coordinates
- map = sd->mapindex; //Current Map
+ int pos = (bl->x&0xFFFF)|(bl->y<<16); /// Current Coordinates
+ int map_index = sd->mapindex; /// Current Map
//1. Place in Jail (val2 -> Jail Map, val3 -> x, val4 -> y
pc->setpos(sd,(unsigned short)val2,val3,val4, CLR_TELEPORT);
//2. Set restore point (val3 -> return map, val4 return coords
- val3 = map;
+ val3 = map_index;
val4 = pos;
- } else if (!val3 || val3 == sd->mapindex) { //Use save point.
+ } else if (!val3
+ || val3 == sd->mapindex
+ || !sd->sc.data[SC_JAILED] // If player is being jailed and is already in jail (issue: 8206)
+ ) { //Use save point.
val3 = sd->status.save_point.map;
val4 = (sd->status.save_point.x&0xFFFF)
|(sd->status.save_point.y<<16);
@@ -7999,7 +8312,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val3= 20*val1; //Int increase
break;
case SC_SWOO:
- if(status->mode&MD_BOSS)
+ if(st->mode&MD_BOSS)
tick /= 5; //TODO: Reduce skill's duration. But for how long?
break;
case SC_SPIDERWEB:
@@ -8067,12 +8380,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_KAIZEL:
val2 = 10*val1; //% of life to be revived with
break;
- // case SC_ARMORPROPERTY:
- // case SC_ARMOR_RESIST:
+ // case SC_ARMORPROPERTY:
+ // case SC_ARMOR_RESIST:
// Mod your resistance against elements:
// val1 = water | val2 = earth | val3 = fire | val4 = wind
// break;
- //case ????:
+ //case ????:
//Place here SCs that have no SCB_* data, no skill associated, no ICON
//associated, and yet are not wrong/unknown. [Skotlex]
//break;
@@ -8100,9 +8413,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_SPL_MATK:
val2 = 2; // Splendide group
break;
- /**
- * General
- **/
+ /**
+ * General
+ **/
case SC_FEAR:
val2 = 2;
val4 = tick / 1000;
@@ -8112,9 +8425,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val4 = tick / 3000; // Total Ticks to Burn!!
tick_time = 3000; // [GodLesZ] tick time
break;
- /**
- * Rune Knight
- **/
+ /**
+ * Rune Knight
+ **/
case SC_DEATHBOUND:
val2 = 500 + 100 * val1;
break;
@@ -8122,19 +8435,13 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if( sd )
val1 = sd->status.job_level * pc->checkskill(sd, RK_RUNEMASTERY) / 4; //DEF/MDEF Increase
break;
- case SC_FIGHTINGSPIRIT:
- val_flag |= 1|2;
- break;
case SC_ABUNDANCE:
val4 = tick / 10000;
tick_time = 10000; // [GodLesZ] tick time
break;
- case SC_GIANTGROWTH:
- val2 = 10; // Triple damage success rate.
- break;
- /**
- * Arch Bishop
- **/
+ /**
+ * Arch Bishop
+ **/
case SC_RENOVATIO:
val4 = tick / 5000;
tick_time = 5000;
@@ -8144,16 +8451,11 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_VENOMIMPRESS:
val2 = 10 * val1;
- val_flag |= 1|2;
- break;
- case SC_POISONINGWEAPON:
- val_flag |= 1|2|4;
break;
case SC_WEAPONBLOCKING:
val2 = 10 + 2 * val1; // Chance
- val4 = tick / 3000;
- tick_time = 3000; // [GodLesZ] tick time
- val_flag |= 1|2;
+ val4 = tick / 5000;
+ tick_time = 5000; // [GodLesZ] tick time
break;
case SC_TOXIN:
val4 = tick / 10000;
@@ -8164,7 +8466,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
tick_time = 4000; // [GodLesZ] tick time
break;
case SC_PYREXIA:
- status_change_start(bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds
+ status->change_start(src, bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds
val4 = tick / 3000;
tick_time = 3000; // [GodLesZ] tick time
break;
@@ -8176,13 +8478,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val4 = tick / 3000;
tick_time = 3000; // [GodLesZ] tick time
break;
- case SC_ROLLINGCUTTER:
- val_flag |= 1;
- break;
case SC_CLOAKINGEXCEED:
val2 = ( val1 + 1 ) / 2; // Hits
val3 = 90 + val1 * 10; // Walk speed
- val_flag |= 1|2|4;
if (bl->type == BL_PC)
val4 |= battle_config.pc_cloak_check_type&7;
else
@@ -8192,7 +8490,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_HALLUCINATIONWALK:
val2 = 50 * val1; // Evasion rate of physical attacks. Flee
val3 = 10 * val1; // Evasion rate of magical attacks.
- val_flag |= 1|2|4;
break;
case SC_WHITEIMPRISON:
status_change_end(bl, SC_BURNING, INVALID_TIMER);
@@ -8210,7 +8507,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_READING_SB:
// val2 = sp reduction per second
- tick_time = 5000; // [GodLesZ] tick time
+ tick_time = 10000; // [GodLesZ] tick time
break;
case SC_SUMMON1:
case SC_SUMMON2:
@@ -8221,19 +8518,22 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
if( val4 < 1 )
val4 = 1;
tick_time = 1000; // [GodLesZ] tick time
- val_flag |= 1;
break;
case SC_SHAPESHIFT:
switch( val1 )
{
- case 1: val2 = ELE_FIRE; break;
- case 2: val2 = ELE_EARTH; break;
- case 3: val2 = ELE_WIND; break;
- case 4: val2 = ELE_WATER; break;
+ case 1: val2 = ELE_FIRE; break;
+ case 2: val2 = ELE_EARTH; break;
+ case 3: val2 = ELE_WIND; break;
+ case 4: val2 = ELE_WATER; break;
}
break;
+ case SC_STEALTHFIELD_MASTER:
+ val4 = tick / 1000;
+ tick_time = 2000 + (1000 * val1);
+ break;
case SC_ELECTRICSHOCKER:
- case SC_CRYSTALIZE:
+ case SC_COLD:
case SC_MEIKYOUSISUI:
val4 = tick / 1000;
if( val4 < 1 )
@@ -8245,17 +8545,26 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_WUGDASH:
- val4 = iTimer->gettick(); //Store time at which you started running.
+ {
+ //Store time at which you started running.
+ int64 currenttick = timer->gettick();
+ // Note: this int64 value is stored in two separate int32 variables (FIXME)
+ val3 = (int)(currenttick&0x00000000ffffffffLL);
+ val4 = (int)((currenttick&0xffffffff00000000LL)>>32);
+ }
tick = -1;
break;
+ case SC__REPRODUCE:
+ val4 = tick / 1000;
+ tick_time = 1000;
+ break;
case SC__SHADOWFORM: {
- struct map_session_data * s_sd = iMap->id2sd(val2);
- if( s_sd )
- s_sd->shadowform_id = bl->id;
- val4 = tick / 1000;
- val_flag |= 1|2|4;
- tick_time = 1000; // [GodLesZ] tick time
- }
+ struct map_session_data * s_sd = map->id2sd(val2);
+ if( s_sd )
+ s_sd->shadowform_id = bl->id;
+ val4 = tick / 1000;
+ tick_time = 1000; // [GodLesZ] tick time
+ }
break;
case SC__STRIPACCESSARY:
if (!sd)
@@ -8263,47 +8572,40 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC__INVISIBILITY:
val2 = 50 - 10 * val1; // ASPD
- val3 = 20 * val1; // CRITICAL
+ val3 = 200 * val1; // CRITICAL
val4 = tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
- val_flag |= 1|2;
break;
case SC__ENERVATION:
val2 = 20 + 10 * val1; // ATK Reduction
- val_flag |= 1|2;
if( sd ) pc->delspiritball(sd,sd->spiritball,0);
break;
case SC__GROOMY:
val2 = 20 + 10 * val1; //ASPD. Need to confirm if Movement Speed reduction is the same. [Jobbie]
val3 = 20 * val1; //HIT
- val_flag |= 1|2|4;
if( sd ) { // Removes Animals
if( pc_isriding(sd) ) pc->setriding(sd, 0);
if( pc_isridingdragon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_DRAGON);
if( pc_iswug(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_WUG);
if( pc_isridingwug(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_WUGRIDER);
if( pc_isfalcon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_FALCON);
- if( sd->status.pet_id > 0 ) pet_menu(sd, 3);
- if( homun_alive(sd->hd) ) homun->vaporize(sd,1);
- if( sd->md ) merc_delete(sd->md,3);
+ if( sd->status.pet_id > 0 ) pet->menu(sd, 3);
+ if( homun_alive(sd->hd) ) homun->vaporize(sd,HOM_ST_REST);
+ if( sd->md ) mercenary->delete(sd->md,3);
}
break;
case SC__LAZINESS:
val2 = 10 + 10 * val1; // Cast reduction
val3 = 10 * val1; // Flee Reduction
- val_flag |= 1|2|4;
break;
case SC__UNLUCKY:
val2 = 10 * val1; // Crit and Flee2 Reduction
- val_flag |= 1|2|4;
break;
case SC__WEAKNESS:
val2 = 10 * val1;
- val_flag |= 1|2;
// bypasses coating protection and MADO
- sc_start(bl,SC_NOEQUIPWEAPON,100,val1,tick);
- sc_start(bl,SC_NOEQUIPSHIELD,100,val1,tick);
- break;
+ sc_start(src, bl,SC_NOEQUIPWEAPON,100,val1,tick);
+ sc_start(src, bl,SC_NOEQUIPSHIELD,100,val1,tick);
break;
case SC_GN_CARTBOOST:
if( val1 < 3 )
@@ -8314,13 +8616,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val2 = 100;
break;
case SC_PROPERTYWALK:
- val_flag |= 1|2;
val3 = 0;
break;
case SC_WARMER:
status_change_end(bl, SC_FREEZE, INVALID_TIMER);
status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER);
- status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER);
+ status_change_end(bl, SC_COLD, INVALID_TIMER);
break;
case SC_STRIKING:
val1 = 6 - val1;//spcost = 6 - level (lvl1:5 ... lvl 5: 1)
@@ -8328,32 +8629,26 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_BLOOD_SUCKER:
- {
- struct block_list *src = iMap->id2bl(sce->val2);
- val3 = 1;
- if(src)
- val3 = 200 + 100 * sce->val1 + status_get_int(src);
- val4 = tick / 1000;
- tick_time = 1000; // [GodLesZ] tick time
- }
- break;
- case SC_VACUUM_EXTREME:
- tick -= (status->str / 20) * 1000;
- val4 = val3 = tick / 100;
- tick_time = 100; // [GodLesZ] tick time
+ {
+ struct block_list *src2 = map->id2bl(val2);
+ val3 = 1;
+ if(src2)
+ val3 = 200 + 100 * val1 + status_get_int(src2);
+ val4 = tick / 1000;
+ tick_time = 1000; // [GodLesZ] tick time
+ }
break;
case SC_SWING:
- val2 = 4 * val1; // Walk speed and aspd reduction.
+ val3 = 5 * val1 + val2;//Movement Speed And ASPD Increase
break;
case SC_SYMPHONY_LOVE:
+ val2 = 12 * val1 + val2 + sd->status.job_level / 4;//MDEF Increase In %
+ case SC_MOONLIT_SERENADE:
case SC_RUSH_WINDMILL:
- case SC_ECHOSONG:
- val2 = 6 * val1;
- val2 += val3; //Adding 1% * Lesson Bonus
- val2 += (int)(val4*2/10); //Adding 0.2% per JobLevel
+ val2 = 6 * val1 + val2 + sd->status.job_level / 5;
break;
- case SC_MOONLIT_SERENADE:
- val2 = 10 * val1;
+ case SC_ECHOSONG:
+ val3 = 6 * val1 + val2 + sd->status.job_level / 4;//DEF Increase In %
break;
case SC_HARMONIZE:
val2 = 5 + 5 * val1;
@@ -8367,34 +8662,36 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
tick_time = 2000; // [GodLesZ] tick time
break;
case SC_SIRCLEOFNATURE:
- val2 = 1 + val1; //SP consume
- val3 = 40 * val1; //HP recovery
+ val2 = 40 * val1;//HP recovery
+ val3 = 4 * val1;//SP drain
val4 = tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_SONG_OF_MANA:
- val3 = 10 + (2 * val2);
- val4 = tick/3000;
- tick_time = 3000; // [GodLesZ] tick time
+ val3 = 10 + 5 * val2;
+ val4 = tick/5000;
+ tick_time = 5000; // [GodLesZ] tick time
break;
case SC_SATURDAY_NIGHT_FEVER:
- if (!val4) val4 = skill->get_time2(status_sc2skill(type),val1);
- if (!val4) val4 = 3000;
- val3 = tick/val4;
- tick_time = val4; // [GodLesZ] tick time
+ /*val2 = 12000 - 2000 * val1;//HP/SP Drain Timer
+ if ( val2 < 1000 )
+ val2 = 1000;//Added to prevent val3 from dividing by 0 when using level 6 or higher through commands. [Rytech]
+ val3 = tick/val2;*/
+ val3 = tick / 3000;
+ tick_time = 3000;// [GodLesZ] tick time
break;
case SC_GLOOMYDAY:
- val2 = 20 + 5 * val1; // Flee reduction.
- val3 = 15 + 5 * val1; // ASPD reduction.
- if( sd && rand()%100 < val1 ){ // (Skill Lv) %
- val4 = 1; // reduce walk speed by half.
- if( pc_isriding(sd) ) pc->setriding(sd, 0);
- if( pc_isridingdragon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_DRAGON);
+ if ( !val2 ) {
+ val2 = (val4 > 0 ? max(15, rnd()%(val4*5)) : 0) + val1 * 10;
+ }
+ if ( rnd()%10000 < val1*100 ) { // 1% per SkillLv chance
+ if ( !val3 )
+ val3 = 50;
+ if( sd ) {
+ if( pc_isriding(sd) ) pc->setriding(sd, 0);
+ if( pc_isridingdragon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_DRAGON);
+ }
}
- break;
- case SC_GLOOMYDAY_SK:
- // Random number between [15 ~ (Voice Lesson Skill Level x 5) + (Skill Level x 10)] %.
- val2 = 15 + rand()%( (sd?pc->checkskill(sd, WM_LESSON)*5:0) + val1*10 );
break;
case SC_SITDOWN_FORCE:
case SC_BANANA_BOMB_SITDOWN_POSTDELAY:
@@ -8406,119 +8703,108 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
}
break;
case SC_DANCE_WITH_WUG:
- val3 = (5 * val1) + (1 * val2); //Still need official value.
+ val3 = 5 + 5 * val2;//ASPD Increase
+ val4 = 20 + 10 * val2;//Fixed Cast Time Reduction
break;
case SC_LERADS_DEW:
- val3 = (5 * val1) + (1 * val2);
+ val3 = 200 * val1 + 300 * val2;//MaxHP Increase
break;
case SC_MELODYOFSINK:
- val3 = (5 * val1) + (1 * val2);
+ val3 = val1 * (2 + val2);//INT Reduction. Formula Includes Caster And 2nd Performer.
+ val4 = tick/1000;
+ tick_time = 1000;
break;
case SC_BEYOND_OF_WARCRY:
- val3 = (5 * val1) + (1 * val2);
+ val3 = val1 * (2 + val2);//STR And Crit Reduction. Formula Includes Caster And 2nd Performer.
+ val4 = 4 * val1 + 4 * val2;//MaxHP Reduction
break;
case SC_UNLIMITED_HUMMING_VOICE:
{
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
if( ud == NULL ) return 0;
ud->state.skillcastcancel = 0;
- val3 = 15 - (2 * val2);
+ val3 = 15 - (3 * val2);//Increased SP Cost.
}
break;
case SC_LG_REFLECTDAMAGE:
val2 = 15 + 5 * val1;
- val3 = (val1==5)?20:(val1+4)*2; // SP consumption
+ val3 = 25 + 5 * val1; //Number of Reflects
val4 = tick/10000;
tick_time = 10000; // [GodLesZ] tick time
break;
- case SC_FORCEOFVANGUARD: // This is not the official way to handle it but I think we should use it. [pakpil]
- val2 = 20 + 12 * (val1 - 1); // Chance
- val3 = 5 + (2 * val1); // Max rage counters
+ case SC_FORCEOFVANGUARD:
+ val2 = 8 + 12 * val1; // Chance
+ val3 = 5 + 2 * val1; // Max rage counters
tick = -1; //endless duration in the client
- tick_time = 6000; // [GodLesZ] tick time
- val_flag |= 1|2|4;
break;
case SC_EXEEDBREAK:
- val1 *= 150; // 150 * skill_lv
- if( sd && sd->inventory_data[sd->equip_index[EQI_HAND_R]] ) { // Chars.
- val1 += (sd->inventory_data[sd->equip_index[EQI_HAND_R]]->weight/10 * sd->inventory_data[sd->equip_index[EQI_HAND_R]]->wlv * status_get_lv(bl) / 100);
- val1 += 15 * (sd ? sd->status.job_level:50) + 100;
+ if( sd ){
+ short index = sd->equip_index[EQI_HAND_R];
+ val1 = 15 * (sd->status.job_level + val1 * 10);
+ if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
+ val1 += (sd->inventory_data[index]->weight / 10 * sd->inventory_data[index]->wlv) * status->get_lv(bl) / 100;
}
- else // Mobs
- val1 += (400 * status_get_lv(bl) / 100) + (15 * (status_get_lv(bl) / 2)); // About 1138% at mob_lvl 99. Is an aproximation to a standard weapon. [pakpil]
break;
- case SC_PRESTIGE: // Bassed on suggested formula in iRO Wiki and some test, still need more test. [pakpil]
- val2 = ((status->int_ + status->luk) / 6) + 5; // Chance to evade magic damage.
+ case SC_PRESTIGE:
+ val2 = (st->int_ + st->luk) * val1 / 20;// Chance to evade magic damage.
+ val2 = val2 * status->get_lv(bl) / 200;
+ val2 += val1;
val1 *= 15; // Defence added
if( sd )
val1 += 10 * pc->checkskill(sd,CR_DEFENDER);
- val_flag |= 1|2;
+ val1 *= status->get_lv(bl) / 100;
break;
case SC_BANDING:
tick_time = 5000; // [GodLesZ] tick time
- val_flag |= 1;
- break;
- case SC_SHIELDSPELL_DEF:
- case SC_SHIELDSPELL_MDEF:
- case SC_SHIELDSPELL_REF:
- val_flag |= 1|2;
break;
case SC_MAGNETICFIELD:
val3 = tick / 1000;
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_INSPIRATION:
- if( sd )
- {
- val2 = (40 * val1) + (3 * sd->status.job_level); // ATK bonus
- val3 = (sd->status.job_level / 10) * 2 + 12; // All stat bonus
+ if( sd ) {
+ val2 = 40 * val1 + 3 * sd->status.job_level;// ATK bonus
+ val3 = sd->status.base_level / 10 + sd->status.job_level / 5;// All stat bonus
}
- val4 = tick / 1000;
- tick_time = 1000; // [GodLesZ] tick time
- status_change_clear_buffs(bl,3); //Remove buffs/debuffs
- break;
- case SC_SPELLFIST:
- case SC_CURSEDCIRCLE_ATKER:
- val_flag |= 1|2|4;
+ val4 = tick / 5000;
+ tick_time = 5000; // [GodLesZ] tick time
+ status->change_clear_buffs(bl,3); //Remove buffs/debuffs
break;
case SC_CRESCENTELBOW:
- val2 = 94 + val1;
- val_flag |= 1|2;
+ val2 = (sd ? sd->status.job_level : 2) / 2 + 50 + 5 * val1;
break;
case SC_LIGHTNINGWALK: // [(Job Level / 2) + (40 + 5 * Skill Level)] %
val1 = (sd?sd->status.job_level:2)/2 + 40 + 5 * val1;
- val_flag |= 1;
break;
case SC_RAISINGDRAGON:
val3 = tick / 5000;
tick_time = 5000; // [GodLesZ] tick time
break;
case SC_GENTLETOUCH_CHANGE:
- {// take note there is no def increase as skill desc says. [malufett]
- struct block_list * src;
- val3 = status->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] %
- if( (src = iMap->id2bl(val2)) ){
- val4 = ( 200/status_get_int(src) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level]
- val2 = ( status_get_dex(src)/4 + status_get_str(src)/2 ) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5]
- }
+ {// take note there is no def increase as skill desc says. [malufett]
+ struct block_list * src2;
+ val3 = st->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] %
+ if( (src2 = map->id2bl(val2)) ){
+ val4 = ( 200/status_get_int(src2) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level]
+ val2 = ( status_get_dex(src2)/4 + status_get_str(src2)/2 ) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5]
}
+ }
break;
case SC_GENTLETOUCH_REVITALIZE:
- {// take note there is no vit,aspd,speed increase as skill desc says. [malufett]
- struct block_list * src;
- val3 = val1 * 30 + 150; // Natural HP recovery increase: [(Skill Level x 30) + 50] %
- if( (src = iMap->id2bl(val2)) ) // the stat def is not shown in the status window and it is process differently
- val4 = ( status_get_vit(src)/4 ) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level]
- }
+ {// take note there is no vit,aspd,speed increase as skill desc says. [malufett]
+ struct block_list * src2;
+ val3 = val1 * 30 + 150; // Natural HP recovery increase: [(Skill Level x 30) + 50] %
+ if( (src2 = map->id2bl(val2)) ) // the stat def is not shown in the status window and it is process differently
+ val4 = ( status_get_vit(src2)/4 ) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level]
+ }
break;
case SC_PYROTECHNIC_OPTION:
- val_flag |= 1|2|4;
+ val2 = 60;
break;
case SC_HEATER_OPTION:
val2 = 120; // Watk. TODO: Renewal (Atk2)
- val3 = 33; // % Increase effects.
+ val3 = (sd ? sd->status.job_level : 0); // % Increase damage.
val4 = 3; // Change into fire element.
- val_flag |= 1|2|4;
break;
case SC_TROPIC_OPTION:
val2 = 180; // Watk. TODO: Renewal (Atk2)
@@ -8526,77 +8812,85 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_AQUAPLAY_OPTION:
val2 = 40;
- val_flag |= 1|2|4;
break;
case SC_COOLER_OPTION:
- val2 = 80; // % Freezing chance
- val3 = 33; // % increased damage
+ val2 = 80; // Bonus Matk
+ val3 = (sd ? sd->status.job_level : 0); // % Freezing chance
val4 = 1; // Change into water elemet
- val_flag |= 1|2|4;
break;
case SC_CHILLY_AIR_OPTION:
val2 = 120; // Matk. TODO: Renewal (Matk1)
val3 = MG_COLDBOLT;
- val_flag |= 1|2;
- break;
- case SC_GUST_OPTION:
- val_flag |= 1|2;
break;
case SC_WIND_STEP_OPTION:
val2 = 50; // % Increase speed and flee.
break;
case SC_BLAST_OPTION:
- val2 = 20;
+ val2 = (sd ? sd->status.job_level : 0); // % Increase damage
val3 = ELE_WIND;
- val_flag |= 1|2|4;
break;
case SC_WILD_STORM_OPTION:
val2 = MG_LIGHTNINGBOLT;
- val_flag |= 1|2;
break;
case SC_PETROLOGY_OPTION:
val2 = 5;
val3 = 50;
- val_flag |= 1|2|4;
+ break;
+ case SC_SOLID_SKIN_OPTION:
+ val2 = 33; // % Increase DEF
break;
case SC_CURSED_SOIL_OPTION:
val2 = 10;
- val3 = 33;
+ val3 = (sd ? sd->status.job_level : 0); // % Increase Damage
val4 = 2;
- val_flag |= 1|2|4;
break;
case SC_UPHEAVAL_OPTION:
val2 = WZ_EARTHSPIKE;
- val_flag |= 1|2;
+ val3 = 15; // Bonus MaxHP
break;
case SC_CIRCLE_OF_FIRE_OPTION:
val2 = 300;
- val_flag |= 1|2;
break;
case SC_FIRE_CLOAK_OPTION:
case SC_WATER_DROP_OPTION:
case SC_WIND_CURTAIN_OPTION:
case SC_STONE_SHIELD_OPTION:
- val2 = 20; // Elemental modifier. Not confirmed.
- break;
+ val2 = 100; // Elemental modifier.
+ break;
+ case SC_TROPIC:
+ case SC_CHILLY_AIR:
+ case SC_WILD_STORM:
+ case SC_UPHEAVAL:
+ val2 += 10;
+ case SC_HEATER:
+ case SC_COOLER:
+ case SC_BLAST:
+ case SC_CURSED_SOIL:
+ val2 += 10;
+ case SC_PYROTECHNIC:
+ case SC_AQUAPLAY:
+ case SC_GUST:
+ case SC_PETROLOGY:
+ val2 += 5;
+ val3 += 9000;
case SC_CIRCLE_OF_FIRE:
+ case SC_WATER_SCREEN:
+ case SC_WIND_STEP:
+ case SC_SOLID_SKIN:
case SC_FIRE_CLOAK:
case SC_WATER_DROP:
- case SC_WATER_SCREEN:
case SC_WIND_CURTAIN:
- case SC_WIND_STEP:
case SC_STONE_SHIELD:
- case SC_SOLID_SKIN:
- val2 = 10;
- tick_time = 2000; // [GodLesZ] tick time
+ val2 += 5;
+ val3 += 1000;
+ val4 = tick;
+ tick_time = val3;
break;
case SC_WATER_BARRIER:
- val2 = 40; // Increasement. Mdef1 ???
- val3 = 20; // Reductions. Atk2, Flee1, Matk1 ????
- val_flag |= 1|2|4;
+ val3 = 20; // Reductions. Atk2, Flee1
break;
case SC_ZEPHYR:
- val2 = 22; // Flee.
+ val2 = 25; // Flee.
break;
case SC_TIDAL_WEAPON:
val2 = 20; // Increase Elemental's attack.
@@ -8626,25 +8920,35 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
tick_time = 1000;
break;
case SC_ZANGETSU:
- val2 = status_get_lv(bl) / 3 + 20 * val1;
- val3 = status_get_lv(bl) / 2 + 30 * val1;
+ val2 = val4 = status->get_lv(bl) / 3 + 20 * val1;
+ val3 = status->get_lv(bl) / 2 + 30 * val1;
val2 = (!(status_get_hp(bl)%2) ? val2 : -val3);
- val3 = (!(status_get_sp(bl)%2) ? val2 : -val3);
+ val3 = (!(status_get_sp(bl)%2) ? val4 : -val3);
break;
case SC_GENSOU:
- {
- int hp = status_get_hp(bl), sp = status_get_sp(bl), lv = 5;
- #define PER( a ) { if( a <= 15 )lv = 1;else if( a <= 30 )lv = 2;else if( a <= 50 )lv = 3;else if( a <= 75 )lv = 4;}
- if( rand()%100 > (25 + 10 * val1) - status_get_int(bl) / 2)
- return 0;
+#define PER( a, lvl ) do { \
+ int temp__ = (a); \
+ if( temp__ <= 15 ) (lvl) = 1; \
+ else if( temp__ <= 30 ) (lvl) = 2; \
+ else if( temp__ <= 50 ) (lvl) = 3; \
+ else if( temp__ <= 75 ) (lvl) = 4; \
+ else (lvl) = 5; \
+} while(0)
- PER( 100 / (status_get_max_hp(bl) / hp) );
- status_heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, 1);
+ {
+ int hp = status_get_hp(bl), sp = status_get_sp(bl), lv = 5;
- PER( 100 / (status_get_max_sp(bl) / sp) );
- status_heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), 1);
- }
+ if( rand()%100 > (25 + 10 * val1) - status_get_int(bl) / 2)
+ return 0;
+
+ PER( 100 / (status_get_max_hp(bl) / hp), lv );
+ status->heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, 1);
+
+ PER( 100 / (status_get_max_sp(bl) / sp), lv );
+ status->heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), 1);
+ }
+#undef PER
break;
case SC_ANGRIFFS_MODUS:
val2 = 50 + 20 * val1; //atk bonus
@@ -8683,7 +8987,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
val2 = 2*val1; //aspd reduction %
val3 = 2*val1; //dmg reduction %
if(sc->data[SC_NEEDLE_OF_PARALYZE])
- sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration
+ sc_start(src, bl, SC_ENDURE, 100, val1, tick); //start endure for same duration
break;
case SC_STYLE_CHANGE: //[Lighta] need real info
tick = -1;
@@ -8710,21 +9014,33 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_FRIGG_SONG:
val2 = 5 * val1;
- val3 = 1000 + 100 * val1;
- tick_time = 10000;
+ val3 = (20 * val1) + 80;
+ tick_time = 1000;
val4 = tick / tick_time;
break;
+ case SC_DARKCROW:
+ val2 = 30 * val1;
+ break;
case SC_MONSTER_TRANSFORM:
- if( !mobdb_checkid(val1) )
+ if( !mob->db_checkid(val1) )
val1 = 1002; // default poring
- val_flag |= 1;
break;
- default:
- if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 )
- { //Status change with no calc, no icon, and no skill associated...?
- ShowError("UnknownStatusChange [%d]\n", type);
- return 0;
- }
+ case SC_ALL_RIDING:
+ tick = -1;
+ break;
+ case SC_FLASHCOMBO:
+ /**
+ * val1 = <IN>skill_id
+ * val2 = <OUT>attack addition
+ **/
+ val2 = 20+(20*val1);
+ break;
+ default:
+ if( calc_flag == SCB_NONE && status->SkillChangeTable[type] == 0 && status->IconChangeTable[type] == 0 )
+ { //Status change with no calc, no icon, and no skill associated...?
+ ShowError("UnknownStatusChange [%d]\n", type);
+ return 0;
+ }
}
} else { //Special considerations when loading SC data.
switch( type ) {
@@ -8732,6 +9048,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_XMAS:
case SC_SUMMER:
case SC_HANBOK:
+ case SC_OKTOBERFEST:
if( !vd ) break;
clif->changelook(bl,LOOK_BASE,vd->class_);
clif->changelook(bl,LOOK_WEAPON,0);
@@ -8741,22 +9058,139 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_KAAHI:
val4 = INVALID_TIMER;
break;
- case SC_SUMMON1:
- case SC_SUMMON2:
- case SC_SUMMON3:
- case SC_SUMMON4:
- case SC_SUMMON5:
- case SC_MONSTER_TRANSFORM:
- val_flag |= 1;
- break;
case SC_KYOUGAKU:
clif->status_change(bl, SI_ACTIVE_MONSTER_TRANSFORM, 1, 0, 1002, 0, 0); // Poring in disguise
break;
}
}
+
+ /* values that must be set regardless of flag&4 e.g. val_flag */
+ switch(type) {
+ case SC_FIGHTINGSPIRIT:
+ val_flag |= 1|2;
+ break;
+ case SC_VENOMIMPRESS:
+ val_flag |= 1|2;
+ break;
+ case SC_POISONINGWEAPON:
+ val_flag |= 1|2|4;
+ break;
+ case SC_WEAPONBLOCKING:
+ val_flag |= 1|2;
+ break;
+ case SC_ROLLINGCUTTER:
+ val_flag |= 1;
+ break;
+ case SC_CLOAKINGEXCEED:
+ val_flag |= 1|2|4;
+ break;
+ case SC_HALLUCINATIONWALK:
+ val_flag |= 1|2|4;
+ break;
+ case SC_SUMMON1:
+ case SC_SUMMON2:
+ case SC_SUMMON3:
+ case SC_SUMMON4:
+ case SC_SUMMON5:
+ val_flag |= 1;
+ break;
+ case SC__SHADOWFORM:
+ val_flag |= 1|2|4;
+ break;
+ case SC__INVISIBILITY:
+ val_flag |= 1|2;
+ break;
+ case SC__ENERVATION:
+ val_flag |= 1|2;
+ break;
+ case SC__GROOMY:
+ val_flag |= 1|2|4;
+ break;
+ case SC__LAZINESS:
+ val_flag |= 1|2|4;
+ break;
+ case SC__UNLUCKY:
+ val_flag |= 1|2|4;
+ break;
+ case SC__WEAKNESS:
+ val_flag |= 1|2;
+ break;
+ case SC_PROPERTYWALK:
+ val_flag |= 1|2;
+ break;
+ case SC_FORCEOFVANGUARD:
+ val_flag |= 1|2|4;
+ break;
+ case SC_PRESTIGE:
+ val_flag |= 1|2;
+ break;
+ case SC_BANDING:
+ val_flag |= 1;
+ break;
+ case SC_SHIELDSPELL_DEF:
+ case SC_SHIELDSPELL_MDEF:
+ case SC_SHIELDSPELL_REF:
+ val_flag |= 1|2;
+ break;
+ case SC_SPELLFIST:
+ case SC_CURSEDCIRCLE_ATKER:
+ val_flag |= 1|2|4;
+ break;
+ case SC_CRESCENTELBOW:
+ val_flag |= 1|2;
+ break;
+ case SC_LIGHTNINGWALK:
+ val_flag |= 1;
+ break;
+ case SC_PYROTECHNIC_OPTION:
+ val_flag |= 1|2|4;
+ break;
+ case SC_HEATER_OPTION:
+ val_flag |= 1|2|4;
+ break;
+ case SC_AQUAPLAY_OPTION:
+ val_flag |= 1|2|4;
+ break;
+ case SC_COOLER_OPTION:
+ val_flag |= 1|2|4;
+ break;
+ case SC_CHILLY_AIR_OPTION:
+ val_flag |= 1|2;
+ break;
+ case SC_GUST_OPTION:
+ val_flag |= 1|2;
+ break;
+ case SC_BLAST_OPTION:
+ val_flag |= 1|2|4;
+ break;
+ case SC_WILD_STORM_OPTION:
+ val_flag |= 1|2;
+ break;
+ case SC_PETROLOGY_OPTION:
+ val_flag |= 1|2|4;
+ break;
+ case SC_CURSED_SOIL_OPTION:
+ val_flag |= 1|2|4;
+ break;
+ case SC_UPHEAVAL_OPTION:
+ val_flag |= 1|2;
+ break;
+ case SC_CIRCLE_OF_FIRE_OPTION:
+ val_flag |= 1|2;
+ break;
+ case SC_WATER_BARRIER:
+ val_flag |= 1|2|4;
+ break;
+ case SC_CASH_PLUSEXP:
+ case SC_CASH_PLUSONLYJOBEXP:
+ case SC_MONSTER_TRANSFORM:
+ case SC_CASH_RECEIVEITEM:
+ val_flag |= 1;
+ break;
+ }
/* [Ind/Hercules] */
- if( sd && StatusDisplayType[type] ) {
+ if( sd && status->DisplayType[type] ) {
int dval1 = 0, dval2 = 0, dval3 = 0;
switch( type ) {
case SC_ALL_RIDING:
@@ -8766,11 +9200,15 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
dval1 = val1;
break;
}
- status_display_add(sd,type,dval1,dval2,dval3);
+ status->display_add(sd,type,dval1,dval2,dval3);
}
//Those that make you stop attacking/walking....
switch (type) {
+ case SC_VACUUM_EXTREME:
+ if(!map_flag_gvg(bl->m))
+ unit->stop_walking(bl,1);
+ break;
case SC_FREEZE:
case SC_STUN:
case SC_SLEEP:
@@ -8782,9 +9220,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
status_change_end(bl, SC_DANCING, INVALID_TIMER);
// Cancel cast when get status [LuzZza]
if (battle_config.sc_castcancel&bl->type)
- unit_skillcastcancel(bl, 0);
+ unit->skillcastcancel(bl, 0);
+ case SC_FALLENEMPIRE:
case SC_WHITEIMPRISON:
- unit_stop_attack(bl);
+ unit->stop_attack(bl);
case SC_STOP:
case SC_CONFUSION:
case SC_RG_CCONFINE_M:
@@ -8794,20 +9233,20 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_WUGBITE:
case SC_THORNS_TRAP:
case SC__MANHOLE:
- case SC_CRYSTALIZE:
+ case SC__CHAOS:
+ case SC_COLD:
case SC_CURSEDCIRCLE_ATKER:
case SC_CURSEDCIRCLE_TARGET:
case SC_FEAR:
- case SC_NETHERWORLD:
case SC_MEIKYOUSISUI:
case SC_KYOUGAKU:
case SC_NEEDLE_OF_PARALYZE:
case SC_DEATHBOUND:
- unit_stop_walking(bl,1);
- break;
+ unit->stop_walking(bl,1);
+ break;
case SC_ANKLESNARE:
if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) )
- unit_stop_walking(bl,1);
+ unit->stop_walking(bl,1);
break;
case SC_HIDING:
case SC_CLOAKING:
@@ -8816,12 +9255,38 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_WEIGHTOVER90:
case SC_CAMOUFLAGE:
case SC_SIREN:
- unit_stop_attack(bl);
- break;
+ case SC_ALL_RIDING:
+ unit->stop_attack(bl);
+ break;
case SC_SILENCE:
if (battle_config.sc_castcancel&bl->type)
- unit_skillcastcancel(bl, 0);
- break;
+ unit->skillcastcancel(bl, 0);
+ break;
+ /* */
+ case SC_ITEMSCRIPT:
+ if( sd ) {
+ switch( val1 ) {
+ case ITEMID_PHREEONI_CARD:
+ clif->status_change(bl, SI_FOOD_BASICHIT, 1, tick, 0, 0, 0);
+ break;
+ case ITEMID_GHOSTRING_CARD:
+ clif->status_change(bl,SI_ARMOR_PROPERTY,1,tick,0,0,0);
+ break;
+ case ITEMID_TAO_GUNKA_CARD:
+ clif->status_change(bl,SI_MVPCARD_TAOGUNKA,1,tick,0,0,0);
+ break;
+ case ITEMID_MISTRESS_CARD:
+ clif->status_change(bl,SI_MVPCARD_MISTRESS,1,tick,0,0,0);
+ break;
+ case ITEMID_ORC_HERO_CARD:
+ clif->status_change(bl,SI_MVPCARD_ORCHERO,1,tick,0,0,0);
+ break;
+ case ITEMID_ORC_LOAD_CARD:
+ clif->status_change(bl,SI_MVPCARD_ORCLORD,1,tick,0,0,0);
+ break;
+ }
+ }
+ break;
}
// Set option as needed.
@@ -8831,17 +9296,17 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break;
case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break;
case SC_STUN: sc->opt1 = OPT1_STUN; break;
- case SC_DEEP_SLEEP: opt_flag = 0;
case SC_SLEEP: sc->opt1 = OPT1_SLEEP; break;
case SC_BURNING: sc->opt1 = OPT1_BURNING; break; // Burning need this to be showed correctly. [pakpil]
case SC_WHITEIMPRISON: sc->opt1 = OPT1_IMPRISON; break;
- case SC_CRYSTALIZE: sc->opt1 = OPT1_CRYSTALIZE; break;
+ case SC_COLD: sc->opt1 = OPT1_CRYSTALIZE; break;
//OPT2
case SC_POISON: sc->opt2 |= OPT2_POISON; break;
case SC_CURSE: sc->opt2 |= OPT2_CURSE; break;
case SC_SILENCE: sc->opt2 |= OPT2_SILENCE; break;
case SC_CRUCIS:
+ case SC__CHAOS:
sc->opt2 |= OPT2_SIGNUMCRUCIS;
break;
@@ -8894,7 +9359,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_BERSERK:
opt_flag = 0;
-// case SC__BLOODYLUST:
sc->opt3 |= OPT3_BERSERK;
break;
// case ???: // doesn't seem to do anything
@@ -8946,10 +9410,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
break;
case SC_CLOAKING:
case SC_CLOAKINGEXCEED:
- case SC__INVISIBILITY:
sc->option |= OPTION_CLOAK;
opt_flag = 2;
break;
+ case SC__INVISIBILITY:
case SC_CHASEWALK:
sc->option |= OPTION_CHASEWALK|OPTION_CLOAK;
opt_flag = 2;
@@ -8982,12 +9446,20 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_FUSION:
sc->option |= OPTION_FLYING;
break;
+ case SC_OKTOBERFEST:
+ sc->option |= OPTION_OKTOBERFEST;
+ opt_flag |= 0x4;
+ break;
+ case SC__FEINTBOMB_MASTER:
+ sc->option |= OPTION_INVISIBLE;
+ opt_flag |= 0x4;
+ break;
default:
opt_flag = 0;
}
//On Aegis, when turning on a status change, first goes the option packet, then the sc packet.
- if(opt_flag) {
+ if(opt_flag) {
clif->changeoption(bl);
if( sd && opt_flag&0x4 ) {
clif->changelook(bl,LOOK_BASE,vd->class_);
@@ -9004,59 +9476,61 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
calc_flag&=~SCB_DYE;
}
- if( !(flag&4 && StatusDisplayType[type]) )
- clif->status_change(bl,StatusIconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0);
+ if( !(flag&4 && status->DisplayType[type]) )
+ clif->status_change(bl,status->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0);
/**
- * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first.
- **/
+ * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first.
+ **/
if( tick_time )
tick = tick_time;
//Don't trust the previous sce assignment, in case the SC ended somewhere between there and here.
if((sce=sc->data[type])) {// reuse old sc
if( sce->timer != INVALID_TIMER )
- iTimer->delete_timer(sce->timer, status_change_timer);
+ timer->delete(sce->timer, status->change_timer);
} else {// new sc
++(sc->count);
- sce = sc->data[type] = ers_alloc(sc_data_ers, struct status_change_entry);
+ sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry);
}
sce->val1 = val1;
sce->val2 = val2;
sce->val3 = val3;
sce->val4 = val4;
if (tick >= 0)
- sce->timer = iTimer->add_timer(iTimer->gettick() + tick, status_change_timer, bl->id, type);
- else
+ sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type);
+ else {
sce->timer = INVALID_TIMER; //Infinite duration
+ if( sd )
+ chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce);
+ }
if (calc_flag)
status_calc_bl(bl,calc_flag);
if(sd && sd->pd)
- pet_sc_check(sd, type); //Skotlex: Pet Status Effect Healing
+ pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing
- switch (type) {
- case SC__BLOODYLUST:
+ switch (type) {
case SC_BERSERK:
if (!(sce->val2)) { //don't heal if already set
- status_heal(bl, status->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block.
- status_set_sp(bl, 0, 0); //Damage all SP
+ status->heal(bl, st->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block.
+ status->set_sp(bl, 0, 0); //Damage all SP
}
- sce->val2 = 5 * status->max_hp / 100;
+ sce->val2 = 5 * st->max_hp / 100;
break;
case SC_HLIF_CHANGE:
status_percent_heal(bl, 100, 100);
break;
case SC_RUN:
{
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
if( ud )
- ud->state.running = unit_run(bl);
+ ud->state.running = unit->run(bl, NULL, SC_RUN);
}
break;
case SC_CASH_BOSS_ALARM:
- clif->bossmapinfo(sd->fd, iMap->id2boss(sce->val1), 0); // First Message
+ clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message
break;
case SC_MER_HP:
status_percent_heal(bl, 100, 0); // Recover Full HP
@@ -9064,87 +9538,86 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_MER_SP:
status_percent_heal(bl, 0, 100); // Recover Full SP
break;
- /**
- * Ranger
- **/
+ /**
+ * Ranger
+ **/
case SC_WUGDASH:
{
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
if( ud )
- ud->state.running = unit_wugdash(bl, sd);
+ ud->state.running = unit->run(bl, sd, SC_WUGDASH);
}
break;
case SC_COMBOATTACK:
switch (sce->val1) {
- case TK_STORMKICK:
- clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1);
- break;
- case TK_DOWNKICK:
- clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1);
- break;
- case TK_TURNKICK:
- clif->skill_nodamage(bl,bl,TK_READYTURN,1,1);
- break;
- case TK_COUNTER:
- clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1);
- break;
- case MO_COMBOFINISH:
- case CH_TIGERFIST:
- case CH_CHAINCRUSH:
- if (sd)
- clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL);
- break;
- case TK_JUMPKICK:
- if (sd)
- clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL);
- break;
- case MO_TRIPLEATTACK:
- if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0)
- clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL);
- break;
- case SR_FALLENEMPIRE:
- if (sd){
- clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL);
- clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL);
- }
- break;
+ case TK_STORMKICK:
+ clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1);
+ break;
+ case TK_DOWNKICK:
+ clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1);
+ break;
+ case TK_TURNKICK:
+ clif->skill_nodamage(bl,bl,TK_READYTURN,1,1);
+ break;
+ case TK_COUNTER:
+ clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1);
+ break;
+ case MO_COMBOFINISH:
+ case CH_TIGERFIST:
+ case CH_CHAINCRUSH:
+ if (sd)
+ clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL);
+ break;
+ case TK_JUMPKICK:
+ if (sd)
+ clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL);
+ break;
+ case MO_TRIPLEATTACK:
+ if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0)
+ clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL);
+ break;
+ case SR_FALLENEMPIRE:
+ if (sd){
+ clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL);
+ clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL);
+ }
+ break;
}
break;
- case SC_RAISINGDRAGON:
- sce->val2 = status->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie]
+ case SC_RAISINGDRAGON:
+ sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie]
break;
}
if( opt_flag&2 && sd && sd->touching_id )
- npc_touchnext_areanpc(sd,false); // run OnTouch_ on next char in range
+ npc->touchnext_areanpc(sd,false); // run OnTouch_ on next char in range
return 1;
}
-
/*==========================================
- * Ending all status except those listed.
- * @TODO maybe usefull for dispel instead reseting a liste there.
- * type:
- * 0 - PC killed -> Place here statuses that do not dispel on death.
- * 1 - If for some reason status_change_end decides to still keep the status when quitting.
- * 2 - Do clif
- * 3 - Do not remove some permanent/time-independent effects
- *------------------------------------------*/
+* Ending all status except those listed.
+* @TODO maybe usefull for dispel instead reseting a liste there.
+* type:
+* 0 - PC killed -> Place here statuses that do not dispel on death.
+* 1 - If for some reason status_change_end decides to still keep the status when quitting.
+* 2 - Do clif
+* 3 - Do not remove some permanent/time-independent effects
+*------------------------------------------*/
int status_change_clear(struct block_list* bl, int type) {
struct status_change* sc;
int i;
- sc = status_get_sc(bl);
+ sc = status->get_sc(bl);
if (!sc || !sc->count)
return 0;
for(i = 0; i < SC_MAX; i++) {
if(!sc->data[i])
- continue;
-
+ continue;
+
if(type == 0){
- if( status_get_sc_type(i)&SC_NO_REM_DEATH ){
+ if( status->get_sc_type(i)&SC_NO_REM_DEATH ) {
switch (i) {
case SC_ARMOR_PROPERTY://Only when its Holy or Dark that it doesn't dispell on death
if( sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK )
@@ -9154,17 +9627,8 @@ int status_change_clear(struct block_list* bl, int type) {
}
}
}
- if( type == 3 ) {
- switch (i) {// TODO: This list may be incomplete
- case SC_WEIGHTOVER50:
- case SC_WEIGHTOVER90:
- case SC_NOCHAT:
- case SC_PUSH_CART:
- case SC_JAILED:
- case SC_ALL_RIDING:
- continue;
- }
- }
+ if( type == 3 && status->get_sc_type(i)&SC_NO_CLEAR )
+ continue;
status_change_end(bl, (sc_type)i, INVALID_TIMER);
@@ -9172,8 +9636,8 @@ int status_change_clear(struct block_list* bl, int type) {
//If for some reason status_change_end decides to still keep the status when quitting. [Skotlex]
(sc->count)--;
if (sc->data[i]->timer != INVALID_TIMER)
- iTimer->delete_timer(sc->data[i]->timer, status_change_timer);
- ers_free(sc_data_ers, sc->data[i]);
+ timer->delete(sc->data[i]->timer, status->change_timer);
+ ers_free(status->data_ers, sc->data[i]);
sc->data[i] = NULL;
}
}
@@ -9182,6 +9646,7 @@ int status_change_clear(struct block_list* bl, int type) {
sc->opt2 = 0;
sc->opt3 = 0;
sc->bs_counter = 0;
+ sc->fv_counter = 0;
#ifndef RENEWAL
sc->sg_counter = 0;
#endif
@@ -9193,20 +9658,23 @@ int status_change_clear(struct block_list* bl, int type) {
}
/*==========================================
- * Special condition we want to effectuate, check before ending a status.
- *------------------------------------------*/
+* Special condition we want to effectuate, check before ending a status.
+*------------------------------------------*/
int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line) {
struct map_session_data *sd;
struct status_change *sc;
struct status_change_entry *sce;
- struct status_data *status;
+ struct status_data *st;
struct view_data *vd;
int opt_flag=0, calc_flag;
-
+#ifdef ANTI_MAYAP_CHEAT
+ bool invisible = false;
+#endif
+
nullpo_ret(bl);
- sc = status_get_sc(bl);
- status = status_get_status_data(bl);
+ sc = status->get_sc(bl);
+ st = status->get_status_data(bl);
if(type < 0 || type >= SC_MAX || !sc || !(sce = sc->data[type]))
return 0;
@@ -9216,30 +9684,33 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
if (sce->timer != tid && tid != INVALID_TIMER)
return 0;
+ if( sd && sce->timer == INVALID_TIMER && !sd->state.loggingout )
+ chrif->del_scdata_single(sd->status.account_id,sd->status.char_id,type);
+
if (tid == INVALID_TIMER) {
if (type == SC_ENDURE && sce->val4)
//Do not end infinite endure.
- return 0;
+ return 0;
if (sce->timer != INVALID_TIMER) //Could be a SC with infinite duration
- iTimer->delete_timer(sce->timer,status_change_timer);
+ timer->delete(sce->timer,status->change_timer);
if (sc->opt1)
- switch (type) {
- //"Ugly workaround" [Skotlex]
- //delays status change ending so that a skill that sets opt1 fails to
- //trigger when it also removed one
- case SC_STONE:
- sce->val3 = 0; //Petrify time counter.
- case SC_FREEZE:
- case SC_STUN:
- case SC_SLEEP:
- if (sce->val1) {
- //Removing the 'level' shouldn't affect anything in the code
- //since these SC are not affected by it, and it lets us know
- //if we have already delayed this attack or not.
- sce->val1 = 0;
- sce->timer = iTimer->add_timer(iTimer->gettick()+10, status_change_timer, bl->id, type);
- return 1;
- }
+ switch (type) {
+ //"Ugly workaround" [Skotlex]
+ //delays status change ending so that a skill that sets opt1 fails to
+ //trigger when it also removed one
+ case SC_STONE:
+ sce->val3 = 0; //Petrify time counter.
+ case SC_FREEZE:
+ case SC_STUN:
+ case SC_SLEEP:
+ if (sce->val1) {
+ //Removing the 'level' shouldn't affect anything in the code
+ //since these SC are not affected by it, and it lets us know
+ //if we have already delayed this attack or not.
+ sce->val1 = 0;
+ sce->timer = timer->add(timer->gettick()+10, status->change_timer, bl->id, type);
+ return 1;
+ }
}
}
@@ -9247,42 +9718,52 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
sc->data[type] = NULL;
- if( sd && StatusDisplayType[type] ) {
- status_display_remove(sd,type);
+ if( sd && status->DisplayType[type] ) {
+ status->display_remove(sd,type);
}
-
- vd = status_get_viewdata(bl);
- calc_flag = StatusChangeFlagTable[type];
- switch(type){
- case SC_GRANITIC_ARMOR:{
- int dammage = status->max_hp*sce->val3/100;
- if(status->hp < dammage) //to not kill him
- dammage = status->hp-1;
- status_damage(NULL, bl, dammage,0,0,1);
- break;
- }
- case SC_PYROCLASTIC:
- if(bl->type == BL_PC)
- skill->break_equip(bl,EQP_WEAPON,10000,BCT_SELF);
- break;
- case SC_RUN:
+
+#ifdef ANTI_MAYAP_CHEAT
+ if (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE))
+ invisible = true;
+#endif
+
+ vd = status->get_viewdata(bl);
+ calc_flag = status->ChangeFlagTable[type];
+ switch(type) {
+ case SC_GRANITIC_ARMOR:
{
- struct unit_data *ud = unit_bl2ud(bl);
- bool begin_spurt = true;
- if (ud) {
- if(!ud->state.running)
- begin_spurt = false;
- ud->state.running = 0;
- if (ud->walktimer != INVALID_TIMER)
- unit_stop_walking(bl,1);
- }
- if (begin_spurt && sce->val1 >= 7 &&
- DIFF_TICK(iTimer->gettick(), sce->val4) <= 1000 &&
- (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0))
- )
- sc_start(bl,SC_STRUP,100,sce->val1,skill->get_time2(status_sc2skill(type), sce->val1));
+ int damage = st->max_hp*sce->val3/100;
+ if(st->hp < damage) //to not kill him
+ damage = st->hp-1;
+ status->damage(NULL, bl, damage,0,0,1);
}
- break;
+ break;
+ case SC_PYROCLASTIC:
+ if(bl->type == BL_PC)
+ skill->break_equip(bl,EQP_WEAPON,10000,BCT_SELF);
+ break;
+ case SC_RUN:
+ {
+ struct unit_data *ud = unit->bl2ud(bl);
+ bool begin_spurt = true;
+ // Note: this int64 value is stored in two separate int32 variables (FIXME)
+ int64 starttick = (int64)sce->val3&0x00000000ffffffffLL;
+ starttick |= ((int64)sce->val4<<32)&0xffffffff00000000LL;
+
+ if (ud) {
+ if(!ud->state.running)
+ begin_spurt = false;
+ ud->state.running = 0;
+ if (ud->walktimer != INVALID_TIMER)
+ unit->stop_walking(bl,1);
+ }
+ if (begin_spurt && sce->val1 >= 7
+ && DIFF_TICK(timer->gettick(), starttick) <= 1000
+ && (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0))
+ )
+ sc_start(bl, bl,SC_STRUP,100,sce->val1,skill->get_time2(status->sc2skill(type), sce->val1));
+ }
+ break;
case SC_AUTOBERSERK:
if (sc->data[SC_PROVOKE] && sc->data[SC_PROVOKE]->val2 == 1)
status_change_end(bl, SC_PROVOKE, INVALID_TIMER);
@@ -9294,17 +9775,15 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
case SC_AUTOGUARD:
{
struct map_session_data *tsd;
- if( bl->type == BL_PC )
- { // Clear Status from others
+ if( bl->type == BL_PC ) {
+ // Clear Status from others
int i;
- for( i = 0; i < 5; i++ )
- {
- if( sd->devotion[i] && (tsd = iMap->id2sd(sd->devotion[i])) && tsd->sc.data[type] )
+ for( i = 0; i < 5; i++ ) {
+ if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) && tsd->sc.data[type] )
status_change_end(&tsd->bl, type, INVALID_TIMER);
}
- }
- else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag )
- { // Clear Status from Master
+ } else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag ) {
+ // Clear Status from Master
tsd = ((TBL_MER*)bl)->master;
if( tsd && tsd->sc.data[type] )
status_change_end(&tsd->bl, type, INVALID_TIMER);
@@ -9313,9 +9792,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_DEVOTION:
{
- struct block_list *d_bl = iMap->id2bl(sce->val1);
- if( d_bl )
- {
+ struct block_list *d_bl = map->id2bl(sce->val1);
+ if( d_bl ) {
if( d_bl->type == BL_PC )
((TBL_PC*)d_bl)->devotion[sce->val2] = 0;
else if( d_bl->type == BL_MER )
@@ -9331,18 +9809,16 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_BLADESTOP:
- if(sce->val4)
- {
- int tid = sce->val4;
- struct block_list *tbl = iMap->id2bl(tid);
- struct status_change *tsc = status_get_sc(tbl);
+ if(sce->val4) {
+ int target_id = sce->val4;
+ struct block_list *tbl = map->id2bl(target_id);
+ struct status_change *tsc = status->get_sc(tbl);
sce->val4 = 0;
- if(tbl && tsc && tsc->data[SC_BLADESTOP])
- {
+ if(tbl && tsc && tsc->data[SC_BLADESTOP]) {
tsc->data[SC_BLADESTOP]->val4 = 0;
status_change_end(tbl, SC_BLADESTOP, INVALID_TIMER);
}
- clif->bladestop(bl, tid, 0);
+ clif->bladestop(bl, target_id, 0);
}
break;
case SC_DANCING:
@@ -9368,7 +9844,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
sd->delunit_prevline = line;
}
- if(sce->val4 && sce->val4 != BCT_SELF && (dsd=iMap->id2sd(sce->val4)))
+ if(sce->val4 && sce->val4 != BCT_SELF && (dsd=map->id2sd(sce->val4)))
{// end status on partner as well
dsc = dsd->sc.data[SC_DANCING];
if(dsc) {
@@ -9415,15 +9891,15 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_SPLASHER:
{
- struct block_list *src=iMap->id2bl(sce->val3);
+ struct block_list *src=map->id2bl(sce->val3);
if(src && tid != INVALID_TIMER)
- skill->castend_damage_id(src, bl, sce->val2, sce->val1, iTimer->gettick(), SD_LEVEL );
+ skill->castend_damage_id(src, bl, sce->val2, sce->val1, timer->gettick(), SD_LEVEL );
}
break;
case SC_RG_CCONFINE_S:
{
- struct block_list *src = sce->val2?iMap->id2bl(sce->val2):NULL;
- struct status_change *sc2 = src?status_get_sc(src):NULL;
+ struct block_list *src = sce->val2 ? map->id2bl(sce->val2) : NULL;
+ struct status_change *sc2 = src ? status->get_sc(src) : NULL;
if (src && sc2 && sc2->data[SC_RG_CCONFINE_M]) {
//If status was already ended, do nothing.
//Decrease count
@@ -9435,15 +9911,15 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
if (sce->val2 > 0) {
//Caster has been unlocked... nearby chars need to be unlocked.
int range = 1
- +skill->get_range2(bl, status_sc2skill(type), sce->val1)
+ +skill->get_range2(bl, status->sc2skill(type), sce->val1)
+skill->get_range2(bl, TF_BACKSLIDING, 1); //Since most people use this to escape the hold....
- iMap->foreachinarea(status_change_timer_sub,
- bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,BL_CHAR,bl,sce,type,iTimer->gettick());
+ map->foreachinarea(status->change_timer_sub,
+ bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,BL_CHAR,bl,sce,type,timer->gettick());
}
break;
case SC_COMBOATTACK:
if( sd )
- switch (sce->val1) {
+ switch (sce->val1) {
case MO_COMBOFINISH:
case CH_TIGERFIST:
case CH_CHAINCRUSH:
@@ -9464,12 +9940,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_MARIONETTE_MASTER:
- case SC_MARIONETTE: /// Marionette target
- if (sce->val1)
- { // check for partner and end their marionette status as well
+ case SC_MARIONETTE: /// Marionette target
+ if (sce->val1) {
+ // check for partner and end their marionette status as well
enum sc_type type2 = (type == SC_MARIONETTE_MASTER) ? SC_MARIONETTE : SC_MARIONETTE_MASTER;
- struct block_list *pbl = iMap->id2bl(sce->val1);
- struct status_change* sc2 = pbl?status_get_sc(pbl):NULL;
+ struct block_list *pbl = map->id2bl(sce->val1);
+ struct status_change* sc2 = pbl ? status->get_sc(pbl) : NULL;
if (sc2 && sc2->data[type2])
{
@@ -9480,19 +9956,18 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_BERSERK:
- case SC_SATURDAY_NIGHT_FEVER:
- //If val2 is removed, no HP penalty (dispelled?) [Skotlex]
- if (status->hp > 100 && sce->val2)
- status_set_hp(bl, 100, 0);
- if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2)
- {
+ if(st->hp > 200 && sc && sc->data[SC__BLOODYLUST]) {
+ status_percent_heal(bl, 100, 0);
+ status_change_end(bl, SC__BLOODYLUST, INVALID_TIMER);
+ } else if(st->hp > 100 && sce->val2) //If val2 is removed, no HP penalty (dispelled?) [Skotlex]
+ status->set_hp(bl, 100, 0);
+ if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2) {
sc->data[SC_ENDURE]->val4 = 0;
status_change_end(bl, SC_ENDURE, INVALID_TIMER);
}
- case SC__BLOODYLUST:
- sc_start4(bl, SC_GDSKILL_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill->get_time(LK_BERSERK, sce->val1));
+ sc_start4(bl, bl, SC_GDSKILL_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill->get_time(LK_BERSERK, sce->val1));
if( type == SC_SATURDAY_NIGHT_FEVER ) //Sit down force of Saturday Night Fever has the duration of only 3 seconds.
- sc_start(bl,SC_SITDOWN_FORCE,100,sce->val1,skill->get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1));
+ sc_start(bl,bl,SC_SITDOWN_FORCE,100,sce->val1,skill->get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1));
break;
case SC_GOSPEL:
if (sce->val3) { //Clear the group.
@@ -9506,8 +9981,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
skill->clear_unitgroup(bl);
break;
case SC_BASILICA: //Clear the skill area. [Skotlex]
- skill->clear_unitgroup(bl);
- break;
+ skill->clear_unitgroup(bl);
+ break;
case SC_TRICKDEAD:
if (vd) vd->dead_sit = 0;
break;
@@ -9523,76 +9998,77 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
case SC_KAAHI:
//Delete timer if it exists.
if (sce->val4 != INVALID_TIMER)
- iTimer->delete_timer(sce->val4,kaahi_heal_timer);
+ timer->delete(sce->val4,status->kaahi_heal_timer);
break;
case SC_JAILED:
if(tid == INVALID_TIMER)
break;
- //natural expiration.
+ //natural expiration.
if(sd && sd->mapindex == sce->val2)
pc->setpos(sd,(unsigned short)sce->val3,sce->val4&0xFFFF, sce->val4>>16, CLR_TELEPORT);
break; //guess hes not in jail :P
case SC_HLIF_CHANGE:
if (tid == INVALID_TIMER)
- break;
+ break;
// "lose almost all their HP and SP" on natural expiration.
- status_set_hp(bl, 10, 0);
- status_set_sp(bl, 10, 0);
+ status->set_hp(bl, 10, 0);
+ status->set_sp(bl, 10, 0);
break;
case SC_AUTOTRADE:
if (tid == INVALID_TIMER)
break;
// Note: vending/buying is closed by unit_remove_map, no
// need to do it here.
- iMap->quit(sd);
- // Because iMap->quit calls status_change_end with tid -1
+ map->quit(sd);
+ // Because map->quit calls status_change_end with tid -1
// from here it's not neccesary to continue
return 1;
break;
case SC_STOP:
- if( sce->val2 )
- {
- struct block_list* tbl = iMap->id2bl(sce->val2);
+ if( sce->val2 ) {
+ struct block_list *tbl = map->id2bl(sce->val2);
+ struct status_change *tsc = NULL;
sce->val2 = 0;
- if( tbl && (sc = status_get_sc(tbl)) && sc->data[SC_STOP] && sc->data[SC_STOP]->val2 == bl->id )
+ if( tbl && (tsc = status->get_sc(tbl)) && tsc->data[SC_STOP] && tsc->data[SC_STOP]->val2 == bl->id )
status_change_end(tbl, SC_STOP, INVALID_TIMER);
}
break;
case SC_LKCONCENTRATION:
status_change_end(bl, SC_ENDURE, INVALID_TIMER);
break;
- /**
- * 3rd Stuff
- **/
+ /**
+ * 3rd Stuff
+ **/
case SC_MILLENNIUMSHIELD:
- clif->millenniumshield(sd,0);
+ clif->millenniumshield(bl,0);
break;
case SC_HALLUCINATIONWALK:
- sc_start(bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill->get_time2(GC_HALLUCINATIONWALK,sce->val1));
+ sc_start(bl,bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill->get_time2(GC_HALLUCINATIONWALK,sce->val1));
break;
case SC_WHITEIMPRISON:
{
- struct block_list* src = iMap->id2bl(sce->val2);
+ struct block_list* src = map->id2bl(sce->val2);
if( tid == -1 || !src)
break; // Terminated by Damage
- status_fix_damage(src,bl,400*sce->val1,clif->damage(bl,bl,iTimer->gettick(),0,0,400*sce->val1,0,0,0));
+ status_fix_damage(src,bl,400*sce->val1,clif->damage(bl,bl,0,0,400*sce->val1,0,0,0));
}
break;
case SC_WUGDASH:
{
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
if (ud) {
ud->state.running = 0;
if (ud->walktimer != -1)
- unit_stop_walking(bl,1);
+ unit->stop_walking(bl,1);
}
}
break;
case SC_ADORAMUS:
status_change_end(bl, SC_BLIND, INVALID_TIMER);
break;
- case SC__SHADOWFORM: {
- struct map_session_data *s_sd = iMap->id2sd(sce->val2);
+ case SC__SHADOWFORM:
+ {
+ struct map_session_data *s_sd = map->id2sd(sce->val2);
if( !s_sd )
break;
s_sd->shadowform_id = 0;
@@ -9614,16 +10090,16 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
break;
case SC_BANDING:
- if(sce->val4) {
- struct skill_unit_group *group = skill->id2group(sce->val4);
- sce->val4 = 0;
- if( group ) /* might have been cleared before status ended, e.g. land protector */
- skill->del_unitgroup(group,ALC_MARK);
- }
+ if(sce->val4) {
+ struct skill_unit_group *group = skill->id2group(sce->val4);
+ sce->val4 = 0;
+ if( group ) /* might have been cleared before status ended, e.g. land protector */
+ skill->del_unitgroup(group,ALC_MARK);
+ }
break;
case SC_CURSEDCIRCLE_ATKER:
if( sce->val2 ) // used the default area size cause there is a chance the caster could knock back and can't clear the target.
- iMap->foreachinrange(status_change_timer_sub, bl, battle_config.area_size,BL_CHAR, bl, sce, SC_CURSEDCIRCLE_TARGET, iTimer->gettick());
+ map->foreachinrange(status->change_timer_sub, bl, battle_config.area_size,BL_CHAR, bl, sce, SC_CURSEDCIRCLE_TARGET, timer->gettick());
break;
case SC_RAISINGDRAGON:
if( sd && sce->val2 && !pc_isdead(sd) ) {
@@ -9638,21 +10114,21 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
break;
case SC_CURSEDCIRCLE_TARGET:
- {
- struct block_list *src = iMap->id2bl(sce->val2);
- struct status_change *sc = status_get_sc(src);
- if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] && --(sc->data[SC_CURSEDCIRCLE_ATKER]->val2) == 0 ){
- status_change_end(src, SC_CURSEDCIRCLE_ATKER, INVALID_TIMER);
- clif->bladestop(bl, sce->val2, 0);
- }
+ {
+ struct block_list *src = map->id2bl(sce->val2);
+ struct status_change *ssc = status->get_sc(src);
+ if( ssc && ssc->data[SC_CURSEDCIRCLE_ATKER] && --(ssc->data[SC_CURSEDCIRCLE_ATKER]->val2) == 0 ){
+ status_change_end(src, SC_CURSEDCIRCLE_ATKER, INVALID_TIMER);
+ clif->bladestop(bl, sce->val2, 0);
}
+ }
break;
case SC_BLOOD_SUCKER:
if( sce->val2 ){
- struct block_list *src = iMap->id2bl(sce->val2);
- if(src){
- struct status_change *sc = status_get_sc(src);
- sc->bs_counter--;
+ struct block_list *src = map->id2bl(sce->val2);
+ if(src) {
+ struct status_change *ssc = status->get_sc(src);
+ ssc->bs_counter--;
}
}
break;
@@ -9663,20 +10139,61 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
calc_flag = SCB_ALL;/* required for overlapping */
break;
case SC_FULL_THROTTLE:
- sc_start(bl,SC_REBOUND,100,sce->val1,skill->get_time2(ALL_FULL_THROTTLE,sce->val1));
+ sc_start(bl,bl,SC_REBOUND,100,sce->val1,skill->get_time2(ALL_FULL_THROTTLE,sce->val1));
break;
- }
+ case SC_MONSTER_TRANSFORM:
+ if( sce->val2 )
+ status_change_end(bl, (sc_type)sce->val2, INVALID_TIMER);
+ break;
+ case SC_ITEMSCRIPT:
+ if( sd ) {
+ switch( sce->val1 ) {
+ case ITEMID_PHREEONI_CARD:
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_FOOD_BASICHIT);
+ break;
+ case ITEMID_GHOSTRING_CARD:
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_ARMOR_PROPERTY);
+ break;
+ case ITEMID_TAO_GUNKA_CARD:
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_MVPCARD_TAOGUNKA);
+ break;
+ case ITEMID_MISTRESS_CARD:
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_MVPCARD_MISTRESS);
+ break;
+ case ITEMID_ORC_HERO_CARD:
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_MVPCARD_ORCHERO);
+ break;
+ case ITEMID_ORC_LOAD_CARD:
+ clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_MVPCARD_ORCLORD);
+ break;
+ }
+ }
+ break;
+ case SC_OVERED_BOOST:
+ switch( bl->type ){
+ case BL_HOM:
+ {
+ struct homun_data *hd = BL_CAST(BL_HOM, bl);
+ if( hd )
+ hd->homunculus.hunger = max(1, hd->homunculus.hunger - 50);
+ }
+ break;
+ case BL_PC:
+ status_zap(bl, 0, status_get_max_sp(bl) / 2);
+ break;
+ }
+ break;
+ }
opt_flag = 1;
- switch(type){
+ switch(type) {
case SC_STONE:
case SC_FREEZE:
case SC_STUN:
case SC_SLEEP:
- case SC_DEEP_SLEEP:
case SC_BURNING:
case SC_WHITEIMPRISON:
- case SC_CRYSTALIZE:
+ case SC_COLD:
sc->opt1 = 0;
break;
@@ -9690,6 +10207,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
sc->opt2 &= ~OPT2_DPOISON;
break;
case SC_CRUCIS:
+ case SC__CHAOS:
sc->opt2 &= ~OPT2_SIGNUMCRUCIS;
break;
@@ -9699,11 +10217,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_CLOAKING:
case SC_CLOAKINGEXCEED:
- case SC__INVISIBILITY:
sc->option &= ~OPTION_CLOAK;
case SC_CAMOUFLAGE:
opt_flag|= 2;
break;
+ case SC__INVISIBILITY:
case SC_CHASEWALK:
sc->option &= ~(OPTION_CHASEWALK|OPTION_CLOAK);
opt_flag|= 2;
@@ -9727,6 +10245,14 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
sc->option &= ~OPTION_HANBOK;
opt_flag |= 0x4;
break;
+ case SC_OKTOBERFEST:
+ sc->option &= ~OPTION_OKTOBERFEST;
+ opt_flag |= 0x4;
+ break;
+ case SC__FEINTBOMB_MASTER:
+ sc->option &= ~OPTION_INVISIBLE;
+ opt_flag |= 0x4;
+ break;
case SC_ORCISH:
sc->option &= ~OPTION_ORCISH;
break;
@@ -9736,7 +10262,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
case SC_FUSION:
sc->option &= ~OPTION_FLYING;
break;
- //opt3
+ //opt3
case SC_TWOHANDQUICKEN:
case SC_ONEHANDQUICKEN:
case SC_SPEARQUICKEN:
@@ -9784,13 +10310,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_BERSERK:
opt_flag = 0;
- // case SC__BLOODYLUST:
sc->opt3 &= ~OPT3_BERSERK;
break;
- // case ???: // doesn't seem to do anything
- // sc->opt3 &= ~OPT3_LIGHTBLADE;
- // opt_flag = 0;
- // break;
+ // case ???: // doesn't seem to do anything
+ // sc->opt3 &= ~OPT3_LIGHTBLADE;
+ // opt_flag = 0;
+ // break;
case SC_DANCING:
if ((sce->val1&0xFFFF) == CG_MOONLIT)
sc->opt3 &= ~OPT3_MOONLIT;
@@ -9825,14 +10350,20 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
sc->opt3 &= ~OPT3_UNDEAD;
opt_flag = 0;
break;
- // case ???: // from DA_CONTRACT (looks like biolab mobs aura)
- // sc->opt3 &= ~OPT3_CONTRACT;
- // opt_flag = 0;
- // break;
+ // case ???: // from DA_CONTRACT (looks like biolab mobs aura)
+ // sc->opt3 &= ~OPT3_CONTRACT;
+ // opt_flag = 0;
+ // break;
default:
opt_flag = 0;
}
+#ifdef ANTI_MAYAP_CHEAT
+ if (invisible && !(sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE))) {
+ clif->fixpos(bl);
+ }
+#endif
+
if (calc_flag&SCB_DYE) { //Restore DYE color
if (vd && !vd->cloth_color && sce->val4)
clif->changelook(bl,LOOK_CLOTHES_COLOR,sce->val4);
@@ -9840,14 +10371,14 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
//On Aegis, when turning off a status change, first goes the sc packet, then the option packet.
- clif->sc_end(bl,bl->id,AREA,StatusIconChangeTable[type]);
+ clif->sc_end(bl,bl->id,AREA,status->IconChangeTable[type]);
if( opt_flag&8 ) //bugreport:681
clif->changeoption2(bl);
else if(opt_flag) {
clif->changeoption(bl);
if( sd && opt_flag&0x4 ) {
- clif->changelook(bl,LOOK_BASE,vd->class_);
+ clif->changelook(bl,LOOK_BASE,sd->vd.class_);
clif->get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield);
clif->changelook(bl,LOOK_WEAPON,sd->vd.weapon);
clif->changelook(bl,LOOK_SHIELD,sd->vd.shield);
@@ -9859,26 +10390,26 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
status_calc_bl(bl,calc_flag);
if(opt_flag&4) //Out of hiding, invoke on place.
- skill->unit_move(bl,iTimer->gettick(),1);
+ skill->unit_move(bl,timer->gettick(),1);
- if(opt_flag&2 && sd && iMap->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC))
- npc_touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event.
+ if(opt_flag&2 && sd && map->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC))
+ npc->touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event.
- ers_free(sc_data_ers, sce);
+ ers_free(status->data_ers, sce);
return 1;
}
-int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) {
struct block_list *bl;
struct status_change *sc;
struct status_change_entry *sce;
- struct status_data *status;
+ struct status_data *st;
int hp;
- if(!((bl=iMap->id2bl(id))&&
- (sc=status_get_sc(bl)) &&
- (sce = sc->data[SC_KAAHI])))
+ if(!( (bl=map->id2bl(id))
+ && (sc=status->get_sc(bl))
+ && (sce=sc->data[SC_KAAHI])
+ ))
return 0;
if(sce->val4 != tid) {
@@ -9887,243 +10418,235 @@ int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data)
return 0;
}
- status=status_get_status_data(bl);
- if(!status_charge(bl, 0, sce->val3)) {
+ st=status->get_status_data(bl);
+ if(!status->charge(bl, 0, sce->val3)) {
sce->val4 = INVALID_TIMER;
return 0;
}
- hp = status->max_hp - status->hp;
+ hp = st->max_hp - st->hp;
if (hp > sce->val2)
hp = sce->val2;
if (hp)
- status_heal(bl, hp, 0, 2);
+ status->heal(bl, hp, 0, 2);
sce->val4 = INVALID_TIMER;
return 1;
}
/*==========================================
- * For recusive status, like for each 5s we drop sp etc.
- * Reseting the end timer.
- *------------------------------------------*/
-int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+* For recusive status, like for each 5s we drop sp etc.
+* Reseting the end timer.
+*------------------------------------------*/
+int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
enum sc_type type = (sc_type)data;
struct block_list *bl;
struct map_session_data *sd;
- struct status_data *status;
+ struct status_data *st;
struct status_change *sc;
struct status_change_entry *sce;
- bl = iMap->id2bl(id);
- if(!bl)
- {
- ShowDebug("status_change_timer: Null pointer id: %d data: %d\n", id, data);
+ bl = map->id2bl(id);
+ if (!bl) {
+ ShowDebug("status_change_timer: Null pointer id: %d data: %"PRIdPTR"\n", id, data);
return 0;
}
- sc = status_get_sc(bl);
- status = status_get_status_data(bl);
+ sc = status->get_sc(bl);
+ st = status->get_status_data(bl);
- if(!(sc && (sce = sc->data[type])))
- {
- ShowDebug("status_change_timer: Null pointer id: %d data: %d bl-type: %d\n", id, data, bl->type);
+ if (!(sc && (sce = sc->data[type]))) {
+ ShowDebug("status_change_timer: Null pointer id: %d data: %"PRIdPTR" bl-type: %d\n", id, data, bl->type);
return 0;
}
- if( sce->timer != tid )
- {
+ if (sce->timer != tid) {
ShowError("status_change_timer: Mismatch for type %d: %d != %d (bl id %d)\n",type,tid,sce->timer, bl->id);
return 0;
}
sd = BL_CAST(BL_PC, bl);
-// set the next timer of the sce (don't assume the status still exists)
-#define sc_timer_next(t,f,i,d) \
- if( (sce=sc->data[type]) ) \
- sce->timer = iTimer->add_timer(t,f,i,d); \
+ // set the next timer of the sce (don't assume the status still exists)
+#define sc_timer_next(t,f,i,d) do { \
+ if ((sce=sc->data[type])) \
+ sce->timer = timer->add((t),(f),(i),(d)); \
else \
- ShowError("status_change_timer: Unexpected NULL status change id: %d data: %d\n", id, data)
+ ShowError("status_change_timer: Unexpected NULL status change id: %d data: %"PRIdPTR"\n", id, data); \
+} while(0)
- switch(type)
- {
- case SC_MAXIMIZEPOWER:
- case SC_CLOAKING:
- if(!status_charge(bl, 0, 1))
- break; //Not enough SP to continue.
- sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data);
- return 0;
-
- case SC_CHASEWALK:
- if(!status_charge(bl, 0, sce->val4))
- break; //Not enough SP to continue.
+ switch(type) {
+ case SC_MAXIMIZEPOWER:
+ case SC_CLOAKING:
+ if(!status->charge(bl, 0, 1))
+ break; //Not enough SP to continue.
+ sc_timer_next(sce->val2+tick, status->change_timer, bl->id, data);
+ return 0;
- if (!sc->data[SC_CHASEWALK2]) {
- sc_start(bl, SC_CHASEWALK2,100,1<<(sce->val1-1),
- (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_ROGUE?10:1) //SL bonus -> x10 duration
- *skill->get_time2(status_sc2skill(type),sce->val1));
- }
- sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data);
- return 0;
- break;
+ case SC_CHASEWALK:
+ if(!status->charge(bl, 0, sce->val4))
+ break; //Not enough SP to continue.
- case SC_SKA:
- if(--(sce->val2)>0){
- sce->val3 = rnd()%100; //Random defense.
- sc_timer_next(1000+tick, status_change_timer,bl->id, data);
+ if (!sc->data[SC_CHASEWALK2]) {
+ sc_start(bl,bl, SC_CHASEWALK2,100,1<<(sce->val1-1),
+ (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_ROGUE?10:1) //SL bonus -> x10 duration
+ * skill->get_time2(status->sc2skill(type),sce->val1));
+ }
+ sc_timer_next(sce->val2+tick, status->change_timer, bl->id, data);
return 0;
- }
- break;
-
- case SC_HIDING:
- if(--(sce->val2)>0){
+ break;
- if(sce->val2 % sce->val4 == 0 && !status_charge(bl, 0, 1))
- break; //Fail if it's time to substract SP and there isn't.
+ case SC_SKA:
+ if(--(sce->val2)>0) {
+ sce->val3 = rnd()%100; //Random defense.
+ sc_timer_next(1000+tick, status->change_timer,bl->id, data);
+ return 0;
+ }
+ break;
- sc_timer_next(1000+tick, status_change_timer,bl->id, data);
- return 0;
- }
- break;
+ case SC_HIDING:
+ if(--(sce->val2)>0) {
+ if(sce->val2 % sce->val4 == 0 && !status->charge(bl, 0, 1))
+ break; //Fail if it's time to substract SP and there isn't.
- case SC_SIGHT:
- case SC_RUWACH:
- case SC_WZ_SIGHTBLASTER:
- if(type == SC_WZ_SIGHTBLASTER)
- iMap->foreachinrange( status_change_timer_sub, bl, sce->val3, BL_CHAR|BL_SKILL, bl, sce, type, tick);
- else
- iMap->foreachinrange( status_change_timer_sub, bl, sce->val3, BL_CHAR, bl, sce, type, tick);
+ sc_timer_next(1000+tick, status->change_timer,bl->id, data);
+ return 0;
+ }
+ break;
- if( --(sce->val2)>0 ){
- sce->val4 += 250; // use for Shadow Form 2 seconds checking.
- sc_timer_next(250+tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_SIGHT:
+ case SC_RUWACH:
+ case SC_WZ_SIGHTBLASTER:
+ if(type == SC_WZ_SIGHTBLASTER)
+ map->foreachinrange(status->change_timer_sub, bl, sce->val3, BL_CHAR|BL_SKILL, bl, sce, type, tick);
+ else
+ map->foreachinrange(status->change_timer_sub, bl, sce->val3, BL_CHAR, bl, sce, type, tick);
- case SC_PROVOKE:
- if(sce->val2) { //Auto-provoke (it is ended in status_heal)
- sc_timer_next(1000*60+tick,status_change_timer, bl->id, data );
- return 0;
- }
- break;
+ if( --(sce->val2)>0 ){
+ sce->val4 += 250; // use for Shadow Form 2 seconds checking.
+ sc_timer_next(250+tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_STONE:
- if(sc->opt1 == OPT1_STONEWAIT && sce->val3) {
- sce->val4 = 0;
- unit_stop_walking(bl,1);
- unit_stop_attack(bl);
- sc->opt1 = OPT1_STONE;
- clif->changeoption(bl);
- sc_timer_next(1000+tick,status_change_timer, bl->id, data );
- status_calc_bl(bl, StatusChangeFlagTable[type]);
- return 0;
- }
- if(--(sce->val3) > 0) {
- if(++(sce->val4)%5 == 0 && status->hp > status->max_hp/4)
- status_percent_damage(NULL, bl, 1, 0, false);
- sc_timer_next(1000+tick,status_change_timer, bl->id, data );
- return 0;
- }
- break;
+ case SC_PROVOKE:
+ if(sce->val2) { //Auto-provoke (it is ended in status->heal)
+ sc_timer_next(1000*60+tick, status->change_timer, bl->id, data );
+ return 0;
+ }
+ break;
- case SC_POISON:
- if(status->hp <= max(status->max_hp>>2, sce->val4)) //Stop damaging after 25% HP left.
+ case SC_STONE:
+ if(sc->opt1 == OPT1_STONEWAIT && sce->val3) {
+ sce->val4 = 0;
+ unit->stop_walking(bl,1);
+ unit->stop_attack(bl);
+ sc->opt1 = OPT1_STONE;
+ clif->changeoption(bl);
+ sc_timer_next(1000+tick, status->change_timer, bl->id, data );
+ status_calc_bl(bl, status->ChangeFlagTable[type]);
+ return 0;
+ }
+ if(--(sce->val3) > 0) {
+ if(++(sce->val4)%5 == 0 && st->hp > st->max_hp/4)
+ status_percent_damage(NULL, bl, 1, 0, false);
+ sc_timer_next(1000+tick, status->change_timer, bl->id, data );
+ return 0;
+ }
break;
- case SC_DPOISON:
- if (--(sce->val3) > 0) {
- if (!sc->data[SC_SLOWPOISON]) {
- if( sce->val2 && bl->type == BL_MOB ) {
- struct block_list* src = iMap->id2bl(sce->val2);
- if( src )
- mob_log_damage((TBL_MOB*)bl,src,sce->val4);
- }
- iMap->freeblock_lock();
- status_zap(bl, sce->val4, 0);
- if (sc->data[type]) { // Check if the status still last ( can be dead since then ).
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data );
+
+ case SC_POISON:
+ if(st->hp <= max(st->max_hp>>2, sce->val4)) //Stop damaging after 25% HP left.
+ break;
+ case SC_DPOISON:
+ if (--(sce->val3) > 0) {
+ if (!sc->data[SC_SLOWPOISON]) {
+ if( sce->val2 && bl->type == BL_MOB ) {
+ struct block_list* src = map->id2bl(sce->val2);
+ if( src )
+ mob->log_damage((TBL_MOB*)bl,src,sce->val4);
+ }
+ map->freeblock_lock();
+ status_zap(bl, sce->val4, 0);
+ if (sc->data[type]) { // Check if the status still last ( can be dead since then ).
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data );
+ }
+ map->freeblock_unlock();
}
- iMap->freeblock_unlock();
+ return 0;
}
- return 0;
- }
- break;
+ break;
- case SC_TENSIONRELAX:
- if(status->max_hp > status->hp && --(sce->val3) > 0){
- sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_TENSIONRELAX:
+ if(st->max_hp > st->hp && --(sce->val3) > 0) {
+ sc_timer_next(sce->val4+tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_KNOWLEDGE:
- if (!sd) break;
- if(bl->m == sd->feel_map[0].m ||
- bl->m == sd->feel_map[1].m ||
- bl->m == sd->feel_map[2].m)
- { //Timeout will be handled by pc->setpos
- sce->timer = INVALID_TIMER;
- return 0;
- }
- break;
+ case SC_KNOWLEDGE:
+ if (!sd) break;
+ if(bl->m == sd->feel_map[0].m ||
+ bl->m == sd->feel_map[1].m ||
+ bl->m == sd->feel_map[2].m)
+ { //Timeout will be handled by pc->setpos
+ sce->timer = INVALID_TIMER;
+ return 0;
+ }
+ break;
- case SC_BLOODING:
- if (--(sce->val4) >= 0) {
- int hp = rnd()%600 + 200;
- struct block_list* src = iMap->id2bl(sce->val2);
- if( src && bl && bl->type == BL_MOB ) {
- mob_log_damage((TBL_MOB*)bl,src,sd||hp<status->hp?hp:status->hp-1);
- }
- iMap->freeblock_lock();
- status_fix_damage(src, bl, sd||hp<status->hp?hp:status->hp-1, 1);
- if( sc->data[type] ) {
- if( status->hp == 1 ) {
- iMap->freeblock_unlock();
- break;
+ case SC_BLOODING:
+ if (--(sce->val4) >= 0) {
+ int hp = rnd()%600 + 200;
+ struct block_list* src = map->id2bl(sce->val2);
+ if( src && bl && bl->type == BL_MOB ) {
+ mob->log_damage((TBL_MOB*)bl,src,sd||hp<st->hp?hp:st->hp-1);
+ }
+ map->freeblock_lock();
+ status_fix_damage(src, bl, sd||hp<st->hp?hp:st->hp-1, 1);
+ if( sc->data[type] ) {
+ if( st->hp == 1 ) {
+ map->freeblock_unlock();
+ break;
+ }
+ sc_timer_next(10000 + tick, status->change_timer, bl->id, data);
}
- sc_timer_next(10000 + tick, status_change_timer, bl->id, data);
+ map->freeblock_unlock();
+ return 0;
}
- iMap->freeblock_unlock();
- return 0;
- }
- break;
+ break;
- case SC_S_LIFEPOTION:
- case SC_L_LIFEPOTION:
- if( sd && --(sce->val4) >= 0 )
- {
- // val1 < 0 = per max% | val1 > 0 = exact amount
- int hp = 0;
- if( status->hp < status->max_hp )
- hp = (sce->val1 < 0) ? (int)(sd->status.max_hp * -1 * sce->val1 / 100.) : sce->val1 ;
- status_heal(bl, hp, 0, 2);
- sc_timer_next((sce->val2 * 1000) + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_S_LIFEPOTION:
+ case SC_L_LIFEPOTION:
+ if( sd && --(sce->val4) >= 0 ) {
+ // val1 < 0 = per max% | val1 > 0 = exact amount
+ int hp = 0;
+ if( st->hp < st->max_hp )
+ hp = (sce->val1 < 0) ? (int)(sd->status.max_hp * -1 * sce->val1 / 100.) : sce->val1 ;
+ status->heal(bl, hp, 0, 2);
+ sc_timer_next((sce->val2 * 1000) + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_CASH_BOSS_ALARM:
- if( sd && --(sce->val4) >= 0 )
- {
- struct mob_data *boss_md = iMap->id2boss(sce->val1);
- if( boss_md && sd->bl.m == boss_md->bl.m )
- {
- clif->bossmapinfo(sd->fd, boss_md, 1); // Update X - Y on minimap
- if (boss_md->bl.prev != NULL) {
- sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
- return 0;
+ case SC_CASH_BOSS_ALARM:
+ if( sd && --(sce->val4) >= 0 ) {
+ struct mob_data *boss_md = map->id2boss(sce->val1);
+ if( boss_md && sd->bl.m == boss_md->bl.m ) {
+ clif->bossmapinfo(sd->fd, boss_md, 1); // Update X - Y on minimap
+ if (boss_md->bl.prev != NULL) {
+ sc_timer_next(5000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
}
}
- }
- break;
+ break;
- case SC_DANCING: //SP consumption by time of dancing skills
- {
- int s = 0;
- int sp = 1;
- if (--sce->val3 <= 0)
- break;
- switch(sce->val1&0xFFFF){
+ case SC_DANCING: //SP consumption by time of dancing skills
+ {
+ int s = 0;
+ int sp = 1;
+ if (--sce->val3 <= 0)
+ break;
+ switch(sce->val1&0xFFFF){
case BD_RICHMANKIM:
case BD_DRUMBATTLEFIELD:
case BD_RINGNIBELUNGEN:
@@ -10148,11 +10671,11 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
s=5;
break;
case BA_APPLEIDUN:
- #ifdef RENEWAL
- s=5;
- #else
- s=6;
- #endif
+ #ifdef RENEWAL
+ s=5;
+ #else
+ s=6;
+ #endif
break;
case CG_MOONLIT:
//Moonlit's cost is 4sp*skill_lv [Skotlex]
@@ -10161,587 +10684,587 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
case DC_DONTFORGETME:
s=10;
break;
+ }
+ if( s != 0 && sce->val3 % s == 0 ) {
+ if (sc->data[SC_LONGING])
+ sp*= 3;
+ if (!status->charge(bl, 0, sp))
+ break;
+ }
+ sc_timer_next(1000+tick, status->change_timer, bl->id, data);
+ return 0;
}
- if( s != 0 && sce->val3 % s == 0 )
- {
- if (sc->data[SC_LONGING])
- sp*= 3;
- if (!status_charge(bl, 0, sp))
- break;
+ break;
+ case SC_BERSERK:
+ // 5% every 10 seconds [DracoRPG]
+ if( --( sce->val3 ) > 0 && status->charge(bl, sce->val2, 0) && st->hp > 100 ) {
+ sc_timer_next(sce->val4+tick, status->change_timer, bl->id, data);
+ return 0;
}
- sc_timer_next(1000+tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
- case SC__BLOODYLUST:
- case SC_BERSERK:
- // 5% every 10 seconds [DracoRPG]
- if( --( sce->val3 ) > 0 && status_charge(bl, sce->val2, 0) && status->hp > 100 )
- {
- sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ break;
- case SC_NOCHAT:
- if(sd){
- sd->status.manner++;
- clif->changestatus(sd,SP_MANNER,sd->status.manner);
- clif->updatestatus(sd,SP_MANNER);
- if (sd->status.manner < 0)
- { //Every 60 seconds your manner goes up by 1 until it gets back to 0.
- sc_timer_next(60000+tick, status_change_timer, bl->id, data);
- return 0;
+ case SC_NOCHAT:
+ if(sd) {
+ sd->status.manner++;
+ clif->changestatus(sd,SP_MANNER,sd->status.manner);
+ clif->updatestatus(sd,SP_MANNER);
+ if (sd->status.manner < 0) {
+ //Every 60 seconds your manner goes up by 1 until it gets back to 0.
+ sc_timer_next(60000+tick, status->change_timer, bl->id, data);
+ return 0;
+ }
}
- }
- break;
+ break;
- case SC_SPLASHER:
- // custom Venom Splasher countdown timer
- //if (sce->val4 % 1000 == 0) {
- // char timer[10];
- // snprintf (timer, 10, "%d", sce->val4/1000);
- // clif->message(bl, timer);
- //}
- if((sce->val4 -= 500) > 0) {
- sc_timer_next(500 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_SPLASHER:
+ // custom Venom Splasher countdown timer
+ //if (sce->val4 % 1000 == 0) {
+ // char counter[10];
+ // snprintf (counter, 10, "%d", sce->val4/1000);
+ // clif->message(bl, counter);
+ //}
+ if((sce->val4 -= 500) > 0) {
+ sc_timer_next(500 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_MARIONETTE_MASTER:
- case SC_MARIONETTE:
- {
- struct block_list *pbl = iMap->id2bl(sce->val1);
- if( pbl && check_distance_bl(bl, pbl, 7) )
+ case SC_MARIONETTE_MASTER:
+ case SC_MARIONETTE:
{
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+ struct block_list *pbl = map->id2bl(sce->val1);
+ if( pbl && check_distance_bl(bl, pbl, 7) ) {
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ }
+ break;
+
+ case SC_GOSPEL:
+ if(sce->val4 == BCT_SELF && --(sce->val2) > 0) {
+ int hp, sp;
+ hp = (sce->val1 > 5) ? 45 : 30;
+ sp = (sce->val1 > 5) ? 35 : 20;
+ if(!status->charge(bl, hp, sp))
+ break;
+ sc_timer_next(10000+tick, status->change_timer, bl->id, data);
return 0;
}
- }
- break;
+ break;
- case SC_GOSPEL:
- if(sce->val4 == BCT_SELF && --(sce->val2) > 0)
- {
- int hp, sp;
- hp = (sce->val1 > 5) ? 45 : 30;
- sp = (sce->val1 > 5) ? 35 : 20;
- if(!status_charge(bl, hp, sp))
- break;
- sc_timer_next(10000+tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_JAILED:
+ if(sce->val1 == INT_MAX || --(sce->val1) > 0) {
+ sc_timer_next(60000+tick, status->change_timer, bl->id,data);
+ return 0;
+ }
+ break;
- case SC_JAILED:
- if(sce->val1 == INT_MAX || --(sce->val1) > 0)
- {
- sc_timer_next(60000+tick, status_change_timer, bl->id,data);
- return 0;
- }
- break;
+ case SC_BLIND:
+ if(sc->data[SC_FOGWALL]) {
+ //Blind lasts forever while you are standing on the fog.
+ sc_timer_next(5000+tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
+ case SC_ABUNDANCE:
+ if(--(sce->val4) > 0) {
+ status->heal(bl,0,60,0);
+ sc_timer_next(10000+tick, status->change_timer, bl->id, data);
+ }
+ break;
- case SC_BLIND:
- if(sc->data[SC_FOGWALL])
- { //Blind lasts forever while you are standing on the fog.
- sc_timer_next(5000+tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
- case SC_ABUNDANCE:
- if(--(sce->val4) > 0) {
- status_heal(bl,0,60,0);
- sc_timer_next(10000+tick, status_change_timer, bl->id, data);
- }
- break;
+ case SC_PYREXIA:
+ if( --(sce->val4) > 0 ) {
+ map->freeblock_lock();
+ clif->damage(bl,bl,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,0,0);
+ status_fix_damage(NULL,bl,100,0);
+ if( sc->data[type] ) {
+ sc_timer_next(3000+tick,status->change_timer,bl->id,data);
+ }
+ map->freeblock_unlock();
+ return 0;
+ }
+ break;
- case SC_PYREXIA:
- if( --(sce->val4) > 0 ) {
- iMap->freeblock_lock();
- clif->damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,0,0);
- status_fix_damage(NULL,bl,100,0);
- if( sc->data[type] ) {
- sc_timer_next(3000+tick,status_change_timer,bl->id,data);
- }
- iMap->freeblock_unlock();
- return 0;
- }
- break;
+ case SC_LEECHESEND:
+ if( --(sce->val4) > 0 ) {
+ int damage = st->max_hp/100; // {Target VIT x (New Poison Research Skill Level - 3)} + (Target HP/100)
+ damage += st->vit * (sce->val1 - 3);
+ unit->skillcastcancel(bl,2);
+ map->freeblock_lock();
+ status->damage(bl, bl, damage, 0, clif->damage(bl,bl,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,0,0), 1);
+ if( sc->data[type] ) {
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data );
+ }
+ map->freeblock_unlock();
+ return 0;
+ }
+ break;
- case SC_LEECHESEND:
- if( --(sce->val4) > 0 ) {
- int damage = status->max_hp/100; // {Target VIT x (New Poison Research Skill Level - 3)} + (Target HP/100)
- damage += status->vit * (sce->val1 - 3);
- unit_skillcastcancel(bl,2);
- iMap->freeblock_lock();
- status_damage(bl, bl, damage, 0, clif->damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,0,0), 1);
- if( sc->data[type] ) {
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data );
- }
- iMap->freeblock_unlock();
- return 0;
- }
- break;
+ case SC_MAGICMUSHROOM:
+ if( --(sce->val4) > 0 ) {
+ bool flag = 0;
+ int damage = st->max_hp * 3 / 100;
+ if( st->hp <= damage )
+ damage = st->hp - 1; // Cannot Kill
+
+ if( damage > 0 ) { // 3% Damage each 4 seconds
+ map->freeblock_lock();
+ status_zap(bl,damage,0);
+ flag = !sc->data[type]; // Killed? Should not
+ map->freeblock_unlock();
+ }
- case SC_MAGICMUSHROOM:
- if( --(sce->val4) > 0 ) {
- bool flag = 0;
- int damage = status->max_hp * 3 / 100;
- if( status->hp <= damage )
- damage = status->hp - 1; // Cannot Kill
-
- if( damage > 0 ) { // 3% Damage each 4 seconds
- iMap->freeblock_lock();
- status_zap(bl,damage,0);
- flag = !sc->data[type]; // Killed? Should not
- iMap->freeblock_unlock();
- }
-
- if( !flag ) { // Random Skill Cast
- if (sd && !pc_issit(sd)) { //can't cast if sit
- int mushroom_skill_id = 0, i;
- unit_stop_attack(bl);
- unit_skillcastcancel(bl,1);
- do {
- i = rnd() % MAX_SKILL_MAGICMUSHROOM_DB;
- mushroom_skill_id = skill_magicmushroom_db[i].skill_id;
- }
- while( mushroom_skill_id == 0 );
+ if( !flag ) { // Random Skill Cast
+ if (sd && !pc_issit(sd)) { //can't cast if sit
+ int mushroom_skill_id = 0, i;
+ unit->stop_attack(bl);
+ unit->skillcastcancel(bl,0);
+ do {
+ i = rnd() % MAX_SKILL_MAGICMUSHROOM_DB;
+ mushroom_skill_id = skill->magicmushroom_db[i].skill_id;
+ }
+ while( mushroom_skill_id == 0 );
- switch( skill->get_casttype(mushroom_skill_id) ) { // Magic Mushroom skills are buffs or area damage
- case CAST_GROUND:
- skill->castend_pos2(bl,bl->x,bl->y,mushroom_skill_id,1,tick,0);
- break;
- case CAST_NODAMAGE:
- skill->castend_nodamage_id(bl,bl,mushroom_skill_id,1,tick,0);
- break;
- case CAST_DAMAGE:
- skill->castend_damage_id(bl,bl,mushroom_skill_id,1,tick,0);
- break;
+ switch( skill->get_casttype(mushroom_skill_id) ) { // Magic Mushroom skills are buffs or area damage
+ case CAST_GROUND:
+ skill->castend_pos2(bl,bl->x,bl->y,mushroom_skill_id,1,tick,0);
+ break;
+ case CAST_NODAMAGE:
+ skill->castend_nodamage_id(bl,bl,mushroom_skill_id,1,tick,0);
+ break;
+ case CAST_DAMAGE:
+ skill->castend_damage_id(bl,bl,mushroom_skill_id,1,tick,0);
+ break;
+ }
}
+
+ clif->emotion(bl,E_HEH);
+ sc_timer_next(4000+tick,status->change_timer,bl->id,data);
}
+ return 0;
+ }
+ break;
- clif->emotion(bl,E_HEH);
- sc_timer_next(4000+tick,status_change_timer,bl->id,data);
+ case SC_TOXIN:
+ if( --(sce->val4) > 0 ) {
+ //Damage is every 10 seconds including 3%sp drain.
+ map->freeblock_lock();
+ clif->damage(bl,bl,status_get_amotion(bl),1,1,0,0,0);
+ status->damage(NULL, bl, 1, st->max_sp * 3 / 100, 0, 0); //cancel dmg only if cancelable
+ if( sc->data[type] ) {
+ sc_timer_next(10000 + tick, status->change_timer, bl->id, data );
+ }
+ map->freeblock_unlock();
+ return 0;
}
- return 0;
- }
- break;
+ break;
- case SC_TOXIN:
- if( --(sce->val4) > 0 )
- { //Damage is every 10 seconds including 3%sp drain.
- iMap->freeblock_lock();
- clif->damage(bl,bl,tick,status_get_amotion(bl),1,1,0,0,0);
- status_damage(NULL, bl, 1, status->max_sp * 3 / 100, 0, 0); //cancel dmg only if cancelable
- if( sc->data[type] ) {
- sc_timer_next(10000 + tick, status_change_timer, bl->id, data );
- }
- iMap->freeblock_unlock();
- return 0;
- }
- break;
+ case SC_OBLIVIONCURSE:
+ if( --(sce->val4) > 0 ) {
+ clif->emotion(bl,E_WHAT);
+ sc_timer_next(3000 + tick, status->change_timer, bl->id, data );
+ return 0;
+ }
+ break;
- case SC_OBLIVIONCURSE:
- if( --(sce->val4) > 0 )
- {
- clif->emotion(bl,E_WHAT);
- sc_timer_next(3000 + tick, status_change_timer, bl->id, data );
- return 0;
- }
- break;
+ case SC_WEAPONBLOCKING:
+ if( --(sce->val4) > 0 ) {
+ if( !status->charge(bl,0,3) )
+ break;
+ sc_timer_next(5000+tick,status->change_timer,bl->id,data);
+ return 0;
+ }
+ break;
- case SC_WEAPONBLOCKING:
- if( --(sce->val4) > 0 )
- {
- if( !status_charge(bl,0,3) )
+ case SC_CLOAKINGEXCEED:
+ if(!status->charge(bl,0,10-sce->val1))
break;
- sc_timer_next(3000+tick,status_change_timer,bl->id,data);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
- }
- break;
- case SC_CLOAKINGEXCEED:
- if(!status_charge(bl,0,10-sce->val1))
+ case SC_RENOVATIO:
+ if( --(sce->val4) > 0 ) {
+ int heal = st->max_hp * 3 / 100;
+ if( sc && sc->data[SC_AKAITSUKI] && heal )
+ heal = ~heal + 1;
+ status->heal(bl, heal, 0, 2);
+ sc_timer_next(5000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
break;
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- return 0;
- case SC_RENOVATIO:
- if( --(sce->val4) > 0 )
- {
- int heal = status->max_hp * 3 / 100;
- if( sc && sc->data[SC_AKAITSUKI] && heal )
- heal = ~heal + 1;
- status_heal(bl, heal, 0, 2);
- sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_BURNING:
+ if( --(sce->val4) > 0 ) {
+ struct block_list *src = map->id2bl(sce->val3);
+ int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP)
- case SC_BURNING:
- if( --(sce->val4) > 0 )
- {
- struct block_list *src = iMap->id2bl(sce->val3);
- int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP)
+ map->freeblock_lock();
+ clif->damage(bl,bl,0,0,damage,1,9,0); //damage is like endure effect with no walk delay
+ status->damage(src, bl, damage, 0, 0, 1);
- iMap->freeblock_lock();
- clif->damage(bl,bl,tick,0,0,damage,1,9,0); //damage is like endure effect with no walk delay
- status_damage(src, bl, damage, 0, 0, 1);
+ if( sc->data[type]){ // Target still lives. [LimitLine]
+ sc_timer_next(3000 + tick, status->change_timer, bl->id, data);
+ }
+ map->freeblock_unlock();
+ return 0;
+ }
+ break;
- if( sc->data[type]){ // Target still lives. [LimitLine]
- sc_timer_next(3000 + tick, status_change_timer, bl->id, data);
+ case SC_FEAR:
+ if( --(sce->val4) > 0 ) {
+ if( sce->val2 > 0 )
+ sce->val2--;
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
}
- iMap->freeblock_unlock();
- return 0;
- }
- break;
+ break;
- case SC_FEAR:
- if( --(sce->val4) > 0 )
- {
- if( sce->val2 > 0 )
- sce->val2--;
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_SUMMON1:
+ case SC_SUMMON2:
+ case SC_SUMMON3:
+ case SC_SUMMON4:
+ case SC_SUMMON5:
+ if( --(sce->val4) > 0 ) {
+ if( !status->charge(bl, 0, 1) )
+ break;
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_SUMMON1:
- case SC_SUMMON2:
- case SC_SUMMON3:
- case SC_SUMMON4:
- case SC_SUMMON5:
- if( --(sce->val4) > 0 )
- {
- if( !status_charge(bl, 0, 1) )
+ case SC_READING_SB:
+ if( !status->charge(bl, 0, sce->val2) ) {
+ int i;
+ for(i = SC_SPELLBOOK1; i <= SC_SPELLBOOK7; i++) // Also remove stored spell as well.
+ status_change_end(bl, (sc_type)i, INVALID_TIMER);
break;
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+ }
+ sc_timer_next(10000 + tick, status->change_timer, bl->id, data);
return 0;
- }
- break;
- case SC_READING_SB:
- if( !status_charge(bl, 0, sce->val2) ){
- int i;
- for(i = SC_SPELLBOOK1; i <= SC_SPELLBOOK7; i++) // Also remove stored spell as well.
- status_change_end(bl, (sc_type)i, INVALID_TIMER);
+ case SC_ELECTRICSHOCKER:
+ if( --(sce->val4) > 0 ) {
+ status->charge(bl, 0, st->max_sp / 100 * sce->val1 );
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
break;
- }
- sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
- return 0;
-
- case SC_ELECTRICSHOCKER:
- if( --(sce->val4) > 0 )
- {
- status_charge(bl, 0, status->max_sp / 100 * sce->val1 );
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
- case SC_CAMOUFLAGE:
- if(--(sce->val4) > 0){
- status_charge(bl,0,7 - sce->val1);
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_CAMOUFLAGE:
+ if(--(sce->val4) > 0) {
+ status->charge(bl,0,7 - sce->val1);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC__REPRODUCE:
- if(!status_charge(bl, 0, 1))
+ case SC__REPRODUCE:
+ if( --(sce->val4) >= 0 ) {
+ if( !status_charge(bl, 0, 9 - (1 + sce->val1) / 2) )
+ break;
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
break;
- sc_timer_next(1000+tick, status_change_timer, bl->id, data);
- return 0;
- case SC__SHADOWFORM:
- if( --(sce->val4) > 0 )
- {
- if( !status_charge(bl, 0, sce->val1 - (sce->val1 - 1)) )
- break;
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC__SHADOWFORM:
+ if( --(sce->val4) > 0 ) {
+ if( !status->charge(bl, 0, sce->val1 - (sce->val1 - 1)) )
+ break;
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC__INVISIBILITY:
- if( --(sce->val4) > 0 )
- {
- if( !status_charge(bl, 0, (status->sp * 6 - sce->val1) / 100) )// 6% - skill_lv.
- break;
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC__INVISIBILITY:
+ if( --(sce->val4) >= 0 ) {
+ if( !status->charge(bl, 0, status_get_max_sp(bl) * (12 - sce->val1*2) / 100) )
+ break;
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_STRIKING:
- if( --(sce->val4) > 0 )
- {
- if( !status_charge(bl,0, sce->val1 ) )
- break;
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
- case SC_VACUUM_EXTREME:
- if( --(sce->val4) > 0 ){
- sc_timer_next(100 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
- case SC_BLOOD_SUCKER:
- if( --(sce->val4) > 0 ) {
- struct block_list *src = iMap->id2bl(sce->val2);
- int damage;
- if( !src || (src && (status_isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12)) )
- break;
- iMap->freeblock_lock();
- damage = sce->val3;
- status_damage(src, bl, damage, 0, clif->damage(bl,bl,tick,status->amotion,status->dmotion+200,damage,1,0,0), 1);
- unit_skillcastcancel(bl,1);
- if ( sc->data[type] ) {
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+ case SC_STRIKING:
+ if( --(sce->val4) > 0 ) {
+ if( !status->charge(bl,0, sce->val1 ) )
+ break;
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
}
- iMap->freeblock_unlock();
- status_heal(src, damage*(5 + 5 * sce->val1)/100, 0, 0); // 5 + 5% per level
- return 0;
- }
- break;
+ break;
+ case SC_BLOOD_SUCKER:
+ if( --(sce->val4) > 0 ) {
+ struct block_list *src = map->id2bl(sce->val2);
+ int damage;
+ if( !src || (src && (status->isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12)) )
+ break;
+ map->freeblock_lock();
+ damage = sce->val3;
+ status->damage(src, bl, damage, 0, clif->damage(bl,bl,st->amotion,st->dmotion+200,damage,1,0,0), 1);
+ unit->skillcastcancel(bl,1);
+ if ( sc->data[type] ) {
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ }
+ map->freeblock_unlock();
+ status->heal(src, damage*(5 + 5 * sce->val1)/100, 0, 0); // 5 + 5% per level
+ return 0;
+ }
+ break;
- case SC_SIREN:
- if( --(sce->val4) > 0 )
- {
- clif->emotion(bl,E_LV);
- sc_timer_next(2000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_SIREN:
+ if( --(sce->val4) > 0 ) {
+ clif->emotion(bl,E_LV);
+ sc_timer_next(2000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_DEEP_SLEEP:
- if( --(sce->val4) > 0 )
- { // Recovers 1% HP/SP every 2 seconds.
- status_heal(bl, status->max_hp / 100, status->max_sp / 100, 2);
- sc_timer_next(2000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_DEEP_SLEEP:
+ if( --(sce->val4) >= 0 )
+ {// Recovers 3% of the player's MaxHP/MaxSP every 2 seconds.
+ status->heal(bl, st->max_hp * 3 / 100, st->max_sp * 3 / 100, 2);
+ sc_timer_next(2000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_SIRCLEOFNATURE:
- if( --(sce->val4) > 0 )
- {
- if( !status_charge(bl,0,sce->val2) )
- break;
- status_heal(bl, sce->val3, 0, 1);
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_SIRCLEOFNATURE:
+ if( --(sce->val4) >= 0 ) {
+ if( !status_charge(bl,0,sce->val3) )
+ break;
+ status->heal(bl, sce->val2, 0, 1);
+ sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_SONG_OF_MANA:
- if( --(sce->val4) > 0 )
- {
- status_heal(bl,0,sce->val3,3);
- sc_timer_next(3000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_SONG_OF_MANA:
+ if( --(sce->val4) >= 0 ) {
+ status->heal(bl,0,sce->val3,3);
+ sc_timer_next(5000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_SATURDAY_NIGHT_FEVER:
- // 1% HP/SP drain every val4 seconds [Jobbie]
- if( --(sce->val3) > 0 )
- {
- int hp = status->hp / 100;
- int sp = status->sp / 100;
- if( !status_charge(bl, hp, sp) )
+ case SC_SATURDAY_NIGHT_FEVER:
+ if( --(sce->val3) >= 0 ) {
+ if( !status_charge(bl, st->max_hp * 1 / 100, st->max_sp * 1 / 100) )
break;
- sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
-
- case SC_CRYSTALIZE:
- if( --(sce->val4) > 0 )
- { // Drains 2% of HP and 1% of SP every seconds.
- if( bl->type != BL_MOB) // doesn't work on mobs
- status_charge(bl, status->max_hp * 2 / 100, status->max_sp / 100);
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ sc_timer_next(3000+tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_FORCEOFVANGUARD:
- if( !status_charge(bl,0,20) )
+ case SC_MELODYOFSINK:
+ if( --(sce->val4) >= 0 ) {
+ status_charge(bl, 0, st->max_sp * ( 2 * sce->val1 + 2 * sce->val2 ) / 100);
+ sc_timer_next(1000+tick, status->change_timer, bl->id, data);
+ return 0;
+ }
break;
- sc_timer_next(6000 + tick, status_change_timer, bl->id, data);
- return 0;
- case SC_BANDING:
- if( status_charge(bl, 0, 7 - sce->val1) )
- {
- if( sd ) pc->banding(sd, sce->val1);
- sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ case SC_COLD:
+ if( --(sce->val4) > 0 ) {
+ // Drains 2% of HP and 1% of SP every seconds.
+ if( bl->type != BL_MOB) // doesn't work on mobs
+ status->charge(bl, st->max_hp * 2 / 100, st->max_sp / 100);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_LG_REFLECTDAMAGE:
- if( --(sce->val4) > 0 ) {
- if( !status_charge(bl,0,sce->val3) )
+ case SC_FORCEOFVANGUARD:
+ if( !status->charge(bl, 0, (24 - 4 * sce->val1)) )
break;
- sc_timer_next(10000 + tick, status_change_timer, bl->id, data);
+ sc_timer_next(10000 + tick, status->change_timer, bl->id, data);
return 0;
- }
- break;
- case SC_OVERHEAT_LIMITPOINT:
- if( --(sce->val1) > 0 ) { // Cooling
- sc_timer_next(30000 + tick, status_change_timer, bl->id, data);
- }
- break;
+ case SC_BANDING:
+ if( status->charge(bl, 0, 7 - sce->val1) ) {
+ if( sd ) pc->banding(sd, sce->val1);
+ sc_timer_next(5000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
- case SC_OVERHEAT:
- {
- int damage = status->max_hp / 100; // Suggestion 1% each second
- if( damage >= status->hp ) damage = status->hp - 1; // Do not kill, just keep you with 1 hp minimum
- iMap->freeblock_lock();
- status_fix_damage(NULL,bl,damage,clif->damage(bl,bl,tick,0,0,damage,0,0,0));
- if( sc->data[type] ) {
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+ case SC_LG_REFLECTDAMAGE:
+ if( --(sce->val4) >= 0 ) {
+ if( !status->charge(bl,0,10) )
+ break;
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
}
- iMap->freeblock_unlock();
- }
- break;
+ break;
- case SC_MAGNETICFIELD:
- {
- if( --(sce->val3) <= 0 )
- break; // Time out
- if( sce->val2 == bl->id )
+ case SC_OVERHEAT_LIMITPOINT:
+ if( --(sce->val1) > 0 ) { // Cooling
+ sc_timer_next(30000 + tick, status->change_timer, bl->id, data);
+ }
+ break;
+
+ case SC_OVERHEAT:
{
- if( !status_charge(bl,0,14 + (3 * sce->val1)) )
- break; // No more SP status should end, and in the next second will end for the other affected players
+ int damage = st->max_hp / 100; // Suggestion 1% each second
+ if( damage >= st->hp ) damage = st->hp - 1; // Do not kill, just keep you with 1 hp minimum
+ map->freeblock_lock();
+ status_fix_damage(NULL,bl,damage,clif->damage(bl,bl,0,0,damage,0,0,0));
+ if( sc->data[type] ) {
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ }
+ map->freeblock_unlock();
}
- else
+ break;
+
+ case SC_MAGNETICFIELD:
{
- struct block_list *src = iMap->id2bl(sce->val2);
- struct status_change *ssc;
- if( !src || (ssc = status_get_sc(src)) == NULL || !ssc->data[SC_MAGNETICFIELD] )
- break; // Source no more under Magnetic Field
+ if( --(sce->val3) <= 0 )
+ break; // Time out
+ if( sce->val2 == bl->id ) {
+ if( !status->charge(bl,0,50) )
+ break; // No more SP status should end, and in the next second will end for the other affected players
+ } else {
+ struct block_list *src = map->id2bl(sce->val2);
+ struct status_change *ssc;
+ if( !src || (ssc = status->get_sc(src)) == NULL || !ssc->data[SC_MAGNETICFIELD] )
+ break; // Source no more under Magnetic Field
+ }
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
}
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- }
- break;
+ break;
- case SC_INSPIRATION:
- if(--(sce->val4) > 0)
- {
- int hp = status->max_hp * (7-sce->val1) / 100;
- int sp = status->max_sp * (9-sce->val1) / 100;
+ case SC_STEALTHFIELD_MASTER:
+ if(--(sce->val4) >= 0) {
+ // 1% SP Upkeep Cost
+ int sp = st->max_sp / 100;
+
+ if( st->sp <= sp )
+ status_change_end(bl,SC_STEALTHFIELD_MASTER,INVALID_TIMER);
- if( !status_charge(bl,hp,sp) ) break;
+ if( !status_charge(bl,0,sp) )
+ break;
- sc_timer_next(1000+tick,status_change_timer,bl->id, data);
- return 0;
- }
- break;
+ if( !sc->data[SC_STEALTHFIELD_MASTER] )
+ break;
- case SC_RAISINGDRAGON:
- // 1% every 5 seconds [Jobbie]
- if( --(sce->val3)>0 && status_charge(bl, sce->val2, 0) )
- {
- if( !sc->data[type] ) return 0;
- sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
+ sc_timer_next((2000 + 1000 * sce->val1)+tick,status->change_timer,bl->id, data);
+ return 0;
+ }
+ break;
+
+ case SC_INSPIRATION:
+ if(--(sce->val4) >= 0) {
+ int hp = st->max_hp * (35 - 5 * sce->val1) / 1000;
+ int sp = st->max_sp * (45 - 5 * sce->val1) / 1000;
+
+ if( !status->charge(bl,hp,sp) ) break;
- case SC_CIRCLE_OF_FIRE:
- case SC_FIRE_CLOAK:
- case SC_WATER_DROP:
- case SC_WATER_SCREEN:
- case SC_WIND_CURTAIN:
- case SC_WIND_STEP:
- case SC_STONE_SHIELD:
- case SC_SOLID_SKIN:
- if( !status_charge(bl,0,sce->val2) ){
- struct block_list *s_bl = battle->get_master(bl);
- if( s_bl )
- status_change_end(s_bl,type+1,INVALID_TIMER);
- status_change_end(bl,type,INVALID_TIMER);
+ sc_timer_next(5000+tick,status->change_timer,bl->id, data);
+ return 0;
+ }
break;
- }
- sc_timer_next(2000 + tick, status_change_timer, bl->id, data);
- return 0;
- case SC_STOMACHACHE:
- if( --(sce->val4) > 0 ){
- status_charge(bl,0,sce->val2); // Reduce 8 every 10 seconds.
- if( sd && !pc_issit(sd) ) // Force to sit every 10 seconds.
- {
- pc_stop_walking(sd,1|4);
- pc_stop_attack(sd);
- pc_setsit(sd);
- clif->sitting(bl);
+ case SC_RAISINGDRAGON:
+ // 1% every 5 seconds [Jobbie]
+ if( --(sce->val3)>0 && status->charge(bl, sce->val2, 0) ) {
+ if( !sc->data[type] ) return 0;
+ sc_timer_next(5000 + tick, status->change_timer, bl->id, data);
+ return 0;
}
- sc_timer_next(10000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
- case SC_LEADERSHIP:
- case SC_GLORYWOUNDS:
- case SC_SOULCOLD:
- case SC_HAWKEYES:
- /* they only end by status_change_end */
- sc_timer_next(600000 + tick, status_change_timer, bl->id, data);
- return 0;
- case SC_MEIKYOUSISUI:
- if( --(sce->val4) > 0 ){
- status_heal(bl, status->max_hp * (sce->val1+1) / 100, status->max_sp * sce->val1 / 100, 0);
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
- case SC_IZAYOI:
- case SC_KAGEMUSYA:
- if( --(sce->val2) > 0 ){
- if(!status_charge(bl, 0, 1)) break;
- sc_timer_next(1000+tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
- case SC_ANGRIFFS_MODUS:
- if(--(sce->val4) > 0) { //drain hp/sp
- if( !status_charge(bl,100,20) ) break;
- sc_timer_next(1000+tick,status_change_timer,bl->id, data);
- return 0;
- }
- break;
- case SC_FULL_THROTTLE:
- if( --(sce->val4) > 0 )
- {
- status_percent_damage(bl, bl, sce->val2, 0, false);
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
- return 0;
- }
- break;
- case SC_KINGS_GRACE:
- if( --(sce->val4) > 0 )
- {
- status_percent_heal(bl, sce->val2, 0);
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+ break;
+
+ case SC_TROPIC:
+ case SC_CHILLY_AIR:
+ case SC_WILD_STORM:
+ case SC_UPHEAVAL:
+ case SC_HEATER:
+ case SC_COOLER:
+ case SC_BLAST:
+ case SC_CURSED_SOIL:
+ case SC_PYROTECHNIC:
+ case SC_AQUAPLAY:
+ case SC_GUST:
+ case SC_PETROLOGY:
+ case SC_CIRCLE_OF_FIRE:
+ case SC_WATER_SCREEN:
+ case SC_WIND_STEP:
+ case SC_SOLID_SKIN:
+ case SC_FIRE_CLOAK:
+ case SC_WATER_DROP:
+ case SC_WIND_CURTAIN:
+ case SC_STONE_SHIELD:
+ if(status->charge(bl, 0, sce->val2) && (sce->val4==-1 || (sce->val4-=sce->val3)>=0))
+ sc_timer_next(sce->val3 + tick, status->change_timer, bl->id, data);
+ else
+ if (bl->type == BL_ELEM)
+ elemental->change_mode(BL_CAST(BL_ELEM,bl),MAX_ELESKILLTREE);
return 0;
- }
- break;
- case SC_FRIGG_SONG:
- if( --(sce->val4) > 0 )
- {
- status_heal(bl, sce->val3, 0, 0);
- sc_timer_next(10000 + tick, status_change_timer, bl->id, data);
+
+ case SC_STOMACHACHE:
+ if( --(sce->val4) > 0 ) {
+ status->charge(bl,0,sce->val2); // Reduce 8 every 10 seconds.
+ if( sd && !pc_issit(sd) ) { // Force to sit every 10 seconds.
+ pc_stop_walking(sd,1|4);
+ pc_stop_attack(sd);
+ pc_setsit(sd);
+ clif->sitting(bl);
+ }
+ sc_timer_next(10000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
+ case SC_LEADERSHIP:
+ case SC_GLORYWOUNDS:
+ case SC_SOULCOLD:
+ case SC_HAWKEYES:
+ /* they only end by status_change_end */
+ sc_timer_next(600000 + tick, status->change_timer, bl->id, data);
return 0;
- }
- break;
+ case SC_MEIKYOUSISUI:
+ if( --(sce->val4) > 0 ) {
+ status->heal(bl, st->max_hp * (sce->val1+1) / 100, st->max_sp * sce->val1 / 100, 0);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
+ case SC_IZAYOI:
+ case SC_KAGEMUSYA:
+ if( --(sce->val2) > 0 ) {
+ if(!status->charge(bl, 0, 1)) break;
+ sc_timer_next(1000+tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
+ case SC_ANGRIFFS_MODUS:
+ if(--(sce->val4) > 0) { //drain hp/sp
+ if( !status->charge(bl,100,20) ) break;
+ sc_timer_next(1000+tick,status->change_timer,bl->id, data);
+ return 0;
+ }
+ break;
+ case SC_FULL_THROTTLE:
+ if( --(sce->val4) >= 0 ) {
+ status_percent_damage(bl, bl, 0, sce->val2, false);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
+ case SC_KINGS_GRACE:
+ if( --(sce->val4) > 0 ) {
+ status_percent_heal(bl, sce->val2, 0);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
+ case SC_FRIGG_SONG:
+ if( --(sce->val4) > 0 ) {
+ status->heal(bl, sce->val3, 0, 0);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
}
// default for all non-handled control paths is to end the status
@@ -10750,96 +11273,93 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
}
/*==========================================
- * Foreach iteration of repetitive status
- *------------------------------------------*/
-int status_change_timer_sub(struct block_list* bl, va_list ap)
-{
+* Foreach iteration of repetitive status
+*------------------------------------------*/
+int status_change_timer_sub(struct block_list* bl, va_list ap) {
struct status_change* tsc;
struct block_list* src = va_arg(ap,struct block_list*);
struct status_change_entry* sce = va_arg(ap,struct status_change_entry*);
enum sc_type type = (sc_type)va_arg(ap,int); //gcc: enum args get promoted to int
- unsigned int tick = va_arg(ap,unsigned int);
+ int64 tick = va_arg(ap, int64);
- if (status_isdead(bl))
+ if (status->isdead(bl))
return 0;
- tsc = status_get_sc(bl);
+ tsc = status->get_sc(bl);
switch( type ) {
- case SC_SIGHT: /* Reveal hidden ennemy on 3*3 range */
- if( tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking
- rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] %
+ case SC_SIGHT: /* Reveal hidden ennemy on 3*3 range */
+ if( tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking
+ rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] %
status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
- case SC_CONCENTRATION:
- status_change_end(bl, SC_HIDING, INVALID_TIMER);
- status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
- status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
- status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER);
- status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER);
- break;
- case SC_RUWACH: /* Reveal hidden target and deal little dammages if ennemy */
- if (tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] ||
- tsc->data[SC_CAMOUFLAGE] || tsc->data[SC_CLOAKINGEXCEED] ||
- tsc->data[SC__INVISIBILITY])) {
+ case SC_CONCENTRATION:
status_change_end(bl, SC_HIDING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
- status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
- status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER);
- if(battle->check_target( src, bl, BCT_ENEMY ) > 0)
- skill->attack(BF_MAGIC,src,src,bl,AL_RUWACH,1,tick,0);
- }
- if( tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking
- rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] %
+ status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER);
+ break;
+ case SC_RUWACH: /* Reveal hidden target and deal little dammages if ennemy */
+ if (tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] ||
+ tsc->data[SC_CAMOUFLAGE] || tsc->data[SC_CLOAKINGEXCEED])) {
+ status_change_end(bl, SC_HIDING, INVALID_TIMER);
+ status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
+ status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER);
+ status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
+ if(battle->check_target( src, bl, BCT_ENEMY ) > 0)
+ skill->attack(BF_MAGIC,src,src,bl,AL_RUWACH,1,tick,0);
+ }
+ if( tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking
+ rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] %
status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
- break;
- case SC_WZ_SIGHTBLASTER:
- if (battle->check_target( src, bl, BCT_ENEMY ) > 0 &&
- status_check_skilluse(src, bl, WZ_SIGHTBLASTER, 2))
- {
- if (sce && !(bl->type&BL_SKILL) //The hit is not counted if it's against a trap
- && skill->attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,1,tick,0)){
- sce->val2 = 0; //This signals it to end.
+ break;
+ case SC_WZ_SIGHTBLASTER:
+ if (battle->check_target( src, bl, BCT_ENEMY ) > 0
+ && status->check_skilluse(src, bl, WZ_SIGHTBLASTER, 2)
+ ) {
+ if (sce && !(bl->type&BL_SKILL) //The hit is not counted if it's against a trap
+ && skill->attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,1,tick,0)
+ ){
+ sce->val2 = 0; //This signals it to end.
+ }
}
- }
- break;
- case SC_RG_CCONFINE_M:
- //Lock char has released the hold on everyone...
- if (tsc && tsc->data[SC_RG_CCONFINE_S] && tsc->data[SC_RG_CCONFINE_S]->val2 == src->id) {
- tsc->data[SC_RG_CCONFINE_S]->val2 = 0;
- status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
- }
- break;
- case SC_CURSEDCIRCLE_TARGET:
- if( tsc && tsc->data[SC_CURSEDCIRCLE_TARGET] && tsc->data[SC_CURSEDCIRCLE_TARGET]->val2 == src->id ) {
- clif->bladestop(bl, tsc->data[SC_CURSEDCIRCLE_TARGET]->val2, 0);
- status_change_end(bl, type, INVALID_TIMER);
- }
- break;
+ break;
+ case SC_RG_CCONFINE_M:
+ //Lock char has released the hold on everyone...
+ if (tsc && tsc->data[SC_RG_CCONFINE_S] && tsc->data[SC_RG_CCONFINE_S]->val2 == src->id) {
+ tsc->data[SC_RG_CCONFINE_S]->val2 = 0;
+ status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
+ }
+ break;
+ case SC_CURSEDCIRCLE_TARGET:
+ if( tsc && tsc->data[SC_CURSEDCIRCLE_TARGET] && tsc->data[SC_CURSEDCIRCLE_TARGET]->val2 == src->id ) {
+ clif->bladestop(bl, tsc->data[SC_CURSEDCIRCLE_TARGET]->val2, 0);
+ status_change_end(bl, type, INVALID_TIMER);
+ }
+ break;
}
return 0;
}
+int status_get_total_def(struct block_list *src) { return status->get_status_data(src)->def2 + (short)status->get_def(src); }
+int status_get_total_mdef(struct block_list *src) { return status->get_status_data(src)->mdef2 + (short)status_get_mdef(src); }
+int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int flag) {
#ifdef RENEWAL
-int status_get_total_def(struct block_list *src){ return status_get_status_data(src)->def2 + (short)status_get_def(src); }
-int status_get_total_mdef(struct block_list *src){ return status_get_status_data(src)->mdef2 + (short)status_get_mdef(src); }
-int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int flag){
int min = 0, max = 0, dstr;
float strdex_bonus, variance;
- struct status_change *sc = status_get_sc(bl);
-
+ struct status_change *sc = status->get_sc(bl);
+
if ( bl->type == BL_PC && watk->atk ){
- if ( flag&16 )
+ if ( flag&2 )
dstr = status_get_dex(bl);
else
dstr = status_get_str(bl);
-
+
variance = 5.0f * watk->atk * watk->wlv / 100.0f;
strdex_bonus = watk->atk * dstr / 200.0f;
- min = (watk->atk - (int)(variance + strdex_bonus)) + watk->atk2;
- max = (watk->atk + (int)(variance + strdex_bonus)) + watk->atk2;
+ min = (int)(watk->atk - variance + strdex_bonus) + watk->atk2;
+ max = (int)(watk->atk + variance + strdex_bonus) + watk->atk2;
}else if( watk->atk ){
min = watk->atk * 80 / 100;
max = watk->atk * 120 / 100;
@@ -10851,152 +11371,218 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl
else
max = min;
}
-
- if( bl->type == BL_PC && ((TBL_PC*)bl)->right_weapon.overrefine > 0)
+
+ if( bl->type == BL_PC && ((TBL_PC*)bl)->right_weapon.overrefine > 0 && !(flag&2) )
max += rnd()%((TBL_PC*)bl)->right_weapon.overrefine + 1;
- max = status_calc_watk(bl, sc, max, false);
+ max = status->calc_watk(bl, sc, max, false);
return max;
-}
+#else
+ return 0;
#endif
+}
-#define GETRANDMATK(){\
- if( status->matk_max > status->matk_min )\
- return status->matk_min + rnd()%(status->matk_max - status->matk_min);\
- else\
- return status->matk_min;\
+/**
+ * Gets a random matk value depending on min matk and max matk
+ **/
+unsigned short status_get_rand_matk( unsigned short matk_max, unsigned short matk_min ) {
+ if( matk_max > matk_min )
+ return matk_min + rnd()%(matk_max - matk_min);
+ else
+ return matk_min;
}
-/*==========================================
- * flag [malufett]
- * 0 - update matk values
- * 1 - get matk w/o SC bonuses
- * 2 - get modified matk
- * 3 - get matk w/o eatk & SC bonuses
- *------------------------------------------*/
-int status_get_matk(struct block_list *bl, int flag){
- struct status_data *status;
+/**
+ * Get bl's matk_max and matk_min values depending on flag
+ * @param flag
+ * 0 - Get MATK
+ * 1 - Get MATK w/o SC bonuses
+ * 3 - Get MATK w/o EATK & SC bonuses
+ **/
+void status_get_matk_sub( struct block_list *bl, int flag, unsigned short *matk_max, unsigned short *matk_min ) {
+ struct status_data *st;
struct status_change *sc;
struct map_session_data *sd;
if( bl == NULL )
- return 1;
+ return;
- status = status_get_status_data(bl);
- sc = status_get_sc(bl);
- sd = BL_CAST(BL_PC, bl);
+ if( flag != 0 && flag != 1 && flag != 3 ) {
+ ShowError("status_get_matk_sub: Unknown flag %d!\n", flag);
+ return;
+ }
- if( flag == 2 ) // just get matk
- GETRANDMATK();
+ st = status->get_status_data(bl);
+ sc = status->get_sc(bl);
+ sd = BL_CAST(BL_PC, bl);
-#ifndef RENEWAL
- status->matk_min = status_base_matk_min(status) + (sd?sd->bonus.ematk:0);
- status->matk_max = status_base_matk_max(status) + (sd?sd->bonus.ematk:0);
-#else
+#ifdef RENEWAL
/**
* RE MATK Formula (from irowiki:http://irowiki.org/wiki/MATK)
* MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers
**/
- status->matk_min = status_base_matk(status, status_get_lv(bl));
-
+ *matk_min = status->base_matk(st, status->get_lv(bl));
+
// Any +MATK you get from skills and cards, including cards in weapon, is added here.
if( sd && sd->bonus.ematk > 0 && flag != 3 )
- status->matk_min += sd->bonus.ematk;
- if( flag != 3 )
- status->matk_min = status_calc_ematk(bl, sc, status->matk_min);
+ *matk_min += sd->bonus.ematk;
+ if( flag != 3 )
+ *matk_min = status->calc_ematk(bl, sc, *matk_min);
- status->matk_max = status->matk_min;
+ *matk_max = *matk_min;
//This is the only portion in MATK that varies depending on the weapon level and refinement rate.
- if( bl->type&BL_PC && (status->rhw.matk + status->lhw.matk) > 0 ){
- int wMatk = status->rhw.matk + status->lhw.matk; // Left and right matk stacks
- int variance = wMatk * status->rhw.wlv / 10; // Only use right hand weapon level
- status->matk_min += wMatk - variance;
- status->matk_max += wMatk + variance;
- }else if( bl->type&BL_MOB ){
- status->matk_min = status->matk_max = status_get_int(bl) + status_get_lv(bl);
- status->matk_min += 70 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
- status->matk_max += 130 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
- }
+ if( bl->type&BL_PC && (st->rhw.matk + st->lhw.matk) > 0 ) {
+ int wMatk = st->rhw.matk + st->lhw.matk; // Left and right matk stacks
+ int variance = wMatk * st->rhw.wlv / 10; // Only use right hand weapon level
+ *matk_min += wMatk - variance;
+ *matk_max += wMatk + variance;
+ } else if( bl->type&BL_MOB ) {
+ *matk_min = *matk_max = status_get_int(bl) + status->get_lv(bl);
+ *matk_min += 70 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
+ *matk_max += 130 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
+ }
+#else // not RENEWAL
+ *matk_min = status_base_matk_min(st) + (sd?sd->bonus.ematk:0);
+ *matk_max = status_base_matk_max(st) + (sd?sd->bonus.ematk:0);
#endif
- if (bl->type&BL_PC && sd->matk_rate != 100) {
- status->matk_max = status->matk_max * sd->matk_rate/100;
- status->matk_min = status->matk_min * sd->matk_rate/100;
+
+ if (sd && sd->matk_rate != 100) {
+ *matk_max = (*matk_max) * sd->matk_rate/100;
+ *matk_min = (*matk_min) * sd->matk_rate/100;
}
if ((bl->type&BL_HOM && battle_config.hom_setting&0x20) //Hom Min Matk is always the same as Max Matk
|| (sc && sc->data[SC_RECOGNIZEDSPELL]))
- status->matk_min = status->matk_max;
+ *matk_min = *matk_max;
#ifdef RENEWAL
- if( sd && sd->right_weapon.overrefine > 0){
- status->matk_min++;
- status->matk_max += sd->right_weapon.overrefine - 1;
+ if( sd && sd->right_weapon.overrefine > 0 ) {
+ (*matk_min)++;
+ *matk_max += sd->right_weapon.overrefine - 1;
}
#endif
+ return;
+}
- if( flag ) // get unmodified from sc matk
- GETRANDMATK();
+/**
+ * Get bl's matk value depending on flag
+ * @param flag [malufett]
+ * 1 - Get MATK w/o SC bonuses
+ * 2 - Get modified MATK
+ * 3 - Get MATK w/o eATK & SC bonuses
+ * @retval 1 failure
+ * @retval MATK success
+ *
+ * Shouldn't change _any_ value! [Panikon]
+ **/
+int status_get_matk( struct block_list *bl, int flag ) {
+ struct status_data *st;
+ unsigned short matk_max, matk_min;
- status->matk_min = status_calc_matk(bl, sc, status->matk_min, true);
- status->matk_max = status_calc_matk(bl, sc, status->matk_max, true);
+ if( bl == NULL )
+ return 1;
- return 0;
+ if( flag < 1 || flag > 3 ) {
+ ShowError("status_get_matk: Unknown flag %d!\n", flag);
+ return 1;
+ }
+
+ if( (st = status->get_status_data(bl)) == NULL )
+ return 0;
+
+ // Just get matk
+ if( flag == 2 )
+ return status_get_rand_matk(st->matk_max, st->matk_min);
+
+ status_get_matk_sub( bl, flag, &matk_max, &matk_min );
+
+ // Get unmodified from sc matk
+ return status_get_rand_matk(matk_max, matk_min);
+}
+
+/**
+ * Updates bl's MATK values
+ **/
+void status_update_matk( struct block_list *bl ) {
+ struct status_data *st;
+ struct status_change *sc;
+ unsigned short matk_max, matk_min;
+
+ if( bl == NULL )
+ return;
+
+ if( (st = status->get_status_data(bl)) == NULL )
+ return;
+
+ if( (sc = status->get_sc(bl)) == NULL )
+ return;
+
+ status_get_matk_sub( bl, 0, &matk_max, &matk_min );
+
+ // Update matk
+ st->matk_min = status->calc_matk(bl, sc, matk_min, true);
+ st->matk_max = status->calc_matk(bl, sc, matk_max, true);
+
+ return;
}
/*==========================================
- * Clears buffs/debuffs of a character.
- * type&1 -> buffs, type&2 -> debuffs
- * type&4 -> especific debuffs(implemented with refresh)
- *------------------------------------------*/
-int status_change_clear_buffs (struct block_list* bl, int type)
-{
+* Clears buffs/debuffs of a character.
+* type&1 -> buffs, type&2 -> debuffs
+* type&4 -> especific debuffs(implemented with refresh)
+*------------------------------------------*/
+int status_change_clear_buffs (struct block_list* bl, int type) {
int i;
- struct status_change *sc= status_get_sc(bl);
+ struct status_change *sc= status->get_sc(bl);
if (!sc || !sc->count)
return 0;
- if (type&6) //Debuffs
- for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++)
- status_change_end(bl, (sc_type)i, INVALID_TIMER);
-
- for( i = SC_COMMON_MAX+1; i < SC_MAX; i++ )
- {
- if( !sc->data[i] || !status_get_sc_type(i) )
- continue;
+ if (type&6) //Debuffs
+ for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++)
+ status_change_end(bl, (sc_type)i, INVALID_TIMER);
- if( type&1 && !(status_get_sc_type(i)&SC_BUFF) )
+ for( i = SC_COMMON_MAX+1; i < SC_MAX; i++ ) {
+ if( !sc->data[i] || !status->get_sc_type(i) )
continue;
- if( type&2 && !(status_get_sc_type(i)&SC_DEBUFF) )
+ if( type&3 && !(status->get_sc_type(i)&SC_BUFF) && !(status->get_sc_type(i)&SC_DEBUFF) )
continue;
+ if( type < 3 ) {
+ if( type&1 && !(status->get_sc_type(i)&SC_BUFF) )
+ continue;
+ if( type&2 && !(status->get_sc_type(i)&SC_DEBUFF) )
+ continue;
+ }
switch (i) {
- case SC_DEEP_SLEEP:
- case SC_FROSTMISTY:
- case SC_CRYSTALIZE:
- case SC_TOXIN:
- case SC_PARALYSE:
- case SC_VENOMBLEED:
- case SC_MAGICMUSHROOM:
- case SC_DEATHHURT:
- case SC_PYREXIA:
- case SC_OBLIVIONCURSE:
- case SC_LEECHESEND:
- case SC_MARSHOFABYSS:
- case SC_MANDRAGORA:
- if(!(type&4))
- continue;
- break;
- case SC__BLOODYLUST:
- case SC_BERSERK:
- case SC_SATURDAY_NIGHT_FEVER:
- if(type&4)
- continue;
- sc->data[i]->val2 = 0;
- break;
+ case SC_DEEP_SLEEP:
+ case SC_FROSTMISTY:
+ case SC_COLD:
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_OBLIVIONCURSE:
+ case SC_LEECHESEND:
+ case SC_MARSHOFABYSS:
+ case SC_MANDRAGORA:
+ if(!(type&4))
+ continue;
+ break;
+ case SC_BERSERK:
+ if(type&4)
+ continue;
+ sc->data[i]->val2 = 0;
+ break;
+ default:
+ if(type&4)
+ continue;
+
}
status_change_end(bl, (sc_type)i, INVALID_TIMER);
}
@@ -11005,15 +11591,14 @@ int status_change_clear_buffs (struct block_list* bl, int type)
int status_change_spread( struct block_list *src, struct block_list *bl ) {
int i, flag = 0;
- struct status_change *sc = status_get_sc(src);
- const struct TimerData *timer;
- unsigned int tick;
+ struct status_change *sc = status->get_sc(src);
+ int64 tick;
struct status_change_data data;
if( !sc || !sc->count )
return 0;
- tick = iTimer->gettick();
+ tick = timer->gettick();
for( i = SC_COMMON_MIN; i < SC_MAX; i++ ) {
if( !sc->data[i] || i == SC_COMMON_MAX )
@@ -11022,70 +11607,69 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) {
switch( i ) {
//Debuffs that can be spreaded.
// NOTE: We'll add/delte SCs when we are able to confirm it.
- case SC_CURSE:
- case SC_SILENCE:
- case SC_CONFUSION:
- case SC_BLIND:
- case SC_NOCHAT:
- case SC_ILLUSION:
- case SC_CRUCIS:
- case SC_DEC_AGI:
- case SC_SLOWDOWN:
- case SC_MINDBREAKER:
- case SC_DC_WINKCHARM:
- case SC_STOP:
- case SC_ORCISH:
+ case SC_CURSE:
+ case SC_SILENCE:
+ case SC_CONFUSION:
+ case SC_BLIND:
+ case SC_NOCHAT:
+ case SC_ILLUSION:
+ case SC_CRUCIS:
+ case SC_DEC_AGI:
+ case SC_SLOWDOWN:
+ case SC_MINDBREAKER:
+ case SC_DC_WINKCHARM:
+ case SC_STOP:
+ case SC_ORCISH:
//case SC_NOEQUIPWEAPON://Omg I got infected and had the urge to strip myself physically.
//case SC_NOEQUIPSHIELD://No this is stupid and shouldnt be spreadable at all.
//case SC_NOEQUIPARMOR:// Disabled until I can confirm if it does or not. [Rytech]
//case SC_NOEQUIPHELM:
//case SC__STRIPACCESSARY:
- case SC_WUGBITE:
- case SC_FROSTMISTY:
- case SC_VENOMBLEED:
- case SC_DEATHHURT:
- case SC_PARALYSE:
- if( sc->data[i]->timer != INVALID_TIMER ) {
- timer = iTimer->get_timer(sc->data[i]->timer);
- if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0)
- continue;
- data.tick = DIFF_TICK(timer->tick,tick);
- } else
- data.tick = INVALID_TIMER;
- break;
- // Special cases
- case SC_POISON:
- case SC_DPOISON:
- data.tick = sc->data[i]->val3 * 1000;
- break;
- case SC_FEAR:
- case SC_LEECHESEND:
- data.tick = sc->data[i]->val4 * 1000;
- break;
- case SC_BURNING:
- data.tick = sc->data[i]->val4 * 2000;
- break;
- case SC_PYREXIA:
- case SC_OBLIVIONCURSE:
- data.tick = sc->data[i]->val4 * 3000;
- break;
- case SC_MAGICMUSHROOM:
- data.tick = sc->data[i]->val4 * 4000;
- break;
- case SC_TOXIN:
- case SC_BLOODING:
- data.tick = sc->data[i]->val4 * 10000;
- break;
- default:
+ case SC_WUGBITE:
+ case SC_FROSTMISTY:
+ case SC_VENOMBLEED:
+ case SC_DEATHHURT:
+ case SC_PARALYSE:
+ if( sc->data[i]->timer != INVALID_TIMER ) {
+ const struct TimerData *td = timer->get(sc->data[i]->timer);
+ if (td == NULL || td->func != status->change_timer || DIFF_TICK(td->tick,tick) < 0)
continue;
- break;
+ data.tick = DIFF_TICK32(td->tick,tick);
+ } else
+ data.tick = INVALID_TIMER;
+ break;
+ // Special cases
+ case SC_POISON:
+ case SC_DPOISON:
+ data.tick = sc->data[i]->val3 * 1000;
+ break;
+ case SC_FEAR:
+ case SC_LEECHESEND:
+ data.tick = sc->data[i]->val4 * 1000;
+ break;
+ case SC_BURNING:
+ data.tick = sc->data[i]->val4 * 2000;
+ break;
+ case SC_PYREXIA:
+ case SC_OBLIVIONCURSE:
+ data.tick = sc->data[i]->val4 * 3000;
+ break;
+ case SC_MAGICMUSHROOM:
+ data.tick = sc->data[i]->val4 * 4000;
+ break;
+ case SC_TOXIN:
+ case SC_BLOODING:
+ data.tick = sc->data[i]->val4 * 10000;
+ break;
+ default:
+ continue;
}
- if( i ){
+ if( i ) {
data.val1 = sc->data[i]->val1;
data.val2 = sc->data[i]->val2;
data.val3 = sc->data[i]->val3;
data.val4 = sc->data[i]->val4;
- status_change_start(bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,1|2|8);
+ status->change_start(src,bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,1|2|8);
flag = 1;
}
}
@@ -11094,11 +11678,9 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) {
}
//Natural regen related stuff.
-static unsigned int natural_heal_prev_tick,natural_heal_diff_tick;
-static int status_natural_heal(struct block_list* bl, va_list args)
-{
+int status_natural_heal(struct block_list* bl, va_list args) {
struct regen_data *regen;
- struct status_data *status;
+ struct status_data *st;
struct status_change *sc;
struct unit_data *ud;
struct view_data *vd = NULL;
@@ -11106,64 +11688,66 @@ static int status_natural_heal(struct block_list* bl, va_list args)
struct map_session_data *sd;
int val,rate,bonus = 0,flag;
- regen = status_get_regen_data(bl);
+ regen = status->get_regen_data(bl);
if (!regen) return 0;
- status = status_get_status_data(bl);
- sc = status_get_sc(bl);
+ st = status->get_status_data(bl);
+ sc = status->get_sc(bl);
if (sc && !sc->count)
sc = NULL;
sd = BL_CAST(BL_PC,bl);
flag = regen->flag;
- if (flag&RGN_HP && (status->hp >= status->max_hp || regen->state.block&1))
+ if (flag&RGN_HP && (st->hp >= st->max_hp || regen->state.block&1))
flag&=~(RGN_HP|RGN_SHP);
- if (flag&RGN_SP && (status->sp >= status->max_sp || regen->state.block&2))
+ if (flag&RGN_SP && (st->sp >= st->max_sp || regen->state.block&2))
flag&=~(RGN_SP|RGN_SSP);
- if (flag && (
- status_isdead(bl) ||
- (sc && (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || sc->data[SC__INVISIBILITY]))
- ))
+ if (flag
+ && (status->isdead(bl)
+ || (sc && (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || sc->data[SC__INVISIBILITY]))
+ )
+ )
flag=0;
if (sd) {
if (sd->hp_loss.value || sd->sp_loss.value)
- pc->bleeding(sd, natural_heal_diff_tick);
+ pc->bleeding(sd, status->natural_heal_diff_tick);
if (sd->hp_regen.value || sd->sp_regen.value)
- pc->regen(sd, natural_heal_diff_tick);
+ pc->regen(sd, status->natural_heal_diff_tick);
}
- if(flag&(RGN_SHP|RGN_SSP) && regen->ssregen &&
- (vd = status_get_viewdata(bl)) && vd->dead_sit == 2)
- { //Apply sitting regen bonus.
+ if (flag&(RGN_SHP|RGN_SSP)
+ && regen->ssregen
+ && (vd = status->get_viewdata(bl))
+ && vd->dead_sit == 2
+ ) {
+ //Apply sitting regen bonus.
sregen = regen->ssregen;
- if(flag&(RGN_SHP))
- { //Sitting HP regen
- val = natural_heal_diff_tick * sregen->rate.hp;
+ if(flag&(RGN_SHP)) {
+ //Sitting HP regen
+ val = status->natural_heal_diff_tick * sregen->rate.hp;
if (regen->state.overweight)
val>>=1; //Half as fast when overweight.
sregen->tick.hp += val;
- while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval)
- {
+ while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) {
sregen->tick.hp -= battle_config.natural_heal_skill_interval;
- if(status_heal(bl, sregen->hp, 0, 3) < sregen->hp)
- { //Full
+ if(status->heal(bl, sregen->hp, 0, 3) < sregen->hp) {
+ //Full
flag&=~(RGN_HP|RGN_SHP);
break;
}
}
}
- if(flag&(RGN_SSP))
- { //Sitting SP regen
- val = natural_heal_diff_tick * sregen->rate.sp;
+ if(flag&(RGN_SSP)) {
+ //Sitting SP regen
+ val = status->natural_heal_diff_tick * sregen->rate.sp;
if (regen->state.overweight)
val>>=1; //Half as fast when overweight.
sregen->tick.sp += val;
- while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval)
- {
+ while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) {
sregen->tick.sp -= battle_config.natural_heal_skill_interval;
- if(status_heal(bl, 0, sregen->sp, 3) < sregen->sp)
- { //Full
+ if(status->heal(bl, 0, sregen->sp, 3) < sregen->sp) {
+ //Full
flag&=~(RGN_SP|RGN_SSP);
break;
}
@@ -11174,10 +11758,9 @@ static int status_natural_heal(struct block_list* bl, va_list args)
if (flag && regen->state.overweight)
flag=0;
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
- if (flag&(RGN_HP|RGN_SHP|RGN_SSP) && ud && ud->walktimer != INVALID_TIMER)
- {
+ if (flag&(RGN_HP|RGN_SHP|RGN_SSP) && ud && ud->walktimer != INVALID_TIMER) {
flag&=~(RGN_SHP|RGN_SSP);
if(!regen->state.walk)
flag&=~RGN_HP;
@@ -11186,9 +11769,8 @@ static int status_natural_heal(struct block_list* bl, va_list args)
if (!flag)
return 0;
- if (flag&(RGN_HP|RGN_SP))
- {
- if(!vd) vd = status_get_viewdata(bl);
+ if (flag&(RGN_HP|RGN_SP)) {
+ if(!vd) vd = status->get_viewdata(bl);
if(vd && vd->dead_sit == 2)
bonus++;
if(regen->state.gc)
@@ -11196,9 +11778,8 @@ static int status_natural_heal(struct block_list* bl, va_list args)
}
//Natural Hp regen
- if (flag&RGN_HP)
- {
- rate = natural_heal_diff_tick*(regen->rate.hp+bonus);
+ if (flag&RGN_HP) {
+ rate = status->natural_heal_diff_tick*(regen->rate.hp+bonus);
if (ud && ud->walktimer != INVALID_TIMER)
rate/=2;
// Homun HP regen fix (they should regen as if they were sitting (twice as fast)
@@ -11206,35 +11787,32 @@ static int status_natural_heal(struct block_list* bl, va_list args)
regen->tick.hp += rate;
- if(regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval)
- {
+ if(regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval) {
val = 0;
do {
val += regen->hp;
regen->tick.hp -= battle_config.natural_healhp_interval;
} while(regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval);
- if (status_heal(bl, val, 0, 1) < val)
+ if (status->heal(bl, val, 0, 1) < val)
flag&=~RGN_SHP; //full.
}
}
//Natural SP regen
- if(flag&RGN_SP)
- {
- rate = natural_heal_diff_tick*(regen->rate.sp+bonus);
+ if(flag&RGN_SP) {
+ rate = status->natural_heal_diff_tick*(regen->rate.sp+bonus);
// Homun SP regen fix (they should regen as if they were sitting (twice as fast)
if(bl->type==BL_HOM) rate *=2;
regen->tick.sp += rate;
- if(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval)
- {
+ if(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval) {
val = 0;
do {
val += regen->sp;
regen->tick.sp -= battle_config.natural_healsp_interval;
} while(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval);
- if (status_heal(bl, 0, val, 1) < val)
+ if (status->heal(bl, 0, val, 1) < val)
flag&=~RGN_SSP; //full.
}
}
@@ -11245,40 +11823,38 @@ static int status_natural_heal(struct block_list* bl, va_list args)
//Skill regen
sregen = regen->sregen;
- if(flag&RGN_SHP)
- { //Skill HP regen
- sregen->tick.hp += natural_heal_diff_tick * sregen->rate.hp;
+ if(flag&RGN_SHP) {
+ //Skill HP regen
+ sregen->tick.hp += status->natural_heal_diff_tick * sregen->rate.hp;
- while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval)
- {
+ while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) {
sregen->tick.hp -= battle_config.natural_heal_skill_interval;
- if(status_heal(bl, sregen->hp, 0, 3) < sregen->hp)
+ if(status->heal(bl, sregen->hp, 0, 3) < sregen->hp)
break; //Full
}
}
- if(flag&RGN_SSP)
- { //Skill SP regen
- sregen->tick.sp += natural_heal_diff_tick * sregen->rate.sp;
- while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval)
- {
+ if(flag&RGN_SSP) {
+ //Skill SP regen
+ sregen->tick.sp += status->natural_heal_diff_tick * sregen->rate.sp;
+ while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) {
val = sregen->sp;
if (sd && sd->state.doridori) {
val*=2;
sd->state.doridori = 0;
if ((rate = pc->checkskill(sd,TK_SPTIME)))
- sc_start(bl,status_skill2sc(TK_SPTIME),
- 100,rate,skill->get_time(TK_SPTIME, rate));
- if (
- (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR &&
- rnd()%10000 < battle_config.sg_angel_skill_ratio
- ) { //Angel of the Sun/Moon/Star
+ sc_start(bl,bl,status->skill2sc(TK_SPTIME),
+ 100,rate,skill->get_time(TK_SPTIME, rate));
+ if ((sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
+ &&rnd()%10000 < battle_config.sg_angel_skill_ratio
+ ) {
+ //Angel of the Sun/Moon/Star
clif->feel_hate_reset(sd);
pc->resethate(sd);
pc->resetfeel(sd);
}
}
sregen->tick.sp -= battle_config.natural_heal_skill_interval;
- if(status_heal(bl, 0, val, 3) < val)
+ if(status->heal(bl, 0, val, 3) < val)
break; //Full
}
}
@@ -11286,26 +11862,26 @@ static int status_natural_heal(struct block_list* bl, va_list args)
}
//Natural heal main timer.
-static int status_natural_heal_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
- natural_heal_diff_tick = DIFF_TICK(tick,natural_heal_prev_tick);
- iMap->map_foreachregen(status_natural_heal);
- natural_heal_prev_tick = tick;
+int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) {
+ // This difference is always positive and lower than UINT_MAX (~24 days)
+ status->natural_heal_diff_tick = (unsigned int)cap_value(DIFF_TICK(tick,status->natural_heal_prev_tick), 0, UINT_MAX);
+ map->foreachregen(status->natural_heal);
+ status->natural_heal_prev_tick = tick;
return 0;
}
/**
- * Get the chance to upgrade a piece of equipment.
- * @param wlv The weapon type of the item to refine (see see enum refine_type)
- * @param refine The target refine level
- * @return The chance to refine the item, in percent (0~100)
- **/
+* Get the chance to upgrade a piece of equipment.
+* @param wlv The weapon type of the item to refine (see see enum refine_type)
+* @param refine The target refine level
+* @return The chance to refine the item, in percent (0~100)
+**/
int status_get_refine_chance(enum refine_type wlv, int refine) {
if ( refine < 0 || refine >= MAX_REFINE)
- return 0;
+ return 0;
- return refine_info[wlv].chance[refine];
+ return status->refine_info[wlv].chance[refine];
}
int status_get_sc_type(sc_type type) {
@@ -11313,17 +11889,17 @@ int status_get_sc_type(sc_type type) {
if( type <= SC_NONE || type >= SC_MAX )
return 0;
- return sc_conf[type];
+ return status->sc_conf[type];
}
/*------------------------------------------
- * DB reading.
- * job_db1.txt - weight, hp, sp, aspd
- * job_db2.txt - job level stat bonuses
- * size_fix.txt - size adjustment table for weapons
- * refine_db.txt - refining data table
- *------------------------------------------*/
-static bool status_readdb_job1(char* fields[], int columns, int current)
+* DB reading.
+* job_db1.txt - weight, hp, sp, aspd
+* job_db2.txt - job level stat bonuses
+* size_fix.txt - size adjustment table for weapons
+* refine_db.txt - refining data table
+*------------------------------------------*/
+bool status_readdb_job1(char* fields[], int columns, int current)
{// Job-specific values (weight, HP, SP, ASPD)
int idx, class_;
unsigned int i;
@@ -11337,22 +11913,22 @@ static bool status_readdb_job1(char* fields[], int columns, int current)
}
idx = pc->class2idx(class_);
- max_weight_base[idx] = atoi(fields[1]);
- hp_coefficient[idx] = atoi(fields[2]);
- hp_coefficient2[idx] = atoi(fields[3]);
- sp_coefficient[idx] = atoi(fields[4]);
+ status->max_weight_base[idx] = atoi(fields[1]);
+ status->hp_coefficient[idx] = atoi(fields[2]);
+ status->hp_coefficient2[idx] = atoi(fields[3]);
+ status->sp_coefficient[idx] = atoi(fields[4]);
#ifdef RENEWAL_ASPD
for(i = 0; i <= MAX_WEAPON_TYPE; i++)
#else
for(i = 0; i < MAX_WEAPON_TYPE; i++)
#endif
{
- aspd_base[idx][i] = atoi(fields[i+5]);
+ status->aspd_base[idx][i] = atoi(fields[i+5]);
}
return true;
}
-static bool status_readdb_job2(char* fields[], int columns, int current)
+bool status_readdb_job2(char* fields[], int columns, int current)
{
int idx, class_, i;
@@ -11367,23 +11943,23 @@ static bool status_readdb_job2(char* fields[], int columns, int current)
for(i = 1; i < columns; i++)
{
- job_bonus[idx][i-1] = atoi(fields[i]);
+ status->job_bonus[idx][i-1] = atoi(fields[i]);
}
return true;
}
-static bool status_readdb_sizefix(char* fields[], int columns, int current)
+bool status_readdb_sizefix(char* fields[], int columns, int current)
{
unsigned int i;
for(i = 0; i < MAX_WEAPON_TYPE; i++)
{
- atkmods[current][i] = atoi(fields[i]);
+ status->atkmods[current][i] = atoi(fields[i]);
}
return true;
}
-static bool status_readdb_refine(char* fields[], int columns, int current)
+bool status_readdb_refine(char* fields[], int columns, int current)
{
int i, bonus_per_level, random_bonus, random_bonus_start_level;
@@ -11405,68 +11981,65 @@ static bool status_readdb_refine(char* fields[], int columns, int current)
*delim = '\0';
- refine_info[current].chance[i] = atoi(fields[4+i]);
+ status->refine_info[current].chance[i] = atoi(fields[4+i]);
if (i >= random_bonus_start_level - 1)
- refine_info[current].randombonus_max[i] = random_bonus * (i - random_bonus_start_level + 2);
+ status->refine_info[current].randombonus_max[i] = random_bonus * (i - random_bonus_start_level + 2);
- refine_info[current].bonus[i] = bonus_per_level + atoi(delim+1);
+ status->refine_info[current].bonus[i] = bonus_per_level + atoi(delim+1);
if (i > 0)
- refine_info[current].bonus[i] += refine_info[current].bonus[i-1];
+ status->refine_info[current].bonus[i] += status->refine_info[current].bonus[i-1];
}
return true;
}
-static bool status_readdb_scconfig(char* fields[], int columns, int current)
-{
+bool status_readdb_scconfig(char* fields[], int columns, int current) {
int val = 0;
char* type = fields[0];
- if( !script_get_constant(type, &val) ){
+ if( !script->get_constant(type, &val) ){
ShowWarning("status_readdb_sc_conf: Invalid status type %s specified.\n", type);
return false;
}
- sc_conf[val] = (int)strtol(fields[1], NULL, 0);
+ status->sc_conf[val] = (int)strtol(fields[1], NULL, 0);
return true;
}
-/*
-* Read status db
-* job1.txt
-* job2.txt
-* size_fixe.txt
-* refine_db.txt
-*/
+/**
+ * Read status db
+ * job1.txt
+ * job2.txt
+ * size_fixe.txt
+ * refine_db.txt
+ **/
int status_readdb(void)
{
int i, j;
// initialize databases to default
//
-
- // reset job_db1.txt data
- memset(max_weight_base, 0, sizeof(max_weight_base));
- memset(hp_coefficient, 0, sizeof(hp_coefficient));
- memset(hp_coefficient2, 0, sizeof(hp_coefficient2));
- memset(sp_coefficient, 0, sizeof(sp_coefficient));
- memset(aspd_base, 0, sizeof(aspd_base));
- // reset job_db2.txt data
- memset(job_bonus,0,sizeof(job_bonus)); // Job-specific stats bonus
-
+ if( runflag == MAPSERVER_ST_RUNNING ) {//not necessary during boot
+ // reset job_db1.txt data
+ memset(status->max_weight_base, 0, sizeof(status->max_weight_base));
+ memset(status->hp_coefficient, 0, sizeof(status->hp_coefficient));
+ memset(status->hp_coefficient2, 0, sizeof(status->hp_coefficient2));
+ memset(status->sp_coefficient, 0, sizeof(status->sp_coefficient));
+ memset(status->aspd_base, 0, sizeof(status->aspd_base));
+ // reset job_db2.txt data
+ memset(status->job_bonus,0,sizeof(status->job_bonus)); // Job-specific stats bonus
+ }
// size_fix.txt
- for(i=0;i<ARRAYLENGTH(atkmods);i++)
- for(j=0;j<MAX_WEAPON_TYPE;j++)
- atkmods[i][j]=100;
+ for(i = 0; i < ARRAYLENGTH(status->atkmods); i++)
+ for(j = 0; j < MAX_WEAPON_TYPE; j++)
+ status->atkmods[i][j] = 100;
// refine_db.txt
- for(i=0;i<ARRAYLENGTH(refine_info);i++)
- {
- for(j=0;j<MAX_REFINE; j++)
- {
- refine_info[i].chance[j] = 100;
- refine_info[i].bonus[j] = 0;
- refine_info[i].randombonus_max[j] = 0;
+ for(i=0;i<ARRAYLENGTH(status->refine_info);i++) {
+ for(j=0;j<MAX_REFINE; j++) {
+ status->refine_info[i].chance[j] = 100;
+ status->refine_info[i].bonus[j] = 0;
+ status->refine_info[i].randombonus_max[j] = 0;
}
}
@@ -11475,36 +12048,202 @@ int status_readdb(void)
#ifdef RENEWAL_ASPD
- sv->readdb(iMap->db_path, "re/job_db1.txt", ',', 6+MAX_WEAPON_TYPE, 6+MAX_WEAPON_TYPE, -1, &status_readdb_job1);
+ sv->readdb(map->db_path, "re/job_db1.txt", ',', 6+MAX_WEAPON_TYPE, 6+MAX_WEAPON_TYPE, -1, status->readdb_job1);
#else
- sv->readdb(iMap->db_path, "pre-re/job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, &status_readdb_job1);
+ sv->readdb(map->db_path, "pre-re/job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, status->readdb_job1);
#endif
- sv->readdb(iMap->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, &status_readdb_job2);
- sv->readdb(iMap->db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(atkmods), &status_readdb_sizefix);
- sv->readdb(iMap->db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(refine_info), &status_readdb_refine);
- sv->readdb(iMap->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, &status_readdb_scconfig);
+ sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2);
+ sv->readdb(map->db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->atkmods), status->readdb_sizefix);
+ sv->readdb(map->db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(status->refine_info), status->readdb_refine);
+ sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig);
return 0;
}
/*==========================================
- * Status db init and destroy.
- *------------------------------------------*/
-int do_init_status(void)
-{
- iTimer->add_timer_func_list(status_change_timer,"status_change_timer");
- iTimer->add_timer_func_list(kaahi_heal_timer,"kaahi_heal_timer");
- iTimer->add_timer_func_list(status_natural_heal_timer,"status_natural_heal_timer");
- initChangeTables();
- initDummyData();
- status_readdb();
- status_calc_sigma();
- natural_heal_prev_tick = iTimer->gettick();
- sc_data_ers = ers_new(sizeof(struct status_change_entry),"status.c::sc_data_ers",ERS_OPT_NONE);
- iTimer->add_timer_interval(natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status_natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL);
+* Status db init and destroy.
+*------------------------------------------*/
+int do_init_status(bool minimal) {
+ if (minimal)
+ return 0;
+
+ timer->add_func_list(status->change_timer,"status_change_timer");
+ timer->add_func_list(status->kaahi_heal_timer,"status_kaahi_heal_timer");
+ timer->add_func_list(status->natural_heal_timer,"status_natural_heal_timer");
+ status->initChangeTables();
+ status->initDummyData();
+ status->readdb();
+ status->calc_sigma();
+ status->natural_heal_prev_tick = timer->gettick();
+ status->data_ers = ers_new(sizeof(struct status_change_entry),"status.c::data_ers",ERS_OPT_NONE);
+ timer->add_interval(status->natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status->natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL);
return 0;
}
-void do_final_status(void)
-{
- ers_destroy(sc_data_ers);
+void do_final_status(void) {
+ ers_destroy(status->data_ers);
+}
+
+/*=====================================
+* Default Functions : status.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+void status_defaults(void) {
+ status = &status_s;
+
+ /* vars */
+ //we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only
+ //to avoid cards exploits
+ status->current_equip_item_index = 0; //Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus]
+ status->current_equip_card_id = 0; //To prevent card-stacking (from jA) [Skotlex]
+
+ memset(status->max_weight_base,0,sizeof(status->max_weight_base)
+ + sizeof(status->hp_coefficient)
+ + sizeof(status->hp_coefficient2)
+ + sizeof(status->hp_sigma_val)
+ + sizeof(status->sp_coefficient)
+ + sizeof(status->aspd_base)
+ + sizeof(status->Skill2SCTable)
+ + sizeof(status->IconChangeTable)
+ + sizeof(status->ChangeFlagTable)
+ + sizeof(status->SkillChangeTable)
+ + sizeof(status->RelevantBLTypes)
+ + sizeof(status->DisplayType)
+ + sizeof(status->refine_info)
+ + sizeof(status->atkmods)
+ + sizeof(status->job_bonus)
+ + sizeof(status->sc_conf)
+ );
+
+ status->data_ers = NULL;
+ memset(&status->dummy, 0, sizeof(status->dummy));
+ status->natural_heal_prev_tick = 0;
+ status->natural_heal_diff_tick = 0;
+ /* funcs */
+ status->get_refine_chance = status_get_refine_chance;
+ // for looking up associated data
+ status->skill2sc = status_skill2sc;
+ status->sc2skill = status_sc2skill;
+ status->sc2scb_flag = status_sc2scb_flag;
+ status->type2relevant_bl_types = status_type2relevant_bl_types;
+ status->get_sc_type = status_get_sc_type;
+
+ status->damage = status_damage;
+ //Define for standard HP/SP skill-related cost triggers (mobs require no HP/SP to use skills)
+ status->charge = status_charge;
+ status->percent_change = status_percent_change;
+ //Used to set the hp/sp of an object to an absolute value (can't kill)
+ status->set_hp = status_set_hp;
+ status->set_sp = status_set_sp;
+ status->heal = status_heal;
+ status->revive = status_revive;
+ status->fixed_revive = status_fixed_revive;
+ status->get_regen_data = status_get_regen_data;
+ status->get_status_data = status_get_status_data;
+ status->get_base_status = status_get_base_status;
+ status->get_name = status_get_name;
+ status->get_class = status_get_class;
+ status->get_lv = status_get_lv;
+ status->get_def = status_get_def;
+ status->get_speed = status_get_speed;
+ status->calc_attack_element = status_calc_attack_element;
+ status->get_party_id = status_get_party_id;
+ status->get_guild_id = status_get_guild_id;
+ status->get_emblem_id = status_get_emblem_id;
+ status->get_mexp = status_get_mexp;
+ status->get_race2 = status_get_race2;
+
+ status->get_viewdata = status_get_viewdata;
+ status->set_viewdata = status_set_viewdata;
+ status->change_init = status_change_init;
+ status->get_sc = status_get_sc;
+
+ status->isdead = status_isdead;
+ status->isimmune = status_isimmune;
+
+ status->get_sc_def = status_get_sc_def;
+
+ status->change_start = status_change_start;
+ status->change_end_ = status_change_end_;
+ status->kaahi_heal_timer = kaahi_heal_timer;
+ status->change_timer = status_change_timer;
+ status->change_timer_sub = status_change_timer_sub;
+ status->change_clear = status_change_clear;
+ status->change_clear_buffs = status_change_clear_buffs;
+
+ status->calc_bl_ = status_calc_bl_;
+ status->calc_mob_ = status_calc_mob_;
+ status->calc_pet_ = status_calc_pet_;
+ status->calc_pc_ = status_calc_pc_;
+ status->calc_homunculus_ = status_calc_homunculus_;
+ status->calc_mercenary_ = status_calc_mercenary_;
+ status->calc_elemental_ = status_calc_elemental_;
+
+ status->calc_misc = status_calc_misc;
+ status->calc_regen = status_calc_regen;
+ status->calc_regen_rate = status_calc_regen_rate;
+
+ status->check_skilluse = status_check_skilluse; // [Skotlex]
+ status->check_visibility = status_check_visibility; //[Skotlex]
+
+ status->change_spread = status_change_spread;
+
+ status->calc_def = status_calc_def;
+ status->calc_def2 = status_calc_def2;
+ status->calc_mdef = status_calc_mdef;
+ status->calc_mdef2 = status_calc_mdef2;
+ status->calc_batk = status_calc_batk;
+ status->base_matk = status_base_matk;
+ status->get_weapon_atk = status_get_weapon_atk;
+ status->get_total_mdef = status_get_total_mdef;
+ status->get_total_def = status_get_total_def;
+
+ status->get_matk = status_get_matk;
+ status->update_matk = status_update_matk;
+
+ status->readdb = status_readdb;
+ status->init = do_init_status;
+ status->final = do_final_status;
+
+ status->initChangeTables = initChangeTables;
+ status->initDummyData = initDummyData;
+ status->base_amotion_pc = status_base_amotion_pc;
+ status->base_atk = status_base_atk;
+ status->calc_sigma = status_calc_sigma;
+ status->base_pc_maxhp = status_base_pc_maxhp;
+ status->base_pc_maxsp = status_base_pc_maxsp;
+ status->calc_npc_ = status_calc_npc_;
+ status->calc_str = status_calc_str;
+ status->calc_agi = status_calc_agi;
+ status->calc_vit = status_calc_vit;
+ status->calc_int = status_calc_int;
+ status->calc_dex = status_calc_dex;
+ status->calc_luk = status_calc_luk;
+ status->calc_watk = status_calc_watk;
+ status->calc_matk = status_calc_matk;
+ status->calc_hit = status_calc_hit;
+ status->calc_critical = status_calc_critical;
+ status->calc_flee = status_calc_flee;
+ status->calc_flee2 = status_calc_flee2;
+ status->calc_speed = status_calc_speed;
+ status->calc_aspd_rate = status_calc_aspd_rate;
+ status->calc_dmotion = status_calc_dmotion;
+ status->calc_aspd = status_calc_aspd;
+ status->calc_fix_aspd = status_calc_fix_aspd;
+ status->calc_maxhp = status_calc_maxhp;
+ status->calc_maxsp = status_calc_maxsp;
+ status->calc_element = status_calc_element;
+ status->calc_element_lv = status_calc_element_lv;
+ status->calc_mode = status_calc_mode;
+ status->calc_ematk = status_calc_ematk;
+ status->calc_bl_main = status_calc_bl_main;
+ status->display_add = status_display_add;
+ status->display_remove = status_display_remove;
+ status->natural_heal = status_natural_heal;
+ status->natural_heal_timer = status_natural_heal_timer;
+ status->readdb_job1 = status_readdb_job1;
+ status->readdb_job2 = status_readdb_job2;
+ status->readdb_sizefix = status_readdb_sizefix;
+ status->readdb_refine = status_readdb_refine;
+ status->readdb_scconfig = status_readdb_scconfig;
}
diff --git a/src/map/status.h b/src/map/status.h
index fbce95f17..942f86d7c 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -1,15 +1,37 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _STATUS_H_
-#define _STATUS_H_
+#ifndef MAP_STATUS_H
+#define MAP_STATUS_H
+
+#include "../config/core.h" // defType, RENEWAL, RENEWAL_ASPD
+
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h" // NEW_CARTS
struct block_list;
-struct mob_data;
-struct pet_data;
+struct elemental_data;
struct homun_data;
struct mercenary_data;
-struct status_change;
+struct mob_data;
+struct npc_data;
+struct pet_data;
+
+//Change the equation when the values are high enough to discard the
+//imprecision in exchange of overflow protection [Skotlex]
+//Also add 100% checks since those are the most used cases where we don't
+//want approximation errors.
+#define APPLY_RATE(value, rate) ( \
+ (rate) == 100 ? \
+ (value) \
+ : ( \
+ (value) > 100000 ? \
+ (rate) * ( (value) / 100 ) \
+ : \
+ (value) * (rate) / 100 \
+ ) \
+)
/**
* Max Refine available to your server
@@ -27,26 +49,27 @@ enum refine_type {
REFINE_TYPE_WEAPON2 = 2,
REFINE_TYPE_WEAPON3 = 3,
REFINE_TYPE_WEAPON4 = 4,
-
REFINE_TYPE_MAX = 5
};
+/**
+ * SC configuration type
+ * @see db/sc_config.txt for more information
+ **/
typedef enum sc_conf_type {
- SC_NO_REM_DEATH = 0x1,
- SC_NO_SAVE = 0x2,
- SC_NO_DISPELL = 0x4,
- SC_NO_CLEARANCE = 0x8,
- SC_BUFF = 0x10,
- SC_DEBUFF = 0x20,
- SC_MADO_NO_RESET = 0x40
+ SC_NO_REM_DEATH = 0x01,
+ SC_NO_SAVE = 0x02,
+ SC_NO_DISPELL = 0x04,
+ SC_NO_CLEARANCE = 0x08,
+ SC_BUFF = 0x10,
+ SC_DEBUFF = 0x20,
+ SC_MADO_NO_RESET = 0x40,
+ SC_NO_CLEAR = 0x80,
} sc_conf_type;
-int status_get_refine_chance(enum refine_type wlv, int refine);
-
-// Status changes listing. These code are for use by the server.
+// Status changes listing. These code are for use by the server.
typedef enum sc_type {
SC_NONE = -1,
-
//First we enumerate common status ailments which are often used around.
SC_STONE = 0,
SC_COMMON_MIN = 0, // begin
@@ -59,9 +82,12 @@ typedef enum sc_type {
SC_CONFUSION,
SC_BLIND,
SC_BLOODING,
- SC_DPOISON,
- SC_BURNING, //11
- SC_COMMON_MAX = 11, // end
+ SC_DPOISON, //10
+ SC_FEAR,
+ SC_COLD,
+ SC_BURNING,
+ SC_DEEP_SLEEP,
+ SC_COMMON_MAX = 14, // end
//Next up, we continue on 20, to leave enough room for additional "common" ailments in the future.
SC_PROVOKE = 20,
@@ -147,7 +173,7 @@ typedef enum sc_type {
SC_VOLCANO, //100,
SC_DELUGE,
SC_VIOLENTGALE,
- SC_WATK_ELEMENT,
+ SC_SUB_WEAPONPROPERTY,
SC_ARMOR,
SC_ARMORPROPERTY,
SC_NOCHAT,
@@ -323,7 +349,6 @@ typedef enum sc_type {
SC_PROTECT_DEF,
//SC_SPREGEN,
SC_WALKSPEED = 278,
-
// Mercenary Only Bonus Effects
SC_MER_FLEE,
SC_MER_ATK, //280
@@ -331,7 +356,6 @@ typedef enum sc_type {
SC_MER_SP,
SC_MER_HIT,
SC_MER_QUICKEN,
-
SC_REBIRTH,
//SC_SKILLCASTRATE, //286
//SC_DEFRATIOATK,
@@ -360,8 +384,8 @@ typedef enum sc_type {
/**
* 3rd
**/
- SC_FEAR,
- SC_FROSTMISTY,
+ //SC_FEAR,
+ SC_FROSTMISTY = 311,
/**
* Rune Knight
**/
@@ -373,20 +397,20 @@ typedef enum sc_type {
SC_REUSE_REFRESH,
SC_GIANTGROWTH,
SC_STONEHARDSKIN,
- SC_VITALITYACTIVATION,
+ SC_VITALITYACTIVATION, // 320
SC_STORMBLAST,
SC_FIGHTINGSPIRIT,
SC_ABUNDANCE,
/**
* Arch Bishop
- **/
+ **/
SC_ADORAMUS,
SC_EPICLESIS,
SC_ORATIO,
SC_LAUDAAGNUS,
SC_LAUDARAMUS,
SC_RENOVATIO,
- SC_EXPIATIO,
+ SC_EXPIATIO, // 330
SC_DUPLELIGHT,
SC_SECRAMENT,
/**
@@ -399,7 +423,7 @@ typedef enum sc_type {
SC_SUMMON1,
SC_SUMMON2,
SC_SUMMON3,
- SC_SUMMON4,
+ SC_SUMMON4, // 340
SC_SUMMON5,
SC_READING_SB,
SC_FREEZINGSP,
@@ -415,7 +439,7 @@ typedef enum sc_type {
* Mechanic
**/
SC_ACCELERATION,
- SC_HOVERING,
+ SC_HOVERING, // 350
SC_SHAPESHIFT,
SC_INFRAREDSCAN,
SC_ANALYZE,
@@ -425,7 +449,7 @@ typedef enum sc_type {
SC_STEALTHFIELD,
SC_STEALTHFIELD_MASTER,
SC_OVERHEAT,
- SC_OVERHEAT_LIMITPOINT,
+ SC_OVERHEAT_LIMITPOINT, // 360
/**
* Guillotine Cross
**/
@@ -438,7 +462,7 @@ typedef enum sc_type {
SC_ROLLINGCUTTER,
SC_TOXIN,
SC_PARALYSE,
- SC_VENOMBLEED,
+ SC_VENOMBLEED, // 370
SC_MAGICMUSHROOM,
SC_DEATHHURT,
SC_PYREXIA,
@@ -451,7 +475,7 @@ typedef enum sc_type {
SC_FORCEOFVANGUARD,
SC_SHIELDSPELL_DEF,
SC_SHIELDSPELL_MDEF,
- SC_SHIELDSPELL_REF,
+ SC_SHIELDSPELL_REF, // 380
SC_EXEEDBREAK,
SC_PRESTIGE,
SC_BANDING,
@@ -462,9 +486,9 @@ typedef enum sc_type {
* Sorcerer
**/
SC_SPELLFIST,
- SC_CRYSTALIZE,
- SC_STRIKING,
- SC_WARMER,
+ //SC_COLD,
+ SC_STRIKING = 389,
+ SC_WARMER, // 390
SC_VACUUM_EXTREME,
SC_PROPERTYWALK,
/**
@@ -477,30 +501,30 @@ typedef enum sc_type {
SC_ECHOSONG,
SC_HARMONIZE,
SC_SIREN,
- SC_DEEP_SLEEP,
- SC_SIRCLEOFNATURE,
+ //SC_DEEP_SLEEP, // 400
+ SC_SIRCLEOFNATURE = 401,
SC_GLOOMYDAY,
- SC_GLOOMYDAY_SK,
- SC_SONG_OF_MANA,
+ //SC_GLOOMYDAY_SK,
+ SC_SONG_OF_MANA = 404,
SC_DANCE_WITH_WUG,
SC_SATURDAY_NIGHT_FEVER,
SC_LERADS_DEW,
SC_MELODYOFSINK,
SC_BEYOND_OF_WARCRY,
- SC_UNLIMITED_HUMMING_VOICE,
+ SC_UNLIMITED_HUMMING_VOICE, // 410
SC_SITDOWN_FORCE,
- SC_NETHERWORLD,
+ //SC_NETHERWORLD,
/**
* Sura
**/
- SC_CRESCENTELBOW,
+ SC_CRESCENTELBOW = 413,
SC_CURSEDCIRCLE_ATKER,
SC_CURSEDCIRCLE_TARGET,
SC_LIGHTNINGWALK,
SC_RAISINGDRAGON,
SC_GENTLETOUCH_ENERGYGAIN,
SC_GENTLETOUCH_CHANGE,
- SC_GENTLETOUCH_REVITALIZE,
+ SC_GENTLETOUCH_REVITALIZE, // 420
/**
* Genetic
**/
@@ -513,7 +537,7 @@ typedef enum sc_type {
SC_STOMACHACHE,
SC_MYSTERIOUS_POWDER,
SC_MELON_BOMB,
- SC_BANANA_BOMB,
+ SC_BANANA_BOMB, // 430
SC_BANANA_BOMB_SITDOWN_POSTDELAY,
SC_SAVAGE_STEAK,
SC_COCKTAIL_WARG_BLOOD,
@@ -523,7 +547,7 @@ typedef enum sc_type {
SC_PUTTI_TAILS_NOODLES,
SC_BOOST500,
SC_FULL_SWING_K,
- SC_MANA_PLUS,
+ SC_MANA_PLUS, // 440
SC_MUSTLE_M,
SC_LIFE_FORCE_F,
SC_EXTRACT_WHITE_POTION_Z,
@@ -536,7 +560,7 @@ typedef enum sc_type {
SC__AUTOSHADOWSPELL,
SC__SHADOWFORM,
SC__BODYPAINT,
- SC__INVISIBILITY,
+ SC__INVISIBILITY, // 450
SC__DEADLYINFECT,
SC__ENERVATION,
SC__GROOMY,
@@ -546,7 +570,7 @@ typedef enum sc_type {
SC__WEAKNESS,
SC__STRIPACCESSARY,
SC__MANHOLE,
- SC__BLOODYLUST,
+ SC__BLOODYLUST, // 460
/**
* Elemental Spirits
**/
@@ -559,7 +583,7 @@ typedef enum sc_type {
SC_WATER_DROP,
SC_WATER_DROP_OPTION,
SC_WATER_BARRIER,
- SC_WIND_STEP,
+ SC_WIND_STEP, // 470
SC_WIND_STEP_OPTION,
SC_WIND_CURTAIN,
SC_WIND_CURTAIN_OPTION,
@@ -569,7 +593,7 @@ typedef enum sc_type {
SC_STONE_SHIELD,
SC_STONE_SHIELD_OPTION,
SC_POWER_OF_GAIA,
- SC_PYROTECHNIC,
+ SC_PYROTECHNIC, // 480
SC_PYROTECHNIC_OPTION,
SC_HEATER,
SC_HEATER_OPTION,
@@ -579,7 +603,7 @@ typedef enum sc_type {
SC_AQUAPLAY_OPTION,
SC_COOLER,
SC_COOLER_OPTION,
- SC_CHILLY_AIR,
+ SC_CHILLY_AIR, // 490
SC_CHILLY_AIR_OPTION,
SC_GUST,
SC_GUST_OPTION,
@@ -589,7 +613,7 @@ typedef enum sc_type {
SC_WILD_STORM_OPTION,
SC_PETROLOGY,
SC_PETROLOGY_OPTION,
- SC_CURSED_SOIL,
+ SC_CURSED_SOIL, // 500
SC_CURSED_SOIL_OPTION,
SC_UPHEAVAL,
SC_UPHEAVAL_OPTION,
@@ -600,21 +624,21 @@ typedef enum sc_type {
/* Guild Aura */
SC_LEADERSHIP,
SC_GLORYWOUNDS,
- SC_SOULCOLD,
+ SC_SOULCOLD, // 510
SC_HAWKEYES,
/* ... */
SC_ODINS_POWER,
/* Sorcerer .extra */
SC_FIRE_INSIGNIA,
SC_WATER_INSIGNIA,
- SC_WIND_INSIGNIA,
+ SC_WIND_INSIGNIA,
SC_EARTH_INSIGNIA,
/* new pushcart */
SC_PUSH_CART,
/* Warlock Spell books */
SC_SPELLBOOK1,
SC_SPELLBOOK2,
- SC_SPELLBOOK3,
+ SC_SPELLBOOK3, // 520
SC_SPELLBOOK4,
SC_SPELLBOOK5,
SC_SPELLBOOK6,
@@ -626,13 +650,13 @@ typedef enum sc_type {
/* Max HP & SP */
SC_INCMHP,
SC_INCMSP,
- SC_PARTYFLEE,
+ SC_PARTYFLEE,
/**
* Kagerou & Oboro [malufett]
**/
SC_MEIKYOUSISUI,
SC_KO_JYUMONJIKIRI,
- SC_KYOUGAKU,
+ SC_KYOUGAKU, // 530
SC_IZAYOI,
SC_ZENKAI,
SC_KG_KAGEHUMI,
@@ -643,19 +667,19 @@ typedef enum sc_type {
SC_AKAITSUKI,
//homon S
- SC_STYLE_CHANGE,
- SC_GOLDENE_FERSE,
- SC_ANGRIFFS_MODUS,
- SC_ERASER_CUTTER,
- SC_OVERED_BOOST,
- SC_LIGHT_OF_REGENE,
- SC_VOLCANIC_ASH,
- SC_GRANITIC_ARMOR,
- SC_MAGMA_FLOW,
- SC_PYROCLASTIC,
- SC_NEEDLE_OF_PARALYZE,
- SC_PAIN_KILLER,
-#ifdef RENEWAL
+ SC_STYLE_CHANGE,
+ SC_GOLDENE_FERSE, // 540
+ SC_ANGRIFFS_MODUS,
+ SC_ERASER_CUTTER,
+ SC_OVERED_BOOST,
+ SC_LIGHT_OF_REGENE,
+ SC_VOLCANIC_ASH,
+ SC_GRANITIC_ARMOR,
+ SC_MAGMA_FLOW,
+ SC_PYROCLASTIC,
+ SC_NEEDLE_OF_PARALYZE,
+ SC_PAIN_KILLER, // 550
+#ifdef RENEWAL
SC_EXTREMITYFIST2,
SC_RAID,
#endif
@@ -666,751 +690,865 @@ typedef enum sc_type {
SC_KINGS_GRACE,
SC_TELEKINESIS_INTENSE,
SC_OFFERTORIUM,
- SC_FRIGG_SONG,
+ SC_FRIGG_SONG, // 560
SC_ALL_RIDING,
SC_HANBOK,
-
SC_MONSTER_TRANSFORM,
+ SC_ANGEL_PROTECT,
+ SC_ILLUSIONDOPING,
+
+ SC_MTF_ASPD,
+ SC_MTF_RANGEATK,
+ SC_MTF_MATK,
+ SC_MTF_MLEATKED,
+ SC_MTF_CRIDAMAGE, // 570
+
+ SC_MOONSTAR,
+ SC_SUPER_STAR,
+
+ SC_OKTOBERFEST,
+ SC_STRANGELIGHTS,
+ SC_DECORATION_OF_MUSIC,
+
+ SC__MAELSTROM,
+ SC__CHAOS,
+
+ SC__FEINTBOMB_MASTER,
+ SC_FALLENEMPIRE,
+ SC_FLASHCOMBO,
+
+ //Vellum Weapon reductions
+ SC_DEFSET,
+ SC_MDEFSET,
+
+ SC_NO_SWITCH_EQUIP,
SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
} sc_type;
-// Official status change ids, used to display status icons on the client.
+/// Official status change ids, used to display status icons in the client.
enum si_type {
- SI_BLANK = -1,
- SI_PROVOKE = 0,
- SI_ENDURE = 1,
- SI_TWOHANDQUICKEN = 2,
- SI_CONCENTRATION = 3,
- SI_HIDING = 4,
- SI_CLOAKING = 5,
- SI_ENCHANTPOISON = 6,
- SI_POISONREACT = 7,
- SI_QUAGMIRE = 8,
- SI_ANGELUS = 9,
- SI_BLESSING = 10,
- SI_CRUCIS = 11,
- SI_INC_AGI = 12,
- SI_DEC_AGI = 13,
- SI_SLOWPOISON = 14,
- SI_IMPOSITIO = 15,
- SI_SUFFRAGIUM = 16,
- SI_ASPERSIO = 17,
- SI_BENEDICTIO = 18,
- SI_KYRIE = 19,
- SI_MAGNIFICAT = 20,
- SI_GLORIA = 21,
- SI_LEXAETERNA = 22,
- SI_ADRENALINE = 23,
- SI_WEAPONPERFECT = 24,
- SI_OVERTHRUST = 25,
- SI_MAXIMIZE = 26,
- SI_RIDING = 27,
- SI_FALCON = 28,
- SI_TRICKDEAD = 29,
- SI_SHOUT = 30,
- SI_ENERGYCOAT = 31,
- SI_BROKENARMOR = 32,
- SI_BROKENWEAPON = 33,
- SI_ILLUSION = 34,
- SI_WEIGHTOVER50 = 35,
- SI_WEIGHTOVER90 = 36,
- SI_ATTHASTE_POTION1 = 37,
- SI_ATTHASTE_POTION2 = 38,
- SI_ATTHASTE_POTION3 = 39,
- SI_ATTHASTE_INFINITY = 40,
- SI_MOVHASTE_POTION = 41,
- SI_MOVHASTE_INFINITY = 42,
-// SI_AUTOCOUNTER = 43,
-// SI_SPLASHER = 44,
- SI_ANKLESNARE = 45,
- SI_POSTDELAY = 46,
-// SI_NOACTION = 47,
-// SI_IMPOSSIBLEPICKUP = 48,
-// SI_BARRIER = 49,
- SI_NOEQUIPWEAPON = 50,
- SI_NOEQUIPSHIELD = 51,
- SI_NOEQUIPARMOR = 52,
- SI_NOEQUIPHELM = 53,
- SI_PROTECTWEAPON = 54,
- SI_PROTECTSHIELD = 55,
- SI_PROTECTARMOR = 56,
- SI_PROTECTHELM = 57,
- SI_AUTOGUARD = 58,
- SI_REFLECTSHIELD = 59,
-// SI_DEVOTION = 60,
- SI_PROVIDENCE = 61,
- SI_DEFENDER = 62,
-// SI_MAGICROD = 63,
-// SI_WEAPONPROPERTY = 64,
- SI_AUTOSPELL = 65,
-// SI_SPECIALZONE = 66,
-// SI_MASK = 67,
- SI_SPEARQUICKEN = 68,
-// SI_BDPLAYING = 69,
-// SI_WHISTLE = 70,
-// SI_ASSASSINCROSS = 71,
-// SI_POEMBRAGI = 72,
-// SI_APPLEIDUN = 73,
-// SI_HUMMING = 74,
-// SI_DONTFORGETME = 75,
-// SI_FORTUNEKISS = 76,
-// SI_SERVICEFORYOU = 77,
-// SI_RICHMANKIM = 78,
-// SI_ETERNALCHAOS = 79,
-// SI_DRUMBATTLEFIELD = 80,
-// SI_RINGNIBELUNGEN = 81,
-// SI_ROKISWEIL = 82,
-// SI_INTOABYSS = 83,
-// SI_SIEGFRIED = 84,
-// SI_BLADESTOP = 85,
- SI_EXPLOSIONSPIRITS = 86,
- SI_STEELBODY = 87,
- SI_EXTREMITYFIST = 88,
-// SI_COMBOATTACK = 89,
- SI_PROPERTYFIRE = 90,
- SI_PROPERTYWATER = 91,
- SI_PROPERTYWIND = 92,
- SI_PROPERTYGROUND = 93,
-// SI_MAGICATTACK = 94,
- SI_STOP = 95,
-// SI_WEAPONBRAKER = 96,
- SI_PROPERTYUNDEAD = 97,
-// SI_POWERUP = 98,
-// SI_AGIUP = 99,
-// SI_SIEGEMODE = 100,
-// SI_INVISIBLE = 101,
-// SI_STATUSONE = 102,
- SI_AURABLADE = 103,
- SI_PARRYING = 104,
- SI_LKCONCENTRATION = 105,
- SI_TENSIONRELAX = 106,
- SI_BERSERK = 107,
-// SI_SACRIFICE = 108,
-// SI_GOSPEL = 109,
- SI_ASSUMPTIO = 110,
-// SI_BASILICA = 111,
- SI_GROUNDMAGIC = 112,
- SI_MAGICPOWER = 113,
- SI_EDP = 114,
- SI_TRUESIGHT = 115,
- SI_WINDWALK = 116,
- SI_MELTDOWN = 117,
- SI_CARTBOOST = 118,
-// SI_CHASEWALK = 119,
- SI_SWORDREJECT = 120,
- SI_MARIONETTE_MASTER = 121,
- SI_MARIONETTE = 122,
- SI_MOON = 123,
- SI_BLOODING = 124,
- SI_JOINTBEAT = 125,
-// SI_MINDBREAKER = 126,
-// SI_MEMORIZE = 127,
-// SI_FOGWALL = 128,
-// SI_SPIDERWEB = 129,
- SI_PROTECTEXP = 130,
-// SI_SUB_WEAPONPROPERTY = 131,
- SI_AUTOBERSERK = 132,
- SI_RUN = 133,
- SI_TING = 134,
- SI_STORMKICK_ON = 135,
- SI_STORMKICK_READY = 136,
- SI_DOWNKICK_ON = 137,
- SI_DOWNKICK_READY = 138,
- SI_TURNKICK_ON = 139,
- SI_TURNKICK_READY = 140,
- SI_COUNTER_ON = 141,
- SI_COUNTER_READY = 142,
- SI_DODGE_ON = 143,
- SI_DODGE_READY = 144,
- SI_STRUP = 145,
- SI_PROPERTYDARK = 146,
- SI_ADRENALINE2 = 147,
- SI_PROPERTYTELEKINESIS = 148,
- SI_SOULLINK = 149,
- SI_PLUSATTACKPOWER = 150,
- SI_PLUSMAGICPOWER = 151,
- SI_DEVIL1 = 152,
- SI_KAITE = 153,
-// SI_SWOO = 154,
-// SI_STAR2 = 155,
- SI_KAIZEL = 156,
- SI_KAAHI = 157,
- SI_KAUPE = 158,
- SI_SMA_READY = 159,
- SI_SKE = 160,
- SI_ONEHANDQUICKEN = 161,
-// SI_FRIEND = 162,
-// SI_FRIENDUP = 163,
-// SI_SG_WARM = 164,
- SI_SG_SUN_WARM = 165,
-// 166 | The three show the exact same display: ultra red character (165, 166, 167)
-// 167 | Their names would be SI_SG_SUN_WARM, SI_SG_MOON_WARM, SI_SG_STAR_WARM
-// SI_EMOTION = 168,
- SI_SUN_COMFORT = 169,
- SI_MOON_COMFORT = 170,
- SI_STAR_COMFORT = 171,
-// SI_EXPUP = 172,
-// SI_GDSKILL_BATTLEORDER = 173,
-// SI_GDSKILL_REGENERATION = 174,
-// SI_GDSKILL_POSTDELAY = 175,
-// SI_RESISTHANDICAP = 176,
-// SI_MAXHPPERCENT = 177,
-// SI_MAXSPPERCENT = 178,
-// SI_DEFENCE = 179,
-// SI_SLOWDOWN = 180,
- SI_PRESERVE = 181,
- SI_INCSTR = 182,
-// SI_NOT_EXTREMITYFIST = 183,
- SI_CLAIRVOYANCE = 184,
-// SI_MOVESLOW_POTION = 185,
- SI_DOUBLECASTING = 186,
-// SI_GRAVITATION = 187,
- SI_OVERTHRUSTMAX = 188,
-// SI_LONGING = 189,
-// SI_HERMODE = 190,
- SI_TAROTCARD = 191, // the icon allows no doubt... but what is it really used for ?? [DracoRPG]
-// SI_HLIF_AVOID = 192,
-// SI_HFLI_FLEET = 193,
-// SI_HFLI_SPEED = 194,
-// SI_HLIF_CHANGE = 195,
-// SI_HAMI_BLOODLUST = 196,
- SI_CR_SHRINK = 197,
- SI_WZ_SIGHTBLASTER = 198,
- SI_DC_WINKCHARM = 199,
- SI_RG_CCONFINE_M = 200,
- SI_RG_CCONFINE_S = 201,
-// SI_DISABLEMOVE = 202,
- SI_GS_MADNESSCANCEL = 203, //[blackhole89]
- SI_GS_GATLINGFEVER = 204,
- SI_EARTHSCROLL = 205,
- SI_NJ_UTSUSEMI = 206,
- SI_NJ_BUNSINJYUTSU = 207,
- SI_NJ_NEN = 208,
- SI_GS_ADJUSTMENT = 209,
- SI_GS_ACCURACY = 210,
- SI_NJ_SUITON = 211,
-// SI_PET = 212,
-// SI_MENTAL = 213,
-// SI_EXPMEMORY = 214,
-// SI_PERFORMANCE = 215,
-// SI_GAIN = 216,
-// SI_GRIFFON = 217,
-// SI_DRIFT = 218,
-// SI_WALLSHIFT = 219,
-// SI_REINCARNATION = 220,
-// SI_PATTACK = 221,
-// SI_PSPEED = 222,
-// SI_PDEFENSE = 223,
-// SI_PCRITICAL = 224,
-// SI_RANKING = 225,
-// SI_PTRIPLE = 226,
-// SI_DENERGY = 227,
-// SI_WAVE1 = 228,
-// SI_WAVE2 = 229,
-// SI_WAVE3 = 230,
-// SI_WAVE4 = 231,
-// SI_DAURA = 232,
-// SI_DFREEZER = 233,
-// SI_DPUNISH = 234,
-// SI_DBARRIER = 235,
-// SI_DWARNING = 236,
-// SI_MOUSEWHEEL = 237,
-// SI_DGAUGE = 238,
-// SI_DACCEL = 239,
-// SI_DBLOCK = 240,
- SI_FOOD_STR = 241,
- SI_FOOD_AGI = 242,
- SI_FOOD_VIT = 243,
- SI_FOOD_DEX = 244,
- SI_FOOD_INT = 245,
- SI_FOOD_LUK = 246,
- SI_FOOD_BASICAVOIDANCE = 247,
- SI_FOOD_BASICHIT = 248,
- SI_FOOD_CRITICALSUCCESSVALUE = 249,
- SI_CASH_PLUSEXP = 250,
- SI_CASH_DEATHPENALTY = 251,
- SI_CASH_RECEIVEITEM = 252,
- SI_CASH_BOSS_ALARM = 253,
-// SI_DA_ENERGY = 254,
-// SI_DA_FIRSTSLOT = 255,
-// SI_DA_HEADDEF = 256,
-// SI_DA_SPACE = 257,
-// SI_DA_TRANSFORM = 258,
-// SI_DA_ITEMREBUILD = 259,
-// SI_DA_ILLUSION = 260, //All mobs display as Turtle General
-// SI_DA_DARKPOWER = 261,
-// SI_DA_EARPLUG = 262,
-// SI_DA_CONTRACT = 263, //Bio Mob effect on you and SI_TRICKDEAD icon
-// SI_DA_BLACK = 264, //For short time blurry screen
-// SI_DA_MAGICCART = 265,
-// SI_CRYSTAL = 266,
-// SI_DA_REBUILD = 267,
-// SI_DA_EDARKNESS = 268,
-// SI_DA_EGUARDIAN = 269,
-// SI_DA_TIMEOUT = 270,
- SI_FOOD_STR_CASH = 271,
- SI_FOOD_AGI_CASH = 272,
- SI_FOOD_VIT_CASH = 273,
- SI_FOOD_DEX_CASH = 274,
- SI_FOOD_INT_CASH = 275,
- SI_FOOD_LUK_CASH = 276,
- SI_MER_FLEE = 277,
- SI_MER_ATK = 278,
- SI_MER_HP = 279,
- SI_MER_SP = 280,
- SI_MER_HIT = 281,
- SI_SLOWCAST = 282,
-// SI_MAGICMIRROR = 283,
-// SI_STONESKIN = 284,
-// SI_ANTIMAGIC = 285,
- SI_CRITICALWOUND = 286,
-// SI_NPC_DEFENDER = 287,
-// SI_NOACTION_WAIT = 288,
- SI_MOVHASTE_HORSE = 289,
- SI_PROTECT_DEF = 290,
- SI_PROTECT_MDEF = 291,
- SI_HEALPLUS = 292,
- SI_S_LIFEPOTION = 293,
- SI_L_LIFEPOTION = 294,
- SI_CRITICALPERCENT = 295,
- SI_PLUSAVOIDVALUE = 296,
-// SI_ATKER_ASPD = 297,
-// SI_TARGET_ASPD = 298,
-// SI_ATKER_MOVESPEED = 299,
- SI_ATKER_BLOOD = 300,
- SI_TARGET_BLOOD = 301,
- SI_ARMOR_PROPERTY = 302,
-// SI_REUSE_LIMIT_A = 303,
- SI_HELLPOWER = 304,
-// SI_STEAMPACK = 305,
-// SI_REUSE_LIMIT_B = 306,
-// SI_REUSE_LIMIT_C = 307,
-// SI_REUSE_LIMIT_D = 308,
-// SI_REUSE_LIMIT_E = 309,
-// SI_REUSE_LIMIT_F = 310,
- SI_INVINCIBLE = 311,
- SI_CASH_PLUSONLYJOBEXP = 312,
- SI_PARTYFLEE = 313,
-// SI_ANGEL_PROTECT = 314,
-// SI_ENDURE_MDEF = 315,
- SI_ENCHANTBLADE = 316,
- SI_DEATHBOUND = 317,
- SI_REFRESH = 318,
- SI_GIANTGROWTH = 319,
- SI_STONEHARDSKIN = 320,
- SI_VITALITYACTIVATION = 321,
- SI_FIGHTINGSPIRIT = 322,
- SI_ABUNDANCE = 323,
- SI_REUSE_MILLENNIUMSHIELD = 324,
- SI_REUSE_CRUSHSTRIKE = 325,
- SI_REUSE_REFRESH = 326,
- SI_REUSE_STORMBLAST = 327,
- SI_VENOMIMPRESS = 328,
- SI_EPICLESIS = 329,
- SI_ORATIO = 330,
- SI_LAUDAAGNUS = 331,
- SI_LAUDARAMUS = 332,
- SI_CLOAKINGEXCEED = 333,
- SI_HALLUCINATIONWALK = 334,
- SI_HALLUCINATIONWALK_POSTDELAY = 335,
- SI_RENOVATIO = 336,
- SI_WEAPONBLOCKING = 337,
- SI_WEAPONBLOCKING_POSTDELAY = 338,
- SI_ROLLINGCUTTER = 339,
- SI_EXPIATIO = 340,
- SI_POISONINGWEAPON = 341,
- SI_TOXIN = 342,
- SI_PARALYSE = 343,
- SI_VENOMBLEED = 344,
- SI_MAGICMUSHROOM = 345,
- SI_DEATHHURT = 346,
- SI_PYREXIA = 347,
- SI_OBLIVIONCURSE = 348,
- SI_LEECHESEND = 349,
- SI_DUPLELIGHT = 350,
- SI_FROSTMISTY = 351,
- SI_FEARBREEZE = 352,
- SI_ELECTRICSHOCKER = 353,
- SI_MARSHOFABYSS = 354,
- SI_RECOGNIZEDSPELL = 355,
- SI_STASIS = 356,
- SI_WUGRIDER = 357,
- SI_WUGDASH = 358,
- SI_WUGBITE = 359,
- SI_CAMOUFLAGE = 360,
- SI_ACCELERATION = 361,
- SI_HOVERING = 362,
- SI_SPHERE_1 = 363,
- SI_SPHERE_2 = 364,
- SI_SPHERE_3 = 365,
- SI_SPHERE_4 = 366,
- SI_SPHERE_5 = 367,
- SI_MVPCARD_TAOGUNKA = 368,
- SI_MVPCARD_MISTRESS = 369,
- SI_MVPCARD_ORCHERO = 370,
- SI_MVPCARD_ORCLORD = 371,
- SI_OVERHEAT_LIMITPOINT = 372,
- SI_OVERHEAT = 373,
- SI_SHAPESHIFT = 374,
- SI_INFRAREDSCAN = 375,
- SI_MAGNETICFIELD = 376,
- SI_NEUTRALBARRIER = 377,
- SI_NEUTRALBARRIER_MASTER = 378,
- SI_STEALTHFIELD = 379,
- SI_STEALTHFIELD_MASTER = 380,
- SI_MANU_ATK = 381,
- SI_MANU_DEF = 382,
- SI_SPL_ATK = 383,
- SI_SPL_DEF = 384,
- SI_REPRODUCE = 385,
- SI_MANU_MATK = 386,
- SI_SPL_MATK = 387,
- SI_STR_SCROLL = 388,
- SI_INT_SCROLL = 389,
- SI_LG_REFLECTDAMAGE = 390,
- SI_FORCEOFVANGUARD = 391,
- SI_BUCHEDENOEL = 392,
- SI_AUTOSHADOWSPELL = 393,
- SI_SHADOWFORM = 394,
- SI_RAID = 395,
- SI_SHIELDSPELL_DEF = 396,
- SI_SHIELDSPELL_MDEF = 397,
- SI_SHIELDSPELL_REF = 398,
- SI_BODYPAINT = 399,
- SI_EXEEDBREAK = 400,
- SI_ADORAMUS = 401,
- SI_PRESTIGE = 402,
- SI_INVISIBILITY = 403,
- SI_DEADLYINFECT = 404,
- SI_BANDING = 405,
- SI_EARTHDRIVE = 406,
- SI_INSPIRATION = 407,
- SI_ENERVATION = 408,
- SI_GROOMY = 409,
- SI_RAISINGDRAGON = 410,
- SI_IGNORANCE = 411,
- SI_LAZINESS = 412,
- SI_LIGHTNINGWALK = 413,
- SI_ACARAJE = 414,
- SI_UNLUCKY = 415,
- SI_CURSEDCIRCLE_ATKER = 416,
- SI_CURSEDCIRCLE_TARGET = 417,
- SI_WEAKNESS = 418,
- SI_CRESCENTELBOW = 419,
- SI_NOEQUIPACCESSARY = 420,
- SI_STRIPACCESSARY = 421,
- SI_MANHOLE = 422,
- SI_POPECOOKIE = 423,
- SI_FALLENEMPIRE = 424,
- SI_GENTLETOUCH_ENERGYGAIN = 425,
- SI_GENTLETOUCH_CHANGE = 426,
- SI_GENTLETOUCH_REVITALIZE = 427,
- SI_BLOODYLUST = 428,
- SI_SWINGDANCE = 429,
- SI_SYMPHONYOFLOVERS = 430,
- SI_PROPERTYWALK = 431,
- SI_SPELLFIST = 432,
- SI_NETHERWORLD = 433,
- SI_SIREN = 434,
- SI_DEEPSLEEP = 435,
- SI_SIRCLEOFNATURE = 436,
- SI_COLD = 437,
- SI_GLOOMYDAY = 438,
- SI_SONG_OF_MANA = 439,
- SI_CLOUDKILL = 440,
- SI_DANCEWITHWUG = 441,
- SI_RUSHWINDMILL = 442,
- SI_ECHOSONG = 443,
- SI_HARMONIZE = 444,
- SI_STRIKING = 445,
- SI_WARMER = 446,
- SI_MOONLITSERENADE = 447,
- SI_SATURDAYNIGHTFEVER = 448,
- SI_SITDOWN_FORCE = 449,
- SI_ANALYZE = 450,
- SI_LERADSDEW = 451,
- SI_MELODYOFSINK = 452,
- SI_WARCRYOFBEYOND = 453,
- SI_UNLIMITEDHUMMINGVOICE = 454,
- SI_SPELLBOOK1 = 455,
- SI_SPELLBOOK2 = 456,
- SI_SPELLBOOK3 = 457,
- SI_FREEZE_SP = 458,
- SI_GN_TRAINING_SWORD = 459,
- SI_GN_REMODELING_CART = 460,
- SI_CARTSBOOST = 461,
- SI_FIXEDCASTINGTM_REDUCE = 462,
- SI_THORNTRAP = 463,
- SI_BLOODSUCKER = 464,
- SI_SPORE_EXPLOSION = 465,
- SI_DEMONIC_FIRE = 466,
- SI_FIRE_EXPANSION_SMOKE_POWDER = 467,
- SI_FIRE_EXPANSION_TEAR_GAS = 468,
- SI_BLOCKING_PLAY = 469,
- SI_MANDRAGORA = 470,
- SI_ACTIVATE = 471,
- SI_SECRAMENT = 472,
- SI_ASSUMPTIO2 = 473,
- SI_TK_SEVENWIND = 474,
- SI_LIMIT_ODINS_RECALL = 475,
- SI_STOMACHACHE = 476,
- SI_MYSTERIOUS_POWDER = 477,
- SI_MELON_BOMB = 478,
- SI_BANANA_BOMB_SITDOWN_POSTDELAY = 479,
- SI_PROMOTE_HEALTH_RESERCH = 480,
- SI_ENERGY_DRINK_RESERCH = 481,
- SI_EXTRACT_WHITE_POTION_Z = 482,
- SI_VITATA_500 = 483,
- SI_EXTRACT_SALAMINE_JUICE = 484,
- SI_BOOST500 = 485,
- SI_FULL_SWING_K = 486,
- SI_MANA_PLUS = 487,
- SI_MUSTLE_M = 488,
- SI_LIFE_FORCE_F = 489,
- SI_VACUUM_EXTREME = 490,
- SI_SAVAGE_STEAK = 491,
- SI_COCKTAIL_WARG_BLOOD = 492,
- SI_MINOR_BBQ = 493,
- SI_SIROMA_ICE_TEA = 494,
- SI_DROCERA_HERB_STEAMED = 495,
- SI_PUTTI_TAILS_NOODLES = 496,
- SI_BANANA_BOMB = 497,
- SI_SUMMON_AGNI = 498,
- SI_SPELLBOOK4 = 499,
- SI_SPELLBOOK5 = 500,
- SI_SPELLBOOK6 = 501,
- SI_SPELLBOOK7 = 502,
- SI_ELEMENTAL_AGGRESSIVE = 503,
- SI_RETURN_TO_ELDICASTES = 504,
- SI_BANDING_DEFENCE = 505,
- SI_SKELSCROLL = 506,
- SI_DISTRUCTIONSCROLL = 507,
- SI_ROYALSCROLL = 508,
- SI_IMMUNITYSCROLL = 509,
- SI_MYSTICSCROLL = 510,
- SI_BATTLESCROLL = 511,
- SI_ARMORSCROLL = 512,
- SI_FREYJASCROLL = 513,
- SI_SOULSCROLL = 514,
- SI_CIRCLE_OF_FIRE = 515,
- SI_CIRCLE_OF_FIRE_OPTION = 516,
- SI_FIRE_CLOAK = 517,
- SI_FIRE_CLOAK_OPTION = 518,
- SI_WATER_SCREEN = 519,
- SI_WATER_SCREEN_OPTION = 520,
- SI_WATER_DROP = 521,
- SI_WATER_DROP_OPTION = 522,
- SI_WIND_STEP = 523,
- SI_WIND_STEP_OPTION = 524,
- SI_WIND_CURTAIN = 525,
- SI_WIND_CURTAIN_OPTION = 526,
- SI_WATER_BARRIER = 527,
- SI_ZEPHYR = 528,
- SI_SOLID_SKIN = 529,
- SI_SOLID_SKIN_OPTION = 530,
- SI_STONE_SHIELD = 531,
- SI_STONE_SHIELD_OPTION = 532,
- SI_POWER_OF_GAIA = 533,
- // SI_EL_WAIT = 534,
- // SI_EL_PASSIVE = 535,
- // SI_EL_DEFENSIVE = 536,
- // SI_EL_OFFENSIVE = 537,
- // SI_EL_COST = 538,
- SI_PYROTECHNIC = 539,
- SI_PYROTECHNIC_OPTION = 540,
- SI_HEATER = 541,
- SI_HEATER_OPTION = 542,
- SI_TROPIC = 543,
- SI_TROPIC_OPTION = 544,
- SI_AQUAPLAY = 545,
- SI_AQUAPLAY_OPTION = 546,
- SI_COOLER = 547,
- SI_COOLER_OPTION = 548,
- SI_CHILLY_AIR = 549,
- SI_CHILLY_AIR_OPTION = 550,
- SI_GUST = 551,
- SI_GUST_OPTION = 552,
- SI_BLAST = 553,
- SI_BLAST_OPTION = 554,
- SI_WILD_STORM = 555,
- SI_WILD_STORM_OPTION = 556,
- SI_PETROLOGY = 557,
- SI_PETROLOGY_OPTION = 558,
- SI_CURSED_SOIL = 559,
- SI_CURSED_SOIL_OPTION = 560,
- SI_UPHEAVAL = 561,
- SI_UPHEAVAL_OPTION = 562,
- SI_TIDAL_WEAPON = 563,
- SI_TIDAL_WEAPON_OPTION = 564,
- SI_ROCK_CRUSHER = 565,
- SI_ROCK_CRUSHER_ATK = 566,
- SI_FIRE_INSIGNIA = 567,
- SI_WATER_INSIGNIA = 568,
- SI_WIND_INSIGNIA = 569,
- SI_EARTH_INSIGNIA = 570,
- SI_EQUIPED_FLOOR = 571,
- SI_GUARDIAN_RECALL = 572,
- SI_MORA_BUFF = 573,
- SI_REUSE_LIMIT_G = 574,
- SI_REUSE_LIMIT_H = 575,
- SI_NEEDLE_OF_PARALYZE = 576,
- SI_PAIN_KILLER = 577,
- SI_G_LIFEPOTION = 578,
- SI_VITALIZE_POTION = 579,
- SI_LIGHT_OF_REGENE = 580,
- SI_OVERED_BOOST = 581,
- SI_SILENT_BREEZE = 582,
- SI_ODINS_POWER = 583,
- SI_STYLE_CHANGE = 584,
- SI_SONIC_CLAW_POSTDELAY = 585,
+ SI_BLANK = -1,
+
+ SI_PROVOKE = 0,
+ SI_ENDURE = 1,
+ SI_TWOHANDQUICKEN = 2,
+ SI_CONCENTRATION = 3,
+ SI_HIDING = 4,
+ SI_CLOAKING = 5,
+ SI_ENCHANTPOISON = 6,
+ SI_POISONREACT = 7,
+ SI_QUAGMIRE = 8,
+ SI_ANGELUS = 9,
+ SI_BLESSING = 10,
+ SI_CRUCIS = 11,
+ SI_INC_AGI = 12,
+ SI_DEC_AGI = 13,
+ SI_SLOWPOISON = 14,
+ SI_IMPOSITIO = 15,
+ SI_SUFFRAGIUM = 16,
+ SI_ASPERSIO = 17,
+ SI_BENEDICTIO = 18,
+ SI_KYRIE = 19,
+ SI_MAGNIFICAT = 20,
+ SI_GLORIA = 21,
+ SI_LEXAETERNA = 22,
+ SI_ADRENALINE = 23,
+ SI_WEAPONPERFECT = 24,
+ SI_OVERTHRUST = 25,
+ SI_MAXIMIZE = 26,
+ SI_RIDING = 27,
+ SI_FALCON = 28,
+ SI_TRICKDEAD = 29,
+ SI_SHOUT = 30,
+ SI_ENERGYCOAT = 31,
+ SI_BROKENARMOR = 32,
+ SI_BROKENWEAPON = 33,
+ SI_ILLUSION = 34,
+ SI_WEIGHTOVER50 = 35,
+ SI_WEIGHTOVER90 = 36,
+ SI_ATTHASTE_POTION1 = 37,
+ SI_ATTHASTE_POTION2 = 38,
+ SI_ATTHASTE_POTION3 = 39,
+ SI_ATTHASTE_INFINITY = 40,
+ SI_MOVHASTE_POTION = 41,
+ SI_MOVHASTE_INFINITY = 42,
+ //SI_AUTOCOUNTER = 43,
+ //SI_SPLASHER = 44,
+ SI_ANKLESNARE = 45,
+ SI_POSTDELAY = 46,
+ //SI_NOACTION = 47,
+ //SI_IMPOSSIBLEPICKUP = 48,
+ //SI_BARRIER = 49,
+
+ SI_NOEQUIPWEAPON = 50,
+ SI_NOEQUIPSHIELD = 51,
+ SI_NOEQUIPARMOR = 52,
+ SI_NOEQUIPHELM = 53,
+ SI_PROTECTWEAPON = 54,
+ SI_PROTECTSHIELD = 55,
+ SI_PROTECTARMOR = 56,
+ SI_PROTECTHELM = 57,
+ SI_AUTOGUARD = 58,
+ SI_REFLECTSHIELD = 59,
+ //SI_DEVOTION = 60,
+ SI_PROVIDENCE = 61,
+ SI_DEFENDER = 62,
+ //SI_MAGICROD = 63,
+ //SI_WEAPONPROPERTY = 64,
+ SI_AUTOSPELL = 65,
+ //SI_SPECIALZONE = 66,
+ //SI_MASK = 67,
+ SI_SPEARQUICKEN = 68,
+ //SI_BDPLAYING = 69,
+ //SI_WHISTLE = 70,
+ //SI_ASSASSINCROSS = 71,
+ //SI_POEMBRAGI = 72,
+ //SI_APPLEIDUN = 73,
+ //SI_HUMMING = 74,
+ //SI_DONTFORGETME = 75,
+ //SI_FORTUNEKISS = 76,
+ //SI_SERVICEFORYOU = 77,
+ //SI_RICHMANKIM = 78,
+ //SI_ETERNALCHAOS = 79,
+ //SI_DRUMBATTLEFIELD = 80,
+ //SI_RINGNIBELUNGEN = 81,
+ //SI_ROKISWEIL = 82,
+ //SI_INTOABYSS = 83,
+ //SI_SIEGFRIED = 84,
+ //SI_BLADESTOP = 85,
+ SI_EXPLOSIONSPIRITS = 86,
+ SI_STEELBODY = 87,
+ SI_EXTREMITYFIST = 88,
+ //SI_COMBOATTACK = 89,
+ SI_PROPERTYFIRE = 90,
+ SI_PROPERTYWATER = 91,
+ SI_PROPERTYWIND = 92,
+ SI_PROPERTYGROUND = 93,
+ //SI_MAGICATTACK = 94,
+ SI_STOP = 95,
+ //SI_WEAPONBRAKER = 96,
+ SI_PROPERTYUNDEAD = 97,
+ //SI_POWERUP = 98,
+ //SI_AGIUP = 99,
+
+ //SI_SIEGEMODE = 100,
+ //SI_INVISIBLE = 101,
+ //SI_STATUSONE = 102,
+ SI_AURABLADE = 103,
+ SI_PARRYING = 104,
+ SI_LKCONCENTRATION = 105,
+ SI_TENSIONRELAX = 106,
+ SI_BERSERK = 107,
+ //SI_SACRIFICE = 108,
+ //SI_GOSPEL = 109,
+ SI_ASSUMPTIO = 110,
+ //SI_BASILICA = 111,
+ SI_GROUNDMAGIC = 112,
+ SI_MAGICPOWER = 113,
+ SI_EDP = 114,
+ SI_TRUESIGHT = 115,
+ SI_WINDWALK = 116,
+ SI_MELTDOWN = 117,
+ SI_CARTBOOST = 118,
+ //SI_CHASEWALK = 119,
+ SI_SWORDREJECT = 120,
+ SI_MARIONETTE_MASTER = 121,
+ SI_MARIONETTE = 122,
+ SI_MOON = 123,
+ SI_BLOODING = 124,
+ SI_JOINTBEAT = 125,
+ //SI_MINDBREAKER = 126,
+ //SI_MEMORIZE = 127,
+ //SI_FOGWALL = 128,
+ //SI_SPIDERWEB = 129,
+ SI_PROTECTEXP = 130,
+ //SI_SUB_WEAPONPROPERTY = 131,
+ SI_AUTOBERSERK = 132,
+ SI_RUN = 133,
+ SI_TING = 134,
+ SI_STORMKICK_ON = 135,
+ SI_STORMKICK_READY = 136,
+ SI_DOWNKICK_ON = 137,
+ SI_DOWNKICK_READY = 138,
+ SI_TURNKICK_ON = 139,
+ SI_TURNKICK_READY = 140,
+ SI_COUNTER_ON = 141,
+ SI_COUNTER_READY = 142,
+ SI_DODGE_ON = 143,
+ SI_DODGE_READY = 144,
+ SI_STRUP = 145,
+ SI_PROPERTYDARK = 146,
+ SI_ADRENALINE2 = 147,
+ SI_PROPERTYTELEKINESIS = 148,
+ SI_SOULLINK = 149,
+
+ SI_PLUSATTACKPOWER = 150,
+ SI_PLUSMAGICPOWER = 151,
+ SI_DEVIL1 = 152,
+ SI_KAITE = 153,
+ //SI_SWOO = 154,
+ //SI_STAR2 = 155,
+ SI_KAIZEL = 156,
+ SI_KAAHI = 157,
+ SI_KAUPE = 158,
+ SI_SMA_READY = 159,
+ SI_SKE = 160,
+ SI_ONEHANDQUICKEN = 161,
+ //SI_FRIEND = 162,
+ //SI_FRIENDUP = 163,
+ //SI_SG_WARM = 164,
+ SI_SG_SUN_WARM = 165,
+ //SI_SG_MOON_WARM = 166 | The three show the exact same display: ultra red character (165, 166, 167)
+ //SI_SG_STAR_WARM = 167 | Their names would be SI_SG_SUN_WARM, SI_SG_MOON_WARM, SI_SG_STAR_WARM
+ //SI_EMOTION = 168,
+ SI_SUN_COMFORT = 169,
+ SI_MOON_COMFORT = 170,
+ SI_STAR_COMFORT = 171,
+ //SI_EXPUP = 172,
+ //SI_GDSKILL_BATTLEORDER = 173,
+ //SI_GDSKILL_REGENERATION = 174,
+ //SI_GDSKILL_POSTDELAY = 175,
+ //SI_RESISTHANDICAP = 176,
+ //SI_MAXHPPERCENT = 177,
+ //SI_MAXSPPERCENT = 178,
+ //SI_DEFENCE = 179,
+ //SI_SLOWDOWN = 180,
+ SI_PRESERVE = 181,
+ SI_INCSTR = 182,
+ //SI_NOT_EXTREMITYFIST = 183,
+ SI_CLAIRVOYANCE = 184,
+ //SI_MOVESLOW_POTION = 185,
+ SI_DOUBLECASTING = 186,
+ //SI_GRAVITATION = 187,
+ SI_OVERTHRUSTMAX = 188,
+ //SI_LONGING = 189,
+ //SI_HERMODE = 190,
+ SI_TAROTCARD = 191, // the icon allows no doubt... but what is it really used for ?? [DracoRPG]
+ //SI_HLIF_AVOID = 192,
+ //SI_HFLI_FLEET = 193,
+ //SI_HFLI_SPEED = 194,
+ //SI_HLIF_CHANGE = 195,
+ //SI_HAMI_BLOODLUST = 196,
+ SI_CR_SHRINK = 197,
+ SI_WZ_SIGHTBLASTER = 198,
+ SI_DC_WINKCHARM = 199,
+
+ SI_RG_CCONFINE_M = 200,
+ SI_RG_CCONFINE_S = 201,
+ //SI_DISABLEMOVE = 202,
+ SI_GS_MADNESSCANCEL = 203, //[blackhole89]
+ SI_GS_GATLINGFEVER = 204,
+ SI_EARTHSCROLL = 205,
+ SI_NJ_UTSUSEMI = 206,
+ SI_NJ_BUNSINJYUTSU = 207,
+ SI_NJ_NEN = 208,
+ SI_GS_ADJUSTMENT = 209,
+ SI_GS_ACCURACY = 210,
+ SI_NJ_SUITON = 211,
+ //SI_PET = 212,
+ //SI_MENTAL = 213,
+ //SI_EXPMEMORY = 214,
+ //SI_PERFORMANCE = 215,
+ //SI_GAIN = 216,
+ //SI_GRIFFON = 217,
+ //SI_DRIFT = 218,
+ //SI_WALLSHIFT = 219,
+ //SI_REINCARNATION = 220,
+ //SI_PATTACK = 221,
+ //SI_PSPEED = 222,
+ //SI_PDEFENSE = 223,
+ //SI_PCRITICAL = 224,
+ //SI_RANKING = 225,
+ //SI_PTRIPLE = 226,
+ //SI_DENERGY = 227,
+ //SI_WAVE1 = 228,
+ //SI_WAVE2 = 229,
+ //SI_WAVE3 = 230,
+ //SI_WAVE4 = 231,
+ //SI_DAURA = 232,
+ //SI_DFREEZER = 233,
+ //SI_DPUNISH = 234,
+ //SI_DBARRIER = 235,
+ //SI_DWARNING = 236,
+ //SI_MOUSEWHEEL = 237,
+ //SI_DGAUGE = 238,
+ //SI_DACCEL = 239,
+ //SI_DBLOCK = 240,
+ SI_FOOD_STR = 241,
+ SI_FOOD_AGI = 242,
+ SI_FOOD_VIT = 243,
+ SI_FOOD_DEX = 244,
+ SI_FOOD_INT = 245,
+ SI_FOOD_LUK = 246,
+ SI_FOOD_BASICAVOIDANCE = 247,
+ SI_FOOD_BASICHIT = 248,
+ SI_FOOD_CRITICALSUCCESSVALUE = 249,
+
+ SI_CASH_PLUSEXP = 250,
+ SI_CASH_DEATHPENALTY = 251,
+ SI_CASH_RECEIVEITEM = 252,
+ SI_CASH_BOSS_ALARM = 253,
+ //SI_DA_ENERGY = 254,
+ //SI_DA_FIRSTSLOT = 255,
+ //SI_DA_HEADDEF = 256,
+ //SI_DA_SPACE = 257,
+ //SI_DA_TRANSFORM = 258,
+ //SI_DA_ITEMREBUILD = 259,
+ //SI_DA_ILLUSION = 260, //All mobs display as Turtle General
+ //SI_DA_DARKPOWER = 261,
+ //SI_DA_EARPLUG = 262,
+ //SI_DA_CONTRACT = 263, //Bio Mob effect on you and SI_TRICKDEAD icon
+ //SI_DA_BLACK = 264, //For short time blurry screen
+ //SI_DA_MAGICCART = 265,
+ //SI_CRYSTAL = 266,
+ //SI_DA_REBUILD = 267,
+ //SI_DA_EDARKNESS = 268,
+ //SI_DA_EGUARDIAN = 269,
+ //SI_DA_TIMEOUT = 270,
+ SI_FOOD_STR_CASH = 271,
+ SI_FOOD_AGI_CASH = 272,
+ SI_FOOD_VIT_CASH = 273,
+ SI_FOOD_DEX_CASH = 274,
+ SI_FOOD_INT_CASH = 275,
+ SI_FOOD_LUK_CASH = 276,
+ SI_MER_FLEE = 277,
+ SI_MER_ATK = 278,
+ SI_MER_HP = 279,
+ SI_MER_SP = 280,
+ SI_MER_HIT = 281,
+ SI_SLOWCAST = 282,
+ //SI_MAGICMIRROR = 283,
+ //SI_STONESKIN = 284,
+ //SI_ANTIMAGIC = 285,
+ SI_CRITICALWOUND = 286,
+ //SI_NPC_DEFENDER = 287,
+ //SI_NOACTION_WAIT = 288,
+ SI_MOVHASTE_HORSE = 289,
+ SI_PROTECT_DEF = 290,
+ SI_PROTECT_MDEF = 291,
+ SI_HEALPLUS = 292,
+ SI_S_LIFEPOTION = 293,
+ SI_L_LIFEPOTION = 294,
+ SI_CRITICALPERCENT = 295,
+ SI_PLUSAVOIDVALUE = 296,
+ //SI_ATKER_ASPD = 297,
+ //SI_TARGET_ASPD = 298,
+ //SI_ATKER_MOVESPEED = 299,
+
+ SI_ATKER_BLOOD = 300,
+ SI_TARGET_BLOOD = 301,
+ SI_ARMOR_PROPERTY = 302,
+ //SI_REUSE_LIMIT_A = 303,
+ SI_HELLPOWER = 304,
+ //SI_STEAMPACK = 305,
+ //SI_REUSE_LIMIT_B = 306,
+ //SI_REUSE_LIMIT_C = 307,
+ //SI_REUSE_LIMIT_D = 308,
+ //SI_REUSE_LIMIT_E = 309,
+ //SI_REUSE_LIMIT_F = 310,
+ SI_INVINCIBLE = 311,
+ SI_CASH_PLUSONLYJOBEXP = 312,
+ SI_PARTYFLEE = 313,
+ SI_ANGEL_PROTECT = 314,
+ //SI_ENDURE_MDEF = 315,
+ SI_ENCHANTBLADE = 316,
+ SI_DEATHBOUND = 317,
+ SI_REFRESH = 318,
+ SI_GIANTGROWTH = 319,
+ SI_STONEHARDSKIN = 320,
+ SI_VITALITYACTIVATION = 321,
+ SI_FIGHTINGSPIRIT = 322,
+ SI_ABUNDANCE = 323,
+ SI_REUSE_MILLENNIUMSHIELD = 324,
+ SI_REUSE_CRUSHSTRIKE = 325,
+ SI_REUSE_REFRESH = 326,
+ SI_REUSE_STORMBLAST = 327,
+ SI_VENOMIMPRESS = 328,
+ SI_EPICLESIS = 329,
+ SI_ORATIO = 330,
+ SI_LAUDAAGNUS = 331,
+ SI_LAUDARAMUS = 332,
+ SI_CLOAKINGEXCEED = 333,
+ SI_HALLUCINATIONWALK = 334,
+ SI_HALLUCINATIONWALK_POSTDELAY = 335,
+ SI_RENOVATIO = 336,
+ SI_WEAPONBLOCKING = 337,
+ SI_WEAPONBLOCKING_POSTDELAY = 338,
+ SI_ROLLINGCUTTER = 339,
+ SI_EXPIATIO = 340,
+ SI_POISONINGWEAPON = 341,
+ SI_TOXIN = 342,
+ SI_PARALYSE = 343,
+ SI_VENOMBLEED = 344,
+ SI_MAGICMUSHROOM = 345,
+ SI_DEATHHURT = 346,
+ SI_PYREXIA = 347,
+ SI_OBLIVIONCURSE = 348,
+ SI_LEECHESEND = 349,
+
+ SI_DUPLELIGHT = 350,
+ SI_FROSTMISTY = 351,
+ SI_FEARBREEZE = 352,
+ SI_ELECTRICSHOCKER = 353,
+ SI_MARSHOFABYSS = 354,
+ SI_RECOGNIZEDSPELL = 355,
+ SI_STASIS = 356,
+ SI_WUGRIDER = 357,
+ SI_WUGDASH = 358,
+ SI_WUGBITE = 359,
+ SI_CAMOUFLAGE = 360,
+ SI_ACCELERATION = 361,
+ SI_HOVERING = 362,
+ SI_SPHERE_1 = 363,
+ SI_SPHERE_2 = 364,
+ SI_SPHERE_3 = 365,
+ SI_SPHERE_4 = 366,
+ SI_SPHERE_5 = 367,
+ SI_MVPCARD_TAOGUNKA = 368,
+ SI_MVPCARD_MISTRESS = 369,
+ SI_MVPCARD_ORCHERO = 370,
+ SI_MVPCARD_ORCLORD = 371,
+ SI_OVERHEAT_LIMITPOINT = 372,
+ SI_OVERHEAT = 373,
+ SI_SHAPESHIFT = 374,
+ SI_INFRAREDSCAN = 375,
+ SI_MAGNETICFIELD = 376,
+ SI_NEUTRALBARRIER = 377,
+ SI_NEUTRALBARRIER_MASTER = 378,
+ SI_STEALTHFIELD = 379,
+ SI_STEALTHFIELD_MASTER = 380,
+ SI_MANU_ATK = 381,
+ SI_MANU_DEF = 382,
+ SI_SPL_ATK = 383,
+ SI_SPL_DEF = 384,
+ SI_REPRODUCE = 385,
+ SI_MANU_MATK = 386,
+ SI_SPL_MATK = 387,
+ SI_STR_SCROLL = 388,
+ SI_INT_SCROLL = 389,
+ SI_LG_REFLECTDAMAGE = 390,
+ SI_FORCEOFVANGUARD = 391,
+ SI_BUCHEDENOEL = 392,
+ SI_AUTOSHADOWSPELL = 393,
+ SI_SHADOWFORM = 394,
+ SI_RAID = 395,
+ SI_SHIELDSPELL_DEF = 396,
+ SI_SHIELDSPELL_MDEF = 397,
+ SI_SHIELDSPELL_REF = 398,
+ SI_BODYPAINT = 399,
+
+ SI_EXEEDBREAK = 400,
+ SI_ADORAMUS = 401,
+ SI_PRESTIGE = 402,
+ SI_INVISIBILITY = 403,
+ SI_DEADLYINFECT = 404,
+ SI_BANDING = 405,
+ SI_EARTHDRIVE = 406,
+ SI_INSPIRATION = 407,
+ SI_ENERVATION = 408,
+ SI_GROOMY = 409,
+ SI_RAISINGDRAGON = 410,
+ SI_IGNORANCE = 411,
+ SI_LAZINESS = 412,
+ SI_LIGHTNINGWALK = 413,
+ SI_ACARAJE = 414,
+ SI_UNLUCKY = 415,
+ SI_CURSEDCIRCLE_ATKER = 416,
+ SI_CURSEDCIRCLE_TARGET = 417,
+ SI_WEAKNESS = 418,
+ SI_CRESCENTELBOW = 419,
+ SI_NOEQUIPACCESSARY = 420,
+ SI_STRIPACCESSARY = 421,
+ SI_MANHOLE = 422,
+ SI_POPECOOKIE = 423,
+ SI_FALLENEMPIRE = 424,
+ SI_GENTLETOUCH_ENERGYGAIN = 425,
+ SI_GENTLETOUCH_CHANGE = 426,
+ SI_GENTLETOUCH_REVITALIZE = 427,
+ SI_BLOODYLUST = 428,
+ SI_SWINGDANCE = 429,
+ SI_SYMPHONYOFLOVERS = 430,
+ SI_PROPERTYWALK = 431,
+ SI_SPELLFIST = 432,
+ SI_NETHERWORLD = 433,
+ SI_SIREN = 434,
+ SI_DEEPSLEEP = 435,
+ SI_SIRCLEOFNATURE = 436,
+ SI_COLD = 437,
+ SI_GLOOMYDAY = 438,
+ SI_SONG_OF_MANA = 439,
+ SI_CLOUDKILL = 440,
+ SI_DANCEWITHWUG = 441,
+ SI_RUSHWINDMILL = 442,
+ SI_ECHOSONG = 443,
+ SI_HARMONIZE = 444,
+ SI_STRIKING = 445,
+ SI_WARMER = 446,
+ SI_MOONLITSERENADE = 447,
+ SI_SATURDAYNIGHTFEVER = 448,
+ SI_SITDOWN_FORCE = 449,
+
+ SI_ANALYZE = 450,
+ SI_LERADSDEW = 451,
+ SI_MELODYOFSINK = 452,
+ SI_WARCRYOFBEYOND = 453,
+ SI_UNLIMITEDHUMMINGVOICE = 454,
+ SI_SPELLBOOK1 = 455,
+ SI_SPELLBOOK2 = 456,
+ SI_SPELLBOOK3 = 457,
+ SI_FREEZE_SP = 458,
+ SI_GN_TRAINING_SWORD = 459,
+ SI_GN_REMODELING_CART = 460,
+ SI_CARTSBOOST = 461,
+ SI_FIXEDCASTINGTM_REDUCE = 462,
+ SI_THORNTRAP = 463,
+ SI_BLOODSUCKER = 464,
+ SI_SPORE_EXPLOSION = 465,
+ SI_DEMONIC_FIRE = 466,
+ SI_FIRE_EXPANSION_SMOKE_POWDER = 467,
+ SI_FIRE_EXPANSION_TEAR_GAS = 468,
+ SI_BLOCKING_PLAY = 469,
+ SI_MANDRAGORA = 470,
+ SI_ACTIVATE = 471,
+ SI_SECRAMENT = 472,
+ SI_ASSUMPTIO2 = 473,
+ SI_TK_SEVENWIND = 474,
+ SI_LIMIT_ODINS_RECALL = 475,
+ SI_STOMACHACHE = 476,
+ SI_MYSTERIOUS_POWDER = 477,
+ SI_MELON_BOMB = 478,
+ SI_BANANA_BOMB_SITDOWN_POSTDELAY = 479,
+ SI_PROMOTE_HEALTH_RESERCH = 480,
+ SI_ENERGY_DRINK_RESERCH = 481,
+ SI_EXTRACT_WHITE_POTION_Z = 482,
+ SI_VITATA_500 = 483,
+ SI_EXTRACT_SALAMINE_JUICE = 484,
+ SI_BOOST500 = 485,
+ SI_FULL_SWING_K = 486,
+ SI_MANA_PLUS = 487,
+ SI_MUSTLE_M = 488,
+ SI_LIFE_FORCE_F = 489,
+ SI_VACUUM_EXTREME = 490,
+ SI_SAVAGE_STEAK = 491,
+ SI_COCKTAIL_WARG_BLOOD = 492,
+ SI_MINOR_BBQ = 493,
+ SI_SIROMA_ICE_TEA = 494,
+ SI_DROCERA_HERB_STEAMED = 495,
+ SI_PUTTI_TAILS_NOODLES = 496,
+ SI_BANANA_BOMB = 497,
+ SI_SUMMON_AGNI = 498,
+ SI_SPELLBOOK4 = 499,
+
+ SI_SPELLBOOK5 = 500,
+ SI_SPELLBOOK6 = 501,
+ SI_SPELLBOOK7 = 502,
+ SI_ELEMENTAL_AGGRESSIVE = 503,
+ SI_RETURN_TO_ELDICASTES = 504,
+ SI_BANDING_DEFENCE = 505,
+ SI_SKELSCROLL = 506,
+ SI_DISTRUCTIONSCROLL = 507,
+ SI_ROYALSCROLL = 508,
+ SI_IMMUNITYSCROLL = 509,
+ SI_MYSTICSCROLL = 510,
+ SI_BATTLESCROLL = 511,
+ SI_ARMORSCROLL = 512,
+ SI_FREYJASCROLL = 513,
+ SI_SOULSCROLL = 514,
+ SI_CIRCLE_OF_FIRE = 515,
+ SI_CIRCLE_OF_FIRE_OPTION = 516,
+ SI_FIRE_CLOAK = 517,
+ SI_FIRE_CLOAK_OPTION = 518,
+ SI_WATER_SCREEN = 519,
+ SI_WATER_SCREEN_OPTION = 520,
+ SI_WATER_DROP = 521,
+ SI_WATER_DROP_OPTION = 522,
+ SI_WIND_STEP = 523,
+ SI_WIND_STEP_OPTION = 524,
+ SI_WIND_CURTAIN = 525,
+ SI_WIND_CURTAIN_OPTION = 526,
+ SI_WATER_BARRIER = 527,
+ SI_ZEPHYR = 528,
+ SI_SOLID_SKIN = 529,
+ SI_SOLID_SKIN_OPTION = 530,
+ SI_STONE_SHIELD = 531,
+ SI_STONE_SHIELD_OPTION = 532,
+ SI_POWER_OF_GAIA = 533,
+ //SI_EL_WAIT = 534,
+ //SI_EL_PASSIVE = 535,
+ //SI_EL_DEFENSIVE = 536,
+ //SI_EL_OFFENSIVE = 537,
+ //SI_EL_COST = 538,
+ SI_PYROTECHNIC = 539,
+ SI_PYROTECHNIC_OPTION = 540,
+ SI_HEATER = 541,
+ SI_HEATER_OPTION = 542,
+ SI_TROPIC = 543,
+ SI_TROPIC_OPTION = 544,
+ SI_AQUAPLAY = 545,
+ SI_AQUAPLAY_OPTION = 546,
+ SI_COOLER = 547,
+ SI_COOLER_OPTION = 548,
+ SI_CHILLY_AIR = 549,
+
+ SI_CHILLY_AIR_OPTION = 550,
+ SI_GUST = 551,
+ SI_GUST_OPTION = 552,
+ SI_BLAST = 553,
+ SI_BLAST_OPTION = 554,
+ SI_WILD_STORM = 555,
+ SI_WILD_STORM_OPTION = 556,
+ SI_PETROLOGY = 557,
+ SI_PETROLOGY_OPTION = 558,
+ SI_CURSED_SOIL = 559,
+ SI_CURSED_SOIL_OPTION = 560,
+ SI_UPHEAVAL = 561,
+ SI_UPHEAVAL_OPTION = 562,
+ SI_TIDAL_WEAPON = 563,
+ SI_TIDAL_WEAPON_OPTION = 564,
+ SI_ROCK_CRUSHER = 565,
+ SI_ROCK_CRUSHER_ATK = 566,
+ SI_FIRE_INSIGNIA = 567,
+ SI_WATER_INSIGNIA = 568,
+ SI_WIND_INSIGNIA = 569,
+ SI_EARTH_INSIGNIA = 570,
+ SI_EQUIPED_FLOOR = 571,
+ SI_GUARDIAN_RECALL = 572,
+ SI_MORA_BUFF = 573,
+ SI_REUSE_LIMIT_G = 574,
+ SI_REUSE_LIMIT_H = 575,
+ SI_NEEDLE_OF_PARALYZE = 576,
+ SI_PAIN_KILLER = 577,
+ SI_G_LIFEPOTION = 578,
+ SI_VITALIZE_POTION = 579,
+ SI_LIGHT_OF_REGENE = 580,
+ SI_OVERED_BOOST = 581,
+ SI_SILENT_BREEZE = 582,
+ SI_ODINS_POWER = 583,
+ SI_STYLE_CHANGE = 584,
+ SI_SONIC_CLAW_POSTDELAY = 585,
// ID's 586 - 595 Currently Unused
- SI_SILVERVEIN_RUSH_POSTDELAY = 596,
- SI_MIDNIGHT_FRENZY_POSTDELAY = 597,
- SI_GOLDENE_FERSE = 598,
- SI_ANGRIFFS_MODUS = 599,
- SI_TINDER_BREAKER = 600,
- SI_TINDER_BREAKER_POSTDELAY = 601,
- SI_CBC = 602,
- SI_CBC_POSTDELAY = 603,
- SI_EQC = 604,
- SI_MAGMA_FLOW = 605,
- SI_GRANITIC_ARMOR = 606,
- SI_PYROCLASTIC = 607,
- SI_VOLCANIC_ASH = 608,
- SI_SPIRITS_SAVEINFO1 = 609,
- SI_SPIRITS_SAVEINFO2 = 610,
- SI_MAGIC_CANDY = 611,
- SI_SEARCH_STORE_INFO = 612,
- SI_ALL_RIDING = 613,
- SI_ALL_RIDING_REUSE_LIMIT = 614,
- SI_MACRO = 615,
- SI_MACRO_POSTDELAY = 616,
- SI_BEER_BOTTLE_CAP = 617,
- SI_OVERLAPEXPUP = 618,
- SI_PC_IZ_DUN05 = 619,
- SI_CRUSHSTRIKE = 620,
- SI_MONSTER_TRANSFORM = 621,
- SI_SIT = 622,
- SI_ONAIR = 623,
- SI_MTF_ASPD = 624,
- SI_MTF_RANGEATK = 625,
- SI_MTF_MATK = 626,
- SI_MTF_MLEATKED = 627,
- SI_MTF_CRIDAMAGE = 628,
- SI_REUSE_LIMIT_MTF = 629,
- SI_MACRO_PERMIT = 630,
- SI_MACRO_PLAY = 631,
- SI_SKF_CAST = 632,
- SI_SKF_ASPD = 633,
- SI_SKF_ATK = 634,
- SI_SKF_MATK = 635,
- SI_REWARD_PLUSONLYJOBEXP = 636,
- SI_HANDICAPSTATE_NORECOVER = 637,
- SI_SET_NUM_DEF = 638,
- SI_SET_NUM_MDEF = 639,
- SI_SET_PER_DEF = 640,
- SI_SET_PER_MDEF = 641,
- SI_PARTYBOOKING_SEARCH_DEALY = 642,
- SI_PARTYBOOKING_REGISTER_DEALY = 643,
- SI_PERIOD_TIME_CHECK_DETECT_SKILL = 644,
- SI_KO_JYUMONJIKIRI = 645,
- SI_MEIKYOUSISUI = 646,
- SI_ATTHASTE_CASH = 647,
- SI_EQUIPPED_DIVINE_ARMOR = 648,
- SI_EQUIPPED_HOLY_ARMOR = 649,
- SI_2011RWC = 650,
- SI_KYOUGAKU = 651,
- SI_IZAYOI = 652,
- SI_ZENKAI = 653,
- SI_KG_KAGEHUMI = 654,
- SI_KYOMU = 655,
- SI_KAGEMUSYA = 656,
- SI_ZANGETSU = 657,
- SI_PHI_DEMON = 658,
- SI_GENSOU = 659,
- SI_AKAITSUKI = 660,
- SI_TETANY = 661,
- SI_GM_BATTLE = 662,
- SI_GM_BATTLE2 = 663,
- SI_2011RWC_SCROLL = 664,
- SI_ACTIVE_MONSTER_TRANSFORM = 665,
- SI_MYSTICPOWDER = 666,
- SI_ECLAGE_RECALL = 667,
- SI_ENTRY_QUEUE_APPLY_DELAY = 668,
- SI_REUSE_LIMIT_ECL = 669,
- SI_M_LIFEPOTION = 670,
+ SI_SILVERVEIN_RUSH_POSTDELAY = 596,
+ SI_MIDNIGHT_FRENZY_POSTDELAY = 597,
+ SI_GOLDENE_FERSE = 598,
+ SI_ANGRIFFS_MODUS = 599,
+
+ SI_TINDER_BREAKER = 600,
+ SI_TINDER_BREAKER_POSTDELAY = 601,
+ SI_CBC = 602,
+ SI_CBC_POSTDELAY = 603,
+ SI_EQC = 604,
+ SI_MAGMA_FLOW = 605,
+ SI_GRANITIC_ARMOR = 606,
+ SI_PYROCLASTIC = 607,
+ SI_VOLCANIC_ASH = 608,
+ SI_SPIRITS_SAVEINFO1 = 609,
+ SI_SPIRITS_SAVEINFO2 = 610,
+ SI_MAGIC_CANDY = 611,
+ SI_SEARCH_STORE_INFO = 612,
+ SI_ALL_RIDING = 613,
+ SI_ALL_RIDING_REUSE_LIMIT = 614,
+ SI_MACRO = 615,
+ SI_MACRO_POSTDELAY = 616,
+ SI_BEER_BOTTLE_CAP = 617,
+ SI_OVERLAPEXPUP = 618,
+ SI_PC_IZ_DUN05 = 619,
+ SI_CRUSHSTRIKE = 620,
+ SI_MONSTER_TRANSFORM = 621,
+ SI_SIT = 622,
+ SI_ONAIR = 623,
+ SI_MTF_ASPD = 624,
+ SI_MTF_RANGEATK = 625,
+ SI_MTF_MATK = 626,
+ SI_MTF_MLEATKED = 627,
+ SI_MTF_CRIDAMAGE = 628,
+ SI_REUSE_LIMIT_MTF = 629,
+ SI_MACRO_PERMIT = 630,
+ SI_MACRO_PLAY = 631,
+ SI_SKF_CAST = 632,
+ SI_SKF_ASPD = 633,
+ SI_SKF_ATK = 634,
+ SI_SKF_MATK = 635,
+ SI_REWARD_PLUSONLYJOBEXP = 636,
+ SI_HANDICAPSTATE_NORECOVER = 637,
+ SI_SET_NUM_DEF = 638,
+ SI_SET_NUM_MDEF = 639,
+ SI_SET_PER_DEF = 640,
+ SI_SET_PER_MDEF = 641,
+ SI_PARTYBOOKING_SEARCH_DEALY = 642,
+ SI_PARTYBOOKING_REGISTER_DEALY = 643,
+ SI_PERIOD_TIME_CHECK_DETECT_SKILL = 644,
+ SI_KO_JYUMONJIKIRI = 645,
+ SI_MEIKYOUSISUI = 646,
+ SI_ATTHASTE_CASH = 647,
+ SI_EQUIPPED_DIVINE_ARMOR = 648,
+ SI_EQUIPPED_HOLY_ARMOR = 649,
+
+ SI_2011RWC = 650,
+ SI_KYOUGAKU = 651,
+ SI_IZAYOI = 652,
+ SI_ZENKAI = 653,
+ SI_KG_KAGEHUMI = 654,
+ SI_KYOMU = 655,
+ SI_KAGEMUSYA = 656,
+ SI_ZANGETSU = 657,
+ SI_PHI_DEMON = 658,
+ SI_GENSOU = 659,
+ SI_AKAITSUKI = 660,
+ SI_TETANY = 661,
+ SI_GM_BATTLE = 662,
+ SI_GM_BATTLE2 = 663,
+ SI_2011RWC_SCROLL = 664,
+ SI_ACTIVE_MONSTER_TRANSFORM = 665,
+ SI_MYSTICPOWDER = 666,
+ SI_ECLAGE_RECALL = 667,
+ SI_ENTRY_QUEUE_APPLY_DELAY = 668,
+ SI_REUSE_LIMIT_ECL = 669,
+ SI_M_LIFEPOTION = 670,
SI_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT = 671,
- SI_UNKNOWN_NAME = 672,
- SI_ON_PUSH_CART = 673,
- SI_HAT_EFFECT = 674,
- SI_FLOWER_LEAF = 675,
- SI_RAY_OF_PROTECTION = 676,
- SI_GLASTHEIM_ATK = 677,
- SI_GLASTHEIM_DEF = 678,
- SI_GLASTHEIM_HEAL = 679,
- SI_GLASTHEIM_HIDDEN = 680,
- SI_GLASTHEIM_STATE = 681,
- SI_GLASTHEIM_ITEMDEF = 682,
- SI_GLASTHEIM_HPSP = 683,
- SI_HOMUN_SKILL_POSTDELAY = 684,
- SI_ALMIGHTY = 685,
- SI_GVG_GIANT = 686,
- SI_GVG_GOLEM = 687,
- SI_GVG_STUN = 688,
- SI_GVG_STONE = 689,
- SI_GVG_FREEZ = 690,
- SI_GVG_SLEEP = 691,
- SI_GVG_CURSE = 692,
- SI_GVG_SILENCE = 693,
- SI_GVG_BLIND = 694,
- SI_CLIENT_ONLY_EQUIP_ARROW = 695,
- SI_CLAN_INFO = 696,
- SI_JP_EVENT01 = 697,
- SI_JP_EVENT02 = 698,
- SI_JP_EVENT03 = 699,
- SI_JP_EVENT04 = 700,
- SI_TELEPORT_FIXEDCASTINGDELAY = 701,
- SI_GEFFEN_MAGIC1 = 702,
- SI_GEFFEN_MAGIC2 = 703,
- SI_GEFFEN_MAGIC3 = 704,
- SI_QUEST_BUFF1 = 705,
- SI_QUEST_BUFF2 = 706,
- SI_QUEST_BUFF3 = 707,
- SI_REUSE_LIMIT_RECALL = 708,
- SI_SAVEPOSITION = 709,
- SI_HANDICAPSTATE_ICEEXPLO = 710,
- SI_FENRIR_CARD = 711,
- SI_REUSE_LIMIT_ASPD_POTION = 712,
- SI_MAXPAIN = 713,
- SI_PC_STOP = 714,
- SI_FRIGG_SONG = 715,
- SI_OFFERTORIUM = 716,
- SI_TELEKINESIS_INTENSE = 717,
- SI_MOONSTAR = 718,
- SI_STRANGELIGHTS = 719,
- SI_FULL_THROTTLE = 720,
- SI_REBOUND = 721,
- SI_UNLIMIT = 722,
- SI_KINGS_GRACE = 723,
- SI_ITEM_ATKMAX = 724,
- SI_ITEM_ATKMIN = 725,
- SI_ITEM_MATKMAX = 726,
- SI_ITEM_MATKMIN = 727,
- SI_SUPER_STAR = 728,
- SI_HIGH_RANKER = 729,
- SI_DARKCROW = 730,
- SI_2013_VALENTINE1 = 731,
- SI_2013_VALENTINE2 = 732,
- SI_2013_VALENTINE3 = 733,
- //SI_ = 734,
- //SI_ = 735,
- SI_CHILL = 736,
- SI_BURNT = 737,
+ SI_UNKNOWN_NAME = 672,
+ SI_ON_PUSH_CART = 673,
+ SI_HAT_EFFECT = 674,
+ SI_FLOWER_LEAF = 675,
+ SI_RAY_OF_PROTECTION = 676,
+ SI_GLASTHEIM_ATK = 677,
+ SI_GLASTHEIM_DEF = 678,
+ SI_GLASTHEIM_HEAL = 679,
+ SI_GLASTHEIM_HIDDEN = 680,
+ SI_GLASTHEIM_STATE = 681,
+ SI_GLASTHEIM_ITEMDEF = 682,
+ SI_GLASTHEIM_HPSP = 683,
+ SI_HOMUN_SKILL_POSTDELAY = 684,
+ SI_ALMIGHTY = 685,
+ SI_GVG_GIANT = 686,
+ SI_GVG_GOLEM = 687,
+ SI_GVG_STUN = 688,
+ SI_GVG_STONE = 689,
+ SI_GVG_FREEZ = 690,
+ SI_GVG_SLEEP = 691,
+ SI_GVG_CURSE = 692,
+ SI_GVG_SILENCE = 693,
+ SI_GVG_BLIND = 694,
+ SI_CLIENT_ONLY_EQUIP_ARROW = 695,
+ SI_CLAN_INFO = 696,
+ SI_JP_EVENT01 = 697,
+ SI_JP_EVENT02 = 698,
+ SI_JP_EVENT03 = 699,
+
+ SI_JP_EVENT04 = 700,
+ SI_TELEPORT_FIXEDCASTINGDELAY = 701,
+ SI_GEFFEN_MAGIC1 = 702,
+ SI_GEFFEN_MAGIC2 = 703,
+ SI_GEFFEN_MAGIC3 = 704,
+ SI_QUEST_BUFF1 = 705,
+ SI_QUEST_BUFF2 = 706,
+ SI_QUEST_BUFF3 = 707,
+ SI_REUSE_LIMIT_RECALL = 708,
+ SI_SAVEPOSITION = 709,
+ SI_HANDICAPSTATE_ICEEXPLO = 710,
+ SI_FENRIR_CARD = 711,
+ SI_REUSE_LIMIT_ASPD_POTION = 712,
+ SI_MAXPAIN = 713,
+ SI_PC_STOP = 714,
+ SI_FRIGG_SONG = 715,
+ SI_OFFERTORIUM = 716,
+ SI_TELEKINESIS_INTENSE = 717,
+ SI_MOONSTAR = 718,
+ SI_STRANGELIGHTS = 719,
+ SI_FULL_THROTTLE = 720,
+ SI_REBOUND = 721,
+ SI_UNLIMIT = 722,
+ SI_KINGS_GRACE = 723,
+ SI_ITEM_ATKMAX = 724,
+ SI_ITEM_ATKMIN = 725,
+ SI_ITEM_MATKMAX = 726,
+ SI_ITEM_MATKMIN = 727,
+ SI_SUPER_STAR = 728,
+ SI_HIGH_RANKER = 729,
+ SI_DARKCROW = 730,
+ SI_2013_VALENTINE1 = 731,
+ SI_2013_VALENTINE2 = 732,
+ SI_2013_VALENTINE3 = 733,
+ SI_ILLUSIONDOPING = 734,
+ //SI_ = 735,
+ SI_CHILL = 736,
+ SI_BURNT = 737,
+// SI_PCCAFE_PLAY_TIME = 738,
+// SI_TWISTED_TIME = 739,
+ SI_FLASHCOMBO = 740,
+
+// SI_JITTER_BUFF1 = 741,
+// SI_JITTER_BUFF2 = 742,
+// SI_JITTER_BUFF3 = 743,
+// SI_JITTER_BUFF4 = 744,
+// SI_JITTER_BUFF5 = 745,
+// SI_JITTER_BUFF6 = 746,
+// SI_JITTER_BUFF7 = 747,
+// SI_JITTER_BUFF8 = 748,
+// SI_JITTER_BUFF9 = 749,
+// SI_JITTER_BUFF10 = 750,
+// SI_CUP_OF_BOZA = 751,
+ SI_B_TRAP = 752,
+ SI_E_CHAIN = 753,
+ SI_E_QD_SHOT_READY = 754,
+ SI_C_MARKER = 755,
+ SI_H_MINE = 756,
+ SI_H_MINE_SPLASH = 757,
+ SI_P_ALTER = 758,
+ SI_HEAT_BARREL = 759,
+ SI_ANTI_M_BLAST = 760,
+ SI_SLUGSHOT = 761,
+ SI_SWORDCLAN = 762,
+ SI_ARCWANDCLAN = 763,
+ SI_GOLDENMACECLAN = 764,
+ SI_CROSSBOWCLAN = 765,
+ SI_PACKING_ENVELOPE1 = 766,
+ SI_PACKING_ENVELOPE2 = 767,
+ SI_PACKING_ENVELOPE3 = 768,
+ SI_PACKING_ENVELOPE4 = 769,
+ SI_PACKING_ENVELOPE5 = 770,
+ SI_PACKING_ENVELOPE6 = 771,
+ SI_PACKING_ENVELOPE7 = 772,
+ SI_PACKING_ENVELOPE8 = 773,
+ SI_PACKING_ENVELOPE9 = 774,
+ SI_PACKING_ENVELOPE10 = 775,
+ SI_GLASTHEIM_TRANS = 776,
+// SI_ZONGZI_POUCH_TRANS = 777,
+ SI_HEAT_BARREL_AFTER = 778,
+ SI_DECORATION_OF_MUSIC = 779,
+
+// SI_OVERSEAEXPUP = 780,
+// SI_CLOWN_N_GYPSY_CARD = 781,
+// SI_OPEN_NPC_MARKET = 782,
+// SI_BEEF_RIB_STEW = 783,
+// SI_PORK_RIB_STEW = 784,
+// SI_CHUSEOK_MONDAY = 785,
+// SI_CHUSEOK_TUESDAY = 786,
+// SI_CHUSEOK_WEDNESDAY = 787,
+// SI_CHUSEOK_THURSDAY = 788,
+// SI_CHUSEOK_FRIDAY = 789,
+// SI_CHUSEOK_WEEKEND = 790,
+// SI_ALL_LIGHTGUARD = 791,
+// SI_ALL_LIGHTGUARD_COOL_TIME = 792,
+// SI_MTF_MHP = 793,
+// SI_MTF_MSP = 794,
+// SI_MTF_PUMPKIN = 795,
+// SI_MTF_HITFLEE = 796,
+// SI_MTF_CRIDAMAGE2 = 797,
+// SI_MTF_SPDRAIN = 798,
+// SI_ACUO_MINT_GUM = 799,
+// ...
+// SI_GUILD_STORAGE = 810,
+// ...
+// SI_JUMPINGCLAN = 815,
+// ...
+// SI_MTF_RANGEATK2 = 818,
+// SI_MTF_ASPD2 = 819,
+// SI_MTF_MATK2 = 820,
+
SI_MAX,
};
-
// JOINTBEAT stackable ailments
enum e_joint_break
{
@@ -1423,8 +1561,6 @@ enum e_joint_break
BREAK_FLAGS = BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK,
};
-extern int current_equip_item_index;
-extern int current_equip_card_id;
//Mode definitions to clear up code reading. [Skotlex]
enum e_mode
@@ -1444,6 +1580,7 @@ enum e_mode
MD_CHANGETARGET_MELEE = 0x1000,
MD_CHANGETARGET_CHASE = 0x2000,
MD_TARGETWEAK = 0x4000,
+ MD_RANDOMTARGET = 0x8000,
MD_MASK = 0xFFFF,
};
@@ -1500,30 +1637,31 @@ enum {
};
enum {
- OPTION_NOTHING = 0x00000000,
- OPTION_SIGHT = 0x00000001,
- OPTION_HIDE = 0x00000002,
- OPTION_CLOAK = 0x00000004,
- OPTION_FALCON = 0x00000010,
- OPTION_RIDING = 0x00000020,
- OPTION_INVISIBLE = 0x00000040,
- OPTION_ORCISH = 0x00000800,
- OPTION_WEDDING = 0x00001000,
- OPTION_RUWACH = 0x00002000,
- OPTION_CHASEWALK = 0x00004000,
- OPTION_FLYING = 0x00008000, //Note that clientside Flying and Xmas are 0x8000 for clients prior to 2007.
- OPTION_XMAS = 0x00010000,
- OPTION_TRANSFORM = 0x00020000,
- OPTION_SUMMER = 0x00040000,
- OPTION_DRAGON1 = 0x00080000,
- OPTION_WUG = 0x00100000,
- OPTION_WUGRIDER = 0x00200000,
- OPTION_MADOGEAR = 0x00400000,
- OPTION_DRAGON2 = 0x00800000,
- OPTION_DRAGON3 = 0x01000000,
- OPTION_DRAGON4 = 0x02000000,
- OPTION_DRAGON5 = 0x04000000,
- OPTION_HANBOK = 0x08000000,
+ OPTION_NOTHING = 0x00000000,
+ OPTION_SIGHT = 0x00000001,
+ OPTION_HIDE = 0x00000002,
+ OPTION_CLOAK = 0x00000004,
+ OPTION_FALCON = 0x00000010,
+ OPTION_RIDING = 0x00000020,
+ OPTION_INVISIBLE = 0x00000040,
+ OPTION_ORCISH = 0x00000800,
+ OPTION_WEDDING = 0x00001000,
+ OPTION_RUWACH = 0x00002000,
+ OPTION_CHASEWALK = 0x00004000,
+ OPTION_FLYING = 0x00008000, //Note that clientside Flying and Xmas are 0x8000 for clients prior to 2007.
+ OPTION_XMAS = 0x00010000,
+ OPTION_TRANSFORM = 0x00020000,
+ OPTION_SUMMER = 0x00040000,
+ OPTION_DRAGON1 = 0x00080000,
+ OPTION_WUG = 0x00100000,
+ OPTION_WUGRIDER = 0x00200000,
+ OPTION_MADOGEAR = 0x00400000,
+ OPTION_DRAGON2 = 0x00800000,
+ OPTION_DRAGON3 = 0x01000000,
+ OPTION_DRAGON4 = 0x02000000,
+ OPTION_DRAGON5 = 0x04000000,
+ OPTION_HANBOK = 0x08000000,
+ OPTION_OKTOBERFEST = 0x10000000,
#ifndef NEW_CARTS
OPTION_CART1 = 0x00000008,
@@ -1538,6 +1676,7 @@ enum {
// compound constants
OPTION_DRAGON = OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5,
+ OPTION_COSTUME = OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK|OPTION_OKTOBERFEST,
};
//Defines for the manner system [Skotlex]
@@ -1590,6 +1729,20 @@ enum scb_flag
SCB_ALL = 0x3FFFFFFF
};
+//Regen related flags.
+enum e_regen {
+ RGN_HP = 0x01,
+ RGN_SP = 0x02,
+ RGN_SHP = 0x04,
+ RGN_SSP = 0x08,
+};
+
+enum e_status_calc_opt {
+ SCO_NONE = 0x0,
+ SCO_FIRST = 0x1, /* trigger the calculations that should take place only onspawn/once */
+ SCO_FORCE = 0x2, /* only relevant to BL_PC types, ensures call bypasses the queue caused by delayed damage */
+};
+
//Define to determine who gets HP/SP consumed on doing skills/etc. [Skotlex]
#define BL_CONSUME (BL_PC|BL_HOM|BL_MER|BL_ELEM)
//Define to determine who has regen
@@ -1608,15 +1761,7 @@ typedef struct weapon_atk {
unsigned short matk;
unsigned char wlv;
#endif
-}weapon_atk;
-
-sc_type SkillStatusChangeTable[MAX_SKILL]; // skill -> status
-int StatusIconChangeTable[SC_MAX]; // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated)
-unsigned int StatusChangeFlagTable[SC_MAX]; // status -> flags
-int StatusSkillChangeTable[SC_MAX]; // status -> skill
-int StatusRelevantBLTypes[SI_MAX]; // "icon" -> enum bl_type (for clif->status_change to identify for which bl types to send packets)
-bool StatusDisplayType[SC_MAX];
-
+} weapon_atk;
//For holding basic status (which can be modified by status changes)
struct status_data {
@@ -1630,7 +1775,7 @@ struct status_data {
speed,
amotion, adelay, dmotion,
mode;
- short
+ short
hit, flee, cri, flee2,
def2, mdef2,
#ifdef RENEWAL_ASPD
@@ -1647,6 +1792,9 @@ struct status_data {
size, race;
struct weapon_atk rhw, lhw; //Right Hand/Left Hand Weapon.
+#ifdef RENEWAL
+ int equip_atk;
+#endif
};
//Additional regen data that only players have.
@@ -1720,151 +1868,234 @@ struct status_change {
unsigned char sg_counter; //Storm gust counter (previous hits from storm gust)
#endif
unsigned char bs_counter; // Blood Sucker counter
+ unsigned char fv_counter; // Force of vanguard counter
struct status_change_entry *data[SC_MAX];
};
-// for looking up associated data
-sc_type status_skill2sc(int skill);
-int status_sc2skill(sc_type sc);
-unsigned int status_sc2scb_flag(sc_type sc);
-int status_type2relevant_bl_types(int type);
-int status_get_sc_type(sc_type idx);
-int status_damage(struct block_list *src,struct block_list *target,int hp,int sp, int walkdelay, int flag);
//Define for standard HP damage attacks.
-#define status_fix_damage(src, target, hp, walkdelay) status_damage(src, target, hp, 0, walkdelay, 0)
+#define status_fix_damage(src, target, hp, walkdelay) (status->damage((src), (target), (hp), 0, (walkdelay), 0))
//Define for standard HP/SP damage triggers.
-#define status_zap(bl, hp, sp) status_damage(NULL, bl, hp, sp, 0, 1)
-//Define for standard HP/SP skill-related cost triggers (mobs require no HP/SP to use skills)
-int status_charge(struct block_list* bl, int hp, int sp);
-int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag);
-//Easier handling of status_percent_change
-#define status_percent_heal(bl, hp_rate, sp_rate) status_percent_change(NULL, bl, -(hp_rate), -(sp_rate), 0)
-#define status_percent_damage(src, target, hp_rate, sp_rate, kill) status_percent_change(src, target, hp_rate, sp_rate, (kill)?1:2)
+#define status_zap(bl, hp, sp) (status->damage(NULL, (bl), (hp), (sp), 0, 1))
+//Easier handling of status->percent_change
+#define status_percent_heal(bl, hp_rate, sp_rate) (status->percent_change(NULL, (bl), -(hp_rate), -(sp_rate), 0))
+#define status_percent_damage(src, target, hp_rate, sp_rate, kill) (status->percent_change((src), (target), (hp_rate), (sp_rate), (kill)?1:2))
//Instant kill with no drops/exp/etc
-#define status_kill(bl) status_percent_damage(NULL, bl, 100, 0, true)
-//Used to set the hp/sp of an object to an absolute value (can't kill)
-int status_set_hp(struct block_list *bl, unsigned int hp, int flag);
-int status_set_sp(struct block_list *bl, unsigned int sp, int flag);
-int status_heal(struct block_list *bl,int hp,int sp, int flag);
-int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp);
-
-struct regen_data *status_get_regen_data(struct block_list *bl);
-struct status_data *status_get_status_data(struct block_list *bl);
-struct status_data *status_get_base_status(struct block_list *bl);
-const char * status_get_name(struct block_list *bl);
-int status_get_class(struct block_list *bl);
-int status_get_lv(struct block_list *bl);
-#define status_get_range(bl) status_get_status_data(bl)->rhw.range
-#define status_get_hp(bl) status_get_status_data(bl)->hp
-#define status_get_max_hp(bl) status_get_status_data(bl)->max_hp
-#define status_get_sp(bl) status_get_status_data(bl)->sp
-#define status_get_max_sp(bl) status_get_status_data(bl)->max_sp
-#define status_get_str(bl) status_get_status_data(bl)->str
-#define status_get_agi(bl) status_get_status_data(bl)->agi
-#define status_get_vit(bl) status_get_status_data(bl)->vit
-#define status_get_int(bl) status_get_status_data(bl)->int_
-#define status_get_dex(bl) status_get_status_data(bl)->dex
-#define status_get_luk(bl) status_get_status_data(bl)->luk
-#define status_get_hit(bl) status_get_status_data(bl)->hit
-#define status_get_flee(bl) status_get_status_data(bl)->flee
-defType status_get_def(struct block_list *bl);
-#define status_get_mdef(bl) status_get_status_data(bl)->mdef
-#define status_get_flee2(bl) status_get_status_data(bl)->flee2
-#define status_get_def2(bl) status_get_status_data(bl)->def2
-#define status_get_mdef2(bl) status_get_status_data(bl)->mdef2
-#define status_get_critical(bl) status_get_status_data(bl)->cri
-#define status_get_batk(bl) status_get_status_data(bl)->batk
-#define status_get_watk(bl) status_get_status_data(bl)->rhw.atk
-#define status_get_watk2(bl) status_get_status_data(bl)->rhw.atk2
-#define status_get_matk_max(bl) status_get_status_data(bl)->matk_max
-#define status_get_matk_min(bl) status_get_status_data(bl)->matk_min
-#define status_get_lwatk(bl) status_get_status_data(bl)->lhw.atk
-#define status_get_lwatk2(bl) status_get_status_data(bl)->lhw.atk2
-unsigned short status_get_speed(struct block_list *bl);
-#define status_get_adelay(bl) status_get_status_data(bl)->adelay
-#define status_get_amotion(bl) status_get_status_data(bl)->amotion
-#define status_get_dmotion(bl) status_get_status_data(bl)->dmotion
-#define status_get_element(bl) status_get_status_data(bl)->def_ele
-#define status_get_element_level(bl) status_get_status_data(bl)->ele_lv
-unsigned char status_calc_attack_element(struct block_list *bl, struct status_change *sc, int element);
-#define status_get_attack_sc_element(bl, sc) status_calc_attack_element(bl, sc, 0)
-#define status_get_attack_element(bl) status_get_status_data(bl)->rhw.ele
-#define status_get_attack_lelement(bl) status_get_status_data(bl)->lhw.ele
-#define status_get_race(bl) status_get_status_data(bl)->race
-#define status_get_size(bl) status_get_status_data(bl)->size
-#define status_get_mode(bl) status_get_status_data(bl)->mode
-int status_get_party_id(struct block_list *bl);
-int status_get_guild_id(struct block_list *bl);
-int status_get_emblem_id(struct block_list *bl);
-int status_get_mexp(struct block_list *bl);
-int status_get_race2(struct block_list *bl);
-
-struct view_data *status_get_viewdata(struct block_list *bl);
-void status_set_viewdata(struct block_list *bl, int class_);
-void status_change_init(struct block_list *bl);
-struct status_change *status_get_sc(struct block_list *bl);
-
-int status_isdead(struct block_list *bl);
-int status_isimmune(struct block_list *bl);
-
-int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int tick, int flag);
+#define status_kill(bl) status_percent_damage(NULL, (bl), 100, 0, true)
+
+#define status_get_range(bl) (status->get_status_data(bl)->rhw.range)
+#define status_get_hp(bl) (status->get_status_data(bl)->hp)
+#define status_get_max_hp(bl) (status->get_status_data(bl)->max_hp)
+#define status_get_sp(bl) (status->get_status_data(bl)->sp)
+#define status_get_max_sp(bl) (status->get_status_data(bl)->max_sp)
+#define status_get_str(bl) (status->get_status_data(bl)->str)
+#define status_get_agi(bl) (status->get_status_data(bl)->agi)
+#define status_get_vit(bl) (status->get_status_data(bl)->vit)
+#define status_get_int(bl) (status->get_status_data(bl)->int_)
+#define status_get_dex(bl) (status->get_status_data(bl)->dex)
+#define status_get_luk(bl) (status->get_status_data(bl)->luk)
+#define status_get_hit(bl) (status->get_status_data(bl)->hit)
+#define status_get_flee(bl) (status->get_status_data(bl)->flee)
+#define status_get_mdef(bl) (status->get_status_data(bl)->mdef)
+#define status_get_flee2(bl) (status->get_status_data(bl)->flee2)
+#define status_get_def2(bl) (status->get_status_data(bl)->def2)
+#define status_get_mdef2(bl) (status->get_status_data(bl)->mdef2)
+#define status_get_critical(bl) (status->get_status_data(bl)->cri)
+#define status_get_batk(bl) (status->get_status_data(bl)->batk)
+#define status_get_watk(bl) (status->get_status_data(bl)->rhw.atk)
+#define status_get_watk2(bl) (status->get_status_data(bl)->rhw.atk2)
+#define status_get_matk_max(bl) (status->get_status_data(bl)->matk_max)
+#define status_get_matk_min(bl) (status->get_status_data(bl)->matk_min)
+#define status_get_lwatk(bl) (status->get_status_data(bl)->lhw.atk)
+#define status_get_lwatk2(bl) (status->get_status_data(bl)->lhw.atk2)
+#define status_get_adelay(bl) (status->get_status_data(bl)->adelay)
+#define status_get_amotion(bl) (status->get_status_data(bl)->amotion)
+#define status_get_dmotion(bl) (status->get_status_data(bl)->dmotion)
+#define status_get_element(bl) (status->get_status_data(bl)->def_ele)
+#define status_get_element_level(bl) (status->get_status_data(bl)->ele_lv)
+#define status_get_attack_sc_element(bl, sc) (status->calc_attack_element((bl), (sc), 0))
+#define status_get_attack_element(bl) (status->get_status_data(bl)->rhw.ele)
+#define status_get_attack_lelement(bl) (status->get_status_data(bl)->lhw.ele)
+#define status_get_race(bl) (status->get_status_data(bl)->race)
+#define status_get_size(bl) (status->get_status_data(bl)->size)
+#define status_get_mode(bl) (status->get_status_data(bl)->mode)
+
//Short version, receives rate in 1->100 range, and does not uses a flag setting.
-#define sc_start(bl, type, rate, val1, tick) status_change_start(bl,type,100*(rate),val1,0,0,0,tick,0)
-#define sc_start2(bl, type, rate, val1, val2, tick) status_change_start(bl,type,100*(rate),val1,val2,0,0,tick,0)
-#define sc_start4(bl, type, rate, val1, val2, val3, val4, tick) status_change_start(bl,type,100*(rate),val1,val2,val3,val4,tick,0)
-
-int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag);
-int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line);
-#define status_change_end(bl,type,tid) status_change_end_(bl,type,tid,__FILE__,__LINE__)
-int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data);
-int status_change_timer(int tid, unsigned int tick, int id, intptr_t data);
-int status_change_timer_sub(struct block_list* bl, va_list ap);
-int status_change_clear(struct block_list* bl, int type);
-int status_change_clear_buffs(struct block_list* bl, int type);
-
-#define status_calc_bl(bl, flag) status_calc_bl_(bl, (enum scb_flag)(flag), false)
-#define status_calc_mob(md, first) status_calc_bl_(&(md)->bl, SCB_ALL, first)
-#define status_calc_pet(pd, first) status_calc_bl_(&(pd)->bl, SCB_ALL, first)
-#define status_calc_pc(sd, first) status_calc_bl_(&(sd)->bl, SCB_ALL, first)
-#define status_calc_homunculus(hd, first) status_calc_bl_(&(hd)->bl, SCB_ALL, first)
-#define status_calc_mercenary(md, first) status_calc_bl_(&(md)->bl, SCB_ALL, first)
-#define status_calc_elemental(ed, first) status_calc_bl_(&(ed)->bl, SCB_ALL, first)
-#define status_calc_npc(nd, first) status_calc_bl_(&(nd)->bl, SCB_ALL, first)
-
-void status_calc_bl_(struct block_list *bl, enum scb_flag flag, bool first);
-int status_calc_mob_(struct mob_data* md, bool first);
-int status_calc_pet_(struct pet_data* pd, bool first);
-int status_calc_pc_(struct map_session_data* sd, bool first);
-int status_calc_homunculus_(struct homun_data *hd, bool first);
-int status_calc_mercenary_(struct mercenary_data *md, bool first);
-int status_calc_elemental_(struct elemental_data *ed, bool first);
-
-void status_calc_misc(struct block_list *bl, struct status_data *status, int level);
-void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen);
-void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, struct status_change *sc);
-
-int status_check_skilluse(struct block_list *src, struct block_list *target, uint16 skill_id, int flag); // [Skotlex]
-int status_check_visibility(struct block_list *src, struct block_list *target); //[Skotlex]
-
-int status_change_spread( struct block_list *src, struct block_list *bl );
-
-defType status_calc_def(struct block_list *bl, struct status_change *sc, int, bool);
-signed short status_calc_def2(struct block_list *,struct status_change *, int, bool);
-defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int, bool);
-signed short status_calc_mdef2(struct block_list *,struct status_change *, int, bool);
+#define sc_start(src, bl, type, rate, val1, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),0,0,0,(tick),0))
+#define sc_start2(src, bl, type, rate, val1, val2, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),0,0,(tick),0))
+#define sc_start4(src, bl, type, rate, val1, val2, val3, val4, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),(val3),(val4),(tick),0))
-#ifdef RENEWAL
-unsigned short status_base_matk(const struct status_data* status, int level);
-int status_get_weapon_atk(struct block_list *src, struct weapon_atk *watk, int flag);
-int status_get_total_mdef(struct block_list *src);
-int status_get_total_def(struct block_list *src);
-#endif
+#define status_change_end(bl,type,tid) (status->change_end_((bl),(type),(tid),__FILE__,__LINE__))
+
+#define status_calc_bl(bl, flag) (status->calc_bl_((bl), (enum scb_flag)(flag), SCO_NONE))
+#define status_calc_mob(md, opt) (status->calc_bl_(&(md)->bl, SCB_ALL, (opt)))
+#define status_calc_pet(pd, opt) (status->calc_bl_(&(pd)->bl, SCB_ALL, (opt)))
+#define status_calc_pc(sd, opt) (status->calc_bl_(&(sd)->bl, SCB_ALL, (opt)))
+#define status_calc_homunculus(hd, opt) (status->calc_bl_(&(hd)->bl, SCB_ALL, (opt)))
+#define status_calc_mercenary(md, opt) (status->calc_bl_(&(md)->bl, SCB_ALL, (opt)))
+#define status_calc_elemental(ed, opt) (status->calc_bl_(&(ed)->bl, SCB_ALL, (opt)))
+#define status_calc_npc(nd, opt) (status->calc_bl_(&(nd)->bl, SCB_ALL, (opt)))
+
+// bonus values and upgrade chances for refining equipment
+struct s_refine_info {
+ int chance[MAX_REFINE]; // success chance
+ int bonus[MAX_REFINE]; // cumulative fixed bonus damage
+ int randombonus_max[MAX_REFINE]; // cumulative maximum random bonus damage
+};
+
+/*=====================================
+* Interface : status.h
+* Generated by HerculesInterfaceMaker
+* created by Susu
+*-------------------------------------*/
+struct status_interface {
+
+ /* vars */
+ int current_equip_item_index;
+ int current_equip_card_id;
+ /* */
+ int max_weight_base[CLASS_COUNT];
+ int hp_coefficient[CLASS_COUNT];
+ int hp_coefficient2[CLASS_COUNT];
+ int hp_sigma_val[CLASS_COUNT][MAX_LEVEL+1];
+ int sp_coefficient[CLASS_COUNT];
+ int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1]; // +1 for RENEWAL_ASPD
+ sc_type Skill2SCTable[MAX_SKILL]; // skill -> status
+ int IconChangeTable[SC_MAX]; // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated)
+ unsigned int ChangeFlagTable[SC_MAX]; // status -> flags
+ int SkillChangeTable[SC_MAX]; // status -> skill
+ int RelevantBLTypes[SI_MAX]; // "icon" -> enum bl_type (for clif->status_change to identify for which bl types to send packets)
+ bool DisplayType[SC_MAX];
+ /* */
+ struct s_refine_info refine_info[REFINE_TYPE_MAX];
+ /* */
+ int atkmods[3][MAX_WEAPON_TYPE];//ATK weapon modification for size (size_fix.txt)
+ char job_bonus[CLASS_COUNT][MAX_LEVEL];
+ sc_conf_type sc_conf[SC_MAX];
+ struct eri *data_ers; //For sc_data entries
+ struct status_data dummy;
+ int64 natural_heal_prev_tick;
+ unsigned int natural_heal_diff_tick;
+ /* */
+ int (*init) (bool minimal);
+ void (*final) (void);
+ /* funcs */
+ int (*get_refine_chance) (enum refine_type wlv, int refine);
+ // for looking up associated data
+ sc_type (*skill2sc) (int skill_id);
+ int (*sc2skill) (sc_type sc);
+ unsigned int (*sc2scb_flag) (sc_type sc);
+ int (*type2relevant_bl_types) (int type);
+ int (*get_sc_type) (sc_type idx);
+ int (*damage) (struct block_list *src,struct block_list *target,int64 hp,int64 sp, int walkdelay, int flag);
+ //Define for standard HP/SP skill-related cost triggers (mobs require no HP/SP to use skills)
+ int (*charge) (struct block_list* bl, int64 hp, int64 sp);
+ int (*percent_change) (struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag);
+ //Used to set the hp/sp of an object to an absolute value (can't kill)
+ int (*set_hp) (struct block_list *bl, unsigned int hp, int flag);
+ int (*set_sp) (struct block_list *bl, unsigned int sp, int flag);
+ int (*heal) (struct block_list *bl,int64 hp,int64 sp, int flag);
+ int (*revive) (struct block_list *bl, unsigned char per_hp, unsigned char per_sp);
+ int (*fixed_revive) (struct block_list *bl, unsigned int per_hp, unsigned int per_sp);
+ struct regen_data * (*get_regen_data) (struct block_list *bl);
+ struct status_data * (*get_status_data) (struct block_list *bl);
+ struct status_data * (*get_base_status) (struct block_list *bl);
+ const char * (*get_name) (struct block_list *bl);
+ int (*get_class) (struct block_list *bl);
+ int (*get_lv) (struct block_list *bl);
+ defType (*get_def) (struct block_list *bl);
+ unsigned short (*get_speed) (struct block_list *bl);
+ unsigned char (*calc_attack_element) (struct block_list *bl, struct status_change *sc, int element);
+ int (*get_party_id) (struct block_list *bl);
+ int (*get_guild_id) (struct block_list *bl);
+ int (*get_emblem_id) (struct block_list *bl);
+ int (*get_mexp) (struct block_list *bl);
+ int (*get_race2) (struct block_list *bl);
+ struct view_data * (*get_viewdata) (struct block_list *bl);
+ void (*set_viewdata) (struct block_list *bl, int class_);
+ void (*change_init) (struct block_list *bl);
+ struct status_change * (*get_sc) (struct block_list *bl);
+ int (*isdead) (struct block_list *bl);
+ int (*isimmune) (struct block_list *bl);
+ int (*get_sc_def) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag);
+ int (*change_start) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag);
+ int (*change_end_) (struct block_list* bl, enum sc_type type, int tid, const char* file, int line);
+ int (*kaahi_heal_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*change_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*change_timer_sub) (struct block_list* bl, va_list ap);
+ int (*change_clear) (struct block_list* bl, int type);
+ int (*change_clear_buffs) (struct block_list* bl, int type);
+ void (*calc_bl_) (struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt);
+ int (*calc_mob_) (struct mob_data* md, enum e_status_calc_opt opt);
+ int (*calc_pet_) (struct pet_data* pd, enum e_status_calc_opt opt);
+ int (*calc_pc_) (struct map_session_data* sd, enum e_status_calc_opt opt);
+ int (*calc_homunculus_) (struct homun_data *hd, enum e_status_calc_opt opt);
+ int (*calc_mercenary_) (struct mercenary_data *md, enum e_status_calc_opt opt);
+ int (*calc_elemental_) (struct elemental_data *ed, enum e_status_calc_opt opt);
+ void (*calc_misc) (struct block_list *bl, struct status_data *st, int level);
+ void (*calc_regen) (struct block_list *bl, struct status_data *st, struct regen_data *regen);
+ void (*calc_regen_rate) (struct block_list *bl, struct regen_data *regen, struct status_change *sc);
+ int (*check_skilluse) (struct block_list *src, struct block_list *target, uint16 skill_id, int flag); // [Skotlex]
+ int (*check_visibility) (struct block_list *src, struct block_list *target); //[Skotlex]
+ int (*change_spread) (struct block_list *src, struct block_list *bl);
+ defType (*calc_def) (struct block_list *bl, struct status_change *sc, int def, bool viewable);
+ short (*calc_def2) (struct block_list *bl, struct status_change *sc, int def2, bool viewable);
+ defType (*calc_mdef) (struct block_list *bl, struct status_change *sc, int mdef, bool viewable);
+ short (*calc_mdef2) (struct block_list *bl, struct status_change *sc, int mdef2, bool viewable);
+ unsigned short (*calc_batk)(struct block_list *bl, struct status_change *sc, int batk, bool viewable);
+ unsigned short (*base_matk) (const struct status_data *st, int level);
+ int (*get_weapon_atk) (struct block_list *src, struct weapon_atk *watk, int flag);
+ int (*get_total_mdef) (struct block_list *src);
+ int (*get_total_def) (struct block_list *src);
+ int (*get_matk) (struct block_list *src, int flag);
+ void (*update_matk) ( struct block_list *bl );
+ int (*readdb) (void);
+
+ void (*initChangeTables) (void);
+ void (*initDummyData) (void);
+ int (*base_amotion_pc) (struct map_session_data *sd, struct status_data *st);
+ unsigned short (*base_atk) (const struct block_list *bl, const struct status_data *st);
+ void (*calc_sigma) (void);
+ unsigned int (*base_pc_maxhp) (struct map_session_data *sd, struct status_data *st);
+ unsigned int (*base_pc_maxsp) (struct map_session_data *sd, struct status_data *st);
+ int (*calc_npc_) (struct npc_data *nd, enum e_status_calc_opt opt);
+ unsigned short (*calc_str) (struct block_list *bl, struct status_change *sc, int str);
+ unsigned short (*calc_agi) (struct block_list *bl, struct status_change *sc, int agi);
+ unsigned short (*calc_vit) (struct block_list *bl, struct status_change *sc, int vit);
+ unsigned short (*calc_int) (struct block_list *bl, struct status_change *sc, int int_);
+ unsigned short (*calc_dex) (struct block_list *bl, struct status_change *sc, int dex);
+ unsigned short (*calc_luk) (struct block_list *bl, struct status_change *sc, int luk);
+ unsigned short (*calc_watk) (struct block_list *bl, struct status_change *sc, int watk, bool viewable);
+ unsigned short (*calc_matk) (struct block_list *bl, struct status_change *sc, int matk, bool viewable);
+ signed short (*calc_hit) (struct block_list *bl, struct status_change *sc, int hit, bool viewable);
+ signed short (*calc_critical) (struct block_list *bl, struct status_change *sc, int critical, bool viewable);
+ signed short (*calc_flee) (struct block_list *bl, struct status_change *sc, int flee, bool viewable);
+ signed short (*calc_flee2) (struct block_list *bl, struct status_change *sc, int flee2, bool viewable);
+ unsigned short (*calc_speed) (struct block_list *bl, struct status_change *sc, int speed);
+ short (*calc_aspd_rate) (struct block_list *bl, struct status_change *sc, int aspd_rate);
+ unsigned short (*calc_dmotion) (struct block_list *bl, struct status_change *sc, int dmotion);
+ short (*calc_aspd) (struct block_list *bl, struct status_change *sc, short flag);
+ short (*calc_fix_aspd) (struct block_list *bl, struct status_change *sc, int aspd);
+ unsigned int (*calc_maxhp) (struct block_list *bl, struct status_change *sc, uint64 maxhp);
+ unsigned int (*calc_maxsp) (struct block_list *bl, struct status_change *sc, unsigned int maxsp);
+ unsigned char (*calc_element) (struct block_list *bl, struct status_change *sc, int element);
+ unsigned char (*calc_element_lv) (struct block_list *bl, struct status_change *sc, int lv);
+ unsigned short (*calc_mode) (struct block_list *bl, struct status_change *sc, int mode);
+ unsigned short (*calc_ematk) (struct block_list *bl, struct status_change *sc, int matk);
+ void (*calc_bl_main) (struct block_list *bl, int flag);
+ void (*display_add) (struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3);
+ void (*display_remove) (struct map_session_data *sd, enum sc_type type);
+ int (*natural_heal) (struct block_list *bl, va_list args);
+ int (*natural_heal_timer) (int tid, int64 tick, int id, intptr_t data);
+ bool (*readdb_job1) (char *fields[], int columns, int current);
+ bool (*readdb_job2) (char *fields[], int columns, int current);
+ bool (*readdb_sizefix) (char *fields[], int columns, int current);
+ bool (*readdb_refine) (char *fields[], int columns, int current);
+ bool (*readdb_scconfig) (char *fields[], int columns, int current);
+};
-int status_get_matk(struct block_list *src, int flag);
+struct status_interface *status;
-int status_readdb(void);
-int do_init_status(void);
-void do_final_status(void);
+void status_defaults(void);
-#endif /* _STATUS_H_ */
+#endif /* MAP_STATUS_H */
diff --git a/src/map/storage.c b/src/map/storage.c
index ea30f6c0f..217f14a3a 100644
--- a/src/map/storage.c
+++ b/src/map/storage.c
@@ -1,38 +1,40 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/db.h"
-#include "../common/nullpo.h"
-#include "../common/malloc.h"
-#include "../common/showmsg.h"
+#define HERCULES_CORE
-#include "map.h" // struct map_session_data
#include "storage.h"
-#include "chrif.h"
-#include "itemdb.h"
-#include "clif.h"
-#include "intif.h"
-#include "pc.h"
-#include "guild.h"
-#include "battle.h"
-#include "atcommand.h"
-#include "log.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "atcommand.h"
+#include "battle.h"
+#include "chrif.h"
+#include "clif.h"
+#include "guild.h"
+#include "intif.h"
+#include "itemdb.h"
+#include "log.h"
+#include "map.h" // struct map_session_data
+#include "pc.h"
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
-static DBMap* guild_storage_db; // int guild_id -> struct guild_storage*
+struct storage_interface storage_s;
+struct guild_storage_interface gstorage_s;
/*==========================================
* Sort items in the warehouse
*------------------------------------------*/
-static int storage_comp_item(const void *_i1, const void *_i2)
+int storage_comp_item(const void *i1_, const void *i2_)
{
- struct item *i1 = (struct item *)_i1;
- struct item *i2 = (struct item *)_i2;
+ struct item *i1 = (struct item *)i1_;
+ struct item *i2 = (struct item *)i2_;
if (i1->nameid == i2->nameid)
return 0;
@@ -44,46 +46,32 @@ static int storage_comp_item(const void *_i1, const void *_i2)
}
//Sort item by storage_comp_item (nameid)
-static void storage_sortitem(struct item* items, unsigned int size)
+void storage_sortitem(struct item* items, unsigned int size)
{
nullpo_retv(items);
if( battle_config.client_sort_storage )
{
- qsort(items, size, sizeof(struct item), storage_comp_item);
+ qsort(items, size, sizeof(struct item), storage->comp_item);
}
}
-/*==========================================
- * Init/Terminate
- *------------------------------------------*/
-int do_init_storage(void) // Called from map.c::do_init()
-{
- guild_storage_db=idb_alloc(DB_OPT_RELEASE_DATA);
- return 1;
-}
-void do_final_storage(void) // by [MC Cameri]
-{
- guild_storage_db->destroy(guild_storage_db,NULL);
-}
-
/**
* Parses storage and saves 'dirty' ones upon reconnect. [Skotlex]
* @see DBApply
*/
-static int storage_reconnect_sub(DBKey key, DBData *data, va_list ap)
+int storage_reconnect_sub(DBKey key, DBData *data, va_list ap)
{
struct guild_storage *stor = DB->data2ptr(data);
if (stor->dirty && stor->storage_status == 0) //Save closed storages.
- storage_guild_storagesave(0, stor->guild_id,0);
+ gstorage->save(0, stor->guild_id,0);
return 0;
}
//Function to be invoked upon server reconnection to char. To save all 'dirty' storages [Skotlex]
-void do_reconnect_storage(void)
-{
- guild_storage_db->foreach(guild_storage_db, storage_reconnect_sub);
+void do_reconnect_storage(void) {
+ gstorage->db->foreach(gstorage->db, storage->reconnect_sub);
}
/*==========================================
@@ -98,14 +86,14 @@ int storage_storageopen(struct map_session_data *sd)
if(sd->state.storage_flag)
return 1; //Already open?
- if( !pc->can_give_items(sd) )
+ if( !pc_can_give_items(sd) )
{ //check is this GM level is allowed to put items to storage
clif->message(sd->fd, msg_txt(246));
return 1;
}
sd->state.storage_flag = 1;
- storage_sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
+ storage->sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE);
return 0;
@@ -120,7 +108,8 @@ int compare_item(struct item *a, struct item *b)
a->identify == b->identify &&
a->refine == b->refine &&
a->attribute == b->attribute &&
- a->expire_time == b->expire_time )
+ a->expire_time == b->expire_time &&
+ a->bound == b->bound )
{
int i;
for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++);
@@ -132,8 +121,7 @@ int compare_item(struct item *a, struct item *b)
/*==========================================
* Internal add-item function.
*------------------------------------------*/
-static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount)
-{
+int storage_additem(struct map_session_data* sd, struct item* item_data, int amount) {
struct storage_data* stor = &sd->status.storage;
struct item_data *data;
int i;
@@ -141,20 +129,25 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data,
if( item_data->nameid <= 0 || amount <= 0 )
return 1;
- data = itemdb_search(item_data->nameid);
+ data = itemdb->search(item_data->nameid);
if( data->stack.storage && amount > data->stack.amount )
{// item stack limitation
return 1;
}
- if( !itemdb_canstore(item_data, pc->get_group_level(sd)) )
+ if( !itemdb_canstore(item_data, pc_get_group_level(sd)) )
{ //Check if item is storable. [Skotlex]
clif->message (sd->fd, msg_txt(264));
return 1;
}
- if( itemdb_isstackable2(data) )
+ if( item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd) ) {
+ clif->message(sd->fd, msg_txt(294));
+ return 1;
+ }
+
+ if( itemdb->isstackable2(data) )
{//Stackable
for( i = 0; i < MAX_STORAGE; i++ )
{
@@ -210,8 +203,7 @@ int storage_delitem(struct map_session_data* sd, int n, int amount)
* 0 : fail
* 1 : success
*------------------------------------------*/
-int storage_storageadd(struct map_session_data* sd, int index, int amount)
-{
+int storage_storageadd(struct map_session_data* sd, int index, int amount) {
nullpo_ret(sd);
if( sd->status.storage.storage_amount > MAX_STORAGE )
@@ -226,8 +218,10 @@ int storage_storageadd(struct map_session_data* sd, int index, int amount)
if( amount < 1 || amount > sd->status.inventory[index].amount )
return 0;
- if( storage_additem(sd,&sd->status.inventory[index],amount) == 0 )
+ if( storage->additem(sd,&sd->status.inventory[index],amount) == 0 )
pc->delitem(sd,index,amount,0,4,LOG_TYPE_STORAGE);
+ else
+ clif->dropitem(sd, index,0);
return 1;
}
@@ -253,7 +247,7 @@ int storage_storageget(struct map_session_data* sd, int index, int amount)
return 0;
if( (flag = pc->additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 )
- storage_delitem(sd,index,amount);
+ storage->delitem(sd,index,amount);
else
clif->additem(sd,0,0,flag);
@@ -283,7 +277,7 @@ int storage_storageaddfromcart(struct map_session_data* sd, int index, int amoun
if( amount < 1 || amount > sd->status.cart[index].amount )
return 0;
- if( storage_additem(sd,&sd->status.cart[index],amount) == 0 )
+ if( storage->additem(sd,&sd->status.cart[index],amount) == 0 )
pc->cart_delitem(sd,index,amount,0,LOG_TYPE_STORAGE);
return 1;
@@ -296,8 +290,8 @@ int storage_storageaddfromcart(struct map_session_data* sd, int index, int amoun
* 0 : fail
* 1 : success
*------------------------------------------*/
-int storage_storagegettocart(struct map_session_data* sd, int index, int amount)
-{
+int storage_storagegettocart(struct map_session_data* sd, int index, int amount) {
+ int flag = 0;
nullpo_ret(sd);
if( index < 0 || index >= MAX_STORAGE )
@@ -309,8 +303,12 @@ int storage_storagegettocart(struct map_session_data* sd, int index, int amount)
if( amount < 1 || amount > sd->status.storage.items[index].amount )
return 0;
- if( pc->cart_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE) == 0 )
- storage_delitem(sd,index,amount);
+ if( (flag = pc->cart_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 )
+ storage->delitem(sd,index,amount);
+ else {
+ clif->dropitem(sd, index,0);
+ clif->cart_additem_ack(sd,flag == 1?0x0:0x1);
+ }
return 1;
}
@@ -319,14 +317,13 @@ int storage_storagegettocart(struct map_session_data* sd, int index, int amount)
/*==========================================
* Modified By Valaris to save upon closing [massdriller]
*------------------------------------------*/
-void storage_storageclose(struct map_session_data* sd)
-{
+void storage_storageclose(struct map_session_data* sd) {
nullpo_retv(sd);
clif->storageclose(sd);
- if( iMap->save_settings&4 )
- chrif_save(sd,0); //Invokes the storage saving as well.
+ if( map->save_settings&4 )
+ chrif->save(sd,0); //Invokes the storage saving as well.
sd->state.storage_flag = 0;
}
@@ -334,12 +331,11 @@ void storage_storageclose(struct map_session_data* sd)
/*==========================================
* When quitting the game.
*------------------------------------------*/
-void storage_storage_quit(struct map_session_data* sd, int flag)
-{
+void storage_storage_quit(struct map_session_data* sd, int flag) {
nullpo_retv(sd);
- if (iMap->save_settings&4)
- chrif_save(sd, flag); //Invokes the storage saving as well.
+ if (map->save_settings&4)
+ chrif->save(sd, flag); //Invokes the storage saving as well.
sd->state.storage_flag = 0;
}
@@ -347,7 +343,7 @@ void storage_storage_quit(struct map_session_data* sd, int flag)
/**
* @see DBCreateData
*/
-static DBData create_guildstorage(DBKey key, va_list args)
+DBData create_guildstorage(DBKey key, va_list args)
{
struct guild_storage *gs = NULL;
gs = (struct guild_storage *) aCalloc(sizeof(struct guild_storage), 1);
@@ -359,19 +355,17 @@ struct guild_storage *guild2storage(int guild_id)
{
struct guild_storage *gs = NULL;
if(guild->search(guild_id) != NULL)
- gs = idb_ensure(guild_storage_db,guild_id,create_guildstorage);
+ gs = idb_ensure(gstorage->db,guild_id,gstorage->create);
return gs;
}
//For just locating a storage without creating one. [Skotlex]
-struct guild_storage *guild2storage2(int guild_id)
-{
- return (struct guild_storage*)idb_get(guild_storage_db,guild_id);
+struct guild_storage *guild2storage2(int guild_id) {
+ return (struct guild_storage*)idb_get(gstorage->db,guild_id);
}
-int guild_storage_delete(int guild_id)
-{
- idb_remove(guild_storage_db,guild_id);
+int guild_storage_delete(int guild_id) {
+ idb_remove(gstorage->db,guild_id);
return 0;
}
@@ -394,13 +388,13 @@ int storage_guild_storageopen(struct map_session_data* sd)
if(sd->state.storage_flag)
return 1; //Can't open both storages at a time.
- if( !pc->can_give_items(sd) ) { //check is this GM level can open guild storage and store items [Lupus]
+ if( !pc_can_give_items(sd) ) { //check is this GM level can open guild storage and store items [Lupus]
clif->message(sd->fd, msg_txt(246));
return 1;
}
- if((gstor = guild2storage2(sd->status.guild_id)) == NULL) {
- intif_request_guild_storage(sd->status.account_id,sd->status.guild_id);
+ if((gstor = gstorage->id2storage2(sd->status.guild_id)) == NULL) {
+ intif->request_guild_storage(sd->status.account_id,sd->status.guild_id);
return 0;
}
if(gstor->storage_status)
@@ -411,7 +405,7 @@ int storage_guild_storageopen(struct map_session_data* sd)
gstor->storage_status = 1;
sd->state.storage_flag = 2;
- storage_sortitem(gstor->items, ARRAYLENGTH(gstor->items));
+ storage->sortitem(gstor->items, ARRAYLENGTH(gstor->items));
clif->storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items));
clif->updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE);
return 0;
@@ -435,20 +429,25 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
if(item_data->nameid <= 0 || amount <= 0)
return 1;
- data = itemdb_search(item_data->nameid);
+ data = itemdb->search(item_data->nameid);
if( data->stack.guildstorage && amount > data->stack.amount )
{// item stack limitation
return 1;
}
- if( !itemdb_canguildstore(item_data, pc->get_group_level(sd)) || item_data->expire_time )
- { //Check if item is storable. [Skotlex]
+ if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time )
+ { //Check if item is storable. [Skotlex]
clif->message (sd->fd, msg_txt(264));
return 1;
}
- if(itemdb_isstackable2(data)){ //Stackable
+ if( item_data->bound && item_data->bound != IBT_GUILD && !pc_can_give_bound_items(sd) ) {
+ clif->message(sd->fd, msg_txt(294));
+ return 1;
+ }
+
+ if(itemdb->isstackable2(data)){ //Stackable
for(i=0;i<MAX_GUILD_STORAGE;i++){
if(compare_item(&stor->items[i], item_data)) {
if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.guildstorage && amount > data->stack.amount - stor->items[i].amount ) )
@@ -512,7 +511,7 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
struct guild_storage *stor;
nullpo_ret(sd);
- nullpo_ret(stor=guild2storage2(sd->status.guild_id));
+ nullpo_ret(stor=gstorage->id2storage2(sd->status.guild_id));
if( !stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE )
return 0;
@@ -527,12 +526,14 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
return 0;
if( stor->lock ) {
- storage_guild_storageclose(sd);
+ gstorage->close(sd);
return 0;
}
- if(guild_storage_additem(sd,stor,&sd->status.inventory[index],amount)==0)
+ if(gstorage->additem(sd,stor,&sd->status.inventory[index],amount)==0)
pc->delitem(sd,index,amount,0,4,LOG_TYPE_GSTORAGE);
+ else
+ clif->dropitem(sd, index,0);
return 1;
}
@@ -542,7 +543,7 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
* @index : storage idx
* return
* 0 : fail
-* 1 : succes
+* 1 : success
*------------------------------------------*/
int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
{
@@ -565,12 +566,12 @@ int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
return 0;
if( stor->lock ) {
- storage_guild_storageclose(sd);
+ gstorage->close(sd);
return 0;
}
if((flag = pc->additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)) == 0)
- guild_storage_delitem(sd,stor,index,amount);
+ gstorage->delitem(sd,stor,index,amount);
else //inform fail
clif->additem(sd,0,0,flag);
// log_fromstorage(sd, index, 1);
@@ -583,7 +584,7 @@ int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
* @index : cart inventory idx
* return
* 0 : fail
-* 1 : succes
+* 1 : success
*------------------------------------------*/
int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int amount)
{
@@ -604,7 +605,7 @@ int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int
if( amount < 1 || amount > sd->status.cart[index].amount )
return 0;
- if(guild_storage_additem(sd,stor,&sd->status.cart[index],amount)==0)
+ if(gstorage->additem(sd,stor,&sd->status.cart[index],amount)==0)
pc->cart_delitem(sd,index,amount,0,LOG_TYPE_GSTORAGE);
return 1;
@@ -615,7 +616,7 @@ int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int
* @index : storage idx
* return
* 0 : fail
-* 1 : succes
+* 1 : success
*------------------------------------------*/
int storage_guild_storagegettocart(struct map_session_data* sd, int index, int amount)
{
@@ -637,7 +638,7 @@ int storage_guild_storagegettocart(struct map_session_data* sd, int index, int a
return 0;
if(pc->cart_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)==0)
- guild_storage_delitem(sd,stor,index,amount);
+ gstorage->delitem(sd,stor,index,amount);
return 1;
}
@@ -646,7 +647,7 @@ int storage_guild_storagegettocart(struct map_session_data* sd, int index, int a
* Request to save guild storage
* return
* 0 : fail (no storage)
-* 1 : succes
+* 1 : success
*------------------------------------------*/
int storage_guild_storagesave(int account_id, int guild_id, int flag)
{
@@ -657,7 +658,7 @@ int storage_guild_storagesave(int account_id, int guild_id, int flag)
if (flag) //Char quitting, close it.
stor->storage_status = 0;
if (stor->dirty)
- intif_send_guild_storage(account_id,stor);
+ intif->send_guild_storage(account_id,stor);
return 1;
}
return 0;
@@ -667,13 +668,13 @@ int storage_guild_storagesave(int account_id, int guild_id, int flag)
* ACK save of guild storage
* return
* 0 : fail (no storage)
-* 1 : succes
+* 1 : success
*------------------------------------------*/
int storage_guild_storagesaved(int guild_id)
{
struct guild_storage *stor;
- if((stor=guild2storage2(guild_id)) != NULL) {
+ if((stor=gstorage->id2storage2(guild_id)) != NULL) {
if (stor->dirty && stor->storage_status == 0)
{ //Storage has been correctly saved.
stor->dirty = 0;
@@ -684,20 +685,18 @@ int storage_guild_storagesaved(int guild_id)
}
//Close storage for sd and save it
-int storage_guild_storageclose(struct map_session_data* sd)
-{
+int storage_guild_storageclose(struct map_session_data* sd) {
struct guild_storage *stor;
nullpo_ret(sd);
- nullpo_ret(stor=guild2storage2(sd->status.guild_id));
+ nullpo_ret(stor=gstorage->id2storage2(sd->status.guild_id));
clif->storageclose(sd);
- if (stor->storage_status)
- {
- if (iMap->save_settings&4)
- chrif_save(sd, 0); //This one also saves the storage. [Skotlex]
+ if (stor->storage_status) {
+ if (map->save_settings&4)
+ chrif->save(sd, 0); //This one also saves the storage. [Skotlex]
else
- storage_guild_storagesave(sd->status.account_id, sd->status.guild_id,0);
+ gstorage->save(sd->status.account_id, sd->status.guild_id,0);
stor->storage_status=0;
}
sd->state.storage_flag = 0;
@@ -705,31 +704,80 @@ int storage_guild_storageclose(struct map_session_data* sd)
return 0;
}
-int storage_guild_storage_quit(struct map_session_data* sd, int flag)
-{
+int storage_guild_storage_quit(struct map_session_data* sd, int flag) {
struct guild_storage *stor;
nullpo_ret(sd);
- nullpo_ret(stor=guild2storage2(sd->status.guild_id));
+ nullpo_ret(stor=gstorage->id2storage2(sd->status.guild_id));
- if(flag)
- { //Only during a guild break flag is 1 (don't save storage)
+ if(flag) {
+ //Only during a guild break flag is 1 (don't save storage)
sd->state.storage_flag = 0;
stor->storage_status = 0;
clif->storageclose(sd);
- if (iMap->save_settings&4)
- chrif_save(sd,0);
+ if (map->save_settings&4)
+ chrif->save(sd,0);
return 0;
}
if(stor->storage_status) {
- if (iMap->save_settings&4)
- chrif_save(sd,0);
+ if (map->save_settings&4)
+ chrif->save(sd,0);
else
- storage_guild_storagesave(sd->status.account_id,sd->status.guild_id,1);
+ gstorage->save(sd->status.account_id,sd->status.guild_id,1);
}
sd->state.storage_flag = 0;
stor->storage_status = 0;
return 0;
}
+void do_init_gstorage(bool minimal) {
+ if (minimal)
+ return;
+ gstorage->db = idb_alloc(DB_OPT_RELEASE_DATA);
+}
+void do_final_gstorage(void) {
+ db_destroy(gstorage->db);
+}
+void storage_defaults(void) {
+ storage = &storage_s;
+
+ /* */
+ storage->reconnect = do_reconnect_storage;
+ /* */
+ storage->delitem = storage_delitem;
+ storage->open = storage_storageopen;
+ storage->add = storage_storageadd;
+ storage->get = storage_storageget;
+ storage->additem = storage_additem;
+ storage->addfromcart = storage_storageaddfromcart;
+ storage->gettocart = storage_storagegettocart;
+ storage->close = storage_storageclose;
+ storage->pc_quit = storage_storage_quit;
+ storage->comp_item = storage_comp_item;
+ storage->sortitem = storage_sortitem;
+ storage->reconnect_sub = storage_reconnect_sub;
+}
+void gstorage_defaults(void) {
+ gstorage = &gstorage_s;
+
+ /* */
+ gstorage->init = do_init_gstorage;
+ gstorage->final = do_final_gstorage;
+ /* */
+ gstorage->id2storage = guild2storage;
+ gstorage->id2storage2 = guild2storage2;
+ gstorage->delete = guild_storage_delete;
+ gstorage->open = storage_guild_storageopen;
+ gstorage->additem = guild_storage_additem;
+ gstorage->delitem = guild_storage_delitem;
+ gstorage->add = storage_guild_storageadd;
+ gstorage->get = storage_guild_storageget;
+ gstorage->addfromcart = storage_guild_storageaddfromcart;
+ gstorage->gettocart = storage_guild_storagegettocart;
+ gstorage->close = storage_guild_storageclose;
+ gstorage->pc_quit = storage_guild_storage_quit;
+ gstorage->save = storage_guild_storagesave;
+ gstorage->saved = storage_guild_storagesaved;
+ gstorage->create = create_guildstorage;
+}
diff --git a/src/map/storage.h b/src/map/storage.h
index c08ec81cb..186f21263 100644
--- a/src/map/storage.h
+++ b/src/map/storage.h
@@ -1,41 +1,63 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _STORAGE_H_
-#define _STORAGE_H_
+#ifndef MAP_STORAGE_H
+#define MAP_STORAGE_H
+
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
-//#include "../common/mmo.h"
-struct storage_data;
struct guild_storage;
struct item;
-//#include "map.h"
struct map_session_data;
-int storage_delitem(struct map_session_data* sd, int n, int amount);
-int storage_storageopen(struct map_session_data *sd);
-int storage_storageadd(struct map_session_data *sd,int index,int amount);
-int storage_storageget(struct map_session_data *sd,int index,int amount);
-int storage_storageaddfromcart(struct map_session_data *sd,int index,int amount);
-int storage_storagegettocart(struct map_session_data *sd,int index,int amount);
-void storage_storageclose(struct map_session_data *sd);
-int do_init_storage(void);
-void do_final_storage(void);
-void do_reconnect_storage(void);
-void storage_storage_quit(struct map_session_data *sd, int flag);
-
-struct guild_storage* guild2storage(int guild_id);
-struct guild_storage *guild2storage2(int guild_id);
-int guild_storage_delete(int guild_id);
-int storage_guild_storageopen(struct map_session_data *sd);
-int guild_storage_additem(struct map_session_data *sd,struct guild_storage *stor,struct item *item_data,int amount);
-int guild_storage_delitem(struct map_session_data *sd,struct guild_storage *stor,int n,int amount);
-int storage_guild_storageadd(struct map_session_data *sd,int index,int amount);
-int storage_guild_storageget(struct map_session_data *sd,int index,int amount);
-int storage_guild_storageaddfromcart(struct map_session_data *sd,int index,int amount);
-int storage_guild_storagegettocart(struct map_session_data *sd,int index,int amount);
-int storage_guild_storageclose(struct map_session_data *sd);
-int storage_guild_storage_quit(struct map_session_data *sd,int flag);
-int storage_guild_storagesave(int account_id, int guild_id, int flag);
-int storage_guild_storagesaved(int guild_id); //Ack from char server that guild store was saved.
-
-#endif /* _STORAGE_H_ */
+struct storage_interface {
+ /* */
+ void (*reconnect) (void);
+ /* */
+ int (*delitem) (struct map_session_data* sd, int n, int amount);
+ int (*open) (struct map_session_data *sd);
+ int (*add) (struct map_session_data *sd,int index,int amount);
+ int (*get) (struct map_session_data *sd,int index,int amount);
+ int (*additem) (struct map_session_data* sd, struct item* item_data, int amount);
+ int (*addfromcart) (struct map_session_data *sd,int index,int amount);
+ int (*gettocart) (struct map_session_data *sd,int index,int amount);
+ void (*close) (struct map_session_data *sd);
+ void (*pc_quit) (struct map_session_data *sd, int flag);
+ int (*comp_item) (const void *i1_, const void *i2_);
+ void (*sortitem) (struct item* items, unsigned int size);
+ int (*reconnect_sub) (DBKey key, DBData *data, va_list ap);
+};
+struct storage_interface *storage;
+
+struct guild_storage_interface {
+ struct DBMap* db; // int guild_id -> struct guild_storage*
+ /* */
+ struct guild_storage *(*id2storage) (int guild_id);
+ struct guild_storage *(*id2storage2) (int guild_id);
+ /* */
+ void (*init) (bool minimal);
+ void (*final) (void);
+ /* */
+ int (*delete) (int guild_id);
+ int (*open) (struct map_session_data *sd);
+ int (*additem) (struct map_session_data *sd,struct guild_storage *stor,struct item *item_data,int amount);
+ int (*delitem) (struct map_session_data *sd,struct guild_storage *stor,int n,int amount);
+ int (*add) (struct map_session_data *sd,int index,int amount);
+ int (*get) (struct map_session_data *sd,int index,int amount);
+ int (*addfromcart) (struct map_session_data *sd,int index,int amount);
+ int (*gettocart) (struct map_session_data *sd,int index,int amount);
+ int (*close) (struct map_session_data *sd);
+ int (*pc_quit) (struct map_session_data *sd,int flag);
+ int (*save) (int account_id, int guild_id, int flag);
+ int (*saved) (int guild_id); //Ack from char server that guild store was saved.
+ DBData (*create) (DBKey key, va_list args);
+};
+
+struct guild_storage_interface *gstorage;
+
+void storage_defaults(void);
+void gstorage_defaults(void);
+
+#endif /* MAP_STORAGE_H */
diff --git a/src/map/trade.c b/src/map/trade.c
index f469f4b28..3bbb73568 100644
--- a/src/map/trade.c
+++ b/src/map/trade.c
@@ -1,28 +1,30 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#include "../common/nullpo.h"
-#include "../common/socket.h"
+#define HERCULES_CORE
+
+#include "trade.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "atcommand.h"
+#include "battle.h"
+#include "chrif.h"
#include "clif.h"
+#include "intif.h"
#include "itemdb.h"
+#include "log.h"
#include "map.h"
+#include "npc.h"
#include "path.h"
-#include "trade.h"
#include "pc.h"
-#include "npc.h"
-#include "battle.h"
-#include "chrif.h"
#include "storage.h"
-#include "intif.h"
-#include "atcommand.h"
-#include "log.h"
-
-#include <stdio.h>
-#include <string.h>
-
+#include "../common/nullpo.h"
+#include "../common/socket.h"
-//Max distance from traders to enable a trade to take place.
-#define TRADE_DISTANCE 2
+struct trade_interface trade_s;
/*==========================================
* Initiates a trade request.
@@ -31,7 +33,7 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
{
nullpo_retv(sd);
- if (map[sd->bl.m].flag.notrade) {
+ if (map->list[sd->bl.m].flag.notrade) {
clif->message (sd->fd, msg_txt(272));
return; //Can't trade in notrade mapflag maps.
}
@@ -55,11 +57,11 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
}
if ( sd->trade_partner != 0 ) { // If a character tries to trade to another one then cancel the previous one
- struct map_session_data *previous_sd = iMap->id2sd(sd->trade_partner);
+ struct map_session_data *previous_sd = map->id2sd(sd->trade_partner);
if( previous_sd ){
previous_sd->trade_partner = 0;
clif->tradecancelled(previous_sd);
- } // Once cancelled then continue to the new one.
+ } // Once canceled then continue to the new one.
sd->trade_partner = 0;
clif->tradecancelled(sd);
}
@@ -69,7 +71,7 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
return;
}
- if (!pc->can_give_items(sd) || !pc->can_give_items(target_sd)) //check if both GMs are allowed to trade
+ if (!pc_can_give_items(sd) || !pc_can_give_items(target_sd)) //check if both GMs are allowed to trade
{
clif->message(sd->fd, msg_txt(246));
clif->tradestart(sd, 2); // GM is not allowed to trade
@@ -99,15 +101,14 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
* Weird enough, the client should only send 3/4
* and the server is the one that can reply 0~2
*------------------------------------------*/
-void trade_tradeack(struct map_session_data *sd, int type)
-{
+void trade_tradeack(struct map_session_data *sd, int type) {
struct map_session_data *tsd;
nullpo_retv(sd);
if (sd->state.trading || !sd->trade_partner)
return; //Already trading or no partner set.
- if ((tsd = iMap->id2sd(sd->trade_partner)) == NULL) {
+ if ((tsd = map->id2sd(sd->trade_partner)) == NULL) {
clif->tradestart(sd, 1); // character does not exist
sd->trade_partner=0;
return;
@@ -165,11 +166,13 @@ void trade_tradeack(struct map_session_data *sd, int type)
clif->tradestart(sd, type);
}
-/*==========================================
- * Check here hacker for duplicate item in trade
- * normal client refuse to have 2 same types of item (except equipment) in same trade window
- * normal client authorise only no equiped item and only from inventory
- *------------------------------------------*/
+/**
+ * Checks if an impossible trade will occur
+ * Normal clients refuse to have 2 items of the same type (except equipment) in the same trade window
+ * Normal clients authorize only no equipped items and only items from inventory
+ * @retval 0 The trade can continue
+ * @retval 1 Hack attempt
+ **/
int impossible_trade_check(struct map_session_data *sd)
{
struct item inventory[MAX_INVENTORY];
@@ -178,17 +181,15 @@ int impossible_trade_check(struct map_session_data *sd)
nullpo_retr(1, sd);
- if(sd->deal.zeny > sd->status.zeny) {
- pc_setglobalreg(sd,"ZENY_HACKER",1);
- return -1;
- }
+ if( sd->deal.zeny > sd->status.zeny )
+ return 1;
// get inventory of player
memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY);
- // remove this part: arrows can be trade and equiped
+ // remove this part: arrows can be trade and equipped
// re-added! [celest]
- // remove equiped items (they can not be trade)
+ // remove equipped items (they can not be trade)
for (i = 0; i < MAX_INVENTORY; i++)
if (inventory[i].nameid > 0 && inventory[i].equip && !(inventory[i].equip & EQP_AMMO))
memset(&inventory[i], 0, sizeof(struct item));
@@ -198,21 +199,21 @@ int impossible_trade_check(struct map_session_data *sd)
if (!sd->deal.item[i].amount)
continue;
index = sd->deal.item[i].index;
- if (inventory[index].amount < sd->deal.item[i].amount)
- { // if more than the player have -> hack
+ if (inventory[index].amount < sd->deal.item[i].amount) {
+ // if more than the player have -> hack
sprintf(message_to_gm, msg_txt(538), sd->status.name, sd->status.account_id); // Hack on trade: character '%s' (account: %d) try to trade more items that he has.
- intif_wis_message_to_gm(iMap->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
+ intif->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
sprintf(message_to_gm, msg_txt(539), inventory[index].amount, inventory[index].nameid, sd->deal.item[i].amount); // This player has %d of a kind of item (id: %d), and try to trade %d of them.
- intif_wis_message_to_gm(iMap->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
+ intif->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
// if we block people
if (battle_config.ban_hack_trade < 0) {
- chrif_char_ask_name(-1, sd->status.name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block
+ chrif->char_ask_name(-1, sd->status.name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block
set_eof(sd->fd); // forced to disconnect because of the hack
// message about the ban
strcpy(message_to_gm, msg_txt(540)); // This player has been definitively blocked.
// if we ban people
} else if (battle_config.ban_hack_trade > 0) {
- chrif_char_ask_name(-1, sd->status.name, 2, 0, 0, 0, 0, battle_config.ban_hack_trade, 0); // type: 2 - ban (year, month, day, hour, minute, second)
+ chrif->char_ask_name(-1, sd->status.name, 2, 0, 0, 0, 0, battle_config.ban_hack_trade, 0); // type: 2 - ban (year, month, day, hour, minute, second)
set_eof(sd->fd); // forced to disconnect because of the hack
// message about the ban
sprintf(message_to_gm, msg_txt(507), battle_config.ban_hack_trade); // This player has been banned for %d minute(s).
@@ -220,7 +221,7 @@ int impossible_trade_check(struct map_session_data *sd)
// message about the ban
strcpy(message_to_gm, msg_txt(508)); // This player hasn't been banned (Ban option is disabled).
- intif_wis_message_to_gm(iMap->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
+ intif->wis_message_to_gm(map->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
return 1;
}
inventory[index].amount -= sd->deal.item[i].amount; // remove item from inventory
@@ -257,9 +258,9 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
if (amount > inventory[n].amount)
return 0; //qty Exploit?
- data = itemdb_search(inventory[n].nameid);
+ data = itemdb->search(inventory[n].nameid);
i = MAX_INVENTORY;
- if (itemdb_isstackable2(data)) { //Stackable item.
+ if (itemdb->isstackable2(data)) { //Stackable item.
for(i = 0; i < MAX_INVENTORY; i++)
if (inventory2[i].nameid == inventory[n].nameid &&
inventory2[i].card[0] == inventory[n].card[0] && inventory2[i].card[1] == inventory[n].card[1] &&
@@ -288,9 +289,9 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
if (amount > inventory2[n].amount)
return 0;
// search if it's possible to add item (for full inventory)
- data = itemdb_search(inventory2[n].nameid);
+ data = itemdb->search(inventory2[n].nameid);
i = MAX_INVENTORY;
- if (itemdb_isstackable2(data)) {
+ if (itemdb->isstackable2(data)) {
for(i = 0; i < MAX_INVENTORY; i++)
if (inventory[i].nameid == inventory2[n].nameid &&
inventory[i].card[0] == inventory2[n].card[0] && inventory[i].card[1] == inventory2[n].card[1] &&
@@ -318,8 +319,7 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
/*==========================================
* Adds an item/qty to the trade window
*------------------------------------------*/
-void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
-{
+void trade_tradeadditem(struct map_session_data *sd, short index, short amount) {
struct map_session_data *target_sd;
struct item *item;
int trade_i, trade_weight;
@@ -329,7 +329,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
if( !sd->state.trading || sd->state.deal_locked > 0 )
return; //Can't add stuff.
- if( (target_sd = iMap->id2sd(sd->trade_partner)) == NULL )
+ if( (target_sd = map->id2sd(sd->trade_partner)) == NULL )
{
trade->cancel(sd);
return;
@@ -337,7 +337,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
if( amount == 0 )
{ //Why do this.. ~.~ just send an ack, the item won't display on the trade window.
- clif->tradeitemok(sd, index, 0);
+ clif->tradeitemok(sd, index, TIO_SUCCESS);
return;
}
@@ -350,35 +350,44 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
return;
item = &sd->status.inventory[index];
- src_lv = pc->get_group_level(sd);
- dst_lv = pc->get_group_level(target_sd);
+ src_lv = pc_get_group_level(sd);
+ dst_lv = pc_get_group_level(target_sd);
if( !itemdb_cantrade(item, src_lv, dst_lv) && //Can't trade
(pc->get_partner(sd) != target_sd || !itemdb_canpartnertrade(item, src_lv, dst_lv)) ) //Can't partner-trade
{
clif->message (sd->fd, msg_txt(260));
- clif->tradeitemok(sd, index+2, 1);
+ clif->tradeitemok(sd, index+2, TIO_INDROCKS);
return;
}
if( item->expire_time )
{ // Rental System
clif->message (sd->fd, msg_txt(260));
- clif->tradeitemok(sd, index+2, 1);
+ clif->tradeitemok(sd, index+2, TIO_INDROCKS);
return;
}
+ if( item->bound &&
+ !( item->bound == IBT_GUILD && sd->status.guild_id == target_sd->status.guild_id ) &&
+ !( item->bound == IBT_PARTY && sd->status.party_id == target_sd->status.party_id )
+ && !pc_can_give_bound_items(sd) ) {
+ clif->message(sd->fd, msg_txt(293));
+ clif->tradeitemok(sd, index+2, TIO_INDROCKS);
+ return;
+ }
+
//Locate a trade position
ARR_FIND( 0, 10, trade_i, sd->deal.item[trade_i].index == index || sd->deal.item[trade_i].amount == 0 );
if( trade_i == 10 ) //No space left
{
- clif->tradeitemok(sd, index+2, 1);
+ clif->tradeitemok(sd, index+2, TIO_OVERWEIGHT);
return;
}
trade_weight = sd->inventory_data[index]->weight * amount;
if( target_sd->weight + sd->deal.weight + trade_weight > target_sd->max_weight )
{ //fail to add item -- the player was over weighted.
- clif->tradeitemok(sd, index+2, 1);
+ clif->tradeitemok(sd, index+2, TIO_OVERWEIGHT);
return;
}
@@ -398,7 +407,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
}
sd->deal.weight += trade_weight;
- clif->tradeitemok(sd, index+2, 0); // Return the index as it was received
+ clif->tradeitemok(sd, index+2, TIO_SUCCESS); // Return the index as it was received
clif->tradeadditem(sd, target_sd, index+2, amount);
}
@@ -413,8 +422,7 @@ void trade_tradeaddzeny(struct map_session_data* sd, int amount)
if( !sd->state.trading || sd->state.deal_locked > 0 )
return; //Can't add stuff.
- if( (target_sd = iMap->id2sd(sd->trade_partner)) == NULL )
- {
+ if( (target_sd = map->id2sd(sd->trade_partner)) == NULL ) {
trade->cancel(sd);
return;
}
@@ -432,35 +440,33 @@ void trade_tradeaddzeny(struct map_session_data* sd, int amount)
/*==========================================
* 'Ok' button on the trade window is pressed.
*------------------------------------------*/
-void trade_tradeok(struct map_session_data *sd)
-{
+void trade_tradeok(struct map_session_data *sd) {
struct map_session_data *target_sd;
if(sd->state.deal_locked || !sd->state.trading)
return;
- if ((target_sd = iMap->id2sd(sd->trade_partner)) == NULL) {
+ if ((target_sd = map->id2sd(sd->trade_partner)) == NULL) {
trade->cancel(sd);
return;
}
sd->state.deal_locked = 1;
- clif->tradeitemok(sd, 0, 0);
+ clif->tradeitemok(sd, 0, TIO_SUCCESS);
clif->tradedeal_lock(sd, 0);
clif->tradedeal_lock(target_sd, 1);
}
/*==========================================
- * 'Cancel' is pressed. (or trade was force-cancelled by the code)
+ * 'Cancel' is pressed. (or trade was force-canceled by the code)
*------------------------------------------*/
-void trade_tradecancel(struct map_session_data *sd)
-{
+void trade_tradecancel(struct map_session_data *sd) {
struct map_session_data *target_sd;
int trade_i;
- target_sd = iMap->id2sd(sd->trade_partner);
+ target_sd = map->id2sd(sd->trade_partner);
if(!sd->state.trading)
- { // Not trade acepted
+ { // Not trade accepted
if( target_sd ) {
target_sd->trade_partner = 0;
clif->tradecancelled(target_sd);
@@ -511,8 +517,7 @@ void trade_tradecancel(struct map_session_data *sd)
/*==========================================
* lock sd and tsd trade data, execute the trade, clear, then save players
*------------------------------------------*/
-void trade_tradecommit(struct map_session_data *sd)
-{
+void trade_tradecommit(struct map_session_data *sd) {
struct map_session_data *tsd;
int trade_i;
int flag;
@@ -520,8 +525,8 @@ void trade_tradecommit(struct map_session_data *sd)
if (!sd->state.trading || !sd->state.deal_locked) //Locked should be 1 (pressed ok) before you can press trade.
return;
- if ((tsd = iMap->id2sd(sd->trade_partner)) == NULL) {
- trade_tradecancel(sd);
+ if ((tsd = map->id2sd(sd->trade_partner)) == NULL) {
+ trade->cancel(sd);
return;
}
@@ -601,10 +606,10 @@ void trade_tradecommit(struct map_session_data *sd)
clif->tradecompleted(tsd, 0);
// save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
- if (iMap->save_settings&1)
+ if (map->save_settings&1)
{
- chrif_save(sd,0);
- chrif_save(tsd,0);
+ chrif->save(sd,0);
+ chrif->save(tsd,0);
}
}
@@ -621,4 +626,4 @@ void trade_defaults(void)
trade->ok = trade_tradeok;
trade->cancel = trade_tradecancel;
trade->commit = trade_tradecommit;
-} \ No newline at end of file
+}
diff --git a/src/map/trade.h b/src/map/trade.h
index f66c70525..f91ccd4a2 100644
--- a/src/map/trade.h
+++ b/src/map/trade.h
@@ -1,10 +1,14 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _TRADE_H_
-#define _TRADE_H_
+#ifndef MAP_TRADE_H
+#define MAP_TRADE_H
+
+//Max distance from traders to enable a trade to take place.
+//TODO: battle_config candidate?
+#define TRADE_DISTANCE 2
-//#include "map.h"
struct map_session_data;
struct trade_interface {
@@ -17,9 +21,10 @@ struct trade_interface {
void (*ok) (struct map_session_data *sd);
void (*cancel) (struct map_session_data *sd);
void (*commit) (struct map_session_data *sd);
-} trade_s;
+};
struct trade_interface *trade;
+
void trade_defaults(void);
-#endif /* _TRADE_H_ */
+#endif /* MAP_TRADE_H */
diff --git a/src/map/unit.c b/src/map/unit.c
index 021859bba..af0c0a948 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -2,50 +2,61 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/showmsg.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/db.h"
-#include "../common/malloc.h"
-#include "../common/random.h"
+#define HERCULES_CORE
+
+#include "../config/core.h" // RENEWAL_CAST
+#include "unit.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "battle.h"
+#include "battleground.h"
+#include "chat.h"
+#include "chrif.h"
+#include "clif.h"
+#include "duel.h"
+#include "elemental.h"
+#include "guild.h"
+#include "homunculus.h"
+#include "instance.h"
+#include "intif.h"
#include "map.h"
+#include "mercenary.h"
+#include "mob.h"
+#include "npc.h"
+#include "party.h"
#include "path.h"
#include "pc.h"
-#include "mob.h"
#include "pet.h"
-#include "homunculus.h"
-#include "instance.h"
-#include "mercenary.h"
-#include "elemental.h"
+#include "script.h"
#include "skill.h"
-#include "clif.h"
-#include "duel.h"
-#include "npc.h"
-#include "guild.h"
#include "status.h"
-#include "unit.h"
-#include "battle.h"
-#include "battleground.h"
-#include "chat.h"
+#include "storage.h"
#include "trade.h"
#include "vending.h"
-#include "party.h"
-#include "intif.h"
-#include "chrif.h"
-#include "script.h"
-#include "storage.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
+#include "../common/HPM.h"
+#include "../common/db.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/timer.h"
const short dirx[8]={0,-1,-1,-1,0,1,1,1};
const short diry[8]={1,1,0,-1,-1,-1,0,1};
-struct unit_data* unit_bl2ud(struct block_list *bl)
-{
+struct unit_interface unit_s;
+
+/**
+ * Returns the unit_data for the given block_list. If the object is using
+ * shared unit_data (i.e. in case of BL_NPC), it returns the shared data.
+ * @param bl block_list to process
+ * @return a pointer to the given object's unit_data
+ **/
+struct unit_data* unit_bl2ud(struct block_list *bl) {
if( bl == NULL) return NULL;
if( bl->type == BL_PC) return &((struct map_session_data*)bl)->ud;
if( bl->type == BL_MOB) return &((struct mob_data*)bl)->ud;
@@ -57,8 +68,22 @@ struct unit_data* unit_bl2ud(struct block_list *bl)
return NULL;
}
-static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data);
-static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data);
+/**
+ * Returns the unit_data for the given block_list. If the object is using
+ * shared unit_data (i.e. in case of BL_NPC), it recreates a copy of the
+ * data so that it's safe to modify.
+ * @param bl block_list to process
+ * @return a pointer to the given object's unit_data
+ */
+struct unit_data* unit_bl2ud2(struct block_list *bl) {
+ if( bl && bl->type == BL_NPC && ((struct npc_data*)bl)->ud == &npc->base_ud ) {
+ struct npc_data *nd = (struct npc_data *)bl;
+ nd->ud = NULL;
+ CREATE(nd->ud, struct unit_data, 1);
+ unit->dataset(&nd->bl);
+ }
+ return unit->bl2ud(bl);
+}
int unit_walktoxy_sub(struct block_list *bl)
{
@@ -67,10 +92,10 @@ int unit_walktoxy_sub(struct block_list *bl)
struct unit_data *ud = NULL;
nullpo_retr(1, bl);
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
if(ud == NULL) return 0;
- if( !path_search(&wpd,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) )
+ if( !path->search(&wpd,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) )
return 0;
memcpy(&ud->walkpath,&wpd,sizeof(wpd));
@@ -85,9 +110,9 @@ int unit_walktoxy_sub(struct block_list *bl)
ud->walkpath.path_len--;
dir = ud->walkpath.path[ud->walkpath.path_len];
if(dir&1)
- i-=14;
+ i -= MOVE_DIAGONAL_COST;
else
- i-=10;
+ i -= MOVE_COST;
ud->to_x -= dirx[dir];
ud->to_y -= diry[dir];
}
@@ -104,16 +129,15 @@ int unit_walktoxy_sub(struct block_list *bl)
if(ud->walkpath.path_pos>=ud->walkpath.path_len)
i = -1;
else if(ud->walkpath.path[ud->walkpath.path_pos]&1)
- i = status_get_speed(bl)*14/10;
+ i = status->get_speed(bl)*MOVE_DIAGONAL_COST/MOVE_COST;
else
- i = status_get_speed(bl);
+ i = status->get_speed(bl);
if( i > 0)
- ud->walktimer = iTimer->add_timer(iTimer->gettick()+i,unit_walktoxy_timer,bl->id,i);
+ ud->walktimer = timer->add(timer->gettick()+i,unit->walktoxy_timer,bl->id,i);
return 1;
}
-static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
int i;
int x,y,dx,dy;
uint8 dir;
@@ -123,13 +147,13 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
struct unit_data *ud;
struct mercenary_data *mrd;
- bl = iMap->id2bl(id);
+ bl = map->id2bl(id);
if(bl == NULL)
return 0;
sd = BL_CAST(BL_PC, bl);
md = BL_CAST(BL_MOB, bl);
mrd = BL_CAST(BL_MER, bl);
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
if(ud == NULL) return 0;
@@ -154,56 +178,61 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
dx = dirx[(int)dir];
dy = diry[(int)dir];
- if(iMap->getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS))
- return unit_walktoxy_sub(bl);
+ if(map->getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS))
+ return unit->walktoxy_sub(bl);
//Refresh view for all those we lose sight
- iMap->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl);
+ map->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl);
x += dx;
y += dy;
- iMap->moveblock(bl, x, y, tick);
+ map->moveblock(bl, x, y, tick);
ud->walk_count++; //walked cell counter, to be used for walk-triggered skills. [Skotlex]
status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); //If you move, you lose your counters. [malufett]
if (bl->x != x || bl->y != y || ud->walktimer != INVALID_TIMER)
- return 0; //iMap->moveblock has altered the object beyond what we expected (moved/warped it)
+ return 0; //map->moveblock has altered the object beyond what we expected (moved/warped it)
ud->walktimer = -2; // arbitrary non-INVALID_TIMER value to make the clif code send walking packets
- iMap->foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl);
+ map->foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl);
ud->walktimer = INVALID_TIMER;
if(sd) {
if( sd->touching_id )
- npc_touchnext_areanpc(sd,false);
- if(iMap->getcell(bl->m,x,y,CELL_CHKNPC)) {
- npc_touch_areanpc(sd,bl->m,x,y);
+ npc->touchnext_areanpc(sd,false);
+ if(map->getcell(bl->m,x,y,CELL_CHKNPC)) {
+ npc->touch_areanpc(sd,bl->m,x,y);
if (bl->prev == NULL) //Script could have warped char, abort remaining of the function.
return 0;
} else
sd->areanpc_id=0;
- if( sd->md && !check_distance_bl(&sd->bl, &sd->md->bl, MAX_MER_DISTANCE) )
- {
- // mercenary should be warped after being 3 seconds too far from the master [greenbox]
- if (sd->md->masterteleport_timer == 0)
- {
- sd->md->masterteleport_timer = iTimer->gettick();
- }
- else if (DIFF_TICK(iTimer->gettick(), sd->md->masterteleport_timer) > 3000)
- {
+ if( sd->md ) { // mercenary should be warped after being 3 seconds too far from the master [greenbox]
+ if( !check_distance_bl(&sd->bl, &sd->md->bl, MAX_MER_DISTANCE) ) {
+ if (sd->md->masterteleport_timer == 0)
+ sd->md->masterteleport_timer = timer->gettick();
+ else if (DIFF_TICK(timer->gettick(), sd->md->masterteleport_timer) > 3000) {
+ sd->md->masterteleport_timer = 0;
+ unit->warp( &sd->md->bl, sd->bl.m, sd->bl.x, sd->bl.y, CLR_TELEPORT );
+ }
+ } else // reset the tick, he is not far anymore
sd->md->masterteleport_timer = 0;
- unit_warp( &sd->md->bl, sd->bl.m, sd->bl.x, sd->bl.y, CLR_TELEPORT );
- }
+
}
- else if( sd->md )
- {
- // reset the tick, he is not far anymore
- sd->md->masterteleport_timer = 0;
+ if( sd->hd ) {
+ if( homun_alive(sd->hd) && !check_distance_bl(&sd->bl, &sd->hd->bl, MAX_MER_DISTANCE) ) {
+ if (sd->hd->masterteleport_timer == 0)
+ sd->hd->masterteleport_timer = timer->gettick();
+ else if (DIFF_TICK(timer->gettick(), sd->hd->masterteleport_timer) > 3000) {
+ sd->hd->masterteleport_timer = 0;
+ unit->warp( &sd->hd->bl, sd->bl.m, sd->bl.x, sd->bl.y, CLR_TELEPORT );
+ }
+ } else
+ sd->hd->masterteleport_timer = 0;
}
} else if (md) {
- if( iMap->getcell(bl->m,x,y,CELL_CHKNPC) ) {
- if( npc_touch_areanpc2(md) ) return 0; // Warped
+ if( map->getcell(bl->m,x,y,CELL_CHKNPC) ) {
+ if( npc->touch_areanpc2(md) ) return 0; // Warped
} else
md->areanpc_id = 0;
if (md->min_chase > md->db->range3) md->min_chase--;
@@ -211,11 +240,11 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
//But avoid triggering on stop-walk calls.
if(tid != INVALID_TIMER &&
!(ud->walk_count%WALK_SKILL_INTERVAL) &&
- mobskill_use(md, tick, -1))
+ mob->skill_use(md, tick, -1))
{
if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER))
{ //Skill used, abort walking
- clif->fixpos(bl); //Fix position as walk has been cancelled.
+ clif->fixpos(bl); //Fix position as walk has been canceled.
return 0;
}
//Resend walk packet for proper Self Destruction display.
@@ -229,12 +258,12 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
// mercenary should be warped after being 3 seconds too far from the master [greenbox]
if (mrd->masterteleport_timer == 0)
{
- mrd->masterteleport_timer = iTimer->gettick();
+ mrd->masterteleport_timer = timer->gettick();
}
- else if (DIFF_TICK(iTimer->gettick(), mrd->masterteleport_timer) > 3000)
+ else if (DIFF_TICK(timer->gettick(), mrd->masterteleport_timer) > 3000)
{
mrd->masterteleport_timer = 0;
- unit_warp( bl, mrd->master->bl.id, mrd->master->bl.x, mrd->master->bl.y, CLR_TELEPORT );
+ unit->warp( bl, mrd->master->bl.m, mrd->master->bl.x, mrd->master->bl.y, CLR_TELEPORT );
}
}
else
@@ -247,64 +276,63 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
return 0;
if(ud->state.change_walk_target)
- return unit_walktoxy_sub(bl);
+ return unit->walktoxy_sub(bl);
ud->walkpath.path_pos++;
if(ud->walkpath.path_pos>=ud->walkpath.path_len)
i = -1;
else if(ud->walkpath.path[ud->walkpath.path_pos]&1)
- i = status_get_speed(bl)*14/10;
+ i = status->get_speed(bl)*14/10;
else
- i = status_get_speed(bl);
+ i = status->get_speed(bl);
if(i > 0) {
- ud->walktimer = iTimer->add_timer(tick+i,unit_walktoxy_timer,id,i);
+ ud->walktimer = timer->add(tick+i,unit->walktoxy_timer,id,i);
if( md && DIFF_TICK(tick,md->dmgtick) < 3000 )//not required not damaged recently
clif->move(ud);
} else if(ud->state.running) {
//Keep trying to run.
- if ( !(unit_run(bl) || unit_wugdash(bl,sd)) )
+ if ( !(unit->run(bl, NULL, SC_RUN) || unit->run(bl, sd, SC_WUGDASH)) )
ud->state.running = 0;
- }
- else if (ud->target_to) {
+ } else if (ud->target_to) {
//Update target trajectory.
- struct block_list *tbl = iMap->id2bl(ud->target_to);
- if (!tbl || !status_check_visibility(bl, tbl)) { //Cancel chase.
+ struct block_list *tbl = map->id2bl(ud->target_to);
+ if (!tbl || !status->check_visibility(bl, tbl)) {
+ //Cancel chase.
ud->to_x = bl->x;
ud->to_y = bl->y;
- if (tbl && bl->type == BL_MOB && mob_warpchase((TBL_MOB*)bl, tbl) )
+ if (tbl && bl->type == BL_MOB && mob->warpchase((TBL_MOB*)bl, tbl) )
return 0;
ud->target_to = 0;
return 0;
}
- if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange))
- { //Reached destination.
+ if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange)) {
+ //Reached destination.
if (ud->state.attack_continue)
{ //Aegis uses one before every attack, we should
//only need this one for syncing purposes. [Skotlex]
ud->target_to = 0;
clif->fixpos(bl);
- unit_attack(bl, tbl->id, ud->state.attack_continue);
+ unit->attack(bl, tbl->id, ud->state.attack_continue);
}
} else { //Update chase-path
- unit_walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy|(ud->state.attack_continue?2:0));
+ unit->walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy|(ud->state.attack_continue?2:0));
return 0;
}
- }
- else { //Stopped walking. Update to_x and to_y to current location [Skotlex]
+ } else {
+ //Stopped walking. Update to_x and to_y to current location [Skotlex]
ud->to_x = bl->x;
ud->to_y = bl->y;
}
return 0;
}
-static int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct block_list *bl = iMap->id2bl(id);
+int unit_delay_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct block_list *bl = map->id2bl(id);
if (!bl || bl->prev == NULL)
return 0;
- unit_walktoxy(bl, (short)((data>>16)&0xffff), (short)(data&0xffff), 0);
+ unit->walktoxy(bl, (short)((data>>16)&0xffff), (short)(data&0xffff), 0);
return 1;
}
@@ -320,52 +348,58 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
nullpo_ret(bl);
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
if( ud == NULL) return 0;
- path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS); // Count walk path cells
+ if (!path->search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS)) // Count walk path cells
+ return 0;
+
#ifdef OFFICIAL_WALKPATH
- if( !path_search_long(NULL, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS) // Check if there is an obstacle between
+ if( !path->search_long(NULL, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS) // Check if there is an obstacle between
&& (wpd.path_len > (battle_config.max_walk_path/17)*14) // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
&& (bl->type != BL_NPC) ) // If type is a NPC, please disregard.
return 0;
#endif
- if( (battle_config.max_walk_path < wpd.path_len) && (bl->type != BL_NPC) )
+ if ((wpd.path_len > battle_config.max_walk_path) && (bl->type != BL_NPC))
return 0;
- if (flag&4 && DIFF_TICK(ud->canmove_tick, iTimer->gettick()) > 0 &&
- DIFF_TICK(ud->canmove_tick, iTimer->gettick()) < 2000)
- { // Delay walking command. [Skotlex]
- iTimer->add_timer(ud->canmove_tick+1, unit_delay_walktoxy_timer, bl->id, (x<<16)|(y&0xFFFF));
+ if (flag&4 && DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0 &&
+ DIFF_TICK(ud->canmove_tick, timer->gettick()) < 2000) {
+ // Delay walking command. [Skotlex]
+ timer->add(ud->canmove_tick+1, unit->delay_walktoxy_timer, bl->id, (x<<16)|(y&0xFFFF));
return 1;
}
- if(!(flag&2) && (!(status_get_mode(bl)&MD_CANMOVE) || !unit_can_move(bl)))
+ if(!(flag&2) && (!(status_get_mode(bl)&MD_CANMOVE) || !unit->can_move(bl)))
return 0;
ud->state.walk_easy = flag&1;
ud->to_x = x;
ud->to_y = y;
- unit_set_target(ud, 0);
+ unit->set_target(ud, 0);
- sc = status_get_sc(bl);
- if (sc && sc->data[SC_CONFUSION]) //Randomize the target position
- iMap->random_dir(bl, &ud->to_x, &ud->to_y);
+ sc = status->get_sc(bl);
+ if( sc ) {
+ if( sc->data[SC_CONFUSION] || sc->data[SC__CHAOS] ) //Randomize the target position
+ map->random_dir(bl, &ud->to_x, &ud->to_y);
+ if( sc->data[SC_COMBOATTACK] )
+ status_change_end(bl, SC_COMBOATTACK, INVALID_TIMER);
+ }
if(ud->walktimer != INVALID_TIMER) {
// When you come to the center of the grid because the change of destination while you're walking right now
- // Call a function from a timer unit_walktoxy_sub
+ // Call a function from a timer unit->walktoxy_sub
ud->state.change_walk_target = 1;
return 1;
}
if(ud->attacktimer != INVALID_TIMER) {
- iTimer->delete_timer( ud->attacktimer, unit_attack_timer );
+ timer->delete( ud->attacktimer, unit->attack_timer );
ud->attacktimer = INVALID_TIMER;
}
- return unit_walktoxy_sub(bl);
+ return unit->walktoxy_sub(bl);
}
//To set Mob's CHASE/FOLLOW states (shouldn't be done if there's no path to reach)
@@ -377,18 +411,15 @@ static inline void set_mobstate(struct block_list* bl, int flag)
md->state.skillstate = md->state.aggressive ? MSS_FOLLOW : MSS_RUSH;
}
-static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr_t data)
-{
- struct block_list *bl = iMap->id2bl(id);
- struct unit_data *ud = bl?unit_bl2ud(bl):NULL;
+int unit_walktobl_sub(int tid, int64 tick, int id, intptr_t data) {
+ struct block_list *bl = map->id2bl(id);
+ struct unit_data *ud = bl?unit->bl2ud(bl):NULL;
- if (ud && ud->walktimer == INVALID_TIMER && ud->target == data)
- {
+ if (ud && ud->walktimer == INVALID_TIMER && ud->target == data) {
if (DIFF_TICK(ud->canmove_tick, tick) > 0) //Keep waiting?
- iTimer->add_timer(ud->canmove_tick+1, unit_walktobl_sub, id, data);
- else if (unit_can_move(bl))
- {
- if (unit_walktoxy_sub(bl))
+ timer->add(ud->canmove_tick+1, unit->walktobl_sub, id, data);
+ else if (unit->can_move(bl)) {
+ if (unit->walktoxy_sub(bl))
set_mobstate(bl, ud->state.attack_continue);
}
}
@@ -405,13 +436,13 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
nullpo_ret(bl);
nullpo_ret(tbl);
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
if( ud == NULL) return 0;
if (!(status_get_mode(bl)&MD_CANMOVE))
return 0;
- if (!unit_can_reach_bl(bl, tbl, distance_bl(bl, tbl)+1, flag&1, &ud->to_x, &ud->to_y)) {
+ if (!unit->can_reach_bl(bl, tbl, distance_bl(bl, tbl)+1, flag&1, &ud->to_x, &ud->to_y)) {
ud->to_x = bl->x;
ud->to_y = bl->y;
ud->target_to = 0;
@@ -422,11 +453,11 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
ud->target_to = tbl->id;
ud->chaserange = range; //Note that if flag&2, this SHOULD be attack-range
ud->state.attack_continue = flag&2?1:0; //Chase to attack.
- unit_set_target(ud, 0);
+ unit->set_target(ud, 0);
- sc = status_get_sc(bl);
- if (sc && sc->data[SC_CONFUSION]) //Randomize the target position
- iMap->random_dir(bl, &ud->to_x, &ud->to_y);
+ sc = status->get_sc(bl);
+ if (sc && (sc->data[SC_CONFUSION] || sc->data[SC__CHAOS])) //Randomize the target position
+ map->random_dir(bl, &ud->to_x, &ud->to_y);
if(ud->walktimer != INVALID_TIMER) {
ud->state.change_walk_target = 1;
@@ -434,176 +465,129 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
return 1;
}
- if(DIFF_TICK(ud->canmove_tick, iTimer->gettick()) > 0)
+ if(DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0)
{ //Can't move, wait a bit before invoking the movement.
- iTimer->add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->target);
+ timer->add(ud->canmove_tick+1, unit->walktobl_sub, bl->id, ud->target);
return 1;
}
- if(!unit_can_move(bl))
+ if(!unit->can_move(bl))
return 0;
if(ud->attacktimer != INVALID_TIMER) {
- iTimer->delete_timer( ud->attacktimer, unit_attack_timer );
+ timer->delete( ud->attacktimer, unit->attack_timer );
ud->attacktimer = INVALID_TIMER;
}
- if (unit_walktoxy_sub(bl)) {
+ if (unit->walktoxy_sub(bl)) {
set_mobstate(bl, flag&2);
return 1;
}
return 0;
}
-int unit_run(struct block_list *bl)
-{
- struct status_change *sc = status_get_sc(bl);
- short to_x,to_y,dir_x,dir_y;
- int lv;
- int i;
-
- if (!(sc && sc->data[SC_RUN]))
- return 0;
-
- if (!unit_can_move(bl)) {
- status_change_end(bl, SC_RUN, INVALID_TIMER);
- return 0;
- }
-
- lv = sc->data[SC_RUN]->val1;
- dir_x = dirx[sc->data[SC_RUN]->val2];
- dir_y = diry[sc->data[SC_RUN]->val2];
-
- // determine destination cell
- to_x = bl->x;
- to_y = bl->y;
- for(i=0;i<AREA_SIZE;i++)
- {
- if(!iMap->getcell(bl->m,to_x+dir_x,to_y+dir_y,CELL_CHKPASS))
- break;
-
- //if sprinting and there's a PC/Mob/NPC, block the path [Kevin]
- if(sc->data[SC_RUN] && iMap->count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC))
- break;
- to_x += dir_x;
- to_y += dir_y;
- }
+/**
+ * Called by unit_run when an object was hit
+ * @param sd Required only when using SC_WUGDASH
+ **/
+void unit_run_hit( struct block_list *bl, struct status_change *sc, struct map_session_data *sd, enum sc_type type ) {
+ int lv = sc->data[type]->val1;
- if( (to_x == bl->x && to_y == bl->y ) || (to_x == (bl->x+1) || to_y == (bl->y+1)) || (to_x == (bl->x-1) || to_y == (bl->y-1))) {
- //If you can't run forward, you must be next to a wall, so bounce back. [Skotlex]
+ //If you can't run forward, you must be next to a wall, so bounce back. [Skotlex]
+ if( type == SC_RUN )
clif->sc_load(bl,bl->id,AREA,SI_TING,0,0,0);
- //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin]
- unit_bl2ud(bl)->state.running = 0;
- status_change_end(bl, SC_RUN, INVALID_TIMER);
+ //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin]
+ unit->bl2ud(bl)->state.running = 0;
+ status_change_end(bl, type, INVALID_TIMER);
- skill->blown(bl,bl,skill->get_blewcount(TK_RUN,lv),unit_getdir(bl),0);
+ if( type == SC_RUN ) {
+ skill->blown(bl,bl,skill->get_blewcount(TK_RUN,lv),unit->getdir(bl),0);
clif->fixpos(bl); //Why is a clif->slide (skill->blown) AND a fixpos needed? Ask Aegis.
clif->sc_end(bl,bl->id,AREA,SI_TING);
- return 0;
- }
- if (unit_walktoxy(bl, to_x, to_y, 1))
- return 1;
- //There must be an obstacle nearby. Attempt walking one cell at a time.
- do {
- to_x -= dir_x;
- to_y -= dir_y;
- } while (--i > 0 && !unit_walktoxy(bl, to_x, to_y, 1));
- if ( i == 0 ) {
- // copy-paste from above
- clif->sc_load(bl,bl->id,AREA,SI_TING,0,0,0);
-
- //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin]
- unit_bl2ud(bl)->state.running = 0;
- status_change_end(bl, SC_RUN, INVALID_TIMER);
-
- skill->blown(bl,bl,skill->get_blewcount(TK_RUN,lv),unit_getdir(bl),0);
+ } else if( sd ) {
clif->fixpos(bl);
- clif->sc_end(bl,bl->id,AREA,SI_TING);
- return 0;
+ skill->castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, timer->gettick(), SD_LEVEL);
}
- return 1;
+ return;
}
-//Exclusive function to Wug Dash state. [Jobbie/3CeAM]
-int unit_wugdash(struct block_list *bl, struct map_session_data *sd) {
- struct status_change *sc = status_get_sc(bl);
+/**
+ * Makes character run, used for SC_RUN and SC_WUGDASH
+ * @param sd Required only when using SC_WUGDASH
+ * @retval true Finished running
+ * @retval false Hit an object/Couldn't run
+ **/
+bool unit_run( struct block_list *bl, struct map_session_data *sd, enum sc_type type ) {
+ struct status_change *sc;
short to_x,to_y,dir_x,dir_y;
- int lv;
int i;
- if (!(sc && sc->data[SC_WUGDASH]))
- return 0;
- nullpo_ret(sd);
- nullpo_ret(bl);
+ nullpo_retr(false, bl);
+ sc = status->get_sc(bl);
- if (!unit_can_move(bl)) {
- status_change_end(bl,SC_WUGDASH,INVALID_TIMER);
- return 0;
+ if( !(sc && sc->data[type]) )
+ return false;
+
+ if( !unit->can_move(bl) ) {
+ status_change_end(bl, type, INVALID_TIMER);
+ return false;
}
- lv = sc->data[SC_WUGDASH]->val1;
- dir_x = dirx[sc->data[SC_WUGDASH]->val2];
- dir_y = diry[sc->data[SC_WUGDASH]->val2];
+ dir_x = dirx[sc->data[type]->val2];
+ dir_y = diry[sc->data[type]->val2];
+ // determine destination cell
to_x = bl->x;
to_y = bl->y;
- for(i=0;i<AREA_SIZE;i++)
- {
- if(!iMap->getcell(bl->m,to_x+dir_x,to_y+dir_y,CELL_CHKPASS))
+
+ // Search for available path
+ for(i = 0; i < AREA_SIZE; i++) {
+ if(!map->getcell(bl->m,to_x+dir_x,to_y+dir_y,CELL_CHKPASS))
break;
- if(sc->data[SC_WUGDASH] && iMap->count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC))
+ //if sprinting and there's a PC/Mob/NPC, block the path [Kevin]
+ if( map->count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC) )
break;
to_x += dir_x;
to_y += dir_y;
}
- if(to_x == bl->x && to_y == bl->y) {
+ // Can't run forward
+ if( (to_x == bl->x && to_y == bl->y ) || (to_x == (bl->x+1) || to_y == (bl->y+1)) || (to_x == (bl->x-1) || to_y == (bl->y-1))) {
+ unit->run_hit(bl, sc, sd, type);
+ return false;
+ }
- unit_bl2ud(bl)->state.running = 0;
- status_change_end(bl,SC_WUGDASH,INVALID_TIMER);
+ if( unit->walktoxy(bl, to_x, to_y, 1) )
+ return true;
- if( sd ){
- clif->fixpos(bl);
- skill->castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, iTimer->gettick(), SD_LEVEL);
- }
- return 0;
- }
- if (unit_walktoxy(bl, to_x, to_y, 1))
- return 1;
+ //There must be an obstacle nearby. Attempt walking one cell at a time.
do {
to_x -= dir_x;
to_y -= dir_y;
- } while (--i > 0 && !unit_walktoxy(bl, to_x, to_y, 1));
- if (i==0) {
+ } while (--i > 0 && !unit->walktoxy(bl, to_x, to_y, 1));
- unit_bl2ud(bl)->state.running = 0;
- status_change_end(bl,SC_WUGDASH,INVALID_TIMER);
-
- if( sd ){
- clif->fixpos(bl);
- skill->castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, iTimer->gettick(), SD_LEVEL);
- }
- return 0;
+ if ( i == 0 ) {
+ unit->run_hit(bl, sc, sd, type);
+ return false;
}
+
return 1;
}
//Makes bl attempt to run dist cells away from target. Uses hard-paths.
-int unit_escape(struct block_list *bl, struct block_list *target, short dist)
-{
- uint8 dir = iMap->calc_dir(target, bl->x, bl->y);
- while( dist > 0 && iMap->getcell(bl->m, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], CELL_CHKNOREACH) )
+int unit_escape(struct block_list *bl, struct block_list *target, short dist) {
+ uint8 dir = map->calc_dir(target, bl->x, bl->y);
+ while( dist > 0 && map->getcell(bl->m, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], CELL_CHKNOREACH) )
dist--;
- return ( dist > 0 && unit_walktoxy(bl, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], 0) );
+ return ( dist > 0 && unit->walktoxy(bl, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], 0) );
}
//Instant warp function.
-int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath)
-{
+int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath) {
short dx,dy;
uint8 dir;
struct unit_data *ud = NULL;
@@ -611,38 +595,38 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool
nullpo_ret(bl);
sd = BL_CAST(BL_PC, bl);
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
if( ud == NULL) return 0;
- unit_stop_walking(bl,1);
- unit_stop_attack(bl);
+ unit->stop_walking(bl,1);
+ unit->stop_attack(bl);
- if( checkpath && (iMap->getcell(bl->m,dst_x,dst_y,CELL_CHKNOPASS) || !path_search(NULL,bl->m,bl->x,bl->y,dst_x,dst_y,easy,CELL_CHKNOREACH)) )
+ if( checkpath && (map->getcell(bl->m,dst_x,dst_y,CELL_CHKNOPASS) || !path->search(NULL,bl->m,bl->x,bl->y,dst_x,dst_y,easy,CELL_CHKNOREACH)) )
return 0; // unreachable
ud->to_x = dst_x;
ud->to_y = dst_y;
- dir = iMap->calc_dir(bl, dst_x, dst_y);
+ dir = map->calc_dir(bl, dst_x, dst_y);
ud->dir = dir;
dx = dst_x - bl->x;
dy = dst_y - bl->y;
- iMap->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl);
+ map->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl);
- iMap->moveblock(bl, dst_x, dst_y, iTimer->gettick());
+ map->moveblock(bl, dst_x, dst_y, timer->gettick());
ud->walktimer = -2; // arbitrary non-INVALID_TIMER value to make the clif code send walking packets
- iMap->foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl);
+ map->foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl);
ud->walktimer = INVALID_TIMER;
if(sd) {
if( sd->touching_id )
- npc_touchnext_areanpc(sd,false);
- if(iMap->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) {
- npc_touch_areanpc(sd,bl->m,bl->x,bl->y);
+ npc->touchnext_areanpc(sd,false);
+ if(map->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) {
+ npc->touch_areanpc(sd,bl->m,bl->x,bl->y);
if (bl->prev == NULL) //Script could have warped char, abort remaining of the function.
return 0;
} else
@@ -651,15 +635,15 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool
if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 )
{ // Check if pet needs to be teleported. [Skotlex]
int flag = 0;
- struct block_list* bl = &sd->pd->bl;
- if( !checkpath && !path_search(NULL,bl->m,bl->x,bl->y,dst_x,dst_y,0,CELL_CHKNOPASS) )
+ struct block_list* pbl = &sd->pd->bl;
+ if( !checkpath && !path->search(NULL,pbl->m,pbl->x,pbl->y,dst_x,dst_y,0,CELL_CHKNOPASS) )
flag = 1;
- else if (!check_distance_bl(&sd->bl, bl, AREA_SIZE)) //Too far, teleport.
+ else if (!check_distance_bl(&sd->bl, pbl, AREA_SIZE)) //Too far, teleport.
flag = 2;
if( flag )
{
- unit_movepos(bl,sd->bl.x,sd->bl.y, 0, 0);
- clif->slide(bl,bl->x,bl->y);
+ unit->movepos(pbl,sd->bl.x,sd->bl.y, 0, 0);
+ clif->slide(pbl,pbl->x,pbl->y);
}
}
}
@@ -670,7 +654,7 @@ int unit_setdir(struct block_list *bl,unsigned char dir)
{
struct unit_data *ud;
nullpo_ret(bl );
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
if (!ud) return 0;
ud->dir = dir;
if (bl->type == BL_PC)
@@ -685,7 +669,7 @@ uint8 unit_getdir(struct block_list *bl) {
if( bl->type == BL_NPC )
return ((TBL_NPC*)bl)->dir;
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
if (!ud) return 0;
return ud->dir;
}
@@ -701,16 +685,18 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
struct skill_unit* su = NULL;
int nx, ny, result;
+ nullpo_ret(bl);
+
sd = BL_CAST(BL_PC, bl);
su = BL_CAST(BL_SKILL, bl);
- result = path_blownpos(bl->m, bl->x, bl->y, dx, dy, count);
+ result = path->blownpos(bl->m, bl->x, bl->y, dx, dy, count);
nx = result>>16;
ny = result&0xffff;
if(!su) {
- unit_stop_walking(bl, 0);
+ unit->stop_walking(bl, 0);
}
if( sd ) {
@@ -722,15 +708,15 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
dy = ny-bl->y;
if(dx || dy) {
- iMap->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl);
+ map->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl);
if(su) {
skill->unit_move_unit_group(su->group, bl->m, dx, dy);
} else {
- iMap->moveblock(bl, nx, ny, iTimer->gettick());
+ map->moveblock(bl, nx, ny, timer->gettick());
}
- iMap->foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl);
+ map->foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl);
if(!(flag&1)) {
clif->blown(bl);
@@ -738,17 +724,17 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
if(sd) {
if(sd->touching_id) {
- npc_touchnext_areanpc(sd, false);
+ npc->touchnext_areanpc(sd, false);
}
- if(iMap->getcell(bl->m, bl->x, bl->y, CELL_CHKNPC)) {
- npc_touch_areanpc(sd, bl->m, bl->x, bl->y);
+ if(map->getcell(bl->m, bl->x, bl->y, CELL_CHKNPC)) {
+ npc->touch_areanpc(sd, bl->m, bl->x, bl->y);
} else {
sd->areanpc_id = 0;
}
}
}
- count = distance(dx, dy);
+ count = path->distance(dx, dy);
}
return count; // return amount of knocked back cells
@@ -761,7 +747,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
{
struct unit_data *ud;
nullpo_ret(bl);
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
if(bl->prev==NULL || !ud)
return 1;
@@ -775,31 +761,31 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
switch (bl->type) {
case BL_MOB:
- if (map[bl->m].flag.monster_noteleport && ((TBL_MOB*)bl)->master_id == 0)
+ if (map->list[bl->m].flag.monster_noteleport && ((TBL_MOB*)bl)->master_id == 0)
return 1;
- if (m != bl->m && map[m].flag.nobranch && battle_config.mob_warp&4 && !(((TBL_MOB *)bl)->master_id))
+ if (m != bl->m && map->list[m].flag.nobranch && battle_config.mob_warp&4 && !(((TBL_MOB *)bl)->master_id))
return 1;
break;
case BL_PC:
- if (map[bl->m].flag.noteleport)
+ if (map->list[bl->m].flag.noteleport)
return 1;
break;
}
- if (x<0 || y<0)
- { //Random map position.
- if (!iMap->search_freecell(NULL, m, &x, &y, -1, -1, 1)) {
- ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y);
+ if (x<0 || y<0) {
+ //Random map position.
+ if (!map->search_freecell(NULL, m, &x, &y, -1, -1, 1)) {
+ ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map->list[m].name, x, y);
return 2;
}
- } else if (iMap->getcell(m,x,y,CELL_CHKNOREACH))
- { //Invalid target cell
- ShowWarning("unit_warp: Specified non-walkable target cell: %d (%s) at [%d,%d]\n", m, map[m].name, x,y);
+ } else if (map->getcell(m,x,y,CELL_CHKNOREACH)) {
+ //Invalid target cell
+ ShowWarning("unit_warp: Specified non-walkable target cell: %d (%s) at [%d,%d]\n", m, map->list[m].name, x,y);
- if (!iMap->search_freecell(NULL, m, &x, &y, 4, 4, 1))
- { //Can't find a nearby cell
- ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y);
+ if (!map->search_freecell(NULL, m, &x, &y, 4, 4, 1)) {
+ //Can't find a nearby cell
+ ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map->list[m].name, x, y);
return 2;
}
}
@@ -807,7 +793,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
if (bl->type == BL_PC) //Use pc_setpos
return pc->setpos((TBL_PC*)bl, map_id2index(m), x, y, type);
- if (!unit_remove_map(bl, type))
+ if (!unit->remove_map(bl, type, ALC_MARK))
return 3;
if (bl->m != m && battle_config.clear_unit_onwarp &&
@@ -818,9 +804,9 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
bl->y=ud->to_y=y;
bl->m=m;
- iMap->addblock(bl);
+ map->addblock(bl);
clif->spawn(bl);
- skill->unit_move(bl,iTimer->gettick(),1);
+ skill->unit_move(bl,timer->gettick(),1);
return 0;
}
@@ -837,25 +823,25 @@ int unit_stop_walking(struct block_list *bl,int type)
{
struct unit_data *ud;
const struct TimerData* td;
- unsigned int tick;
+ int64 tick;
nullpo_ret(bl);
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
if(!ud || ud->walktimer == INVALID_TIMER)
return 0;
//NOTE: We are using timer data after deleting it because we know the
- //iTimer->delete_timer function does not messes with it. If the function's
- //behaviour changes in the future, this code could break!
- td = iTimer->get_timer(ud->walktimer);
- iTimer->delete_timer(ud->walktimer, unit_walktoxy_timer);
+ //timer->delete function does not messes with it. If the function's
+ //behavior changes in the future, this code could break!
+ td = timer->get(ud->walktimer);
+ timer->delete(ud->walktimer, unit->walktoxy_timer);
ud->walktimer = INVALID_TIMER;
ud->state.change_walk_target = 0;
- tick = iTimer->gettick();
+ tick = timer->gettick();
if( (type&0x02 && !ud->walkpath.path_pos) //Force moving at least one cell.
|| (type&0x04 && td && DIFF_TICK(td->tick, tick) <= td->data/2) //Enough time has passed to cover half-cell
) {
ud->walkpath.path_len = ud->walkpath.path_pos+1;
- unit_walktoxy_timer(INVALID_TIMER, tick, bl->id, ud->walkpath.path_pos);
+ unit->walktoxy_timer(INVALID_TIMER, tick, bl->id, ud->walkpath.path_pos);
}
if(type&0x01)
@@ -866,9 +852,9 @@ int unit_stop_walking(struct block_list *bl,int type)
ud->to_x = bl->x;
ud->to_y = bl->y;
if(bl->type == BL_PET && type&~0xff)
- ud->canmove_tick = iTimer->gettick() + (type>>8);
+ ud->canmove_tick = timer->gettick() + (type>>8);
- //Readded, the check in unit_set_walkdelay means dmg during running won't fall through to this place in code [Kevin]
+ //Read, the check in unit_set_walkdelay means dmg during running won't fall through to this place in code [Kevin]
if (ud->state.running) {
status_change_end(bl, SC_RUN, INVALID_TIMER);
status_change_end(bl, SC_WUGDASH, INVALID_TIMER);
@@ -878,7 +864,7 @@ int unit_stop_walking(struct block_list *bl,int type)
int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv)
{
- return unit_skilluse_id2(
+ return unit->skilluse_id2(
src, target_id, skill_id, skill_lv,
skill->cast_fix(src, skill_id, skill_lv),
skill->get_castcancel(skill_id)
@@ -887,7 +873,7 @@ int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uin
int unit_is_walking(struct block_list *bl)
{
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
nullpo_ret(bl);
if(!ud) return 0;
return (ud->walktimer != INVALID_TIMER);
@@ -902,8 +888,8 @@ int unit_can_move(struct block_list *bl) {
struct status_change *sc;
nullpo_ret(bl);
- ud = unit_bl2ud(bl);
- sc = status_get_sc(bl);
+ ud = unit->bl2ud(bl);
+ sc = status->get_sc(bl);
sd = BL_CAST(BL_PC, bl);
if (!ud)
@@ -912,7 +898,7 @@ int unit_can_move(struct block_list *bl) {
if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK && (!sd || !pc->checkskill(sd, SA_FREECAST) || skill->get_inf2(ud->skill_id)&INF2_GUILD_SKILL))
return 0; // prevent moving while casting
- if (DIFF_TICK(ud->canmove_tick, iTimer->gettick()) > 0)
+ if (DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0)
return 0;
if (sd && (
@@ -923,46 +909,52 @@ int unit_can_move(struct block_list *bl) {
))
return 0; //Can't move
+ // Status changes that block movement
if (sc) {
- if( sc->count && (
- sc->data[SC_ANKLESNARE]
- || sc->data[SC_AUTOCOUNTER]
- || sc->data[SC_TRICKDEAD]
- || sc->data[SC_BLADESTOP]
- || sc->data[SC_BLADESTOP_WAIT]
- || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect
- || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move
- || sc->data[SC_STOP]
- || sc->data[SC_RG_CCONFINE_M]
- || sc->data[SC_RG_CCONFINE_S]
- || sc->data[SC_GS_MADNESSCANCEL]
- || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF)
- || sc->data[SC_WHITEIMPRISON]
- || sc->data[SC_ELECTRICSHOCKER]
- || sc->data[SC_WUGBITE]
- || sc->data[SC_THORNS_TRAP]
- || sc->data[SC_MAGNETICFIELD]
- || sc->data[SC__MANHOLE]
- || sc->data[SC_CURSEDCIRCLE_ATKER]
- || sc->data[SC_CURSEDCIRCLE_TARGET]
- || (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB)
- || sc->data[SC_NETHERWORLD]
- || (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3 && !(sc->data[SC_CAMOUFLAGE]->val3&1))
- || sc->data[SC_MEIKYOUSISUI]
- || sc->data[SC_KG_KAGEHUMI]
- || sc->data[SC_KYOUGAKU]
- || sc->data[SC_NEEDLE_OF_PARALYZE]
- || sc->data[SC_VACUUM_EXTREME]
- || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0)
- || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1)
- || (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && (
- !sc->data[SC_LONGING] ||
- (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT ||
- (sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE
- ) )
- || (sc->data[SC_CLOAKING] && //Need wall at level 1-2
- sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1))
- ) )
+ if( sc->count
+ && (
+ sc->data[SC_ANKLESNARE]
+ || sc->data[SC_AUTOCOUNTER]
+ || sc->data[SC_TRICKDEAD]
+ || sc->data[SC_BLADESTOP]
+ || sc->data[SC_BLADESTOP_WAIT]
+ || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect
+ || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move
+ || sc->data[SC_STOP]
+ || sc->data[SC_FALLENEMPIRE]
+ || sc->data[SC_RG_CCONFINE_M]
+ || sc->data[SC_RG_CCONFINE_S]
+ || sc->data[SC_GS_MADNESSCANCEL]
+ || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF)
+ || sc->data[SC_WHITEIMPRISON]
+ || sc->data[SC_ELECTRICSHOCKER]
+ || sc->data[SC_WUGBITE]
+ || sc->data[SC_THORNS_TRAP]
+ || sc->data[SC_MAGNETICFIELD]
+ || sc->data[SC__MANHOLE]
+ || sc->data[SC_CURSEDCIRCLE_ATKER]
+ || sc->data[SC_CURSEDCIRCLE_TARGET]
+ || (sc->data[SC_COLD] && bl->type != BL_MOB)
+ || sc->data[SC_DEEP_SLEEP]
+ || (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3 && !(sc->data[SC_CAMOUFLAGE]->val3&1))
+ || sc->data[SC_MEIKYOUSISUI]
+ || sc->data[SC_KG_KAGEHUMI]
+ || sc->data[SC_KYOUGAKU]
+ || sc->data[SC_NEEDLE_OF_PARALYZE]
+ || sc->data[SC_VACUUM_EXTREME]
+ || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0)
+ || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1)
+ || (sc->data[SC_CLOAKING] && sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)) //Need wall at level 1-2
+ || (
+ sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4
+ && (
+ !sc->data[SC_LONGING]
+ || (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT
+ || (sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE
+ )
+ )
+ )
+ )
return 0;
@@ -980,18 +972,17 @@ int unit_can_move(struct block_list *bl) {
* Resume running after a walk delay
*------------------------------------------*/
-int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data)
-{
+int unit_resume_running(int tid, int64 tick, int id, intptr_t data) {
struct unit_data *ud = (struct unit_data *)data;
- TBL_PC * sd = iMap->id2sd(id);
+ TBL_PC * sd = map->id2sd(id);
if(sd && pc_isridingwug(sd))
clif->skill_nodamage(ud->bl,ud->bl,RA_WUGDASH,ud->skill_lv,
- sc_start4(ud->bl,status_skill2sc(RA_WUGDASH),100,ud->skill_lv,unit_getdir(ud->bl),0,0,1));
+ sc_start4(ud->bl,ud->bl,status->skill2sc(RA_WUGDASH),100,ud->skill_lv,unit->getdir(ud->bl),0,0,1));
else
clif->skill_nodamage(ud->bl,ud->bl,TK_RUN,ud->skill_lv,
- sc_start4(ud->bl,status_skill2sc(TK_RUN),100,ud->skill_lv,unit_getdir(ud->bl),0,0,0));
+ sc_start4(ud->bl,ud->bl,status->skill2sc(TK_RUN),100,ud->skill_lv,unit->getdir(ud->bl),0,0,0));
if (sd) clif->walkok(sd);
@@ -1005,9 +996,8 @@ int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data)
* if type is 0, this is a damage induced delay: if previous delay is active, do not change it.
* if type is 1, this is a skill induced delay: walk-delay may only be increased, not decreased.
*------------------------------------------*/
-int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int type)
-{
- struct unit_data *ud = unit_bl2ud(bl);
+int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) {
+ struct unit_data *ud = unit->bl2ud(bl);
if (delay <= 0 || !ud) return 0;
/**
@@ -1021,7 +1011,7 @@ int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int
return 0;
} else {
//Don't set walk delays when already trapped.
- if (!unit_can_move(bl))
+ if (!unit->can_move(bl))
return 0;
}
ud->canmove_tick = tick + delay;
@@ -1029,52 +1019,55 @@ int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int
{ //Stop walking, if chasing, readjust timers.
if (delay == 1)
{ //Minimal delay (walk-delay) disabled. Just stop walking.
- unit_stop_walking(bl,4);
+ unit->stop_walking(bl,4);
} else {
//Resume running after can move again [Kevin]
if(ud->state.running)
{
- iTimer->add_timer(ud->canmove_tick, unit_resume_running, bl->id, (intptr_t)ud);
+ timer->add(ud->canmove_tick, unit->resume_running, bl->id, (intptr_t)ud);
}
else
{
- unit_stop_walking(bl,2|4);
+ unit->stop_walking(bl,2|4);
if(ud->target)
- iTimer->add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->target);
+ timer->add(ud->canmove_tick+1, unit->walktobl_sub, bl->id, ud->target);
}
}
}
return 1;
}
-int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel)
-{
+int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel) {
struct unit_data *ud;
struct status_data *tstatus;
struct status_change *sc;
struct map_session_data *sd = NULL;
struct block_list * target = NULL;
- unsigned int tick = iTimer->gettick();
+ int64 tick = timer->gettick();
int temp = 0, range;
nullpo_ret(src);
- if(status_isdead(src))
+ if(status->isdead(src))
return 0; //Do not continue source is dead
sd = BL_CAST(BL_PC, src);
- ud = unit_bl2ud(src);
+ ud = unit->bl2ud(src);
if(ud == NULL) return 0;
- sc = status_get_sc(src);
+ sc = status->get_sc(src);
if (sc && !sc->count)
sc = NULL; //Unneeded
//temp: used to signal combo-skills right now.
- if (sc && sc->data[SC_COMBOATTACK] && (sc->data[SC_COMBOATTACK]->val1 == skill_id ||
- (sd?skill->check_condition_castbegin(sd,skill_id,skill_lv):0) )) {
+ if (sc && sc->data[SC_COMBOATTACK]
+ && skill->is_combo(skill_id)
+ && (sc->data[SC_COMBOATTACK]->val1 == skill_id
+ || ( sd?skill->check_condition_castbegin(sd,skill_id,skill_lv):0 )
+ )
+ ) {
if (sc->data[SC_COMBOATTACK]->val2)
target_id = sc->data[SC_COMBOATTACK]->val2;
- else
+ else if( skill->get_inf(skill_id) != 1 ) // Only non-targetable skills should use auto target
target_id = ud->target;
if( skill->get_inf(skill_id)&INF_SELF_SKILL && skill->get_nk(skill_id)&NK_NO_DAMAGE )// exploit fix
@@ -1095,8 +1088,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
switch(skill_id) { //Check for skills that auto-select target
case MO_CHAINCOMBO:
- if (sc && sc->data[SC_BLADESTOP]){
- if ((target=iMap->id2bl(sc->data[SC_BLADESTOP]->val4)) == NULL)
+ if (sc && sc->data[SC_BLADESTOP]) {
+ if ((target=map->id2bl(sc->data[SC_BLADESTOP]->val4)) == NULL)
return 0;
}
break;
@@ -1104,7 +1097,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
case WE_FEMALE:
if (!sd->status.partner_id)
return 0;
- target = (struct block_list*)iMap->charid2sd(sd->status.partner_id);
+ target = (struct block_list*)map->charid2sd(sd->status.partner_id);
if (!target) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
@@ -1127,12 +1120,12 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
}
if( !target ) // choose default target
- target = iMap->id2bl(target_id);
+ target = map->id2bl(target_id);
if( !target || src->m != target->m || !src->prev || !target->prev )
return 0;
- if( battle_config.ksprotection && sd && mob_ksprotected(src, target) )
+ if( battle_config.ksprotection && sd && mob->ksprotected(src, target) )
return 0;
//Normally not needed because clif.c checks for it, but the at/char/script commands don't! [Skotlex]
@@ -1142,17 +1135,17 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if(skill->get_inf2(skill_id)&INF2_NO_TARGET_SELF && src->id == target_id)
return 0;
- if(!status_check_skilluse(src, target, skill_id, 0))
+ if(!status->check_skilluse(src, target, skill_id, 0))
return 0;
- tstatus = status_get_status_data(target);
+ tstatus = status->get_status_data(target);
// Record the status of the previous skill)
if(sd) {
if( (skill->get_inf2(skill_id)&INF2_ENSEMBLE_SKILL) && skill->check_pc_partner(sd, skill_id, &skill_lv, 1, 0) < 1 ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- return 0;
- }
+ return 0;
+ }
switch(skill_id){
case SA_CASTCANCEL:
@@ -1209,7 +1202,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
//(these are supposed to always have the same range as your attack)
if( src->id != target_id && (!temp || ud->attacktimer == INVALID_TIMER) ) {
if( skill->get_state(ud->skill_id) == ST_MOVE_ENABLE ) {
- if( !unit_can_reach_bl(src, target, range + 1, 1, NULL, NULL) )
+ if( !unit->can_reach_bl(src, target, range + 1, 1, NULL, NULL) )
return 0; // Walk-path check failed.
} else if( src->type == BL_MER && skill_id == MA_REMOVETRAP ) {
if( !battle->check_range(battle->get_master(src), target, range + 1) )
@@ -1220,8 +1213,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
}
if (!temp) //Stop attack on non-combo skills [Skotlex]
- unit_stop_attack(src);
- else if(ud->attacktimer != INVALID_TIMER) //Elsewise, delay current attack sequence
+ unit->stop_attack(src);
+ else if(ud->attacktimer != INVALID_TIMER) //Else-wise, delay current attack sequence
ud->attackabletime = tick + status_get_adelay(src);
ud->state.skillcastcancel = castcancel;
@@ -1233,7 +1226,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
case ALL_RESURRECTION:
if(battle->check_undead(tstatus->race,tstatus->def_ele)) {
temp = 1;
- } else if (!status_isdead(target))
+ } else if (!status->isdead(target))
return 0; //Can't cast on non-dead characters.
break;
case MO_FINGEROFFENSIVE:
@@ -1302,6 +1295,13 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
}
}
break;
+ case NC_DISJOINT:
+ if( target->type == BL_PC ){
+ struct mob_data *md;
+ if( (md = map->id2md(target->id)) && md->master_id != src->id )
+ casttime <<= 1;
+ }
+ break;
}
// moved here to prevent Suffragium from ending if skill fails
@@ -1316,17 +1316,30 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
casttime = 0;
}
+ if( sc ) {
+ /**
+ * why the if else chain: these 3 status do not stack, so its efficient that way.
+ **/
+ if( sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4) && skill_id != AS_CLOAKING ) {
+ status_change_end(src, SC_CLOAKING, INVALID_TIMER);
+ if (!src->prev) return 0; //Warped away!
+ } else if( sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4&4) && skill_id != GC_CLOAKINGEXCEED ) {
+ status_change_end(src,SC_CLOAKINGEXCEED, INVALID_TIMER);
+ if (!src->prev) return 0;
+ }
+ }
+
if(!ud->state.running) //need TK_RUN or WUGDASH handler to be done before that, see bugreport:6026
- unit_stop_walking(src,1);// eventhough this is not how official works but this will do the trick. bugreport:6829
+ unit->stop_walking(src,1);// even though this is not how official works but this will do the trick. bugreport:6829
// in official this is triggered even if no cast time.
clif->skillcasting(src, src->id, target_id, 0,0, skill_id, skill->get_ele(skill_id, skill_lv), casttime);
if( casttime > 0 || temp )
- {
+ {
if (sd && target->type == BL_MOB)
{
TBL_MOB *md = (TBL_MOB*)target;
- mobskill_event(md, src, tick, -1); //Cast targetted skill event.
+ mob->skill_event(md, src, tick, -1); //Cast targeted skill event.
if (tstatus->mode&(MD_CASTSENSOR_IDLE|MD_CASTSENSOR_CHASE) &&
battle->check_target(target, src, BCT_ENEMY) > 0)
{
@@ -1372,22 +1385,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
ud->skill_id = skill_id;
ud->skill_lv = skill_lv;
- if( sc ) {
- /**
- * why the if else chain: these 3 status do not stack, so its efficient that way.
- **/
- if( sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4) && skill_id != AS_CLOAKING ) {
- status_change_end(src, SC_CLOAKING, INVALID_TIMER);
- if (!src->prev) return 0; //Warped away!
- } else if( sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4&4) && skill_id != GC_CLOAKINGEXCEED ) {
- status_change_end(src,SC_CLOAKINGEXCEED, INVALID_TIMER);
- if (!src->prev) return 0;
- }
- }
-
-
if( casttime > 0 ) {
- ud->skilltimer = iTimer->add_timer( tick+casttime, skill->castend_id, src->id, 0 );
+ ud->skilltimer = timer->add( tick+casttime, skill->castend_id, src->id, 0 );
if( sd && (pc->checkskill(sd,SA_FREECAST) > 0 || skill_id == LG_EXEEDBREAK) )
status_calc_bl(&sd->bl, SCB_SPEED);
} else
@@ -1398,7 +1397,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv)
{
- return unit_skilluse_pos2(
+ return unit->skilluse_pos2(
src, skill_x, skill_y, skill_id, skill_lv,
skill->cast_fix(src, skill_id, skill_lv),
skill->get_castcancel(skill_id)
@@ -1411,22 +1410,22 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
struct unit_data *ud = NULL;
struct status_change *sc;
struct block_list bl;
- unsigned int tick = iTimer->gettick();
+ int64 tick = timer->gettick();
int range;
nullpo_ret(src);
if (!src->prev) return 0; // not on the map
- if(status_isdead(src)) return 0;
+ if(status->isdead(src)) return 0;
sd = BL_CAST(BL_PC, src);
- ud = unit_bl2ud(src);
+ ud = unit->bl2ud(src);
if(ud == NULL) return 0;
if(ud->skilltimer != INVALID_TIMER) //Normally not needed since clif.c checks for it, but at/char/script commands don't! [Skotlex]
return 0;
- sc = status_get_sc(src);
+ sc = status->get_sc(src);
if (sc && !sc->count)
sc = NULL;
@@ -1435,20 +1434,20 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
if( skill->not_ok(skill_id, sd) || !skill->check_condition_castbegin(sd, skill_id, skill_lv) )
return 0;
/**
- * "WHY IS IT HEREE": pneuma cannot be cancelled past this point, the client displays the animation even,
+ * "WHY IS IT HEREE": pneuma cannot be canceled past this point, the client displays the animation even,
* if we cancel it from nodamage_id, so it has to be here for it to not display the animation.
**/
- if( skill_id == AL_PNEUMA && iMap->getcell(src->m, skill_x, skill_y, CELL_CHKLANDPROTECTOR) ) {
+ if( skill_id == AL_PNEUMA && map->getcell(src->m, skill_x, skill_y, CELL_CHKLANDPROTECTOR) ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
}
- if (!status_check_skilluse(src, NULL, skill_id, 0))
+ if (!status->check_skilluse(src, NULL, skill_id, 0))
return 0;
- if( iMap->getcell(src->m, skill_x, skill_y, CELL_CHKWALL) )
- {// can't cast ground targeted spells on wall cells
+ if( map->getcell(src->m, skill_x, skill_y, CELL_CHKWALL) ) {
+ // can't cast ground targeted spells on wall cells
if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
@@ -1465,12 +1464,12 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
range = skill->get_range2(src, skill_id, skill_lv); // Skill cast distance from database
if( skill->get_state(ud->skill_id) == ST_MOVE_ENABLE ) {
- if( !unit_can_reach_bl(src, &bl, range + 1, 1, NULL, NULL) )
+ if( !unit->can_reach_bl(src, &bl, range + 1, 1, NULL, NULL) )
return 0; //Walk-path check failed.
} else if( !battle->check_range(src, &bl, range + 1) )
return 0; //Arrow-path check failed.
- unit_stop_attack(src);
+ unit->stop_attack(src);
// moved here to prevent Suffragium from ending if skill fails
#ifndef RENEWAL_CAST
@@ -1514,13 +1513,13 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
}
}
- unit_stop_walking(src,1);
+ unit->stop_walking(src,1);
// in official this is triggered even if no cast time.
clif->skillcasting(src, src->id, 0, skill_x, skill_y, skill_id, skill->get_ele(skill_id, skill_lv), casttime);
if( casttime > 0 ) {
- ud->skilltimer = iTimer->add_timer( tick+casttime, skill->castend_pos, src->id, 0 );
+ ud->skilltimer = timer->add( tick+casttime, skill->castend_pos, src->id, 0 );
if( (sd && pc->checkskill(sd,SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK)
- status_calc_bl(&sd->bl, SCB_SPEED);
+ status_calc_bl(&sd->bl, SCB_SPEED);
} else {
ud->skilltimer = INVALID_TIMER;
skill->castend_pos(ud->skilltimer,tick,src->id,0);
@@ -1539,9 +1538,9 @@ int unit_set_target(struct unit_data* ud, int target_id)
nullpo_ret(ud);
if( ud->target != target_id ) {
- if( ud->target && (target = iMap->id2bl(ud->target)) && (ux = unit_bl2ud(target)) && ux->target_count > 0 )
+ if( ud->target && (target = map->id2bl(ud->target)) && (ux = unit->bl2ud(target)) && ux->target_count > 0 )
ux->target_count --;
- if( target_id && (target = iMap->id2bl(target_id)) && (ux = unit_bl2ud(target)) )
+ if( target_id && (target = map->id2bl(target_id)) && (ux = unit->bl2ud(target)) )
ux->target_count ++;
}
@@ -1551,31 +1550,31 @@ int unit_set_target(struct unit_data* ud, int target_id)
int unit_stop_attack(struct block_list *bl)
{
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
nullpo_ret(bl);
if(!ud || ud->attacktimer == INVALID_TIMER)
return 0;
- iTimer->delete_timer( ud->attacktimer, unit_attack_timer );
+ timer->delete( ud->attacktimer, unit->attack_timer );
ud->attacktimer = INVALID_TIMER;
- unit_set_target(ud, 0);
+ unit->set_target(ud, 0);
return 0;
}
//Means current target is unattackable. For now only unlocks mobs.
int unit_unattackable(struct block_list *bl)
{
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
if (ud) {
ud->state.attack_continue = 0;
- unit_set_target(ud, 0);
+ unit->set_target(ud, 0);
}
if(bl->type == BL_MOB)
- mob_unlocktarget((struct mob_data*)bl, iTimer->gettick()) ;
+ mob->unlocktarget((struct mob_data*)bl, timer->gettick()) ;
else if(bl->type == BL_PET)
- pet_unlocktarget((struct pet_data*)bl);
+ pet->unlocktarget((struct pet_data*)bl);
return 0;
}
@@ -1583,38 +1582,41 @@ int unit_unattackable(struct block_list *bl)
* Attack request
* If type is an ongoing attack
*------------------------------------------*/
-int unit_attack(struct block_list *src,int target_id,int continuous)
-{
+int unit_attack(struct block_list *src,int target_id,int continuous) {
struct block_list *target;
struct unit_data *ud;
- nullpo_ret(ud = unit_bl2ud(src));
+ nullpo_ret(ud = unit->bl2ud(src));
- target = iMap->id2bl(target_id);
- if( target==NULL || status_isdead(target) ) {
- unit_unattackable(src);
+ target = map->id2bl(target_id);
+ if( target==NULL || status->isdead(target) ) {
+ unit->unattackable(src);
return 1;
}
if( src->type == BL_PC ) {
TBL_PC* sd = (TBL_PC*)src;
if( target->type == BL_NPC ) { // monster npcs [Valaris]
- npc_click(sd,(TBL_NPC*)target); // submitted by leinsirk10 [Celest]
+ npc->click(sd,(TBL_NPC*)target); // submitted by leinsirk10 [Celest]
return 0;
}
if( pc_is90overweight(sd) || pc_isridingwug(sd) ) { // overweight or mounted on warg - stop attacking
- unit_stop_attack(src);
+ unit->stop_attack(src);
+ return 0;
+ }
+ if( !pc->can_attack(sd, target_id) ) {
+ unit->stop_attack(src);
return 0;
}
}
- if( battle->check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) ) {
- unit_unattackable(src);
+ if( battle->check_target(src,target,BCT_ENEMY) <= 0 || !status->check_skilluse(src, target, 0, 0) ) {
+ unit->unattackable(src);
return 1;
}
ud->state.attack_continue = continuous;
- unit_set_target(ud, target_id);
+ unit->set_target(ud, target_id);
- if (continuous) //If you're to attack continously, set to auto-case character
+ if (continuous) //If you're to attack continuously, set to auto-case character
ud->chaserange = status_get_range(src);
//Just change target/type. [Skotlex]
@@ -1625,11 +1627,11 @@ int unit_attack(struct block_list *src,int target_id,int continuous)
if(src->type == BL_MOB)
((TBL_MOB*)src)->state.skillstate = ((TBL_MOB*)src)->state.aggressive?MSS_ANGRY:MSS_BERSERK;
- if(DIFF_TICK(ud->attackabletime, iTimer->gettick()) > 0)
+ if(DIFF_TICK(ud->attackabletime, timer->gettick()) > 0)
//Do attack next time it is possible. [Skotlex]
- ud->attacktimer=iTimer->add_timer(ud->attackabletime,unit_attack_timer,src->id,0);
+ ud->attacktimer=timer->add(ud->attackabletime,unit->attack_timer,src->id,0);
else //Attack NOW.
- unit_attack_timer(INVALID_TIMER, iTimer->gettick(), src->id, 0);
+ unit->attack_timer(INVALID_TIMER, timer->gettick(), src->id, 0);
return 0;
}
@@ -1643,16 +1645,16 @@ int unit_cancel_combo(struct block_list *bl)
if (!status_change_end(bl, SC_COMBOATTACK, INVALID_TIMER))
return 0; //Combo wasn't active.
- ud = unit_bl2ud(bl);
+ ud = unit->bl2ud(bl);
nullpo_ret(ud);
- ud->attackabletime = iTimer->gettick() + status_get_amotion(bl);
+ ud->attackabletime = timer->gettick() + status_get_amotion(bl);
if (ud->attacktimer == INVALID_TIMER)
return 1; //Nothing more to do.
- iTimer->delete_timer(ud->attacktimer, unit_attack_timer);
- ud->attacktimer=iTimer->add_timer(ud->attackabletime,unit_attack_timer,bl->id,0);
+ timer->delete(ud->attacktimer, unit->attack_timer);
+ ud->attacktimer=timer->add(ud->attackabletime,unit->attack_timer,bl->id,0);
return 1;
}
/*==========================================
@@ -1665,7 +1667,7 @@ bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy)
if (bl->x == x && bl->y == y) //Same place
return true;
- return path_search(NULL,bl->m,bl->x,bl->y,x,y,easy,CELL_CHKNOREACH);
+ return path->search(NULL,bl->m,bl->x,bl->y,x,y,easy,CELL_CHKNOREACH);
}
/*==========================================
@@ -1693,9 +1695,9 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range,
dx=(dx>0)?1:((dx<0)?-1:0);
dy=(dy>0)?1:((dy<0)?-1:0);
- if (iMap->getcell(tbl->m,tbl->x-dx,tbl->y-dy,CELL_CHKNOPASS))
- { //Look for a suitable cell to place in.
- for(i=0;i<9 && iMap->getcell(tbl->m,tbl->x-dirx[i],tbl->y-diry[i],CELL_CHKNOPASS);i++);
+ if (map->getcell(tbl->m,tbl->x-dx,tbl->y-dy,CELL_CHKNOPASS)) {
+ //Look for a suitable cell to place in.
+ for(i=0;i<9 && map->getcell(tbl->m,tbl->x-dirx[i],tbl->y-diry[i],CELL_CHKNOPASS);i++);
if (i==9) return false; //No valid cells.
dx = dirx[i];
dy = diry[i];
@@ -1703,7 +1705,7 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range,
if (x) *x = tbl->x-dx;
if (y) *y = tbl->y-dy;
- return path_search(NULL,bl->m,bl->x,bl->y,tbl->x-dx,tbl->y-dy,easy,CELL_CHKNOREACH);
+ return path->search(NULL,bl->m,bl->x,bl->y,tbl->x-dx,tbl->y-dy,easy,CELL_CHKNOREACH);
}
/*==========================================
* Calculates position of Pet/Mercenary/Homunculus/Elemental
@@ -1711,7 +1713,7 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range,
int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
{
int dx, dy, x, y, i, k;
- struct unit_data *ud = unit_bl2ud(bl);
+ struct unit_data *ud = unit->bl2ud(bl);
nullpo_ret(ud);
if(dir > 7)
@@ -1726,11 +1728,11 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
x = tx + dx;
y = ty + dy;
- if( !unit_can_reach_pos(bl, x, y, 0) )
+ if( !unit->can_reach_pos(bl, x, y, 0) )
{
if( dx > 0 ) x--; else if( dx < 0 ) x++;
if( dy > 0 ) y--; else if( dy < 0 ) y++;
- if( !unit_can_reach_pos(bl, x, y, 0) )
+ if( !unit->can_reach_pos(bl, x, y, 0) )
{
for( i = 0; i < 12; i++ )
{
@@ -1739,20 +1741,20 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
dy = -diry[k] * 2;
x = tx + dx;
y = ty + dy;
- if( unit_can_reach_pos(bl, x, y, 0) )
+ if( unit->can_reach_pos(bl, x, y, 0) )
break;
else
{
if( dx > 0 ) x--; else if( dx < 0 ) x++;
if( dy > 0 ) y--; else if( dy < 0 ) y++;
- if( unit_can_reach_pos(bl, x, y, 0) )
+ if( unit->can_reach_pos(bl, x, y, 0) )
break;
}
}
if( i == 12 )
{
x = tx; y = tx; // Exactly Master Position
- if( !unit_can_reach_pos(bl, x, y, 0) )
+ if( !unit->can_reach_pos(bl, x, y, 0) )
return 1;
}
}
@@ -1766,8 +1768,7 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
/*==========================================
* Continuous Attack (function timer)
*------------------------------------------*/
-static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int tick)
-{
+int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
struct block_list *target;
struct unit_data *ud;
struct status_data *sstatus;
@@ -1775,7 +1776,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
struct mob_data *md = NULL;
int range;
- if( (ud=unit_bl2ud(src))==NULL )
+ if( (ud=unit->bl2ud(src))==NULL )
return 0;
if( ud->attacktimer != tid )
{
@@ -1786,22 +1787,23 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
sd = BL_CAST(BL_PC, src);
md = BL_CAST(BL_MOB, src);
ud->attacktimer = INVALID_TIMER;
- target=iMap->id2bl(ud->target);
+ target=map->id2bl(ud->target);
if( src == NULL || src->prev == NULL || target==NULL || target->prev == NULL )
return 0;
- if( status_isdead(src) || status_isdead(target) ||
- battle->check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0)
+ if( status->isdead(src) || status->isdead(target)
+ || battle->check_target(src,target,BCT_ENEMY) <= 0 || !status->check_skilluse(src, target, 0, 0)
#ifdef OFFICIAL_WALKPATH
- || !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL)
+ || !path->search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL)
#endif
- )
+ || (sd && !pc->can_attack(sd, ud->target) )
+ )
return 0; // can't attack under these conditions
if( src->m != target->m )
{
- if( src->type == BL_MOB && mob_warpchase((TBL_MOB*)src, target) )
+ if( src->type == BL_MOB && mob->warpchase((TBL_MOB*)src, target) )
return 1; // Follow up.
return 0;
}
@@ -1811,38 +1813,36 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
if( !battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick,tick) > 0 && !(sd && pc->checkskill(sd,SA_FREECAST) > 0) )
{ // attacking when under cast delay has restrictions:
- if( tid == INVALID_TIMER )
- { //requested attack.
+ if( tid == INVALID_TIMER ) { //requested attack.
if(sd) clif->skill_fail(sd,1,USESKILL_FAIL_SKILLINTERVAL,0);
return 0;
}
//Otherwise, we are in a combo-attack, delay this until your canact time is over. [Skotlex]
- if( ud->state.attack_continue )
- {
+ if( ud->state.attack_continue ) {
if( DIFF_TICK(ud->canact_tick, ud->attackabletime) > 0 )
ud->attackabletime = ud->canact_tick;
- ud->attacktimer=iTimer->add_timer(ud->attackabletime,unit_attack_timer,src->id,0);
+ ud->attacktimer=timer->add(ud->attackabletime,unit->attack_timer,src->id,0);
}
return 1;
}
- sstatus = status_get_status_data(src);
+ sstatus = status->get_status_data(src);
range = sstatus->rhw.range + 1;
- if( unit_is_walking(target) )
+ if( unit->is_walking(target) )
range++; //Extra range when chasing
if( !check_distance_bl(src,target,range) ) { //Chase if required.
if(sd)
clif->movetoattack(sd,target);
else if(ud->state.attack_continue)
- unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2);
+ unit->walktobl(src,target,ud->chaserange,ud->state.walk_easy|2);
return 1;
}
if( !battle->check_range(src,target,range) ) {
- //Within range, but no direct line of attack
+ //Within range, but no direct line of attack
if( ud->state.attack_continue ) {
if(ud->chaserange > 2) ud->chaserange-=2;
- unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2);
+ unit->walktobl(src,target,ud->chaserange,ud->state.walk_easy|2);
}
return 1;
}
@@ -1850,31 +1850,30 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
//Non-players use the sync packet on the walk timer. [Skotlex]
if (tid == INVALID_TIMER && sd) clif->fixpos(src);
- if( DIFF_TICK(ud->attackabletime,tick) <= 0 )
- {
+ if( DIFF_TICK(ud->attackabletime,tick) <= 0 ) {
if (battle_config.attack_direction_change && (src->type&battle_config.attack_direction_change)) {
- ud->dir = iMap->calc_dir(src, target->x,target->y );
+ ud->dir = map->calc_dir(src, target->x,target->y );
}
if(ud->walktimer != INVALID_TIMER)
- unit_stop_walking(src,1);
+ unit->stop_walking(src,1);
if(md) {
- if (mobskill_use(md,tick,-1))
+ if (mob->skill_use(md,tick,-1))
return 1;
if (sstatus->mode&MD_ASSIST && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME)
{ // Link monsters nearby [Skotlex]
md->last_linktime = tick;
- iMap->foreachinrange(mob_linksearch, src, md->db->range2, BL_MOB, md->class_, target, tick);
+ map->foreachinrange(mob->linksearch, src, md->db->range2, BL_MOB, md->class_, target, tick);
}
}
- if(src->type == BL_PET && pet_attackskill((TBL_PET*)src, target->id))
+ if(src->type == BL_PET && pet->attackskill((TBL_PET*)src, target->id))
return 1;
- iMap->freeblock_lock();
+ map->freeblock_lock();
ud->attacktarget_lv = battle->weapon_attack(src,target,tick,0);
if(sd && sd->status.pet_id > 0 && sd->pd && battle_config.pet_attack_support)
- pet_target_check(sd,target,0);
- iMap->freeblock_unlock();
+ pet->target_check(sd,target,0);
+ map->freeblock_unlock();
/**
* Applied when you're unable to attack (e.g. out of ammo)
* We should stop here otherwise timer keeps on and this happens endlessly
@@ -1885,34 +1884,36 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
ud->attackabletime = tick + sstatus->adelay;
// You can't move if you can't attack neither.
if (src->type&battle_config.attack_walk_delay)
- unit_set_walkdelay(src, tick, sstatus->amotion, 1);
+ unit->set_walkdelay(src, tick, sstatus->amotion, 1);
}
- if(ud->state.attack_continue)
- ud->attacktimer = iTimer->add_timer(ud->attackabletime,unit_attack_timer,src->id,0);
+ if(ud->state.attack_continue) {
+ if( src->type == BL_PC && battle_config.idletime_criteria & BCIDLE_ATTACK )
+ ((TBL_PC*)src)->idletime = sockt->last_tick;
+ ud->attacktimer = timer->add(ud->attackabletime,unit->attack_timer,src->id,0);
+ }
return 1;
}
-static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data)
-{
+int unit_attack_timer(int tid, int64 tick, int id, intptr_t data) {
struct block_list *bl;
- bl = iMap->id2bl(id);
- if(bl && unit_attack_timer_sub(bl, tid, tick) == 0)
- unit_unattackable(bl);
+ bl = map->id2bl(id);
+ if(bl && unit->attack_timer_sub(bl, tid, tick) == 0)
+ unit->unattackable(bl);
return 0;
}
/*==========================================
* Cancels an ongoing skill cast.
* flag&1: Cast-Cancel invoked.
- * flag&2: Cancel only if skill is cancellable.
+ * flag&2: Cancel only if skill is can be cancel.
*------------------------------------------*/
int unit_skillcastcancel(struct block_list *bl,int type)
{
struct map_session_data *sd = NULL;
- struct unit_data *ud = unit_bl2ud( bl);
- unsigned int tick=iTimer->gettick();
+ struct unit_data *ud = unit->bl2ud( bl);
+ int64 tick = timer->gettick();
int ret=0, skill_id;
nullpo_ret(bl);
@@ -1922,12 +1923,12 @@ int unit_skillcastcancel(struct block_list *bl,int type)
sd = BL_CAST(BL_PC, bl);
if (type&2) {
- //See if it can be cancelled.
+ //See if it can be canceled.
if (!ud->state.skillcastcancel)
return 0;
if (sd && (sd->special_state.no_castcancel2 ||
- ((sd->sc.data[SC_UNLIMITED_HUMMING_VOICE] || sd->special_state.no_castcancel) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground))) //fixed flags being read the wrong way around [blackhole89]
+ ( sd->special_state.no_castcancel && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground))) //fixed flags being read the wrong way around [blackhole89]
return 0;
}
@@ -1939,11 +1940,11 @@ int unit_skillcastcancel(struct block_list *bl,int type)
skill_id = ud->skill_id;
if (skill->get_inf(skill_id) & INF_GROUND_SKILL)
- ret = iTimer->delete_timer( ud->skilltimer, skill->castend_pos );
+ ret = timer->delete( ud->skilltimer, skill->castend_pos );
else
- ret = iTimer->delete_timer( ud->skilltimer, skill->castend_id );
+ ret = timer->delete( ud->skilltimer, skill->castend_id );
if( ret < 0 )
- ShowError("delete timer error : skill_id : %d\n",ret);
+ ShowError("delete timer error %d : skill %d (%s)\n",ret,skill_id,skill->get_name(skill_id));
ud->skilltimer = INVALID_TIMER;
@@ -1967,7 +1968,7 @@ int unit_skillcastcancel(struct block_list *bl,int type)
// unit_data initialization process
void unit_dataset(struct block_list *bl) {
struct unit_data *ud;
- nullpo_retv(ud = unit_bl2ud(bl));
+ nullpo_retv(ud = unit->bl2ud(bl));
memset( ud, 0, sizeof( struct unit_data) );
ud->bl = bl;
@@ -1976,7 +1977,7 @@ void unit_dataset(struct block_list *bl) {
ud->attacktimer = INVALID_TIMER;
ud->attackabletime =
ud->canact_tick =
- ud->canmove_tick = iTimer->gettick();
+ ud->canmove_tick = timer->gettick();
}
/*==========================================
@@ -1985,7 +1986,7 @@ void unit_dataset(struct block_list *bl) {
int unit_counttargeted(struct block_list* bl)
{
struct unit_data* ud;
- if( bl && (ud = unit_bl2ud(bl)) )
+ if( bl && (ud = unit->bl2ud(bl)) )
return ud->target_count;
return 0;
}
@@ -1993,14 +1994,13 @@ int unit_counttargeted(struct block_list* bl)
/*==========================================
*
*------------------------------------------*/
-int unit_fixdamage(struct block_list *src,struct block_list *target,unsigned int tick,int sdelay,int ddelay,int damage,int div,int type,int damage2)
-{
+int unit_fixdamage(struct block_list *src, struct block_list *target, int sdelay, int ddelay, int64 damage, short div, unsigned char type, int64 damage2) {
nullpo_ret(target);
if(damage+damage2 <= 0)
return 0;
- return status_fix_damage(src,target,damage+damage2,clif->damage(target,target,tick,sdelay,ddelay,damage,div,type,damage2));
+ return status_fix_damage(src,target,damage+damage2,clif->damage(target,target,sdelay,ddelay,damage,div,type,damage2));
}
/*==========================================
@@ -2026,32 +2026,31 @@ int unit_changeviewsize(struct block_list *bl,short size)
/*==========================================
* Removes a bl/ud from the map.
* Returns 1 on success. 0 if it couldn't be removed or the bl was free'd
- * if clrtype is 1 (death), appropiate cleanup is performed.
+ * if clrtype is 1 (death), appropriate cleanup is performed.
* Otherwise it is assumed bl is being warped.
- * On-Kill specific stuff is not performed here, look at status_damage for that.
+ * On-Kill specific stuff is not performed here, look at status->damage for that.
*------------------------------------------*/
-int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, int line, const char* func)
-{
- struct unit_data *ud = unit_bl2ud(bl);
- struct status_change *sc = status_get_sc(bl);
+int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, int line, const char* func) {
+ struct unit_data *ud = unit->bl2ud(bl);
+ struct status_change *sc = status->get_sc(bl);
nullpo_ret(ud);
if(bl->prev == NULL)
return 0; //Already removed?
- iMap->freeblock_lock();
+ map->freeblock_lock();
- unit_set_target(ud, 0);
+ unit->set_target(ud, 0);
if (ud->walktimer != INVALID_TIMER)
- unit_stop_walking(bl,0);
+ unit->stop_walking(bl,0);
if (ud->attacktimer != INVALID_TIMER)
- unit_stop_attack(bl);
+ unit->stop_attack(bl);
if (ud->skilltimer != INVALID_TIMER)
- unit_skillcastcancel(bl,0);
+ unit->skillcastcancel(bl,0);
// Do not reset can-act delay. [Skotlex]
- ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = iTimer->gettick();
+ ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = timer->gettick();
if(sc && sc->count ) { //map-change/warp dispells.
status_change_end(bl, SC_BLADESTOP, INVALID_TIMER);
status_change_end(bl, SC_BASILICA, INVALID_TIMER);
@@ -2068,8 +2067,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
status_change_end(bl, SC_HIDING, INVALID_TIMER);
// Ensure the bl is a PC; if so, we'll handle the removal of cloaking and cloaking exceed later
- if ( bl->type != BL_PC )
- {
+ if ( bl->type != BL_PC ) {
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
}
@@ -2080,6 +2078,11 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
status_change_end(bl, SC_STOP, INVALID_TIMER);
status_change_end(bl, SC_WUGDASH, INVALID_TIMER);
status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER);
+ status_change_end(bl, SC_MAGNETICFIELD, INVALID_TIMER);
+ status_change_end(bl, SC_NEUTRALBARRIER_MASTER, INVALID_TIMER);
+ status_change_end(bl, SC_NEUTRALBARRIER, INVALID_TIMER);
+ status_change_end(bl, SC_STEALTHFIELD_MASTER, INVALID_TIMER);
+ status_change_end(bl, SC_STEALTHFIELD, INVALID_TIMER);
status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
status_change_end(bl, SC__MANHOLE, INVALID_TIMER);
status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER);
@@ -2087,7 +2090,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
}
if (bl->type&(BL_CHAR|BL_PET)) {
- skill->unit_move(bl,iTimer->gettick(),4);
+ skill->unit_move(bl,timer->gettick(),4);
skill->cleartimerskill(bl);
}
@@ -2095,23 +2098,26 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
case BL_PC: {
struct map_session_data *sd = (struct map_session_data*)bl;
- if(sd->shadowform_id){
- struct block_list *d_bl = iMap->id2bl(sd->shadowform_id);
- if( d_bl )
- status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER);
+ if(sd->shadowform_id) {
+ struct block_list *d_bl = map->id2bl(sd->shadowform_id);
+ if( d_bl )
+ status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER);
}
//Leave/reject all invitations.
if(sd->chatID)
- chat_leavechat(sd,0);
+ chat->leave(sd,0);
if(sd->trade_partner)
trade->cancel(sd);
buyingstore->close(sd);
searchstore->close(sd);
- if(sd->state.storage_flag == 1)
- storage_storage_quit(sd,0);
- else if (sd->state.storage_flag == 2)
- storage_guild_storage_quit(sd,0);
- sd->state.storage_flag = 0; //Force close it when being warped.
+ if( sd->menuskill_id != AL_TELEPORT ) { // issue: 8027
+ if(sd->state.storage_flag == 1)
+ storage->pc_quit(sd,0);
+ else if (sd->state.storage_flag == 2)
+ gstorage->pc_quit(sd,0);
+
+ sd->state.storage_flag = 0; //Force close it when being warped.
+ }
if(sd->party_invite>0)
party->reply_invite(sd,sd->party_invite,0);
if(sd->guild_invite>0)
@@ -2121,7 +2127,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
if(sd->menuskill_id)
sd->menuskill_id = sd->menuskill_val = 0;
if( sd->touching_id )
- npc_touchnext_areanpc(sd,true);
+ npc->touchnext_areanpc(sd,true);
// Check if warping and not changing the map.
if ( sd->state.warping && !sd->state.changemap ) {
@@ -2133,12 +2139,12 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
sd->adopt_invite = 0;
if(sd->pvp_timer != INVALID_TIMER) {
- iTimer->delete_timer(sd->pvp_timer,pc->calc_pvprank_timer);
+ timer->delete(sd->pvp_timer,pc->calc_pvprank_timer);
sd->pvp_timer = INVALID_TIMER;
sd->pvp_rank = 0;
}
if(sd->duel_group > 0)
- duel_leave(sd->duel_group, sd);
+ duel->leave(sd->duel_group, sd);
if(pc_issit(sd)) {
pc->setstand(sd);
@@ -2146,12 +2152,11 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
}
party->send_dot_remove(sd);//minimap dot fix [Kevin]
guild->send_dot_remove(sd);
- bg_send_dot_remove(sd);
+ bg->send_dot_remove(sd);
- if( map[bl->m].users <= 0 || sd->state.debug_remove_map )
- {// this is only place where map users is decreased, if the mobs were removed too soon then this function was executed too many times [FlavioJS]
- if( sd->debug_file == NULL || !(sd->state.debug_remove_map) )
- {
+ if( map->list[bl->m].users <= 0 || sd->state.debug_remove_map ) {
+ // this is only place where map users is decreased, if the mobs were removed too soon then this function was executed too many times [FlavioJS]
+ if( sd->debug_file == NULL || !(sd->state.debug_remove_map) ) {
sd->debug_file = "";
sd->debug_line = 0;
sd->debug_func = "";
@@ -2163,17 +2168,21 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
" Please report this!!!\n",
sd->status.account_id, sd->status.char_id,
sd->state.active, sd->state.connect_new, sd->state.rewarp, sd->state.changemap, sd->state.debug_remove_map,
- map[bl->m].name, map[bl->m].users,
+ map->list[bl->m].name, map->list[bl->m].users,
sd->debug_file, sd->debug_line, sd->debug_func, file, line, func);
- } else if (--map[bl->m].users == 0 && battle_config.dynamic_mobs) //[Skotlex]
- iMap->removemobs(bl->m);
- if( !(sd->sc.option&OPTION_INVISIBLE) )
- {// decrement the number of active pvp players on the map
- --map[bl->m].users_pvp;
+ } else if (--map->list[bl->m].users == 0 && battle_config.dynamic_mobs) //[Skotlex]
+ map->removemobs(bl->m);
+ if( !(sd->sc.option&OPTION_INVISIBLE) ) {
+ // decrement the number of active pvp players on the map
+ --map->list[bl->m].users_pvp;
+ }
+ if( map->list[bl->m].instance_id >= 0 ) {
+ instance->list[map->list[bl->m].instance_id].users--;
+ instance->check_idle(map->list[bl->m].instance_id);
}
- if( map[bl->m].instance_id >= 0 ) {
- instances[map[bl->m].instance_id].users--;
- instance->check_idle(map[bl->m].instance_id);
+ if( sd->state.hpmeter_visible ) {
+ map->list[bl->m].hpmeter_visible--;
+ sd->state.hpmeter_visible = 0;
}
sd->state.debug_remove_map = 1; // temporary state to track double remove_map's [FlavioJS]
sd->debug_file = file;
@@ -2195,12 +2204,12 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
}
case BL_PET: {
struct pet_data *pd = (struct pet_data*)bl;
- if( pd->pet.intimate <= 0 && !(pd->msd && !pd->msd->state.active) )
- { //If logging out, this is deleted on unit_free
+ if( pd->pet.intimate <= 0 && !(pd->msd && !pd->msd->state.active) ) {
+ //If logging out, this is deleted on unit->free
clif->clearunit_area(bl,clrtype);
- iMap->delblock(bl);
- unit_free(bl,CLR_OUTSIGHT);
- iMap->freeblock_unlock();
+ map->delblock(bl);
+ unit->free(bl,CLR_OUTSIGHT);
+ map->freeblock_unlock();
return 0;
}
@@ -2208,14 +2217,13 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
}
case BL_HOM: {
struct homun_data *hd = (struct homun_data *)bl;
- ud->canact_tick = ud->canmove_tick; //It appears HOM do reset the can-act tick.
- if( !hd->homunculus.intimacy && !(hd->master && !hd->master->state.active) )
- { //If logging out, this is deleted on unit_free
+ if( !hd->homunculus.intimacy && !(hd->master && !hd->master->state.active) ) {
+ //If logging out, this is deleted on unit->free
clif->emotion(bl, E_SOB);
clif->clearunit_area(bl,clrtype);
- iMap->delblock(bl);
- unit_free(bl,CLR_OUTSIGHT);
- iMap->freeblock_unlock();
+ map->delblock(bl);
+ unit->free(bl,CLR_OUTSIGHT);
+ map->freeblock_unlock();
return 0;
}
break;
@@ -2223,12 +2231,11 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
case BL_MER: {
struct mercenary_data *md = (struct mercenary_data *)bl;
ud->canact_tick = ud->canmove_tick;
- if( mercenary_get_lifetime(md) <= 0 && !(md->master && !md->master->state.active) )
- {
+ if( mercenary->get_lifetime(md) <= 0 && !(md->master && !md->master->state.active) ) {
clif->clearunit_area(bl,clrtype);
- iMap->delblock(bl);
- unit_free(bl,CLR_OUTSIGHT);
- iMap->freeblock_unlock();
+ map->delblock(bl);
+ unit->free(bl,CLR_OUTSIGHT);
+ map->freeblock_unlock();
return 0;
}
break;
@@ -2236,12 +2243,11 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
case BL_ELEM: {
struct elemental_data *ed = (struct elemental_data *)bl;
ud->canact_tick = ud->canmove_tick;
- if( elemental_get_lifetime(ed) <= 0 && !(ed->master && !ed->master->state.active) )
- {
+ if( elemental->get_lifetime(ed) <= 0 && !(ed->master && !ed->master->state.active) ) {
clif->clearunit_area(bl,clrtype);
- iMap->delblock(bl);
- unit_free(bl,0);
- iMap->freeblock_unlock();
+ map->delblock(bl);
+ unit->free(bl,0);
+ map->freeblock_unlock();
return 0;
}
break;
@@ -2251,58 +2257,61 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
/**
* BL_MOB is handled by mob_dead unless the monster is not dead.
**/
- if( bl->type != BL_MOB || !status_isdead(bl) )
+ if( bl->type != BL_MOB || !status->isdead(bl) )
clif->clearunit_area(bl,clrtype);
- iMap->delblock(bl);
- iMap->freeblock_unlock();
+ map->delblock(bl);
+ map->freeblock_unlock();
return 1;
}
void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype)
{
- unit_remove_map(&sd->bl,clrtype);
-
- if (clrtype == CLR_TELEPORT) clrtype = CLR_OUTSIGHT; //CLR_TELEPORT is the warp from logging out, but pets/homunc need to just 'vanish' instead of showing the warping out animation.
-
+ unit->remove_map(&sd->bl,clrtype,ALC_MARK);
+
+ //CLR_RESPAWN is the warp from logging out, CLR_TELEPORT is the warp from teleporting, but pets/homunc need to just 'vanish' instead of showing the warping animation.
+ if (clrtype == CLR_RESPAWN || clrtype == CLR_TELEPORT) clrtype = CLR_OUTSIGHT;
+
if(sd->pd)
- unit_remove_map(&sd->pd->bl, clrtype);
+ unit->remove_map(&sd->pd->bl, clrtype, ALC_MARK);
if(homun_alive(sd->hd))
- unit_remove_map(&sd->hd->bl, clrtype);
+ unit->remove_map(&sd->hd->bl, clrtype, ALC_MARK);
if(sd->md)
- unit_remove_map(&sd->md->bl, clrtype);
+ unit->remove_map(&sd->md->bl, clrtype, ALC_MARK);
if(sd->ed)
- unit_remove_map(&sd->ed->bl, clrtype);
+ unit->remove_map(&sd->ed->bl, clrtype, ALC_MARK);
}
void unit_free_pc(struct map_session_data *sd)
{
- if (sd->pd) unit_free(&sd->pd->bl,CLR_OUTSIGHT);
- if (sd->hd) unit_free(&sd->hd->bl,CLR_OUTSIGHT);
- if (sd->md) unit_free(&sd->md->bl,CLR_OUTSIGHT);
- if (sd->ed) unit_free(&sd->ed->bl,CLR_OUTSIGHT);
- unit_free(&sd->bl,CLR_TELEPORT);
+ if (sd->pd) unit->free(&sd->pd->bl,CLR_OUTSIGHT);
+ if (sd->hd) unit->free(&sd->hd->bl,CLR_OUTSIGHT);
+ if (sd->md) unit->free(&sd->md->bl,CLR_OUTSIGHT);
+ if (sd->ed) unit->free(&sd->ed->bl,CLR_OUTSIGHT);
+ unit->free(&sd->bl,CLR_TELEPORT);
}
/*==========================================
* Function to free all related resources to the bl
* if unit is on map, it is removed using the clrtype specified
*------------------------------------------*/
-int unit_free(struct block_list *bl, clr_type clrtype)
-{
- struct unit_data *ud = unit_bl2ud( bl );
+int unit_free(struct block_list *bl, clr_type clrtype) {
+ struct unit_data *ud = unit->bl2ud( bl );
nullpo_ret(ud);
- iMap->freeblock_lock();
+ map->freeblock_lock();
if( bl->prev ) //Players are supposed to logout with a "warp" effect.
- unit_remove_map(bl, clrtype);
+ unit->remove_map(bl, clrtype, ALC_MARK);
switch( bl->type ) {
case BL_PC:
{
struct map_session_data *sd = (struct map_session_data*)bl;
int i;
+ unsigned int k;
- if( status_isdead(bl) )
+ sd->state.loggingout = 1;
+
+ if( status->isdead(bl) )
pc->setrestartvalue(sd,2);
pc->delinvincibletimer(sd);
@@ -2314,10 +2323,10 @@ int unit_free(struct block_list *bl, clr_type clrtype)
pc->stop_following(sd);
if( sd->duel_invite > 0 )
- duel_reject(sd->duel_invite, sd);
+ duel->reject(sd->duel_invite, sd);
// Notify friends that this char logged out. [Skotlex]
- iMap->map_foreachpc(clif->friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0);
+ map->foreachpc(clif->friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0);
party->send_logout(sd);
guild->send_memberinfoshort(sd,0);
pc->cleareventtimer(sd);
@@ -2326,33 +2335,20 @@ int unit_free(struct block_list *bl, clr_type clrtype)
for(i = 1; i < 5; i++)
pc->del_charm(sd, sd->charm[i], i);
- if( sd->reg ) { //Double logout already freed pointer fix... [Skotlex]
- aFree(sd->reg);
- sd->reg = NULL;
- sd->reg_num = 0;
- }
- if( sd->regstr ) {
- for( i = 0; i < sd->regstr_num; ++i )
- if( sd->regstr[i].data )
- aFree(sd->regstr[i].data);
- aFree(sd->regstr);
- sd->regstr = NULL;
- sd->regstr_num = 0;
- }
if( sd->st && sd->st->state != RUN ) {// free attached scripts that are waiting
- script_free_state(sd->st);
+ script->free_state(sd->st);
sd->st = NULL;
sd->npc_id = 0;
}
- if( sd->combos.count ) {
- aFree(sd->combos.bonus);
- aFree(sd->combos.id);
- sd->combos.count = 0;
+ if( sd->combos ) {
+ aFree(sd->combos);
+ sd->combos = NULL;
}
+ sd->combo_count = 0;
/* [Ind/Hercules] */
if( sd->sc_display_count ) {
for(i = 0; i < sd->sc_display_count; i++) {
- ers_free(pc_sc_display_ers, sd->sc_display[i]);
+ ers_free(pc->sc_display_ers, sd->sc_display[i]);
}
sd->sc_display_count = 0;
}
@@ -2368,13 +2364,27 @@ int unit_free(struct block_list *bl, clr_type clrtype)
aFree(sd->queues);
sd->queues = NULL;
}
+ if( sd->quest_log != NULL ) {
+ aFree(sd->quest_log);
+ sd->quest_log = NULL;
+ sd->num_quests = sd->avail_quests = 0;
+ }
+
+ for( k = 0; k < sd->hdatac; k++ ) {
+ if( sd->hdata[k]->flag.free ) {
+ aFree(sd->hdata[k]->data);
+ }
+ aFree(sd->hdata[k]);
+ }
+ if( sd->hdata )
+ aFree(sd->hdata);
break;
}
case BL_PET:
{
struct pet_data *pd = (struct pet_data*)bl;
struct map_session_data *sd = pd->msd;
- pet_hungry_timer_delete(pd);
+ pet->hungry_timer_delete(pd);
if( pd->a_skill )
{
aFree(pd->a_skill);
@@ -2384,9 +2394,9 @@ int unit_free(struct block_list *bl, clr_type clrtype)
{
if (pd->s_skill->timer != INVALID_TIMER) {
if (pd->s_skill->id)
- iTimer->delete_timer(pd->s_skill->timer, pet_skill_support_timer);
+ timer->delete(pd->s_skill->timer, pet->skill_support_timer);
else
- iTimer->delete_timer(pd->s_skill->timer, pet_heal_timer);
+ timer->delete(pd->s_skill->timer, pet->heal_timer);
}
aFree(pd->s_skill);
pd->s_skill = NULL;
@@ -2394,30 +2404,30 @@ int unit_free(struct block_list *bl, clr_type clrtype)
if( pd->recovery )
{
if(pd->recovery->timer != INVALID_TIMER)
- iTimer->delete_timer(pd->recovery->timer, pet_recovery_timer);
+ timer->delete(pd->recovery->timer, pet->recovery_timer);
aFree(pd->recovery);
pd->recovery = NULL;
}
if( pd->bonus )
{
if (pd->bonus->timer != INVALID_TIMER)
- iTimer->delete_timer(pd->bonus->timer, pet_skill_bonus_timer);
+ timer->delete(pd->bonus->timer, pet->skill_bonus_timer);
aFree(pd->bonus);
pd->bonus = NULL;
}
if( pd->loot )
{
- pet_lootitem_drop(pd,sd);
+ pet->lootitem_drop(pd,sd);
if (pd->loot->item)
aFree(pd->loot->item);
aFree (pd->loot);
pd->loot = NULL;
}
if( pd->pet.intimate > 0 )
- intif_save_petdata(pd->pet.account_id,&pd->pet);
+ intif->save_petdata(pd->pet.account_id,&pd->pet);
else
{ //Remove pet.
- intif_delete_petdata(pd->pet.pet_id);
+ intif->delete_petdata(pd->pet.pet_id);
if (sd) sd->status.pet_id = 0;
}
if( sd )
@@ -2429,12 +2439,12 @@ int unit_free(struct block_list *bl, clr_type clrtype)
struct mob_data *md = (struct mob_data*)bl;
if( md->spawn_timer != INVALID_TIMER )
{
- iTimer->delete_timer(md->spawn_timer,mob_delayspawn);
+ timer->delete(md->spawn_timer,mob->delayspawn);
md->spawn_timer = INVALID_TIMER;
}
if( md->deletetimer != INVALID_TIMER )
{
- iTimer->delete_timer(md->deletetimer,mob_timer_delete);
+ timer->delete(md->deletetimer,mob->timer_delete);
md->deletetimer = INVALID_TIMER;
}
if( md->lootitem )
@@ -2476,10 +2486,10 @@ int unit_free(struct block_list *bl, clr_type clrtype)
aFree(md->base_status);
md->base_status = NULL;
}
- if( mob_is_clone(md->class_) )
- mob_clone_delete(md);
+ if( mob->is_clone(md->class_) )
+ mob->clone_delete(md);
if( md->tomb_nid )
- mvptomb_destroy(md);
+ mob->mvptomb_destroy(md);
break;
}
case BL_HOM:
@@ -2490,7 +2500,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
if( hd->homunculus.intimacy > 0 )
homun->save(hd);
else {
- intif_homunculus_requestdelete(hd->homunculus.hom_id);
+ intif->homunculus_requestdelete(hd->homunculus.hom_id);
if( sd )
sd->status.hom_id = 0;
}
@@ -2502,58 +2512,111 @@ int unit_free(struct block_list *bl, clr_type clrtype)
{
struct mercenary_data *md = (TBL_MER*)bl;
struct map_session_data *sd = md->master;
- if( mercenary_get_lifetime(md) > 0 )
- mercenary_save(md);
+ if( mercenary->get_lifetime(md) > 0 )
+ mercenary->save(md);
else
{
- intif_mercenary_delete(md->mercenary.mercenary_id);
+ intif->mercenary_delete(md->mercenary.mercenary_id);
if( sd )
sd->status.mer_id = 0;
}
if( sd )
sd->md = NULL;
- merc_contract_stop(md);
+ mercenary->contract_stop(md);
break;
}
case BL_ELEM: {
struct elemental_data *ed = (TBL_ELEM*)bl;
struct map_session_data *sd = ed->master;
- if( elemental_get_lifetime(ed) > 0 )
- elemental_save(ed);
+ if( elemental->get_lifetime(ed) > 0 )
+ elemental->save(ed);
else {
- intif_elemental_delete(ed->elemental.elemental_id);
+ intif->elemental_delete(ed->elemental.elemental_id);
if( sd )
sd->status.ele_id = 0;
}
if( sd )
sd->ed = NULL;
- elemental_summon_stop(ed);
+ elemental->summon_stop(ed);
break;
}
}
skill->clear_unitgroup(bl);
- status_change_clear(bl,1);
- iMap->deliddb(bl);
+ status->change_clear(bl,1);
+ map->deliddb(bl);
if( bl->type != BL_PC ) //Players are handled by map_quit
- iMap->freeblock(bl);
- iMap->freeblock_unlock();
+ map->freeblock(bl);
+ map->freeblock_unlock();
return 0;
}
-int do_init_unit(void)
-{
- iTimer->add_timer_func_list(unit_attack_timer, "unit_attack_timer");
- iTimer->add_timer_func_list(unit_walktoxy_timer,"unit_walktoxy_timer");
- iTimer->add_timer_func_list(unit_walktobl_sub, "unit_walktobl_sub");
- iTimer->add_timer_func_list(unit_delay_walktoxy_timer,"unit_delay_walktoxy_timer");
+int do_init_unit(bool minimal) {
+ if (minimal)
+ return 0;
+
+ timer->add_func_list(unit->attack_timer, "unit_attack_timer");
+ timer->add_func_list(unit->walktoxy_timer,"unit_walktoxy_timer");
+ timer->add_func_list(unit->walktobl_sub, "unit_walktobl_sub");
+ timer->add_func_list(unit->delay_walktoxy_timer,"unit_delay_walktoxy_timer");
return 0;
}
-int do_final_unit(void)
-{
+int do_final_unit(void) {
// nothing to do
return 0;
}
+
+void unit_defaults(void) {
+ unit = &unit_s;
+
+ unit->init = do_init_unit;
+ unit->final = do_final_unit;
+ /* */
+ unit->bl2ud = unit_bl2ud;
+ unit->bl2ud2 = unit_bl2ud2;
+ unit->attack_timer = unit_attack_timer;
+ unit->walktoxy_timer = unit_walktoxy_timer;
+ unit->walktoxy_sub = unit_walktoxy_sub;
+ unit->delay_walktoxy_timer = unit_delay_walktoxy_timer;
+ unit->walktoxy = unit_walktoxy;
+ unit->walktobl_sub = unit_walktobl_sub;
+ unit->walktobl = unit_walktobl;
+ unit->run = unit_run;
+ unit->run_hit = unit_run_hit;
+ unit->escape = unit_escape;
+ unit->movepos = unit_movepos;
+ unit->setdir = unit_setdir;
+ unit->getdir = unit_getdir;
+ unit->blown = unit_blown;
+ unit->warp = unit_warp;
+ unit->stop_walking = unit_stop_walking;
+ unit->skilluse_id = unit_skilluse_id;
+ unit->is_walking = unit_is_walking;
+ unit->can_move = unit_can_move;
+ unit->resume_running = unit_resume_running;
+ unit->set_walkdelay = unit_set_walkdelay;
+ unit->skilluse_id2 = unit_skilluse_id2;
+ unit->skilluse_pos = unit_skilluse_pos;
+ unit->skilluse_pos2 = unit_skilluse_pos2;
+ unit->set_target = unit_set_target;
+ unit->stop_attack = unit_stop_attack;
+ unit->unattackable = unit_unattackable;
+ unit->attack = unit_attack;
+ unit->cancel_combo = unit_cancel_combo;
+ unit->can_reach_pos = unit_can_reach_pos;
+ unit->can_reach_bl = unit_can_reach_bl;
+ unit->calc_pos = unit_calc_pos;
+ unit->attack_timer_sub = unit_attack_timer_sub;
+ unit->skillcastcancel = unit_skillcastcancel;
+ unit->dataset = unit_dataset;
+ unit->counttargeted = unit_counttargeted;
+ unit->fixdamage = unit_fixdamage;
+ unit->changeviewsize = unit_changeviewsize;
+ unit->remove_map = unit_remove_map;
+ unit->remove_map_pc = unit_remove_map_pc;
+ unit->free_pc = unit_free_pc;
+ unit->free = unit_free;
+}
diff --git a/src/map/unit.h b/src/map/unit.h
index 9d1c02a31..9b95bae41 100644
--- a/src/map/unit.h
+++ b/src/map/unit.h
@@ -1,18 +1,17 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
-#ifndef _UNIT_H_
-#define _UNIT_H_
-
-//#include "map.h"
-struct block_list;
-struct unit_data;
-struct map_session_data;
+#ifndef MAP_UNIT_H
+#define MAP_UNIT_H
#include "clif.h" // clr_type
-#include "map.h" // struct block_list
#include "path.h" // struct walkpath_data
-#include "skill.h" // struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset
+#include "skill.h" // 'MAX_SKILLTIMERSKILL, struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset
+#include "../common/cbasetypes.h"
+
+struct map_session_data;
+struct block_list;
struct unit_data {
struct block_list *bl;
@@ -30,10 +29,10 @@ struct unit_data {
int target_to;
int attacktimer;
int walktimer;
- int chaserange;
- unsigned int attackabletime;
- unsigned int canact_tick;
- unsigned int canmove_tick;
+ int chaserange;
+ int64 attackabletime;
+ int64 canact_tick;
+ int64 canmove_tick;
uint8 dir;
unsigned char walk_count;
unsigned char target_count;
@@ -68,78 +67,61 @@ struct view_data {
unsigned dead_sit : 2;
};
-// PC, MOB, PET に共通する処理を1つにまとめる計画
-
-// 歩行開始
-// 戻り値は、0 ( 成功 ), 1 ( 失敗 )
-int unit_walktoxy( struct block_list *bl, short x, short y, int easy);
-int unit_walktobl( struct block_list *bl, struct block_list *target, int range, int easy);
-int unit_run(struct block_list *bl);
-int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir);
-
-// 歩行停止
-// typeは以下の組み合わせ :
-// 1: 位置情報の送信( この関数の後に位置情報を送信する場合は不要 )
-// 2: ダメージディレイ有り
-// 4: 不明(MOBのみ?)
-int unit_stop_walking(struct block_list *bl,int type);
-int unit_can_move(struct block_list *bl);
-int unit_is_walking(struct block_list *bl);
-int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int type);
-
-int unit_escape(struct block_list *bl, struct block_list *target, short dist);
-// 位置の強制移動(吹き飛ばしなど)
-int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath);
-int unit_warp(struct block_list *bl, short map, short x, short y, clr_type type);
-int unit_setdir(struct block_list *bl,unsigned char dir);
-uint8 unit_getdir(struct block_list *bl);
-int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag);
-
-// そこまで歩行でたどり着けるかの判定
-bool unit_can_reach_pos(struct block_list *bl,int x,int y,int easy);
-bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range, int easy, short *x, short *y);
-
-// 攻撃関連
-int unit_stop_attack(struct block_list *bl);
-int unit_attack(struct block_list *src,int target_id,int continuous);
-int unit_cancel_combo(struct block_list *bl);
-
-// スキル使用
-int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv);
-int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv);
-
-// スキル使用( 補正済みキャスト時間、キャンセル不可設定付き )
-int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel);
-int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel);
-
-// 詠唱キャンセル
-int unit_skillcastcancel(struct block_list *bl,int type);
-
-int unit_counttargeted(struct block_list *bl);
-int unit_set_target(struct unit_data* ud, int target_id);
-
-// unit_data の初期化処理
-void unit_dataset(struct block_list *bl);
+extern const short dirx[8];
+extern const short diry[8];
-int unit_fixdamage(struct block_list *src,struct block_list *target,unsigned int tick,int sdelay,int ddelay,int damage,int div,int type,int damage2);
-// その他
-struct unit_data* unit_bl2ud(struct block_list *bl);
-void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype);
-void unit_free_pc(struct map_session_data *sd);
-#define unit_remove_map(bl,clrtype) unit_remove_map_(bl,clrtype,__FILE__,__LINE__,__func__)
-int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, int line, const char* func);
-int unit_free(struct block_list *bl, clr_type clrtype);
-int unit_changeviewsize(struct block_list *bl,short size);
+struct unit_interface {
+ int (*init) (bool minimal);
+ int (*final) (void);
+ /* */
+ struct unit_data* (*bl2ud) (struct block_list *bl);
+ struct unit_data* (*bl2ud2) (struct block_list *bl);
+ int (*attack_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*walktoxy_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*walktoxy_sub) (struct block_list *bl);
+ int (*delay_walktoxy_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*walktoxy) (struct block_list *bl, short x, short y, int flag);
+ int (*walktobl_sub) (int tid, int64 tick, int id, intptr_t data);
+ int (*walktobl) (struct block_list *bl, struct block_list *tbl, int range, int flag);
+ bool (*run) (struct block_list *bl, struct map_session_data *sd, enum sc_type type);
+ void (*run_hit) (struct block_list *bl, struct status_change *sc, struct map_session_data *sd, enum sc_type type);
+ int (*escape) (struct block_list *bl, struct block_list *target, short dist);
+ int (*movepos) (struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath);
+ int (*setdir) (struct block_list *bl, unsigned char dir);
+ uint8 (*getdir) (struct block_list *bl);
+ int (*blown) (struct block_list *bl, int dx, int dy, int count, int flag);
+ int (*warp) (struct block_list *bl, short m, short x, short y, clr_type type);
+ int (*stop_walking) (struct block_list *bl, int type);
+ int (*skilluse_id) (struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv);
+ int (*is_walking) (struct block_list *bl);
+ int (*can_move) (struct block_list *bl);
+ int (*resume_running) (int tid, int64 tick, int id, intptr_t data);
+ int (*set_walkdelay) (struct block_list *bl, int64 tick, int delay, int type);
+ int (*skilluse_id2) (struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel);
+ int (*skilluse_pos) (struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv);
+ int (*skilluse_pos2) (struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel);
+ int (*set_target) (struct unit_data *ud, int target_id);
+ int (*stop_attack) (struct block_list *bl);
+ int (*unattackable) (struct block_list *bl);
+ int (*attack) (struct block_list *src, int target_id, int continuous);
+ int (*cancel_combo) (struct block_list *bl);
+ bool (*can_reach_pos) (struct block_list *bl, int x, int y, int easy);
+ bool (*can_reach_bl) (struct block_list *bl, struct block_list *tbl, int range, int easy, short *x, short *y);
+ int (*calc_pos) (struct block_list *bl, int tx, int ty, uint8 dir);
+ int (*attack_timer_sub) (struct block_list *src, int tid, int64 tick);
+ int (*skillcastcancel) (struct block_list *bl, int type);
+ void (*dataset) (struct block_list *bl);
+ int (*counttargeted) (struct block_list *bl);
+ int (*fixdamage) (struct block_list *src, struct block_list *target, int sdelay, int ddelay, int64 damage, short div, unsigned char type, int64 damage2);
+ int (*changeviewsize) (struct block_list *bl, short size);
+ int (*remove_map) (struct block_list *bl, clr_type clrtype, const char *file, int line, const char *func);
+ void (*remove_map_pc) (struct map_session_data *sd, clr_type clrtype);
+ void (*free_pc) (struct map_session_data *sd);
+ int (*free) (struct block_list *bl, clr_type clrtype);
+};
-// 初期化ルーチン
-int do_init_unit(void);
-int do_final_unit(void);
-/**
- * Ranger
- **/
-int unit_wugdash(struct block_list *bl, struct map_session_data *sd);
+struct unit_interface *unit;
-extern const short dirx[8];
-extern const short diry[8];
+void unit_defaults(void);
-#endif /* _UNIT_H_ */
+#endif /* MAP_UNIT_H */
diff --git a/src/map/vending.c b/src/map/vending.c
index b9575c8dd..7e9393bf2 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -2,24 +2,29 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/nullpo.h"
-#include "../common/strlib.h"
-#include "../common/utils.h"
+#define HERCULES_CORE
+
+#include "vending.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "atcommand.h"
+#include "battle.h"
+#include "chrif.h"
#include "clif.h"
#include "itemdb.h"
-#include "atcommand.h"
+#include "log.h"
#include "map.h"
+#include "npc.h"
#include "path.h"
-#include "chrif.h"
-#include "vending.h"
#include "pc.h"
-#include "npc.h"
#include "skill.h"
-#include "battle.h"
-#include "log.h"
+#include "../common/nullpo.h"
+#include "../common/strlib.h"
+#include "../common/utils.h"
-#include <stdio.h>
-#include <string.h>
+struct vending_interface vending_s;
/// Returns an unique vending shop id.
static inline unsigned int getid(void) {
@@ -46,16 +51,16 @@ void vending_vendinglistreq(struct map_session_data* sd, unsigned int id) {
struct map_session_data* vsd;
nullpo_retv(sd);
- if( (vsd = iMap->id2sd(id)) == NULL )
+ if( (vsd = map->id2sd(id)) == NULL )
return;
if( !vsd->state.vending )
return; // not vending
- if (!pc->can_give_items(sd) || !pc->can_give_items(vsd)) { //check if both GMs are allowed to trade
+ if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) { //check if both GMs are allowed to trade
// GM is not allowed to trade
clif->message(sd->fd, msg_txt(246));
return;
- }
+ }
sd->vended_id = vsd->vender_id; // register vending uid
@@ -69,7 +74,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING];
double z;
struct s_vending vend[MAX_VENDING]; // against duplicate packets
- struct map_session_data* vsd = iMap->id2sd(aid);
+ struct map_session_data* vsd = map->id2sd(aid);
nullpo_retv(sd);
if( vsd == NULL || !vsd->state.vending || vsd->bl.id == sd->bl.id )
@@ -177,7 +182,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
if( battle_config.buyer_name ) {
char temp[256];
sprintf(temp, msg_txt(265), sd->status.name);
- clif->disp_onlyself(vsd,temp,strlen(temp));
+ clif_disp_onlyself(vsd,temp,strlen(temp));
}
}
@@ -197,9 +202,9 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
vsd->vend_num = cursor;
//Always save BOTH: buyer and customer
- if( iMap->save_settings&2 ) {
- chrif_save(sd,0);
- chrif_save(vsd,0);
+ if( map->save_settings&2 ) {
+ chrif->save(sd,0);
+ chrif->save(vsd,0);
}
//check for @AUTOTRADE users [durf]
@@ -209,8 +214,9 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
if( i == vsd->vend_num ) {
//Close Vending (this was automatically done by the client, we have to do it manually for autovenders) [Skotlex]
vending->close(vsd);
- iMap->quit(vsd); //They have no reason to stay around anymore, do they?
- }
+ map->quit(vsd); //They have no reason to stay around anymore, do they?
+ } else
+ pc->autotrade_update(vsd,PAUC_REFRESH);
}
}
@@ -255,7 +261,8 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
|| !sd->status.cart[index].identify // unidentified item
|| sd->status.cart[index].attribute == 1 // broken item
|| sd->status.cart[index].expire_time // It should not be in the cart but just in case
- || !itemdb_cantrade(&sd->status.cart[index], pc->get_group_level(sd), pc->get_group_level(sd)) ) // untradeable item
+ || (sd->status.cart[index].bound && !pc_can_give_bound_items(sd)) // can't trade bound items w/o permission
+ || !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item
continue;
sd->vending[i].index = index;
@@ -281,7 +288,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
clif->openvending(sd,sd->bl.id,sd->vending);
clif->showvendingboard(&sd->bl,message,0);
- idb_put(vending->db, sd->vender_id, sd);
+ idb_put(vending->db, sd->status.char_id, sd);
}
@@ -358,7 +365,7 @@ void final(void) {
db_destroy(vending->db);
}
-void init(void) {
+void init(bool minimal) {
vending->db = idb_alloc(DB_OPT_BASE);
vending->next_id = 0;
}
diff --git a/src/map/vending.h b/src/map/vending.h
index 0148deb71..63cb632a9 100644
--- a/src/map/vending.h
+++ b/src/map/vending.h
@@ -2,25 +2,26 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#ifndef _VENDING_H_
-#define _VENDING_H_
+#ifndef MAP_VENDING_H
+#define MAP_VENDING_H
#include "../common/cbasetypes.h"
#include "../common/db.h"
+
struct map_session_data;
struct s_search_store_search;
struct s_vending {
short index; //cart index (return item data)
- short amount; //amout of the item for vending
- unsigned int value; //at wich price
+ short amount; //amount of the item for vending
+ unsigned int value; //at which price
};
struct vending_interface {
unsigned int next_id;/* next vender id */
DBMap *db;
/* */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
/* */
void (*close) (struct map_session_data* sd);
@@ -29,10 +30,10 @@ struct vending_interface {
void (*purchase) (struct map_session_data* sd, int aid, unsigned int uid, const uint8* data, int count);
bool (*search) (struct map_session_data* sd, unsigned short nameid);
bool (*searchall) (struct map_session_data* sd, const struct s_search_store_search* s);
-} vending_s;
+};
-struct vending_interface * vending;
+struct vending_interface *vending;
void vending_defaults(void);
-#endif /* _VENDING_H_ */
+#endif /* MAP_VENDING_H */