summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/Makefile.in25
-rw-r--r--src/char/int_pet.c231
-rw-r--r--src/common/HPMDataCheck.h2
-rw-r--r--src/common/Makefile.in27
-rw-r--r--src/common/core.c2
-rw-r--r--src/common/mmo.h23
-rw-r--r--src/common/nullpo.c133
-rw-r--r--src/common/nullpo.h7
-rw-r--r--src/common/packets/packets2020_len_main.h32
-rw-r--r--src/common/packets/packets2020_len_re.h19
-rw-r--r--src/common/packets/packets2020_len_zero.h32
-rw-r--r--src/common/packets/packets_len_main.h4
-rw-r--r--src/common/packets/packets_len_re.h4
-rw-r--r--src/common/packets/packets_len_zero.h4
-rw-r--r--src/login/Makefile.in25
-rw-r--r--src/map/Makefile.in25
-rw-r--r--src/map/atcommand.c187
-rw-r--r--src/map/battle.c55
-rw-r--r--src/map/battle.h3
-rw-r--r--src/map/clif.c597
-rw-r--r--src/map/elemental.c4
-rw-r--r--src/map/map.c129
-rw-r--r--src/map/map.h5
-rw-r--r--src/map/mapdefines.h8
-rw-r--r--src/map/messages_main.h97
-rw-r--r--src/map/messages_re.h97
-rw-r--r--src/map/messages_zero.h102
-rw-r--r--src/map/mob.c8
-rw-r--r--src/map/mob.h2
-rw-r--r--src/map/npc.c3
-rw-r--r--src/map/npc.h4
-rw-r--r--src/map/packets_keys_main.h13
-rw-r--r--src/map/packets_keys_zero.h13
-rw-r--r--src/map/packets_shuffle_main.h13
-rw-r--r--src/map/packets_shuffle_re.h11
-rw-r--r--src/map/packets_shuffle_zero.h13
-rw-r--r--src/map/packets_struct.h10
-rw-r--r--src/map/pc.c1225
-rw-r--r--src/map/pc.h30
-rw-r--r--src/map/pet.c939
-rw-r--r--src/map/pet.h4
-rw-r--r--src/map/script.c857
-rw-r--r--src/map/script.h5
-rw-r--r--src/map/skill.c436
-rw-r--r--src/map/skill.h20
-rw-r--r--src/map/status.c89
-rw-r--r--src/map/status.h7
-rw-r--r--src/map/unit.c825
-rw-r--r--src/map/unit.h23
-rw-r--r--src/map/unitdefines.h58
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Defs.inc82
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc8
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc2
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.Hooks.inc52
-rw-r--r--src/plugins/HPMHooking/HPMHooking_login.HPMHooksCore.inc8
-rw-r--r--src/plugins/HPMHooking/HPMHooking_login.HookingPoints.inc2
-rw-r--r--src/plugins/HPMHooking/HPMHooking_login.Hooks.inc52
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc92
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc23
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc375
-rw-r--r--src/plugins/Makefile.in2
-rw-r--r--src/test/Makefile.in25
62 files changed, 4526 insertions, 2684 deletions
diff --git a/src/char/Makefile.in b/src/char/Makefile.in
index 79ee3e18f..88a99c96c 100644
--- a/src/char/Makefile.in
+++ b/src/char/Makefile.in
@@ -36,6 +36,19 @@ LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \
LIBCONFIG_H = $(addprefix $(LIBCONFIG_D)/, libconfig.h grammar.h parsectx.h \
scanctx.h scanner.h strbuf.h wincompat.h)
+ifeq (@USE_LIBBACKTRACE@,yes)
+ LIBBACKTRACE_D = $(THIRDPARTY_D)/libbacktrace
+ LIBBACKTRACE_OBJ = $(addprefix $(LIBBACKTRACE_D)/, atomic.o backtrace.o \
+ dwarf.o @LIBBACKTRACE_FORMAT_FILE@ fileline.o mmapio.o mmap.o posix.o print.o \
+ simple.o sort.o state.o)
+ LIBBACKTRACE_H = $(addprefix $(LIBBACKTRACE_D)/, backtrace.h \
+ backtrace-supported.h config.h filenames.h internal.h)
+else
+ LIBBACKTRACE_D =
+ LIBBACKTRACE_OBJ =
+ LIBBACKTRACE_H =
+endif
+
MT19937AR_D = $(THIRDPARTY_D)/mt19937ar
MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
@@ -51,7 +64,7 @@ CHAR_PH =
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
- CHAR_SERVER_SQL_DEPENDS=$(CHAR_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(SYSINFO_INC)
+ CHAR_SERVER_SQL_DEPENDS=$(CHAR_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) $(SYSINFO_INC)
else
CHAR_SERVER_SQL_DEPENDS=needs_mysql
endif
@@ -90,7 +103,7 @@ help:
Makefile: Makefile.in
@$(MAKE) -C ../.. src/char/Makefile
-$(SYSINFO_INC): $(CHAR_C) $(CHAR_PH) $(CHAR_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H)
+$(SYSINFO_INC): $(CHAR_C) $(CHAR_PH) $(CHAR_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H)
@echo " MAKE $@"
@$(MAKE) -C ../.. sysinfo
@@ -111,7 +124,7 @@ char-server: ../../char-server@EXEEXT@
../../char-server@EXEEXT@: $(CHAR_SERVER_SQL_DEPENDS) Makefile
@echo " LD $(notdir $@)"
@$(CC) @STATIC@ @LDFLAGS@ -o ../../char-server@EXEEXT@ $(CHAR_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a \
- $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
+ $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) @LIBS@ @MYSQL_LIBS@
# missing object files
$(COMMON_D)/obj_all/common.a:
@@ -130,10 +143,14 @@ $(LIBCONFIG_OBJ):
@echo " MAKE $@"
@$(MAKE) -C $(LIBCONFIG_D)
+$(LIBBACKTRACE_OBJ):
+ @echo " MAKE $@"
+ @$(MAKE) -C $(LIBBACKTRACE_D)
+
.SECONDEXPANSION:
# char object files
-obj_sql/%.o: %.c $$(filter %.p.h, $(CHAR_PH)) $(CHAR_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_sql
+obj_sql/%.o: %.c $$(filter %.p.h, $(CHAR_PH)) $(CHAR_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H) | obj_sql
@echo " CC $<"
@$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
diff --git a/src/char/int_pet.c b/src/char/int_pet.c
index 880de668d..176025f13 100644
--- a/src/char/int_pet.c
+++ b/src/char/int_pet.c
@@ -43,97 +43,161 @@ struct inter_pet_interface *inter_pet;
/**
* Saves a pet to the SQL database.
*
- * @remark
- * In case of newly created pet, the pet ID is not updated to reflect the
- * newly assigned ID. The caller must do so.
+ * Table structure:
+ * `pet` (`pet_id`, `class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, `intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed`)
+ *
+ * @remark In case of newly created pet, the pet ID is not updated to reflect the newly assigned ID. The caller must do so.
*
* @param p The pet data to save.
- * @return The ID of the saved pet.
- * @retval 0 in case of errors.
- */
+ * @return The ID of the saved pet, or 0 in case of errors.
+ *
+ **/
static int inter_pet_tosql(const struct s_pet *p)
{
- //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`)
- char esc_name[NAME_LENGTH*2+1];// escaped pet name
- int pet_id = 0, hungry = 0, intimate = 0;
-
nullpo_ret(p);
- SQL->EscapeStringLen(inter->sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH));
- hungry = cap_value(p->hungry, 0, 100);
- intimate = cap_value(p->intimate, 0, 1000);
-
- if (p->pet_id == 0) {
- // New pet.
- if (SQL_ERROR == SQL->Query(inter->sql_handle, "INSERT INTO `%s` "
- "(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`, `autofeed`) "
- "VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')",
- pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
- p->equip, intimate, hungry, p->rename_flag, p->incubate, p->autofeed)) {
- Sql_ShowDebug(inter->sql_handle);
+ struct SqlStmt *stmt = SQL->StmtMalloc(inter->sql_handle);
+
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return 0;
+ }
+
+ int pet_id = 0;
+
+ if (p->pet_id == 0) { // New pet.
+ const char *query = "INSERT INTO `%s` "
+ "(`class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, "
+ "`intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed`) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, pet_db) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT32, &p->class_, sizeof(p->class_)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_STRING, &p->name, strnlen(p->name, sizeof(p->name))) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 2, SQLDT_INT32, &p->account_id, sizeof(p->account_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 3, SQLDT_INT32, &p->char_id, sizeof(p->char_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 4, SQLDT_INT16, &p->level, sizeof(p->level)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 5, SQLDT_INT32, &p->egg_id, sizeof(p->egg_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 6, SQLDT_INT32, &p->equip, sizeof(p->equip)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 7, SQLDT_INT16, &p->intimate, sizeof(p->intimate)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 8, SQLDT_INT16, &p->hungry, sizeof(p->hungry)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 9, SQLDT_INT8, &p->rename_flag, sizeof(p->rename_flag)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 10, SQLDT_INT8, &p->incubate, sizeof(p->incubate)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 11, SQLDT_INT32, &p->autofeed, sizeof(p->autofeed)) ||
+ SQL_ERROR == SQL->StmtExecute(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
return 0;
}
+
pet_id = (int)SQL->LastInsertId(inter->sql_handle);
- } else {
- // Update pet.
- if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incubate`='%d', `autofeed`='%d' WHERE `pet_id`='%d'",
- pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id,
- p->equip, intimate, hungry, p->rename_flag, p->incubate, p->autofeed, p->pet_id)) {
- Sql_ShowDebug(inter->sql_handle);
+ } else { // Update pet.
+ const char *query = "UPDATE `%s` SET "
+ "`class`=?, `name`=?, `account_id`=?, `char_id`=?, `level`=?, `egg_id`=?, `equip`=?, "
+ "`intimate`=?, `hungry`=?, `rename_flag`=?, `incubate`=?, `autofeed`=? "
+ "WHERE `pet_id`=?";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, pet_db) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT32, &p->class_, sizeof(p->class_)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_STRING, &p->name, strnlen(p->name, sizeof(p->name))) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 2, SQLDT_INT32, &p->account_id, sizeof(p->account_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 3, SQLDT_INT32, &p->char_id, sizeof(p->char_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 4, SQLDT_INT16, &p->level, sizeof(p->level)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 5, SQLDT_INT32, &p->egg_id, sizeof(p->egg_id)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 6, SQLDT_INT32, &p->equip, sizeof(p->equip)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 7, SQLDT_INT16, &p->intimate, sizeof(p->intimate)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 8, SQLDT_INT16, &p->hungry, sizeof(p->hungry)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 9, SQLDT_INT8, &p->rename_flag, sizeof(p->rename_flag)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 10, SQLDT_INT8, &p->incubate, sizeof(p->incubate)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 11, SQLDT_INT32, &p->autofeed, sizeof(p->autofeed)) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 12, SQLDT_INT32, &p->pet_id, sizeof(p->pet_id)) ||
+ SQL_ERROR == SQL->StmtExecute(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
return 0;
}
+
pet_id = p->pet_id;
}
+ SQL->StmtFree(stmt);
+
if (chr->show_save_log)
ShowInfo("Pet saved %d - %s.\n", pet_id, p->name);
return pet_id;
}
+/**
+ * Loads a pet's data from the SQL database.
+ *
+ * Table structure:
+ * `pet` (`pet_id`, `class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, `intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed`)
+ *
+ * @param pet_id The pet's ID.
+ * @param p The pet data to save the SQL data in.
+ * @return Always 0.
+ *
+ **/
static int inter_pet_fromsql(int pet_id, struct s_pet *p)
{
- char* data;
- size_t len;
+ nullpo_ret(p);
+
+ struct SqlStmt *stmt = SQL->StmtMalloc(inter->sql_handle);
+
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return 0;
+ }
#ifdef NOISY
ShowInfo("Loading pet (%d)...\n",pet_id);
#endif
- nullpo_ret(p);
+
memset(p, 0, sizeof(struct s_pet));
- //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`, `autofeed`)
+ const char *query = "SELECT "
+ "`class`, `name`, `account_id`, `char_id`, `level`, `egg_id`, `equip`, "
+ "`intimate`, `hungry`, `rename_flag`, `incubate`, `autofeed` "
+ "FROM `%s` WHERE `pet_id`=?";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, pet_db) ||
+ SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT32, &pet_id, sizeof(pet_id)) ||
+ SQL_ERROR == SQL->StmtExecute(stmt) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT32, &p->class_, sizeof(p->class_), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_STRING, &p->name, sizeof(p->name), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_INT32, &p->account_id, sizeof(p->account_id), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 3, SQLDT_INT32, &p->char_id, sizeof(p->char_id), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 4, SQLDT_INT16, &p->level, sizeof(p->level), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 5, SQLDT_INT32, &p->egg_id, sizeof(p->egg_id), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 6, SQLDT_INT32, &p->equip, sizeof(p->equip), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 7, SQLDT_INT16, &p->intimate, sizeof(p->intimate), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 8, SQLDT_INT16, &p->hungry, sizeof(p->hungry), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 9, SQLDT_INT8, &p->rename_flag, sizeof(p->rename_flag), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 10, SQLDT_INT8, &p->incubate, sizeof(p->incubate), NULL, NULL) ||
+ SQL_ERROR == SQL->StmtBindColumn(stmt, 11, SQLDT_INT32, &p->autofeed, sizeof(p->autofeed), NULL, NULL)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return 0;
+ }
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incubate`,`autofeed` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) )
- {
- Sql_ShowDebug(inter->sql_handle);
+ if (SQL->StmtNumRows(stmt) < 1) {
+ ShowError("inter_pet_fromsql: Requested non-existant pet ID: %d\n", pet_id);
+ SQL->StmtFree(stmt);
return 0;
}
- if( SQL_SUCCESS == SQL->NextRow(inter->sql_handle) )
- {
- p->pet_id = pet_id;
- SQL->GetData(inter->sql_handle, 1, &data, NULL); p->class_ = atoi(data);
- SQL->GetData(inter->sql_handle, 2, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH));
- SQL->GetData(inter->sql_handle, 3, &data, NULL); p->account_id = atoi(data);
- SQL->GetData(inter->sql_handle, 4, &data, NULL); p->char_id = atoi(data);
- SQL->GetData(inter->sql_handle, 5, &data, NULL); p->level = atoi(data);
- SQL->GetData(inter->sql_handle, 6, &data, NULL); p->egg_id = atoi(data);
- SQL->GetData(inter->sql_handle, 7, &data, NULL); p->equip = atoi(data);
- SQL->GetData(inter->sql_handle, 8, &data, NULL); p->intimate = atoi(data);
- SQL->GetData(inter->sql_handle, 9, &data, NULL); p->hungry = atoi(data);
- SQL->GetData(inter->sql_handle, 10, &data, NULL); p->rename_flag = atoi(data);
- SQL->GetData(inter->sql_handle, 11, &data, NULL); p->incubate = atoi(data);
- SQL->GetData(inter->sql_handle, 12, &data, NULL); p->autofeed = atoi(data);
-
- SQL->FreeResult(inter->sql_handle);
-
- p->hungry = cap_value(p->hungry, 0, 100);
- p->intimate = cap_value(p->intimate, 0, 1000);
-
- if (chr->show_save_log)
- ShowInfo("Pet loaded (%d - %s).\n", pet_id, p->name);
+ if (SQL_ERROR == SQL->StmtNextRow(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return 0;
}
+
+ SQL->StmtFree(stmt);
+
+ if (chr->show_save_log)
+ ShowInfo("Pet loaded %d - %s.\n", pet_id, p->name);
+
return 0;
}
//----------------------------------------------
@@ -160,41 +224,48 @@ static int inter_pet_delete(int pet_id)
return 0;
}
//------------------------------------------------------
+
+/**
+ * Creates a new pet and inserts its data into the `pet` SQL table.
+ *
+ * @param account_id The pet's master's account ID.
+ * @param char_id The pet's master's char ID.
+ * @param pet_class The pet's class/monster ID.
+ * @param pet_lv The pet's level.
+ * @param pet_egg_id The pet's egg's item ID.
+ * @param pet_equip The pet's equipment's item ID.
+ * @param intimate The pet's intimacy value.
+ * @param hungry The pet's hunger value.
+ * @param rename_flag The pet's rename flag.
+ * @param incubate The pet's incubate state.
+ * @param pet_name The pet's name.
+ * @return The created pet's data struct, or NULL in case of errors.
+ *
+ **/
static struct s_pet *inter_pet_create(int account_id, int char_id, int pet_class, int pet_lv, int pet_egg_id,
- int pet_equip, short intimate, short hungry, char rename_flag, char incubate, const char *pet_name)
+ int pet_equip, short intimate, short hungry, char rename_flag,
+ char incubate, const char *pet_name)
{
- nullpo_ret(pet_name);
+ nullpo_retr(NULL, pet_name);
+
memset(inter_pet->pt, 0, sizeof(struct s_pet));
safestrncpy(inter_pet->pt->name, pet_name, NAME_LENGTH);
- if(incubate == 1)
- inter_pet->pt->account_id = inter_pet->pt->char_id = 0;
- else {
- inter_pet->pt->account_id = account_id;
- inter_pet->pt->char_id = char_id;
- }
+ inter_pet->pt->account_id = (incubate == 1) ? 0 : account_id;
+ inter_pet->pt->char_id = (incubate == 1) ? 0 : char_id;
inter_pet->pt->class_ = pet_class;
inter_pet->pt->level = pet_lv;
inter_pet->pt->egg_id = pet_egg_id;
inter_pet->pt->equip = pet_equip;
- inter_pet->pt->intimate = intimate;
- inter_pet->pt->hungry = hungry;
+ inter_pet->pt->intimate = cap_value(intimate, PET_INTIMACY_NONE, PET_INTIMACY_MAX);
+ inter_pet->pt->hungry = cap_value(hungry, PET_HUNGER_STARVING, PET_HUNGER_STUFFED);
inter_pet->pt->rename_flag = rename_flag;
inter_pet->pt->incubate = incubate;
+ inter_pet->pt->pet_id = 0; // Signal NEW pet.
- if(inter_pet->pt->hungry < 0)
- inter_pet->pt->hungry = 0;
- else if(inter_pet->pt->hungry > 100)
- inter_pet->pt->hungry = 100;
- if(inter_pet->pt->intimate < 0)
- inter_pet->pt->intimate = 0;
- else if(inter_pet->pt->intimate > 1000)
- inter_pet->pt->intimate = 1000;
-
- inter_pet->pt->pet_id = 0; //Signal NEW pet.
if ((inter_pet->pt->pet_id = inter_pet->tosql(inter_pet->pt)) != 0)
return inter_pet->pt;
- else //Failed...
- return NULL;
+
+ return NULL;
}
static struct s_pet *inter_pet_load(int account_id, int char_id, int pet_id)
diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h
index d2e491ad2..72ae64525 100644
--- a/src/common/HPMDataCheck.h
+++ b/src/common/HPMDataCheck.h
@@ -738,7 +738,6 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = {
{ "PACKET_ZC_REPAIRITEMLIST", sizeof(struct PACKET_ZC_REPAIRITEMLIST), SERVER_TYPE_MAP },
{ "PACKET_ZC_REPAIRITEMLIST_sub", sizeof(struct PACKET_ZC_REPAIRITEMLIST_sub), SERVER_TYPE_MAP },
{ "PACKET_ZC_ROLE_CHANGE", sizeof(struct PACKET_ZC_ROLE_CHANGE), SERVER_TYPE_MAP },
- { "PACKET_ZC_SE_CASHSHOP_OPEN", sizeof(struct PACKET_ZC_SE_CASHSHOP_OPEN), SERVER_TYPE_MAP },
{ "PACKET_ZC_SEARCH_STORE_INFO_ACK", sizeof(struct PACKET_ZC_SEARCH_STORE_INFO_ACK), SERVER_TYPE_MAP },
{ "PACKET_ZC_SEARCH_STORE_INFO_ACK_sub", sizeof(struct PACKET_ZC_SEARCH_STORE_INFO_ACK_sub), SERVER_TYPE_MAP },
{ "PACKET_ZC_SKILL_SCALE", sizeof(struct PACKET_ZC_SKILL_SCALE), SERVER_TYPE_MAP },
@@ -859,6 +858,7 @@ HPExport const struct s_HPMDataCheck HPMDataCheck[] = {
#define MAP_PC_GROUPS_H
#endif // MAP_PC_GROUPS_H
#ifdef MAP_PC_H
+ { "autocast_data", sizeof(struct autocast_data), SERVER_TYPE_MAP },
{ "autotrade_vending", sizeof(struct autotrade_vending), SERVER_TYPE_MAP },
{ "class_exp_group", sizeof(struct class_exp_group), SERVER_TYPE_MAP },
{ "class_exp_tables", sizeof(struct class_exp_tables), SERVER_TYPE_MAP },
diff --git a/src/common/Makefile.in b/src/common/Makefile.in
index 033b26ae3..22b974cfd 100644
--- a/src/common/Makefile.in
+++ b/src/common/Makefile.in
@@ -33,6 +33,19 @@ LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \
LIBCONFIG_H = $(addprefix $(LIBCONFIG_D)/, libconfig.h grammar.h parsectx.h \
scanctx.h scanner.h strbuf.h wincompat.h)
+ifeq (@USE_LIBBACKTRACE@,yes)
+ LIBBACKTRACE_D = $(THIRDPARTY_D)/libbacktrace
+ LIBBACKTRACE_OBJ = $(addprefix $(LIBBACKTRACE_D)/, atomic.o backtrace.o \
+ dwarf.o @LIBBACKTRACE_FORMAT_FILE@ fileline.o mmapio.o mmap.o posix.o print.o \
+ simple.o sort.o state.o)
+ LIBBACKTRACE_H = $(addprefix $(LIBBACKTRACE_D)/, backtrace.h \
+ backtrace-supported.h config.h filenames.h internal.h)
+else
+ LIBBACKTRACE_D =
+ LIBBACKTRACE_OBJ =
+ LIBBACKTRACE_H =
+endif
+
MT19937AR_D = $(THIRDPARTY_D)/mt19937ar
MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
@@ -95,7 +108,7 @@ help:
Makefile: Makefile.in
@$(MAKE) -C ../.. src/common/Makefile
-$(SYSINFO_INC): $(COMMON_C) $(COMMON_PH) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H)
+$(SYSINFO_INC): $(COMMON_C) $(COMMON_PH) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H)
@echo " MAKE $@"
@$(MAKE) -C ../.. sysinfo
@@ -121,7 +134,7 @@ obj_sql/common_sql.a: $(COMMON_SQL_OBJ) Makefile
@echo " AR $@"
@@AR@ rcs obj_sql/common_sql.a $(COMMON_SQL_OBJ)
-common: $(COMMON_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) obj_all/common.a Makefile
+common: $(COMMON_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) obj_all/common.a Makefile
common_sql: $(COMMON_SQL_OBJ) obj_sql/common_sql.a Makefile
@@ -134,14 +147,18 @@ $(LIBCONFIG_OBJ):
@echo " MAKE $@"
@$(MAKE) -C $(LIBCONFIG_D)
+$(LIBBACKTRACE_OBJ):
+ @echo " MAKE $@"
+ @$(MAKE) -C $(LIBBACKTRACE_D)
+
.SECONDEXPANSION:
-obj_all/sysinfo.o: sysinfo.c $(filter sysinfo.p.h, $(COMMON_PH)) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(SYSINFO_INC) | obj_all
+obj_all/sysinfo.o: sysinfo.c $(filter sysinfo.p.h, $(COMMON_PH)) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H) $(SYSINFO_INC) | obj_all
-obj_all/%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | $(SYSINFO_INC) obj_all
+obj_all/%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H) | $(SYSINFO_INC) obj_all
@echo " CC $<"
@$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-obj_sql/%.o: %.c $$(filter %.p.h, $(COMMON_PH)) $(COMMON_H) $(COMMON_SQL_H) $(CONFIG_H) $(LIBCONFIG_H) | $(SYSINFO_INC) obj_sql
+obj_sql/%.o: %.c $$(filter %.p.h, $(COMMON_PH)) $(COMMON_H) $(COMMON_SQL_H) $(CONFIG_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H) | $(SYSINFO_INC) obj_sql
@echo " CC $<"
@$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
diff --git a/src/common/core.c b/src/common/core.c
index 54358b85c..5be90a411 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -489,6 +489,7 @@ int main(int argc, char **argv)
iMalloc->init();// needed for Show* in display_title() [FlavioJS]
showmsg->init();
+ nullpo->init();
cmdline->init();
@@ -552,6 +553,7 @@ int main(int argc, char **argv)
cmdline->final();
//sysinfo->final(); Called by iMalloc->final()
+ nullpo->final();
iMalloc->final();
showmsg->final(); // Should be after iMalloc->final()
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 687f5a187..9421f6e35 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -64,7 +64,7 @@
// 20120307 - 2012-03-07aRagexeRE+ - 0x970
#ifndef PACKETVER
- #define PACKETVER 20141022
+ #define PACKETVER 20190530
#endif // PACKETVER
//Uncomment the following line if your client is ragexeRE instead of ragexe (required because of conflicting packets in ragexe vs ragexeRE).
@@ -1378,6 +1378,27 @@ enum questinfo_type {
QINFO_MERCENARY_CLASS
};
+/** Pet hunger level **/
+enum e_pet_hunger_level {
+ PET_HUNGER_STARVING = 0,
+ PET_HUNGER_VERY_HUNGRY = 10,
+ PET_HUNGER_HUNGRY = 25,
+ PET_HUNGER_NEUTRAL = 75,
+ PET_HUNGER_SATISFIED = 90,
+ PET_HUNGER_STUFFED = 100
+};
+
+/** Pet intimacy level **/
+enum e_pet_intimacy_level {
+ PET_INTIMACY_NONE = 0,
+ PET_INTIMACY_AWKWARD = 1,
+ PET_INTIMACY_SHY = 100,
+ PET_INTIMACY_NEUTRAL = 250,
+ PET_INTIMACY_CORDIAL = 750,
+ PET_INTIMACY_LOYAL = 900,
+ PET_INTIMACY_MAX = 1000
+};
+
/* packet size constant for itemlist */
#if MAX_INVENTORY > MAX_STORAGE && MAX_INVENTORY > MAX_CART
#define MAX_ITEMLIST MAX_INVENTORY
diff --git a/src/common/nullpo.c b/src/common/nullpo.c
index dfb938708..11741745c 100644
--- a/src/common/nullpo.c
+++ b/src/common/nullpo.c
@@ -23,18 +23,106 @@
#include "nullpo.h"
#include "common/showmsg.h"
+#include "common/strlib.h"
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
-#ifdef HAVE_EXECINFO
+#if defined(HAVE_LIBBACKTRACE)
+#include "libbacktrace/backtrace.h"
+#include "libbacktrace/backtrace-supported.h"
+# if defined(WIN32)
+# include <windows.h>
+# elif defined(__sun)
+# include <limits.h>
+# elif defined(__linux) || defined(__linux__)
+# include <unistd.h>
+# include <limits.h>
+# elif defined(__APPLE__) && defined(__MACH__)
+# include <mach-o/dyld.h>
+# elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__)
+# include <sys/types.h>
+# include <sys/sysctl.h>
+# endif
+#elif defined(HAVE_EXECINFO)
#include <execinfo.h>
-#endif // HAVE_EXECINFO
+#endif // HAVE_LIBBACKTRACE
+
static struct nullpo_interface nullpo_s;
struct nullpo_interface *nullpo;
+#ifdef HAVE_LIBBACKTRACE
+static char executable_path[PATH_MAX];
+
+static void nullpo_error_callback(void *data, const char *msg, int errnum)
+{
+ ShowError("Error: %s (%d)", msg, errnum);
+}
+
+static int nullpo_print_callback(void *data, uintptr_t pc, const char *filename, int lineno, const char *function)
+{
+ ShowError("0x%lx %s\n",
+ (unsigned long) pc,
+ function == NULL ? "???" : function);
+ ShowError("\t%s:%d\n",
+ filename == NULL ? "???" : filename,
+ lineno);
+ return 0;
+}
+
+static void nullpo_backtrace_print(struct backtrace_state *state)
+{
+ backtrace_full(state, 0, nullpo_print_callback, nullpo_error_callback, state);
+}
+
+static bool nullpo_backtrace_get_executable_path(char *buf, size_t length)
+{
+#if defined(WIN32)
+ char *exe_path = NULL;
+ if (_get_pgmptr(&exe_path) != 0)
+ return false;
+ safestrncpy(buf, exe_path, length);
+ return true;
+#elif defined(__sun)
+ if (length < MAX_PATH)
+ return false;
+ if (realpath(getexecname(), buf) == NULL)
+ return false;
+ buf[length - 1] = '\0';
+ return true;
+#elif defined(__linux) || defined(__linux__)
+ ssize_t len = readlink("/proc/self/exe", buf, length);
+ if (len <= 0 || len == length)
+ return false;
+ buf[len] = '\0';
+ return true;
+#elif defined(__APPLE__) && defined(__MACH__)
+ uint32_t len = (uint32_t)length;
+ if (_NSGetExecutablePath(buf, &len) != 0)
+ return false; // buffer too small (!)
+ // resolve symlinks, ., .. if possible
+ char *canonical_path = realpath(buf, NULL);
+ if (canonical_path != NULL) {
+ safestrncpy(buf, canonical_path, length);
+ free(canonical_path);
+ }
+ return true;
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__)
+ int mib[4];
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PATHNAME;
+ mib[3] = -1;
+ if (sysctl(mib, 4, buf, &length, NULL, 0) != 0)
+ return false;
+ return true;
+#endif
+ return false;
+}
+#endif // HAVE_LIBBACKTRACE
+
/**
* Reports failed assertions or NULL pointers
*
@@ -46,12 +134,6 @@ struct nullpo_interface *nullpo;
*/
static void assert_report(const char *file, int line, const char *func, const char *targetname, const char *title)
{
-#ifdef HAVE_EXECINFO
- void *array[10];
- int size;
- char **strings;
- int i;
-#endif // HAVE_EXECINFO
if (file == NULL)
file = "??";
@@ -60,21 +142,46 @@ static void assert_report(const char *file, int line, const char *func, const ch
ShowError("--- %s --------------------------------------------\n", title);
ShowError("%s:%d: '%s' in function `%s'\n", file, line, targetname, func);
-#ifdef HAVE_EXECINFO
- size = (int)backtrace(array, 10);
- strings = backtrace_symbols(array, size);
- for (i = 0; i < size; i++)
+#ifdef HAVE_LIBBACKTRACE
+ if (nullpo->backtrace_state != NULL)
+ nullpo_backtrace_print(nullpo->backtrace_state);
+#elif defined(HAVE_EXECINFO)
+ void *array[10];
+ int size = (int)backtrace(array, 10);
+ char **strings = backtrace_symbols(array, size);
+ for (int i = 0; i < size; i++)
ShowError("%s\n", strings[i]);
free(strings);
-#endif // HAVE_EXECINFO
+#endif // HAVE_LIBBACKTRACE
ShowError("--- end %s ----------------------------------------\n", title);
}
+static void nullpo_init(void)
+{
+#ifdef HAVE_LIBBACKTRACE
+ if (!nullpo_backtrace_get_executable_path(executable_path, sizeof executable_path)) {
+ safestrncpy(executable_path, "hercules", sizeof executable_path);
+ }
+ nullpo->backtrace_state = backtrace_create_state(executable_path, BACKTRACE_SUPPORTS_THREADS, nullpo_error_callback, NULL);
+#endif
+}
+
+static void nullpo_final(void)
+{
+ // FIXME: libbacktrace doesn't provide a backtrace_free_state, and it's unsafe to pass the state to
+ // backtrace_free (the function itself uses the state internally). For the time being, we'll leave the state
+ // allocated until program termination as shown in their examples.
+}
+
/**
*
**/
void nullpo_defaults(void)
{
nullpo = &nullpo_s;
+ nullpo->init = nullpo_init;
+ nullpo->final = nullpo_final;
nullpo->assert_report = assert_report;
+
+ nullpo->backtrace_state = NULL;
}
diff --git a/src/common/nullpo.h b/src/common/nullpo.h
index fc5386243..3eb002834 100644
--- a/src/common/nullpo.h
+++ b/src/common/nullpo.h
@@ -28,6 +28,8 @@
// if need disable asserts checks this line can be commented
#define ASSERT_CHECK
+struct backtrace_state;
+
/** Assert */
#if defined(ASSERT_CHECK)
@@ -148,7 +150,12 @@
struct nullpo_interface {
+ void (*init) (void);
+ void (*final) (void);
+
void (*assert_report) (const char *file, int line, const char *func, const char *targetname, const char *title);
+
+ struct backtrace_state *backtrace_state;
};
#ifdef HERCULES_CORE
diff --git a/src/common/packets/packets2020_len_main.h b/src/common/packets/packets2020_len_main.h
index 3349c9872..d3adf8405 100644
--- a/src/common/packets/packets2020_len_main.h
+++ b/src/common/packets/packets2020_len_main.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2018-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2018-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -4617,7 +4617,9 @@ packetLen(0x0b6f, 177)
#endif
// Packet: 0x0b70
-#if PACKETVER >= 20200122
+#if PACKETVER >= 20200318
+packetLen(0x0b70, -1)
+#elif PACKETVER >= 20200122
packetLen(0x0b70, 8)
#endif
@@ -4627,9 +4629,31 @@ packetLen(0x0b71, 177)
#endif
// Packet: 0x0b72
-#if PACKETVER >= 20200122
+#if PACKETVER >= 20200318
+packetLen(0x0b72, -1)
+#elif PACKETVER >= 20200122
packetLen(0x0b72, 4)
#endif
+// Packet: 0x0b73
+#if PACKETVER >= 20200212
+packetLen(0x0b73, 8)
+#endif
+
+// Packet: 0x0b74
+#if PACKETVER >= 20200304
+packetLen(0x0b74, 1026)
+#endif
+
+// Packet: 0x0b75
+#if PACKETVER >= 20200304
+packetLen(0x0b75, 1026)
+#endif
+
+// Packet: 0x0b76
+#if PACKETVER >= 20200401
+packetLen(0x0b76, 77)
+#endif
+
#endif /* COMMON_PACKETS2020_LEN_MAIN_H */
diff --git a/src/common/packets/packets2020_len_re.h b/src/common/packets/packets2020_len_re.h
index b33278c1c..2c21b1c67 100644
--- a/src/common/packets/packets2020_len_re.h
+++ b/src/common/packets/packets2020_len_re.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2018-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2018-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -4637,5 +4637,20 @@ packetLen(0x0b71, 177)
packetLen(0x0b72, 4)
#endif
+// Packet: 0x0b73
+#if PACKETVER >= 20200212
+packetLen(0x0b73, 8)
+#endif
+
+// Packet: 0x0b74
+#if PACKETVER >= 20200304
+packetLen(0x0b74, 1026)
+#endif
+
+// Packet: 0x0b75
+#if PACKETVER >= 20200304
+packetLen(0x0b75, 1026)
+#endif
+
#endif /* COMMON_PACKETS2020_LEN_RE_H */
diff --git a/src/common/packets/packets2020_len_zero.h b/src/common/packets/packets2020_len_zero.h
index 153b66286..888d7999b 100644
--- a/src/common/packets/packets2020_len_zero.h
+++ b/src/common/packets/packets2020_len_zero.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2018-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2018-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -4617,7 +4617,9 @@ packetLen(0x0b6f, 177)
#endif
// Packet: 0x0b70
-#if PACKETVER >= 20200129
+#if PACKETVER >= 20200401
+packetLen(0x0b70, -1)
+#elif PACKETVER >= 20200129
packetLen(0x0b70, 8)
#endif
@@ -4627,9 +4629,31 @@ packetLen(0x0b71, 177)
#endif
// Packet: 0x0b72
-#if PACKETVER >= 20200129
+#if PACKETVER >= 20200401
+packetLen(0x0b72, -1)
+#elif PACKETVER >= 20200129
packetLen(0x0b72, 4)
#endif
+// Packet: 0x0b73
+#if PACKETVER >= 20200212
+packetLen(0x0b73, 8)
+#endif
+
+// Packet: 0x0b74
+#if PACKETVER >= 20200304
+packetLen(0x0b74, 1026)
+#endif
+
+// Packet: 0x0b75
+#if PACKETVER >= 20200304
+packetLen(0x0b75, 1026)
+#endif
+
+// Packet: 0x0b76
+#if PACKETVER >= 20200401
+packetLen(0x0b76, 77)
+#endif
+
#endif /* COMMON_PACKETS2020_LEN_ZERO_H */
diff --git a/src/common/packets/packets_len_main.h b/src/common/packets/packets_len_main.h
index 7b93b35b0..365b0af6f 100644
--- a/src/common/packets/packets_len_main.h
+++ b/src/common/packets/packets_len_main.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2018-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2018-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/src/common/packets/packets_len_re.h b/src/common/packets/packets_len_re.h
index 23a507886..302381722 100644
--- a/src/common/packets/packets_len_re.h
+++ b/src/common/packets/packets_len_re.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2018-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2018-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/src/common/packets/packets_len_zero.h b/src/common/packets/packets_len_zero.h
index 9f1595459..c07f89e3f 100644
--- a/src/common/packets/packets_len_zero.h
+++ b/src/common/packets/packets_len_zero.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2018-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2018-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/src/login/Makefile.in b/src/login/Makefile.in
index 464b33e56..7252eea04 100644
--- a/src/login/Makefile.in
+++ b/src/login/Makefile.in
@@ -36,6 +36,19 @@ LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \
LIBCONFIG_H = $(addprefix $(LIBCONFIG_D)/, libconfig.h grammar.h parsectx.h \
scanctx.h scanner.h strbuf.h wincompat.h)
+ifeq (@USE_LIBBACKTRACE@,yes)
+ LIBBACKTRACE_D = $(THIRDPARTY_D)/libbacktrace
+ LIBBACKTRACE_OBJ = $(addprefix $(LIBBACKTRACE_D)/, atomic.o backtrace.o \
+ dwarf.o @LIBBACKTRACE_FORMAT_FILE@ fileline.o mmapio.o mmap.o posix.o print.o \
+ simple.o sort.o state.o)
+ LIBBACKTRACE_H = $(addprefix $(LIBBACKTRACE_D)/, backtrace.h \
+ backtrace-supported.h config.h filenames.h internal.h)
+else
+ LIBBACKTRACE_D =
+ LIBBACKTRACE_OBJ =
+ LIBBACKTRACE_H =
+endif
+
MT19937AR_D = $(THIRDPARTY_D)/mt19937ar
MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
@@ -47,7 +60,7 @@ LOGIN_PH = lclif.p.h
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
- LOGIN_SERVER_SQL_DEPENDS=$(LOGIN_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(SYSINFO_INC)
+ LOGIN_SERVER_SQL_DEPENDS=$(LOGIN_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) $(SYSINFO_INC)
else
LOGIN_SERVER_SQL_DEPENDS=needs_mysql
endif
@@ -86,7 +99,7 @@ help:
Makefile: Makefile.in
@$(MAKE) -C ../.. src/login/Makefile
-$(SYSINFO_INC): $(LOGIN_C) $(LOGIN_PH) $(LOGIN_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H)
+$(SYSINFO_INC): $(LOGIN_C) $(LOGIN_PH) $(LOGIN_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H)
@echo " MAKE $@"
@$(MAKE) -C ../.. sysinfo
@@ -107,7 +120,7 @@ login-server: ../../login-server@EXEEXT@
../../login-server@EXEEXT@: $(LOGIN_SERVER_SQL_DEPENDS) Makefile
@echo " LD $(notdir $@)"
@$(CC) @STATIC@ @LDFLAGS@ -o ../../login-server@EXEEXT@ $(LOGIN_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a \
- $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
+ $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) @LIBS@ @MYSQL_LIBS@
# missing object files
$(COMMON_D)/obj_all/common.a:
@@ -126,10 +139,14 @@ $(LIBCONFIG_OBJ):
@echo " MAKE $@"
@$(MAKE) -C $(LIBCONFIG_D)
+$(LIBBACKTRACE_OBJ):
+ @echo " MAKE $@"
+ @$(MAKE) -C $(LIBBACKTRACE_D)
+
.SECONDEXPANSION:
# login object files
-obj_sql/%.o: %.c $$(filter %.p.h, $(LOGIN_PH)) $(LOGIN_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_sql
+obj_sql/%.o: %.c $$(filter %.p.h, $(LOGIN_PH)) $(LOGIN_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H) | obj_sql
@echo " CC $<"
@$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
diff --git a/src/map/Makefile.in b/src/map/Makefile.in
index 6dbebb5ad..75093662f 100644
--- a/src/map/Makefile.in
+++ b/src/map/Makefile.in
@@ -36,6 +36,19 @@ LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \
LIBCONFIG_H = $(addprefix $(LIBCONFIG_D)/, libconfig.h grammar.h parsectx.h \
scanctx.h scanner.h strbuf.h wincompat.h)
+ifeq (@USE_LIBBACKTRACE@,yes)
+ LIBBACKTRACE_D = $(THIRDPARTY_D)/libbacktrace
+ LIBBACKTRACE_OBJ = $(addprefix $(LIBBACKTRACE_D)/, atomic.o backtrace.o \
+ dwarf.o @LIBBACKTRACE_FORMAT_FILE@ fileline.o mmapio.o mmap.o posix.o print.o \
+ simple.o sort.o state.o)
+ LIBBACKTRACE_H = $(addprefix $(LIBBACKTRACE_D)/, backtrace.h \
+ backtrace-supported.h config.h filenames.h internal.h)
+else
+ LIBBACKTRACE_D =
+ LIBBACKTRACE_OBJ =
+ LIBBACKTRACE_H =
+endif
+
MT19937AR_D = $(THIRDPARTY_D)/mt19937ar
MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
@@ -60,7 +73,7 @@ MAP_PH = refine.p.h
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
- MAP_SERVER_SQL_DEPENDS=$(MAP_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(SYSINFO_INC)
+ MAP_SERVER_SQL_DEPENDS=$(MAP_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) $(SYSINFO_INC)
else
MAP_SERVER_SQL_DEPENDS=needs_mysql
endif
@@ -99,7 +112,7 @@ help:
Makefile: Makefile.in
@$(MAKE) -C ../.. src/map/Makefile
-$(SYSINFO_INC): $(MAP_C) $(MAP_PH) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H)
+$(SYSINFO_INC): $(MAP_C) $(MAP_PH) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H)
@echo " MAKE $@"
@$(MAKE) -C ../.. sysinfo
@@ -120,7 +133,7 @@ map-server: ../../map-server@EXEEXT@
../../map-server@EXEEXT@: $(MAP_SERVER_SQL_DEPENDS) Makefile
@echo " LD $(notdir $@)"
@$(CC) @STATIC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_OBJ) $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a \
- $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
+ $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) @LIBS@ @MYSQL_LIBS@
# missing object files
$(COMMON_D)/obj_all/common.a:
@@ -139,10 +152,14 @@ $(LIBCONFIG_OBJ):
@echo " MAKE $@"
@$(MAKE) -C $(LIBCONFIG_D)
+$(LIBBACKTRACE_OBJ):
+ @echo " MAKE $@"
+ @$(MAKE) -C $(LIBBACKTRACE_D)
+
.SECONDEXPANSION:
# map object files
-obj_sql/%.o: %.c $$(filter %.p.h, $(MAP_PH)) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_sql
+obj_sql/%.o: %.c $$(filter %.p.h, $(MAP_PH)) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H) | obj_sql
@echo " CC $<"
@$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index df851bbcc..91ddc3ef9 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -2744,42 +2744,49 @@ ACMD(guildlevelup)
return true;
}
-/*==========================================
+/**
+ * Creates a pet egg in the character's inventory.
*
- *------------------------------------------*/
+ * @code{.herc}
+ * @makeegg <pet>
+ * @endcode
+ *
+ **/
ACMD(makeegg)
{
- struct item_data *item_data;
- int id, pet_id;
-
- if (!*message) {
- clif->message(fd, msg_fd(fd,1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>).
+ if (*message == '\0') {
+ clif->message(fd, msg_fd(fd, 1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>).
return false;
}
- if ((item_data = itemdb->search_name(message)) != NULL) // for egg name
+ struct item_data *item_data = itemdb->search_name(message);
+ int id;
+
+ if (item_data != NULL) { // Egg name.
id = item_data->nameid;
- else
- if ((id = mob->db_searchname(message)) != 0) // for monster name
- ;
- else
- id = atoi(message);
+ } else {
+ id = mob->db_searchname(message); // Monster name.
+
+ if (id == 0)
+ id = atoi(message); // Egg/monster ID.
+ }
+
+ int pet_id = pet->search_petDB_index(id, PET_CLASS);
- pet_id = pet->search_petDB_index(id, PET_CLASS);
- if (pet_id < 0)
+ if (pet_id == INDEX_NOT_FOUND)
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->status.account_id, sd->status.char_id,
- pet->db[pet_id].class_, mob->db(pet->db[pet_id].class_)->lv,
- 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_fd(fd,180)); // The monster/egg name/id doesn't exist.
+
+ if (pet_id == INDEX_NOT_FOUND) {
+ clif->message(fd, msg_fd(fd, 180)); // The monster/egg name/ID doesn't exist.
return false;
}
+ sd->catch_target_class = pet->db[pet_id].class_;
+ intif->create_pet(sd->status.account_id, sd->status.char_id, pet->db[pet_id].class_,
+ mob->db(pet->db[pet_id].class_)->lv, pet->db[pet_id].EggID, 0,
+ (short)pet->db[pet_id].intimate, PET_HUNGER_STUFFED,
+ 0, 1,pet->db[pet_id].jname);
+
return true;
}
@@ -2798,72 +2805,90 @@ ACMD(hatch)
return true;
}
-/*==========================================
+/**
+ * Sets a pet's intimacy value.
*
- *------------------------------------------*/
+ * @code{.herc}
+ * @petfriendly <0-1000>
+ * @endcode
+ *
+ **/
ACMD(petfriendly)
{
- int friendly;
- struct pet_data *pd;
-
- if (!*message || (friendly = atoi(message)) < 0) {
- clif->message(fd, msg_fd(fd,1016)); // Please enter a valid value (usage: @petfriendly <0-1000>).
+ if (*message == '\0' || (atoi(message) == 0 && isdigit(*message) == 0)) {
+ clif->message(fd, msg_fd(fd, 1016)); // Please enter a valid value (usage: @petfriendly <0-1000>).
return false;
}
- pd = sd->pd;
- if (!pd) {
- clif->message(fd, msg_fd(fd,184)); // Sorry, but you have no pet.
+ int friendly = atoi(message);
+
+ if (friendly < PET_INTIMACY_NONE || friendly > PET_INTIMACY_MAX) {
+ clif->message(fd, msg_fd(fd, 1016)); // Please enter a valid value (usage: @petfriendly <0-1000>).
return false;
}
- if (friendly < 0 || friendly > 1000)
- {
- clif->message(fd, msg_fd(fd,37)); // An invalid number was specified.
+ struct pet_data *pd = sd->pd;
+
+ if (sd->status.pet_id == 0 || pd == NULL) {
+ clif->message(fd, msg_fd(fd, 184)); // Sorry, but you have no pet.
return false;
}
- if (friendly == pd->pet.intimate) {
- clif->message(fd, msg_fd(fd,183)); // Pet intimacy is already at maximum.
+ if (friendly == pd->pet.intimate && friendly == PET_INTIMACY_MAX) {
+ clif->message(fd, msg_fd(fd, 183)); // Pet intimacy is already at maximum.
return false;
}
- pet->set_intimate(pd, friendly);
- clif->send_petstatus(sd);
- clif->message(fd, msg_fd(fd,182)); // Pet intimacy changed.
+ if (friendly != pd->pet.intimate) { // No need to update the pet's status if intimacy value won't change.
+ pet->set_intimate(pd, friendly);
+ clif->send_petstatus(sd);
+ }
+
+ clif->message(fd, msg_fd(fd, 182)); // Pet intimacy changed. (Send message regardless of value has changed or not.)
+
return true;
}
-/*==========================================
+/**
+ * Sets a pet's hunger value.
*
- *------------------------------------------*/
+ * @code{.herc}
+ * @pethungry <0-100>
+ * @endcode
+ *
+ **/
ACMD(pethungry)
{
- int hungry;
- struct pet_data *pd;
-
- if (!*message || (hungry = atoi(message)) < 0) {
- clif->message(fd, msg_fd(fd,1017)); // Please enter a valid number (usage: @pethungry <0-100>).
+ if (*message == '\0' || (atoi(message) == 0 && isdigit(*message) == 0)) {
+ clif->message(fd, msg_fd(fd, 1017)); // Please enter a valid number (usage: @pethungry <0-100>).
return false;
}
- pd = sd->pd;
- if (!sd->status.pet_id || !pd) {
- clif->message(fd, msg_fd(fd,184)); // Sorry, but you have no pet.
+ int hungry = atoi(message);
+
+ if (hungry < PET_HUNGER_STARVING || hungry > PET_HUNGER_STUFFED) {
+ clif->message(fd, msg_fd(fd, 1017)); // Please enter a valid number (usage: @pethungry <0-100>).
return false;
}
- if (hungry < 0 || hungry > 100) {
- clif->message(fd, msg_fd(fd,37)); // An invalid number was specified.
+
+ struct pet_data *pd = sd->pd;
+
+ if (sd->status.pet_id == 0 || pd == NULL) {
+ clif->message(fd, msg_fd(fd, 184)); // Sorry, but you have no pet.
return false;
}
- if (hungry == pd->pet.hungry) {
- clif->message(fd, msg_fd(fd,186)); // Pet hunger is already at maximum.
+
+ if (hungry == pd->pet.hungry && hungry == PET_HUNGER_STUFFED) {
+ clif->message(fd, msg_fd(fd, 186)); // Pet hunger is already at maximum.
return false;
}
- pd->pet.hungry = hungry;
- clif->send_petstatus(sd);
- clif->message(fd, msg_fd(fd,185)); // Pet hunger changed.
+ if (hungry != pd->pet.hungry) { // No need to update the pet's status if hunger value won't change.
+ pd->pet.hungry = hungry;
+ clif->send_petstatus(sd);
+ }
+
+ clif->message(fd, msg_fd(fd, 185)); // Pet hunger changed. (Send message regardless of value has changed or not.)
return true;
}
@@ -4123,16 +4148,36 @@ ACMD(mapinfo)
for (i = 0; i < map->list[m_id].npc_num;) {
struct npc_data *nd = map->list[m_id].npc[i];
switch(nd->dir) {
- case 0: strcpy(direction, msg_fd(fd,1101)); break; // North
- case 1: strcpy(direction, msg_fd(fd,1102)); break; // North West
- case 2: strcpy(direction, msg_fd(fd,1103)); break; // West
- case 3: strcpy(direction, msg_fd(fd,1104)); break; // South West
- case 4: strcpy(direction, msg_fd(fd,1105)); break; // South
- case 5: strcpy(direction, msg_fd(fd,1106)); break; // South East
- case 6: strcpy(direction, msg_fd(fd,1107)); break; // East
- case 7: strcpy(direction, msg_fd(fd,1108)); break; // North East
- case 9: strcpy(direction, msg_fd(fd,1109)); break; // North
- default: strcpy(direction, msg_fd(fd,1110)); break; // Unknown
+ case UNIT_DIR_NORTH:
+ strcpy(direction, msg_fd(fd, 1101)); // North
+ break;
+ case UNIT_DIR_NORTHWEST:
+ strcpy(direction, msg_fd(fd, 1102)); // North West
+ break;
+ case UNIT_DIR_WEST:
+ strcpy(direction, msg_fd(fd, 1103)); // West
+ break;
+ case UNIT_DIR_SOUTHWEST:
+ strcpy(direction, msg_fd(fd, 1104)); // South West
+ break;
+ case UNIT_DIR_SOUTH:
+ strcpy(direction, msg_fd(fd, 1105)); // South
+ break;
+ case UNIT_DIR_SOUTHEAST:
+ strcpy(direction, msg_fd(fd, 1106)); // South East
+ break;
+ case UNIT_DIR_EAST:
+ strcpy(direction, msg_fd(fd, 1107)); // East
+ break;
+ case UNIT_DIR_NORTHEAST:
+ strcpy(direction, msg_fd(fd, 1108)); // North East
+ break;
+ case 9: // is this actually used? [skyleo]
+ strcpy(direction, msg_fd(fd, 1109)); // North
+ break;
+ default:
+ strcpy(direction, msg_fd(fd, 1110)); // Unknown
+ break;
}
if(strcmp(nd->name,nd->exname) == 0)
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1111), // NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d
@@ -5651,6 +5696,8 @@ ACMD(useskill)
return false;
}
+ pc->autocast_clear(sd);
+
if (skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL
&& sd->hd && homun_alive(sd->hd)) // (If used with @useskill, put the homunc as dest)
bl = &sd->hd->bl;
@@ -6899,7 +6946,7 @@ ACMD(identify)
}
}
}
-
+
if (num == 0)
clif->message(fd,msg_fd(fd,1238)); // There are no items to appraise.
else if (!identifyall)
diff --git a/src/map/battle.c b/src/map/battle.c
index 40e7d3161..40c645cf7 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -3231,12 +3231,11 @@ static int64 battle_calc_damage(struct block_list *src, struct block_list *bl, s
if (!damage) return 0;
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 = 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);
+ enum unit_dir dir = map->calc_dir(bl, src->x, src->y);
+ Assert_ret(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
+ if (unit->movepos(bl, src->x - dirx[dir], src->y - diry[dir], 1, 1)) {
+ clif->slide(bl, src->x - dirx[dir], src->y - diry[dir]);
+ unit->set_dir(bl, dir);
}
d->dmg_lv = ATK_DEF;
status_change_end(bl, SC_LIGHTNINGWALK, INVALID_TIMER);
@@ -5858,10 +5857,10 @@ static void battle_reflect_damage(struct block_list *target, struct block_list *
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);
+ enum unit_dir dir = map->calc_dir(target, src->x, src->y);
+ enum unit_dir t_dir = unit->getdir(target);
- if( !map->check_dir(dir,t_dir) ) {
+ if (map->check_dir(dir, t_dir) == 0) {
int64 rd1 = damage * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage.
trdamage += rdamage = rd1 - (damage = rd1 * 30 / 100); // not normalized as intended.
@@ -5929,21 +5928,21 @@ static void battle_reflect_damage(struct block_list *target, struct block_list *
delay += 100;/* gradual increase so the numbers don't clip in the client */
}
if( sc->data[SC_LG_REFLECTDAMAGE] && rnd()%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;
+ enum autocast_type ac_type;
+
+ if (sd != NULL) {
+ ac_type = sd->autocast.type;
+ sd->autocast.type = AUTOCAST_TEMP;
}
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;
+ if (sd != NULL)
+ sd->autocast.type = ac_type;
delay += 150;/* gradual increase so the numbers don't clip in the client */
@@ -6133,7 +6132,7 @@ static int battle_damage_area(struct block_list *bl, va_list ap)
else
status_fix_damage(src,bl,damage,0);
clif->damage(bl,bl,amotion,dmotion,damage,1,BDT_ENDURE,0);
- if (src->type != BL_PC || !BL_UCCAST(BL_PC, src)->state.autocast)
+ if (src->type != BL_PC || BL_UCCAST(BL_PC, src)->autocast.type != AUTOCAST_TEMP)
skill->additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
map->freeblock_unlock();
}
@@ -6229,10 +6228,10 @@ static enum damage_lv battle_weapon_attack(struct block_list *src, struct block_
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);
+ enum unit_dir dir = map->calc_dir(target, src->x, src->y);
+ enum unit_dir t_dir = unit->getdir(target);
int dist = distance_bl(src, target);
- if(dist <= 0 || (!map->check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) {
+ if(dist <= 0 || (map->check_dir(dir, t_dir) == 0 && 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, sstatus->amotion, 1, 0, 1, BDT_NORMAL, 0); //Display MISS.
@@ -6457,10 +6456,10 @@ static enum damage_lv battle_weapon_attack(struct block_list *src, struct block_
}
}
- sd->state.autocast = 1;
+ sd->autocast.type = AUTOCAST_TEMP;
skill->consume_requirement(sd,r_skill,r_lv,3);
skill->castend_type(type, src, target, r_skill, r_lv, tick, flag);
- sd->state.autocast = 0;
+ sd->autocast.type = AUTOCAST_NONE;
sd->ud.canact_tick = tick + skill->delay_fix(src, r_skill, r_lv);
clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, skill->delay_fix(src, r_skill, r_lv), 0, 0, 1);
}
@@ -6601,10 +6600,6 @@ static int battle_check_target(struct block_list *src, struct block_list *target
m = target->m;
- if (flag & BCT_ENEMY && (map->getcell(m, src, src->x, src->y, CELL_CHKBASILICA) || map->getcell(m, src, 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 )
@@ -6613,6 +6608,11 @@ static int battle_check_target(struct block_list *src, struct block_list *target
if( (s_bl = battle->get_master(src)) == NULL )
s_bl = src;
+ if ((flag & BCT_ENEMY) != 0 && (status_get_mode(s_bl) & MD_BOSS) == 0 && (map->getcell(m, src, src->x, src->y, CELL_CHKBASILICA) != 0
+ || map->getcell(m, src, target->x, target->y, CELL_CHKBASILICA) != 0)) {
+ return -1;
+ }
+
if (s_bl->type == BL_PC) {
const struct map_session_data *s_sd = BL_UCCAST(BL_PC, s_bl);
switch (t_bl->type) {
@@ -7085,16 +7085,15 @@ static const struct battle_data {
{ "guild_emperium_check", &battle_config.guild_emperium_check, 1, 0, 1, },
{ "guild_exp_limit", &battle_config.guild_exp_limit, 50, 0, 99, },
{ "player_invincible_time", &battle_config.pc_invincible_time, 5000, 0, INT_MAX, },
+ { "pet_catch_rate_official_formula", &battle_config.pet_catch_rate_official_formula, 1, 0, 1, },
{ "pet_catch_rate", &battle_config.pet_catch_rate, 100, 0, INT_MAX, },
{ "pet_rename", &battle_config.pet_rename, 0, 0, 1, },
{ "pet_friendly_rate", &battle_config.pet_friendly_rate, 100, 0, INT_MAX, },
{ "pet_hungry_delay_rate", &battle_config.pet_hungry_delay_rate, 100, 10, INT_MAX, },
- { "pet_hungry_friendly_decrease", &battle_config.pet_hungry_friendly_decrease, 5, 0, INT_MAX, },
{ "pet_status_support", &battle_config.pet_status_support, 0, 0, 1, },
{ "pet_attack_support", &battle_config.pet_attack_support, 0, 0, 1, },
{ "pet_damage_support", &battle_config.pet_damage_support, 0, 0, 1, },
{ "pet_support_min_friendly", &battle_config.pet_support_min_friendly, 900, 0, 950, },
- { "pet_equip_min_friendly", &battle_config.pet_equip_min_friendly, 900, 0, 950, },
{ "pet_support_rate", &battle_config.pet_support_rate, 100, 0, INT_MAX, },
{ "pet_attack_exp_to_master", &battle_config.pet_attack_exp_to_master, 0, 0, 1, },
{ "pet_attack_exp_rate", &battle_config.pet_attack_exp_rate, 100, 0, INT_MAX, },
diff --git a/src/map/battle.h b/src/map/battle.h
index 2e710f7f8..bb907d5b9 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -212,16 +212,15 @@ struct Battle_Config {
int guild_aura;
int pc_invincible_time;
+ int pet_catch_rate_official_formula;
int pet_catch_rate;
int pet_rename;
int pet_friendly_rate;
int pet_hungry_delay_rate;
- int pet_hungry_friendly_decrease;
int pet_status_support;
int pet_attack_support;
int pet_damage_support;
int pet_support_min_friendly; //[Skotlex]
- int pet_equip_min_friendly;
int pet_support_rate;
int pet_attack_exp_to_master;
int pet_attack_exp_rate;
diff --git a/src/map/clif.c b/src/map/clif.c
index ddd364a75..496a8beda 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -2179,6 +2179,9 @@ static void clif_selllist(struct map_session_data *sd)
if( !itemdb_cansell(&sd->status.inventory[i], pc_get_group_level(sd)) )
continue;
+ if (sd->status.inventory[i].favorite != 0)
+ continue; // Cannot Sell Favorite item
+
if( sd->status.inventory[i].expire_time )
continue; // Cannot Sell Rental Items
@@ -4900,7 +4903,7 @@ static int clif_damage(struct block_list *src, struct block_list *dst, int sdela
}
if(src == dst) {
- unit->setdir(src,unit->getdir(src));
+ unit->set_dir(src, unit->getdir(src));
}
//Return adjusted can't walk delay for further processing.
@@ -6763,7 +6766,7 @@ static void clif_item_skill(struct map_session_data *sd, uint16 skill_id, uint16
struct PACKET_ZC_AUTORUN_SKILL *p = WFIFOP(fd, 0);
int type = skill->get_inf(skill_id);
- if (sd->state.itemskill_castonself == 1 && skill->is_item_skill(sd, skill_id, skill_lv))
+ if (sd->autocast.itemskill_cast_on_self && sd->autocast.type == AUTOCAST_ITEM)
type = INF_SELF_SKILL;
p->packetType = HEADER_ZC_AUTORUN_SKILL;
@@ -9723,6 +9726,7 @@ static void clif_unknownname_ack(int fd, struct block_list *bl)
{
nullpo_retv(bl);
ShowError("clif_blname_ack: bad type %u(%d)\n", bl->type, bl->id);
+ Assert_retv(0);
}
static void clif_blname_ack(int fd, struct block_list *bl)
@@ -10586,55 +10590,123 @@ static void clif_parse_WantToConnection(int fd, struct map_session_data *sd)
chrif->authreq(sd,false);
}
+/**
+ * Notification from the client, that it has finished map loading and is about to display player's character. (CZ_NOTIFY_ACTORINIT)
+ *
+ * @code
+ * 007d
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ *
+ **/
static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-/// Notification from the client, that it has finished map loading and is about to display player's character (CZ_NOTIFY_ACTORINIT).
-/// 007d
static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd)
{
- bool first_time = false;
-
- if(sd->bl.prev != NULL)
+ if (sd->bl.prev != NULL)
return;
- if (!sd->state.active) { //Character loading is not complete yet!
- //Let pc->reg_received reinvoke this when ready.
+ if (sd->state.active == 0) { // Character loading is not complete yet! Let pc->reg_received reinvoke this when ready.
sd->state.connect_new = 0;
return;
}
- if (sd->state.rewarp) { //Rewarp player.
+ if (sd->state.rewarp != 0) { // Rewarp character.
sd->state.rewarp = 0;
clif->changemap(sd, sd->bl.m, sd->bl.x, sd->bl.y);
return;
}
sd->state.warping = 0;
- sd->state.dialog = 0;/* reset when warping, client dialog will go missing */
+ sd->state.dialog = 0; // Reset when warping. Client dialog will go missing.
- // Character Looks
+ // Character looks.
#if PACKETVER < 4
clif->changelook(&sd->bl, LOOK_WEAPON, sd->status.look.weapon);
clif->changelook(&sd->bl, LOOK_SHIELD, sd->status.look.shield);
#else
- clif->changelook(&sd->bl,LOOK_WEAPON,0);
+ clif->changelook(&sd->bl, LOOK_WEAPON, 0);
#endif
- if(sd->vd.cloth_color)
- clif->refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF);
+ if (sd->vd.cloth_color != 0)
+ clif->refreshlook(&sd->bl, sd->bl.id, LOOK_CLOTHES_COLOR, sd->vd.cloth_color, SELF);
- if (sd->vd.body_style)
- clif->refreshlook(&sd->bl,sd->bl.id,LOOK_BODY2,sd->vd.body_style,SELF);
+ if (sd->vd.body_style != 0)
+ clif->refreshlook(&sd->bl, sd->bl.id, LOOK_BODY2, sd->vd.body_style, SELF);
- // Send character inventory to the client.
- // call this before pc->checkitem() so that the client isn't called to delete a non-existent item.
+ /**
+ * Send character inventory to the client.
+ * Call this before pc->checkitem() so that the client isn't called to delete a non-existent items.
+ *
+ **/
clif->inventoryList(sd);
// Send the cart inventory, counts & weight to the client.
- if(pc_iscarton(sd)) {
+ if (pc_iscarton(sd)) {
clif->cartList(sd);
clif->updatestatus(sd, SP_CARTINFO);
}
+ /**
+ * In official servers, an item's unequip script is executed when entering a zone where the item is restricted,
+ * even if the item won't be unequipped.
+ *
+ **/
+ if (map->list[sd->bl.m].zone != NULL && map->list[sd->bl.m].zone->disabled_items_count != 0) {
+ struct map_zone_data *zone = map->list[sd->bl.m].zone;
+ int dis_items_cnt = zone->disabled_items_count;
+ int handled_equip = 0x00000000;
+
+ for (int i = 0; i < EQI_MAX; i++) {
+ if (sd->equip_index[i] == INDEX_NOT_FOUND)
+ continue;
+
+ int inv_idx = sd->equip_index[i];
+ struct item_data *equip_data = sd->inventory_data[inv_idx];
+
+ if (equip_data == NULL)
+ continue;
+
+ if ((handled_equip & equip_data->equip) != 0)
+ continue; // Equipment takes multiple slots and was already handled.
+
+ handled_equip |= equip_data->equip;
+
+ if (equip_data->unequip_script != NULL) {
+ int idx;
+
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == equip_data->nameid);
+
+ if (idx < dis_items_cnt)
+ script->run_item_unequip_script(sd, equip_data, npc->fake_nd->bl.id);
+ }
+
+ if (inv_idx != sd->equip_index[i])
+ continue; // Unequip script execution corrupted the inventory index.
+
+ struct item *equip = &sd->status.inventory[inv_idx];
+
+ if (equip != NULL && !itemdb_isspecial(equip->card[0])) {
+ for (int slot = 0; slot < equip_data->slot; slot++) {
+ if (equip->card[slot] == 0)
+ continue;
+
+ struct item_data *card_data = itemdb->exists(equip->card[slot]);
+
+ if (card_data != NULL && card_data->unequip_script != NULL) {
+ int idx;
+
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == card_data->nameid);
+
+ if (idx < dis_items_cnt)
+ script->run_item_unequip_script(sd, card_data, npc->fake_nd->bl.id);
+ }
+ }
+ }
+ }
+ }
+
// Check for and delete unavailable/disabled items.
pc->checkitem(sd);
@@ -10642,309 +10714,330 @@ static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd)
clif->updatestatus(sd, SP_WEIGHT);
clif->updatestatus(sd, SP_MAXWEIGHT);
- // guild
- // (needs to go before clif_spawn() to show guild emblems correctly)
- if(sd->status.guild_id)
- guild->send_memberinfoshort(sd,1);
+ // Send character's guild info to the client. Call this before clif->spawn() to show guild emblems correctly.
+ if (sd->status.guild_id != 0)
+ guild->send_memberinfoshort(sd, 1);
- if(battle_config.pc_invincible_time > 0) {
- pc->setinvincibletimer(sd,battle_config.pc_invincible_time);
- }
+ if (battle_config.pc_invincible_time > 0)
+ pc->setinvincibletimer(sd, battle_config.pc_invincible_time);
- if( map->list[sd->bl.m].users++ == 0 && battle_config.dynamic_mobs )
+ if (map->list[sd->bl.m].users++ == 0 && battle_config.dynamic_mobs != 0)
map->spawnmobs(sd->bl.m);
- if( map->list[sd->bl.m].instance_id >= 0 ) {
+ 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) ) {
+ if (pc_has_permission(sd, PC_PERM_VIEW_HPMETER)) {
map->list[sd->bl.m].hpmeter_visible++;
sd->state.hpmeter_visible = 1;
}
- if (!pc_isinvisible(sd)) { // increment the number of pvp players on the map
+ if (!pc_isinvisible(sd)) // 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;
+ sd->state.debug_remove_map = 0; // Temporary state to track double calls of unit->remove_map(). [FlavioJS]
+ sd->state.callshop = 0; // Reset the callshop flag if the character changes map.
+ map->addblock(&sd->bl); // Add the character to the map.
+ clif->spawn(&sd->bl); // Spawn character client side.
- map->addblock(&sd->bl);
- clif->spawn(&sd->bl);
-
- // Party
- // (needs to go after clif_spawn() to show hp bars correctly)
- if(sd->status.party_id) {
+ // Send character's party info to the client. Call this after clif->spawn() to show HP bars correctly.
+ if (sd->status.party_id != 0) {
party->send_movemap(sd);
- clif->party_hp(sd); // Show hp after displacement [LuzZza]
+ clif->party_hp(sd); // Show HP after displacement. [LuzZza]
}
- if( sd->bg_id ) clif->bg_hp(sd); // BattleGround System
+ if (sd->bg_id != 0)
+ clif->bg_hp(sd); // BattleGround system.
+
+ if (map->list[sd->bl.m].flag.pvp != 0 && !pc_isinvisible(sd)) {
+ if (battle_config.pk_mode == 0) { // Remove PVP stuff for pk_mode. [Valaris]
+ if (map->list[sd->bl.m].flag.pvp_nocalcrank == 0)
+ sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
- if (map->list[sd->bl.m].flag.pvp && !pc_isinvisible(sd)) {
- if(!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris]
- 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;
sd->pvp_won = 0;
sd->pvp_lost = 0;
}
+
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE);
- } else
- // set flag, if it's a duel [LuzZza]
- if(sd->duel_group)
+ } else if(sd->duel_group != 0) { // Set flag, if it's a duel. [LuzZza]
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE);
+ }
- if (map->list[sd->bl.m].flag.gvg_dungeon)
+ if (map->list[sd->bl.m].flag.gvg_dungeon != 0)
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); //TODO: Figure out the real packet to send here.
- if( map_flag_gvg2(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)
- 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);
+ // Info about nearby objects. Must use map->foreachinarea(). (CIRCULAR_AREA interferes with map->foreachinrange().)
+ 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_gvg2(sd->bl.m) ) { //Return the pet to egg. [Skotlex]
- clif->message(sd->fd, msg_sd(sd,866)); // "Pets are not allowed in Guild Wars."
- pet->menu(sd, 3); //Option 3 is return to egg.
+ // Spawn pet.
+ if (sd->pd != NULL) {
+ if (battle_config.pet_no_gvg != 0 && map_flag_gvg2(sd->bl.m)) { // Return the pet to egg. [Skotlex]
+ clif->message(sd->fd, msg_sd(sd, 866)); // "Pets are not allowed in Guild Wars."
+ pet->menu(sd, 3); // Option 3 is return to egg.
} else {
map->addblock(&sd->pd->bl);
clif->spawn(&sd->pd->bl);
- clif->send_petdata(sd,sd->pd,0,0);
+ clif->send_petdata(sd,sd->pd, 0, 0);
clif->send_petstatus(sd);
- //skill->unit_move(&sd->pd->bl,timer->gettick(),1);
}
}
- //homunculus [blackhole89]
- if( homun_alive(sd->hd) ) {
+ // Spawn homunculus. [blackhole89]
+ if (homun_alive(sd->hd)) {
map->addblock(&sd->hd->bl);
clif->spawn(&sd->hd->bl);
- clif->send_homdata(sd,SP_ACK,0);
- clif->hominfo(sd,sd->hd,1);
- clif->hominfo(sd,sd->hd,0); //for some reason, at least older clients want this sent twice
+ clif->send_homdata(sd, SP_ACK, 0);
+ clif->hominfo(sd,sd->hd, 1);
+ clif->hominfo(sd,sd->hd, 0); // For some reason, at least older clients want this sent twice.
clif->homskillinfoblock(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,timer->gettick(),1); // apply land skills immediately
+
+ if ((battle_config.hom_setting & 0x8) != 0)
+ status_calc_bl(&sd->hd->bl, SCB_SPEED); // Homunculi mimic their master's speed on each map change.
+
+ if ((battle_config.hom_setting & 0x2) == 0)
+ skill->unit_move(&sd->hd->bl, timer->gettick(), 1); // Apply land skills immediately.
}
- if( sd->md ) {
+ // Spawn mercenary.
+ if (sd->md != NULL) {
map->addblock(&sd->md->bl);
clif->spawn(&sd->md->bl);
clif->mercenary_info(sd);
clif->mercenary_skillblock(sd);
- status_calc_bl(&sd->md->bl, SCB_SPEED); // Mercenary mimic their master's speed on each map change
+ status_calc_bl(&sd->md->bl, SCB_SPEED); // Mercenaries mimic their master's speed on each map change.
}
- if( sd->ed ) {
+ // Spawn elemental.
+ if (sd->ed != NULL) {
map->addblock(&sd->ed->bl);
clif->spawn(&sd->ed->bl);
clif->elemental_info(sd);
- clif->elemental_updatestatus(sd,SP_HP);
- clif->hpmeter_single(sd->fd,sd->ed->bl.id,sd->ed->battle_status.hp,sd->ed->battle_status.max_hp);
- clif->elemental_updatestatus(sd,SP_SP);
- status_calc_bl(&sd->ed->bl, SCB_SPEED); //Elemental mimic their master's speed on each map change
+ clif->elemental_updatestatus(sd, SP_HP);
+ clif->hpmeter_single(sd->fd, sd->ed->bl.id, sd->ed->battle_status.hp, sd->ed->battle_status.max_hp);
+ clif->elemental_updatestatus(sd, SP_SP);
+ status_calc_bl(&sd->ed->bl, SCB_SPEED); // Elementals mimic their master's speed on each map change.
}
- if(sd->state.connect_new) {
- int lv;
+ bool first_time = false;
+
+ if (sd->state.connect_new != 0) {
first_time = true;
sd->state.connect_new = 0;
clif->skillinfoblock(sd);
clif->hotkeysAll(sd);
- clif->updatestatus(sd,SP_BASEEXP);
- clif->updatestatus(sd,SP_NEXTBASEEXP);
- clif->updatestatus(sd,SP_JOBEXP);
- clif->updatestatus(sd,SP_NEXTJOBEXP);
- clif->updatestatus(sd,SP_SKILLPOINT);
+ clif->updatestatus(sd, SP_BASEEXP);
+ clif->updatestatus(sd, SP_NEXTBASEEXP);
+ clif->updatestatus(sd, SP_JOBEXP);
+ clif->updatestatus(sd, SP_NEXTJOBEXP);
+ clif->updatestatus(sd, SP_SKILLPOINT);
clif->initialstatus(sd);
- if (pc_isfalcon(sd))
- clif->status_change(&sd->bl, status->get_sc_icon(SC_FALCON), status->get_sc_relevant_bl_types(SC_FALCON), 1, 0, 0, 0, 0);
- if (pc_isridingpeco(sd) || pc_isridingdragon(sd))
- clif->status_change(&sd->bl, status->get_sc_icon(SC_RIDING), status->get_sc_relevant_bl_types(SC_RIDING), 1, 0, 0, 0, 0);
- else if (pc_isridingwug(sd))
- clif->status_change(&sd->bl, status->get_sc_icon(SC_WUGRIDER), status->get_sc_relevant_bl_types(SC_WUGRIDER), 1, 0, 0, 0, 0);
+ if (pc_isfalcon(sd)) {
+ int sc_icn = status->get_sc_icon(SC_FALCON);
+ int sc_typ = status->get_sc_relevant_bl_types(SC_FALCON);
+ clif->status_change(&sd->bl, sc_icn, sc_typ, 1, 0, 0, 0, 0);
+ }
- if(sd->status.manner < 0)
- sc_start(NULL,&sd->bl,SC_NOCHAT,100,0,0);
+ if (pc_isridingpeco(sd) || pc_isridingdragon(sd)) {
+ int sc_icn = status->get_sc_icon(SC_RIDING);
+ int sc_typ = status->get_sc_relevant_bl_types(SC_RIDING);
+ clif->status_change(&sd->bl, sc_icn, sc_typ, 1, 0, 0, 0, 0);
+ } else if (pc_isridingwug(sd)) {
+ int sc_icn = status->get_sc_icon(SC_WUGRIDER);
+ int sc_typ = status->get_sc_relevant_bl_types(SC_WUGRIDER);
+ clif->status_change(&sd->bl, sc_icn, sc_typ, 1, 0, 0, 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) {
- int i;
- for (i = 0; i < MAX_PC_FEELHATE; i++) {
+ if (sd->status.manner < 0)
+ sc_start(NULL, &sd->bl, SC_NOCHAT, 100, 0, 0);
+
+ int lv = pc->checkskill(sd,SG_KNOWLEDGE);
+
+ // Auron reported that this skill only triggers when you logon on the map. [Skotlex]
+ if (lv > 0) {
+ for (int i = 0; i < MAX_PC_FEELHATE; i++) {
if (sd->bl.m == sd->feel_map[i].m) {
- sc_start(NULL,&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));
break;
}
}
}
- 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));
+ if (sd->pd != NULL && sd->pd->pet.intimate > PET_INTIMACY_LOYAL)
+ clif->pet_emotion(sd->pd, (sd->pd->pet.class_ - 100) * 100 + 50 + pet->hungry_val(sd->pd));
- if(homun_alive(sd->hd))
+ if (homun_alive(sd->hd))
homun->init_timers(sd->hd);
- if (map->night_flag && map->list[sd->bl.m].flag.nightenabled) {
+ if (map->night_flag != 0 && map->list[sd->bl.m].flag.nightenabled != 0) {
+ int sc_icn = status->get_sc_icon(SC_SKE);
+ int sc_typ = status->get_sc_relevant_bl_types(SC_SKE);
+
sd->state.night = 1;
- clif->status_change(&sd->bl, status->get_sc_icon(SC_SKE), status->get_sc_relevant_bl_types(SC_SKE), 1, 0, 0, 0, 0);
+ clif->status_change(&sd->bl, sc_icn, sc_typ, 1, 0, 0, 0, 0);
}
- // Notify everyone that this char logged in [Skotlex].
+ // Notify everyone that this character logged in. [Skotlex]
map->foreachpc(clif->friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 1);
- //Login Event
+ // Run OnPCLoginEvent labels.
npc->script_event(sd, NPCE_LOGIN);
} else {
- //For some reason the client "loses" these on warp/map-change.
- clif->updatestatus(sd,SP_STR);
- clif->updatestatus(sd,SP_AGI);
- clif->updatestatus(sd,SP_VIT);
- clif->updatestatus(sd,SP_INT);
- clif->updatestatus(sd,SP_DEX);
- clif->updatestatus(sd,SP_LUK);
-
- if (sd->state.warp_clean) {
- // abort currently running script
+ // For some reason the client "loses" these on warp/map-change.
+ clif->updatestatus(sd, SP_STR);
+ clif->updatestatus(sd, SP_AGI);
+ clif->updatestatus(sd, SP_VIT);
+ clif->updatestatus(sd, SP_INT);
+ clif->updatestatus(sd, SP_DEX);
+ clif->updatestatus(sd, SP_LUK);
+
+ if (sd->state.warp_clean != 0) { // Abort currently running script.
sd->state.using_fake_npc = 0;
sd->state.menu_or_input = 0;
sd->npc_menu = 0;
- if(sd->npc_id)
+
+ if (sd->npc_id != 0)
npc->event_dequeue(sd);
} else {
sd->state.warp_clean = 1;
}
- 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->guild != NULL && ((battle_config.guild_notice_changemap == 1 && sd->state.changemap != 0)
+ || battle_config.guild_notice_changemap == 2)) {
+ clif->guild_notice(sd, sd->guild);
+ }
}
- if( sd->state.changemap ) {// restore information that gets lost on map-change
+ if (sd->state.changemap != 0) { // Restore information that gets lost on map-change.
#if PACKETVER >= 20070918
clif->partyinvitationstate(sd);
clif->equpcheckbox(sd);
#endif
#if PACKETVER_MAIN_NUM >= 20171025 || PACKETVER_RE_NUM >= 20170920
- if (sd->hd != NULL)
- clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, sd->hd->homunculus.autofeed);
- else
- clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, false);
+ if (sd->hd != NULL)
+ clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, sd->hd->homunculus.autofeed);
+ else
+ clif->zc_config(sd, CZ_CONFIG_HOMUNCULUS_AUTOFEEDING, false);
#endif
- 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( map->night_flag && map->list[sd->bl.m].flag.nightenabled ) {
- //Display night.
- if( !sd->state.night ) {
+ bool flee_penalty = (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100);
+ bool is_gvg = (map_flag_gvg2(sd->state.pmap) || map_flag_gvg2(sd->bl.m));
+ bool is_bg = (map->list[sd->state.pmap].flag.battleground != 0 || map->list[sd->bl.m].flag.battleground != 0);
+
+ if (flee_penalty && (is_gvg || is_bg))
+ status_calc_bl(&sd->bl, SCB_FLEE); // Refresh flee penalty.
+
+ if (map->night_flag != 0 && map->list[sd->bl.m].flag.nightenabled != 0) {
+ if (sd->state.night == 0) { // Display night.
+ int sc_icn = status->get_sc_icon(SC_SKE);
+ int sc_typ = status->get_sc_relevant_bl_types(SC_SKE);
+
sd->state.night = 1;
- clif->status_change(&sd->bl, status->get_sc_icon(SC_SKE), status->get_sc_relevant_bl_types(SC_SKE), 1, 0, 0, 0, 0);
+ clif->status_change(&sd->bl, sc_icn, sc_typ, 1, 0, 0, 0, 0);
}
- } else if( sd->state.night ) { //Clear night display.
+ } else if (sd->state.night != 0) { // Clear night display.
sd->state.night = 0;
clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_SKE));
}
- if( map->list[sd->bl.m].flag.battleground ) {
- clif->map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground Mode
- if( map->list[sd->bl.m].flag.battleground == 2 )
+ if (map->list[sd->bl.m].flag.battleground != 0) {
+ clif->map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground mode.
+
+ if (map->list[sd->bl.m].flag.battleground == 2)
clif->bg_updatescore_single(sd);
}
- if( map->list[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m) ) {
+ if (map->list[sd->bl.m].flag.allowks != 0 && !map_flag_ks(sd->bl.m)) {
char output[128];
+
sprintf(output, "%s", msg_sd(sd, 893)); // [ Kill Steal Protection Disabled. KS is allowed in this map ]
clif->broadcast(&sd->bl, output, (int)strlen(output) + 1, BC_BLUE, SELF);
}
- 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 */
+ 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 (channel->config->local && channel->config->local_autojoin) {
+ if (channel->config->local && channel->config->local_autojoin)
channel->map_join(sd);
- }
- if (channel->config->irc && channel->config->irc_autojoin) {
+
+ if (channel->config->irc && channel->config->irc_autojoin)
channel->irc_join(sd);
- }
}
mail->clear(sd);
+ clif->maptypeproperty2(&sd->bl, SELF);
- clif->maptypeproperty2(&sd->bl,SELF);
-
- /* Guild Aura Init */
- if( sd->state.gmaster_flag ) {
- 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));
+ // Init guild aura.
+ if (sd->state.gmaster_flag != 0) {
+ 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 */
- clif->openvending(sd,sd->bl.id,sd->vending);
- clif->showvendingboard(&sd->bl,sd->message,0);
+ if (sd->state.vending != 0) { // Character is vending.
+ clif->openvending(sd, sd->bl.id, sd->vending);
+ clif->showvendingboard(&sd->bl, sd->message, 0);
}
- if(map->list[sd->bl.m].flag.loadevent) // Lance
+ if (map->list[sd->bl.m].flag.loadevent != 0) // Run OnPCLoadMapEvent labels. [Lance]
npc->script_event(sd, NPCE_LOADMAP);
- if (pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd)) //blindness [Komurka]
+ if (pc->checkskill(sd, SG_DEVIL) > 0 && pc->nextjobexp(sd) == 0) // Blindness. [Komurka]
clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_DEVIL1));
- if (sd->sc.opt2) //Client loses these on warp.
+ if (sd->sc.opt2 != 0) // 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) ){
+ if (sd->sc.data[SC_MONSTER_TRANSFORM] != NULL && battle_config.mon_trans_disable_in_gvg != 0
+ && map_flag_gvg2(sd->bl.m)) {
status_change_end(&sd->bl, SC_MONSTER_TRANSFORM, INVALID_TIMER);
- clif->message(sd->fd, msg_sd(sd,1488)); // Transforming into monster is not allowed in Guild Wars.
+ clif->message(sd->fd, msg_sd(sd, 1488)); // Transforming into monster is not allowed in Guild Wars.
}
clif->weather_check(sd);
- // This should be displayed last
- if( sd->guild && first_time )
+ // This should be displayed last.
+ if (sd->guild != NULL && 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 (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNPC))
- npc->touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y);
+ // For automatic triggering of NPCs after map loading. (So you don't need to walk 1 step first.)
+ if (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNPC) != 0)
+ npc->touch_areanpc(sd, sd->bl.m, sd->bl.x, sd->bl.y);
else
npc->untouch_areanpc(sd, sd->bl.m, sd->bl.x, sd->bl.y);
- /* 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) )
+ // It broke at some point (e.g. during a crash), so we make it visibly dead again.
+ if (sd->status.hp == 0 && !pc_isdead(sd) && status->isdead(&sd->bl) != 0)
pc_setdead(sd);
- // If player is dead, and is spawned (such as @refresh) send death packet. [Valaris]
- if(pc_isdead(sd))
+ // Send death packet, if character is dead and is spawned (such as @refresh). [Valaris]
+ if (pc_isdead(sd)) {
clif->clearunit_area(&sd->bl, CLR_DEAD);
- else {
+ } else {
skill->usave_trigger(sd);
+
if (battle_config.player_warp_keep_direction == 1)
clif->changed_dir(&sd->bl, SELF); // Visually updates player facing direction
}
- // Trigger skill effects if you appear standing on them
- if(!battle_config.pc_invincible_time)
- skill->unit_move(&sd->bl,timer->gettick(),1);
+ // Trigger skill effects if you appear standing on them.
+ if (battle_config.pc_invincible_time == 0)
+ skill->unit_move(&sd->bl, timer->gettick(), 1);
- // NPC Quest / Event Icon Check [Kisuka]
#if PACKETVER >= 20090218
- quest->questinfo_refresh(sd);
+ quest->questinfo_refresh(sd); // NPC quest/event icon check. [Kisuka]
#endif
}
@@ -11180,7 +11273,7 @@ static void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
//Set last idle time... [Skotlex]
pc->update_idle_time(sd, BCIDLE_WALK);
- unit->walktoxy(&sd->bl, x, y, 4);
+ unit->walk_toxy(&sd->bl, x, y, 4);
}
/// Notification about the result of a disconnect request (ZC_ACK_REQ_DISCONNECT).
@@ -11398,15 +11491,7 @@ static void clif_parse_MapMove(int fd, struct map_session_data *sd)
/// 0 = straight
/// 1 = turned CW
/// 2 = turned CCW
-/// dir:
-/// 0 = north
-/// 1 = northwest
-/// 2 = west
-/// 3 = southwest
-/// 4 = south
-/// 5 = southeast
-/// 6 = east
-/// 7 = northeast
+/// dir: @see enum unit_dir
static void clif_changed_dir(struct block_list *bl, enum send_target target)
{
unsigned char buf[64];
@@ -12702,6 +12787,14 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill
{
int64 tick = timer->gettick();
+ /**
+ * According to Skotlex' comment below, the client sometimes passes 0 for the skill level.
+ * Even though this seems to only affect guild skills, sd->autocast.skill_lv is used
+ * for the auto-cast data validation if skill_lv is 0.
+ *
+ **/
+ skill->validate_autocast_data(sd, skill_id, (skill_lv == 0) ? sd->autocast.skill_lv : skill_lv);
+
if (skill_lv < 1)
skill_lv = 1; //No clue, I have seen the client do this with guild skills :/ [Skotlex]
@@ -12755,7 +12848,7 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill
if (skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST)
return;
} else if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) {
- if (sd->skillitem != skill_id) {
+ if (sd->autocast.type == AUTOCAST_NONE) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
@@ -12773,16 +12866,16 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill
} else if (sd->menuskill_id != SA_AUTOSPELL)
return; //Can't use skills while a menu is open.
}
- if (sd->skillitem == skill_id) {
- if (skill_lv != sd->skillitemlv)
- skill_lv = sd->skillitemlv;
+ if (sd->autocast.type != AUTOCAST_NONE) {
+ if (skill_lv != sd->autocast.skill_lv)
+ skill_lv = sd->autocast.skill_lv;
if (!(tmp&INF_SELF_SKILL))
pc->delinvincibletimer(sd); // Target skills through items cancel invincibility. [Inkfish]
unit->skilluse_id(&sd->bl, target_id, skill_id, skill_lv);
return;
}
- sd->skillitem = sd->skillitemlv = 0;
+ pc->autocast_clear(sd);
if (skill_id >= GD_SKILLBASE && skill_id < GD_MAX) {
if (sd->state.gmaster_flag)
@@ -12843,6 +12936,16 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
int64 tick = timer->gettick();
nullpo_retv(sd);
+
+ /**
+ * When using clif_item_skill() to initiate the execution of ground skills,
+ * the client sometimes passes 0 for the skill level in packet 0x0af4.
+ * In that case sd->autocast.skill_lv is used for the auto-cast data validation,
+ * since clif_item_skill() is only used for auto-cast skills.
+ *
+ **/
+ skill->validate_autocast_data(sd, skill_id, (skill_lv == 0) ? sd->autocast.skill_lv : skill_lv);
+
if( !(skill->get_inf(skill_id)&INF_GROUND_SKILL) )
return; //Using a target skill on the ground? WRONG.
@@ -12883,7 +12986,7 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
return;
if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) {
- if( sd->skillitem != skill_id ) {
+ if (sd->autocast.type == AUTOCAST_NONE) {
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0, 0);
return;
}
@@ -12904,13 +13007,13 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
pc->delinvincibletimer(sd);
- if( sd->skillitem == skill_id ) {
- if( skill_lv != sd->skillitemlv )
- skill_lv = sd->skillitemlv;
+ if (sd->autocast.type != AUTOCAST_NONE) {
+ if (skill_lv != sd->autocast.skill_lv)
+ skill_lv = sd->autocast.skill_lv;
unit->skilluse_pos(&sd->bl, x, y, skill_id, skill_lv);
} else {
int lv;
- sd->skillitem = sd->skillitemlv = 0;
+ pc->autocast_clear(sd);
if( (lv = pc->checkskill(sd, skill_id)) > 0 ) {
if( skill_lv > lv )
skill_lv = lv;
@@ -12981,9 +13084,15 @@ static void clif_parse_UseSkillMap(int fd, struct map_session_data *sd)
return;
}
+ /**
+ * Since no skill level was passed use 0 to notify skill_validate_autocast_data() of this special case.
+ *
+ **/
+ skill->validate_autocast_data(sd, skill_id, 0);
+
pc->delinvincibletimer(sd);
skill->castend_map(sd,skill_id,map_name);
- pc->itemskill_clear(sd);
+ pc->autocast_clear(sd);
}
static void clif_parse_RequestMemo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -15176,58 +15285,68 @@ static void clif_parse_ChangePetName(int fd, struct map_session_data *sd)
pet->change_name(sd, RFIFOP(fd,2));
}
+/**
+ * Request to evolve the pet. (CZ_PET_EVOLUTION)
+ *
+ * @code
+ * 09fb <Length>.W <EvolvedPetEggID>.W {<index>.W <amount>.W}*items
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ *
+ **/
static void clif_parse_pet_evolution(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
-/// Request to Evolve the pet (CZ_PET_EVOLUTION) [Dastgir/Hercules]
-/// 09fb <Length>.W <EvolvedPetEggID>.W {<index>.W <amount>.W}*items
static void clif_parse_pet_evolution(int fd, struct map_session_data *sd)
{
- if (sd->state.trading || pc_isdead(sd) || pc_isvending(sd))
+ if (sd->state.trading != 0 || pc_isdead(sd) || pc_isvending(sd))
return;
- const struct PACKET_CZ_PET_EVOLUTION *p = RP2PTR(fd);
- int i = 0, idx, petIndex;
-
- Assert_retv(p->PacketLength >= (uint16)sizeof(struct PACKET_CZ_PET_EVOLUTION));
-
- if (sd->status.pet_id == 0) {
+ if (sd->pd == NULL || sd->status.pet_id == 0) { // No pet.
clif->petEvolutionResult(fd, PET_EVOL_NO_CALLPET);
return;
}
- ARR_FIND(0, sd->status.inventorySize, idx, sd->status.inventory[idx].card[0] == CARD0_PET &&
- sd->status.pet_id == MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2]));
+ int inv_index;
- if (idx == sd->status.inventorySize) {
+ ARR_FIND(0, sd->status.inventorySize, inv_index, sd->status.inventory[inv_index].card[0] == CARD0_PET
+ && sd->status.pet_id == MakeDWord(sd->status.inventory[inv_index].card[1],
+ sd->status.inventory[inv_index].card[2]));
+
+ if (inv_index == sd->status.inventorySize) { // No pet egg.
clif->petEvolutionResult(fd, PET_EVOL_NO_PETEGG);
return;
}
- // Not Loyal Yet
- if (sd->pd == NULL || sd->pd->pet.intimate < 900) {
+ if (sd->pd->pet.intimate < PET_INTIMACY_LOYAL) { // Pet isn't loyal.
clif->petEvolutionResult(fd, PET_EVOL_RG_FAMILIAR);
return;
}
- ARR_FIND(0, MAX_PET_DB, petIndex, pet->db[petIndex].class_ == sd->pd->pet.class_);
+ int pet_index;
+
+ ARR_FIND(0, MAX_PET_DB, pet_index, pet->db[pet_index].class_ == sd->pd->pet.class_);
- if (petIndex == MAX_PET_DB) {
- // Which error?
- clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN);
+ if (pet_index == MAX_PET_DB) {
+ clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN); // Which error?
return;
}
+ const struct PACKET_CZ_PET_EVOLUTION *p = RP2PTR(fd);
+
+ Assert_retv(p->PacketLength >= (uint16)sizeof(struct PACKET_CZ_PET_EVOLUTION));
+
// Client side validation is not done as it is insecure.
- for (i = 0; i < VECTOR_LENGTH(pet->db[petIndex].evolve_data); i++) {
- struct pet_evolve_data *ped = &VECTOR_INDEX(pet->db[petIndex].evolve_data, i);
- if (ped->petEggId == p->EvolvedPetEggID) {
- int j;
- int pet_id;
+ for (int i = 0; i < VECTOR_LENGTH(pet->db[pet_index].evolve_data); i++) {
+ struct pet_evolve_data *ped = &VECTOR_INDEX(pet->db[pet_index].evolve_data, i);
+ if (ped->petEggId == p->EvolvedPetEggID) {
if (VECTOR_LENGTH(ped->items) == 0) {
clif->petEvolutionResult(fd, PET_EVOL_NO_RECIPE);
return;
}
- for (j = 0; j < VECTOR_LENGTH(ped->items); j++) {
+
+ for (int j = 0; j < VECTOR_LENGTH(ped->items); j++) {
struct itemlist_entry *list = &VECTOR_INDEX(ped->items, j);
int n = pc->search_inventory(sd, list->id);
@@ -15237,7 +15356,7 @@ static void clif_parse_pet_evolution(int fd, struct map_session_data *sd)
}
}
- for (j = 0; j < VECTOR_LENGTH(ped->items); j++) {
+ for (int j = 0; j < VECTOR_LENGTH(ped->items); j++) {
struct itemlist_entry *list = &VECTOR_INDEX(ped->items, j);
int n = pc->search_inventory(sd, list->id);
@@ -15247,27 +15366,26 @@ static void clif_parse_pet_evolution(int fd, struct map_session_data *sd)
}
}
- // Return to Egg
- pet->return_egg(sd, sd->pd);
+ pet->return_egg(sd, sd->pd); // Return pet to egg.
- if (pc->delitem(sd, idx, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG) == 1) {
+ if (pc->delitem(sd, inv_index, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG) == 1) {
clif->petEvolutionResult(fd, PET_EVOL_NO_PETEGG);
return;
}
- pet_id = pet->search_petDB_index(ped->petEggId, PET_EGG);
+ int pet_id = pet->search_petDB_index(ped->petEggId, PET_EGG);
+
if (pet_id >= 0) {
sd->catch_target_class = pet->db[pet_id].class_;
-
- intif->create_pet(
- sd->status.account_id, sd->status.char_id,
- pet->db[pet_id].class_, mob->db(pet->db[pet_id].class_)->lv,
- pet->db[pet_id].EggID, 0, (short)pet->db[pet_id].intimate,
- 100, 0, 1, pet->db[pet_id].jname);
+ intif->create_pet(sd->status.account_id, sd->status.char_id, pet->db[pet_id].class_,
+ mob->db(pet->db[pet_id].class_)->lv, pet->db[pet_id].EggID,
+ 0, (short)pet->db[pet_id].intimate, PET_HUNGER_STUFFED,
+ 0, 1, pet->db[pet_id].jname);
clif->petEvolutionResult(fd, PET_EVOL_SUCCESS);
} else {
clif->petEvolutionResult(fd, PET_EVOL_UNKNOWN);
}
+
return;
}
}
@@ -16509,7 +16627,7 @@ static void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd)
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->walk_toxy(bl, ud->to_x, ud->to_y, 4);
}
static void clif_parse_HomMoveTo(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -16533,7 +16651,7 @@ static void clif_parse_HomMoveTo(int fd, struct map_session_data *sd)
else
return;
- unit->walktoxy(bl, x, y, 4);
+ unit->walk_toxy(bl, x, y, 4);
}
static void clif_parse_HomAttack(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -20087,7 +20205,7 @@ static void clif_parse_cashShopOpen2(int fd, struct map_session_data *sd)
static void clif_cashShopOpen(int fd, struct map_session_data *sd, int tab)
{
-#if PACKETVER_MAIN_NUM >= 20101123 || PACKETVER_RE_NUM >= 20120328 || PACKETVER_ZERO_NUM >= defined(PACKETVER_ZERO)
+#if PACKETVER_MAIN_NUM >= 20101123 || PACKETVER_RE_NUM >= 20120328 || defined(PACKETVER_ZERO)
WFIFOHEAD(fd, sizeof(struct PACKET_ZC_SE_CASHSHOP_OPEN));
struct PACKET_ZC_SE_CASHSHOP_OPEN *p = WFIFOP(fd, 0);
p->packetType = HEADER_ZC_SE_CASHSHOP_OPEN;
@@ -23282,7 +23400,8 @@ static void clif_parse_npc_expanded_barter_closed(int fd, struct map_session_dat
#if PACKETVER_MAIN_NUM >= 20191120 || PACKETVER_RE_NUM >= 20191106 || PACKETVER_ZERO_NUM >= 20191127
#define NEXT_EXPANDED_BARTER_ITEM(var, count) \
var = (struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub *)((char*)item + \
- sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub) + \
+ sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub) - \
+ sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2) + \
count * sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2))
#endif
@@ -23302,7 +23421,11 @@ static void clif_npc_expanded_barter_open(struct map_session_data *sd, struct np
packet->packetType = HEADER_ZC_NPC_EXPANDED_BARTER_OPEN;
struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub *item = &packet->items[0];
- for (int i = 0; i < shop_size && buf_left >= sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub); i++) {
+ // Workaround for fix Visual Studio bug (error C2233)
+ // Here should be sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub)
+ const int ptr_size = sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub) -
+ sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2);
+ for (int i = 0; i < shop_size && buf_left >= ptr_size; i++) {
if (shop[i].nameid) {
struct item_data *id = itemdb->exists(shop[i].nameid);
if (id == NULL)
@@ -23315,7 +23438,7 @@ static void clif_npc_expanded_barter_open(struct map_session_data *sd, struct np
item->index = i;
item->zeny = shop[i].value;
item->currency_count = 0;
- buf_left -= sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub);
+ buf_left -= ptr_size;
items_count ++;
int count = shop[i].value2;
if (buf_left < sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2) * count) {
@@ -23344,7 +23467,7 @@ static void clif_npc_expanded_barter_open(struct map_session_data *sd, struct np
packet->items_count = items_count;
packet->packetLength = sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN) +
- sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub) * items_count +
+ ptr_size * items_count +
sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2) * currencies_count;
clif->send(packet, packet->packetLength, &sd->bl, SELF);
#endif
diff --git a/src/map/elemental.c b/src/map/elemental.c
index 1c1d98634..f176bb9e2 100644
--- a/src/map/elemental.c
+++ b/src/map/elemental.c
@@ -788,8 +788,8 @@ static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_
return 0; //Already walking to him
if( DIFF_TICK(tick, ed->ud.canmove_tick) < 0 )
return 0; //Can't move yet.
- if( map->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) != 0
+ && unit->walk_toxy(&ed->bl, x, y, 0) == 0)
return 0;
}
diff --git a/src/map/map.c b/src/map/map.c
index 70623ae22..defa56b2e 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -1670,7 +1670,7 @@ static int map_search_freecell(struct block_list *src, int16 m, int16 *x, int16
*------------------------------------------*/
static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16 *y, int type, int flag)
{
- uint8 dir = 6;
+ enum unit_dir dir = UNIT_DIR_EAST;
int16 tx;
int16 ty;
int costrange = 10;
@@ -1689,7 +1689,7 @@ static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x,
short dy = diry[dir];
//Linear search
- if(dir%2 == 0 && costrange%MOVE_COST == 0) {
+ if (!unit_is_diagonal_dir(dir) && (costrange % MOVE_COST) == 0) {
tx = *x+dx*(costrange/MOVE_COST);
ty = *y+dy*(costrange/MOVE_COST);
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
@@ -1699,7 +1699,7 @@ static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x,
}
}
//Full diagonal search
- else if(dir%2 == 1 && costrange%MOVE_DIAGONAL_COST == 0) {
+ else if (unit_is_diagonal_dir(dir) && (costrange % MOVE_DIAGONAL_COST) == 0) {
tx = *x+dx*(costrange/MOVE_DIAGONAL_COST);
ty = *y+dy*(costrange/MOVE_DIAGONAL_COST);
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
@@ -1709,16 +1709,24 @@ static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x,
}
}
//One cell diagonal, rest linear (TODO: Find a better algorithm for this)
- else if(dir%2 == 1 && costrange%MOVE_COST == 4) {
- tx = *x+dx*((dir%4==3)?(costrange/MOVE_COST):1);
- ty = *y+dy*((dir%4==1)?(costrange/MOVE_COST):1);
+ else if (unit_is_diagonal_dir(dir) && (costrange % MOVE_COST) == 4) {
+ tx = *x + dx;
+ ty = *y + dy;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_SOUTHWEST))
+ tx *= costrange / MOVE_COST;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_NORTHWEST))
+ ty *= costrange / MOVE_COST;
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
*x = tx;
*y = ty;
return true;
}
- tx = *x+dx*((dir%4==1)?(costrange/MOVE_COST):1);
- ty = *y+dy*((dir%4==3)?(costrange/MOVE_COST):1);
+ tx = *x + dx;
+ ty = *y + dy;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_NORTHWEST))
+ tx *= costrange / MOVE_COST;
+ if (unit_is_dir_or_opposite(dir, UNIT_DIR_SOUTHWEST))
+ ty *= costrange / MOVE_COST;
if (!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m, bl, tx, ty, CELL_CHKPASS)) {
*x = tx;
*y = ty;
@@ -1727,17 +1735,17 @@ static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x,
}
//Get next direction
- if (dir == 5) {
+ if (dir == UNIT_DIR_SOUTHEAST) {
//Diagonal search complete, repeat with higher cost range
if(costrange == 14) costrange += 6;
else if(costrange == 28 || costrange >= 38) costrange += 2;
else costrange += 4;
- dir = 6;
- } else if (dir == 4) {
+ dir = UNIT_DIR_EAST;
+ } else if (dir == UNIT_DIR_SOUTH) {
//Linear search complete, switch to diagonal directions
- dir = 7;
+ dir = UNIT_DIR_NORTHEAST;
} else {
- dir = (dir+2)%8;
+ dir = unit_get_ccw90_dir(dir);
}
}
@@ -2845,63 +2853,70 @@ static int map_mapname2ipport(unsigned short name, uint32 *ip, uint16 *port)
return 0;
}
-/*==========================================
+/**
* Checks if both dirs point in the same direction.
- *------------------------------------------*/
-static int map_check_dir(int s_dir, int t_dir)
+ * @param s_dir: direction source is facing
+ * @param t_dir: direction target is facing
+ * @return 0: success(both face the same direction), 1: failure
+ **/
+static int map_check_dir(enum unit_dir s_dir, enum unit_dir t_dir)
{
- if(s_dir == t_dir)
+ if (s_dir == t_dir || ((t_dir + UNIT_DIR_MAX - 1) % UNIT_DIR_MAX) == s_dir
+ || ((t_dir + UNIT_DIR_MAX + 1) % UNIT_DIR_MAX) == s_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;
- }
return 1;
}
-/*==========================================
+/**
* Returns the direction of the given cell, relative to 'src'
- *------------------------------------------*/
-static uint8 map_calc_dir(struct block_list *src, int16 x, int16 y)
+ * @param src: object to put in relation between coordinates
+ * @param x: x-coordinate of cell
+ * @param y: y-coordinate of cell
+ * @return the direction of the given cell, relative to 'src'
+ **/
+static enum unit_dir map_calc_dir(const struct block_list *src, int16 x, int16 y)
{
- uint8 dir = 0;
- int dx, dy;
-
- nullpo_ret(src);
+ nullpo_retr(UNIT_DIR_NORTH, src);
+ enum unit_dir dir = UNIT_DIR_NORTH;
- dx = x-src->x;
- dy = y-src->y;
+ int dx = x - src->x;
+ int dy = y - src->y;
if (dx == 0 && dy == 0) {
// 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
- if( dx*2 < dy || dx == 0 ) dir = 0; // up
- else if( dx > dy*2+1 || dy == 0 ) dir = 6; // right
- else dir = 7; // up-right
+ if (battle_config.knockback_left != 0)
+ dir = UNIT_DIR_EAST;
+ else
+ dir = unit->getdir(src);
+ } else if (dx >= 0 && dy >= 0) {
+ if (dx * 2 < dy || dx == 0)
+ dir = UNIT_DIR_NORTH;
+ else if (dx > dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_EAST;
+ else
+ dir = UNIT_DIR_NORTHEAST;
} else if (dx >= 0 && dy <= 0) {
- // lower-right
- if( dx*2 < -dy || dx == 0 ) dir = 4; // down
- else if( dx > -dy*2+1 || dy == 0 ) dir = 6; // right
- else dir = 5; // down-right
+ if (dx * 2 < -dy || dx == 0)
+ dir = UNIT_DIR_SOUTH;
+ else if (dx > -dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_EAST;
+ else
+ dir = UNIT_DIR_SOUTHEAST;
} else if (dx <= 0 && dy <= 0) {
- // lower-left
- if( dx*2 > dy || dx == 0 ) dir = 4; // down
- else if( dx < dy*2-1 || dy == 0 ) dir = 2; // left
- else dir = 3; // down-left
+ if (dx * 2 > dy || dx == 0 )
+ dir = UNIT_DIR_SOUTH;
+ else if (dx < dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_WEST;
+ else
+ dir = UNIT_DIR_SOUTHWEST;
} else {
- // upper-left
- if( -dx*2 < dy || dx == 0 ) dir = 0; // up
- else if( -dx > dy*2+1 || dy == 0) dir = 2; // left
- else dir = 1; // up-left
+ if (-dx * 2 < dy || dx == 0 )
+ dir = UNIT_DIR_NORTH;
+ else if (-dx > dy * 2 + 1 || dy == 0)
+ dir = UNIT_DIR_WEST;
+ else
+ dir = UNIT_DIR_NORTHWEST;
}
return dir;
}
@@ -2929,11 +2944,11 @@ static int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
if (dist < 1) dist =1;
do {
- int j = 1 + 2*(rnd()%4); //Pick a random diagonal direction
+ enum unit_dir dir = unit_get_rnd_diagonal_dir();
short segment = 1+(rnd()%dist); //Pick a random interval from the whole vector in that direction
- xi = bl->x + segment*dirx[j];
+ xi = bl->x + segment * dirx[dir];
segment = (short)sqrt((float)(dist2 - segment*segment)); //The complement of the previously picked segment
- yi = bl->y + segment*diry[j];
+ yi = bl->y + segment * diry[dir];
} while ((map->getcell(bl->m, bl, xi, yi, CELL_CHKNOPASS) || !path->search(NULL, bl, bl->m, bl->x, bl->y, xi, yi, 1, CELL_CHKNOREACH))
&& (++i)<100);
diff --git a/src/map/map.h b/src/map/map.h
index dbd9c0fba..a876539d0 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -27,6 +27,7 @@
#include "common/db.h"
#include "common/mapindex.h"
#include "common/mmo.h"
+#include "map/unitdefines.h" // enum unit_dir
#include <stdio.h>
#include <stdarg.h>
@@ -1216,8 +1217,8 @@ END_ZEROED_BLOCK;
// reload config file looking only for npcs
void (*reloadnpc) (bool clear);
- int (*check_dir) (int s_dir,int t_dir);
- uint8 (*calc_dir) (struct block_list *src,int16 x,int16 y);
+ int (*check_dir) (enum unit_dir s_dir, enum unit_dir t_dir);
+ enum unit_dir (*calc_dir) (const struct block_list *src, int16 x, int16 y);
int (*random_dir) (struct block_list *bl, short *x, short *y); // [Skotlex]
int (*cleanup_sub) (struct block_list *bl, va_list ap);
diff --git a/src/map/mapdefines.h b/src/map/mapdefines.h
index f5a8149d4..8a363e2d4 100644
--- a/src/map/mapdefines.h
+++ b/src/map/mapdefines.h
@@ -30,7 +30,15 @@
#define DAMAGELOG_SIZE 30
#define LOOTITEM_SIZE 10
#define MAX_MOBSKILL 50
+
+#ifndef MAX_MOB_LIST_PER_MAP
+#ifdef RENEWAL
#define MAX_MOB_LIST_PER_MAP 100
+#else
+#define MAX_MOB_LIST_PER_MAP 115
+#endif
+#endif
+
#define MAX_EVENTQUEUE 2
#define MAX_EVENTTIMER 32
#define NATURAL_HEAL_INTERVAL 500
diff --git a/src/map/messages_main.h b/src/map/messages_main.h
index 6fc0310e7..9f5a17662 100644
--- a/src/map/messages_main.h
+++ b/src/map/messages_main.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
/* This file is autogenerated, please do not commit manual changes
-Latest version: 20200129
+Latest version: 20200304
*/
enum clif_messages {
@@ -22521,6 +22521,97 @@ Search
*/
MSG_ID_ECE = 0xece,
#endif
+#if PACKETVER >= 20200212
+/*20200212 to latest
+합주를 혼자 사용할 수 있습니다.
+*/
+ MSG_ID_ECF = 0xecf,
+/*20200212 to latest
+크바시르의 지혜가 사라집니다.
+*/
+ MSG_ID_ED0 = 0xed0,
+/*20200212 to latest
+미스틱 심포니의 효과가 부여됩니다.
+*/
+ MSG_ID_ED1 = 0xed1,
+/*20200212 to latest
+미스틱 심포니의 효과가 사라집니다.
+*/
+ MSG_ID_ED2 = 0xed2,
+/*20200212 to latest
+마법 저항력이 감소했습니다.
+*/
+ MSG_ID_ED3 = 0xed3,
+/*20200212 to latest
+게페니아 녹턴의 효과가 해제 되었습니다.
+*/
+ MSG_ID_ED4 = 0xed4,
+/*20200212 to latest
+물리 저항력이 감소했습니다.
+*/
+ MSG_ID_ED5 = 0xed5,
+/*20200212 to latest
+마인워커 랩소디 상태가 해제되었습니다.
+*/
+ MSG_ID_ED6 = 0xed6,
+/*20200212 to latest
+물리 저항력이 증가했습니다.
+*/
+ MSG_ID_ED7 = 0xed7,
+/*20200212 to latest
+뮤지컬 인터루드 상태가 해제되었습니다.
+*/
+ MSG_ID_ED8 = 0xed8,
+/*20200212 to latest
+특성 마법 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_ED9 = 0xed9,
+/*20200212 to latest
+저녁 노을의 세레나데 효과가 해제되었습니다.
+*/
+ MSG_ID_EDA = 0xeda,
+/*20200212 to latest
+특성 물리 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_EDB = 0xedb,
+/*20200212 to latest
+ 프론테라의 행진곡 효과가 해제되었습니다.
+*/
+ MSG_ID_EDC = 0xedc,
+/*20200212 to latest
+바람의 분노가 시전자에게 흘러 들어옵니다.
+*/
+ MSG_ID_EDD = 0xedd,
+/*20200212 to latest
+캘러미티 가일 상태가 해제되었습니다.
+*/
+ MSG_ID_EDE = 0xede,
+/*20200212 to latest
+바람에 의해 약점과 모습이 드러납니다.
+*/
+ MSG_ID_EDF = 0xedf,
+/*20200212 to latest
+윈드 사인 효과가 사라집니다.
+*/
+ MSG_ID_EE0 = 0xee0,
+#endif
+#if PACKETVER >= 20200304
+/*20200304 to latest
+E X P : %.1f%% ( basic 100.0%% %s %.1f%%)
+EXP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE1 = 0xee1,
+/*20200304 to latest
+DROP : %.1f%% ( basic 100.0%% %s %.1f%%)
+DROP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE2 = 0xee2,
+/*20200304 to latest
+DEATH : %.1f%% ( basic 100.0%% %s %.1f%%)
+DEATH: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE3 = 0xee3,
+#endif
};
#endif /* MAP_MESSAGES_MAIN_H */
diff --git a/src/map/messages_re.h b/src/map/messages_re.h
index f4cc62d68..e32f6b275 100644
--- a/src/map/messages_re.h
+++ b/src/map/messages_re.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
/* This file is autogenerated, please do not commit manual changes
-Latest version: 20200205
+Latest version: 20200304
*/
enum clif_messages {
@@ -21998,6 +21998,97 @@ Search
*/
MSG_ID_ECE = 0xece,
#endif
+#if PACKETVER >= 20200212
+/*20200212 to latest
+합주를 혼자 사용할 수 있습니다.
+*/
+ MSG_ID_ECF = 0xecf,
+/*20200212 to latest
+크바시르의 지혜가 사라집니다.
+*/
+ MSG_ID_ED0 = 0xed0,
+/*20200212 to latest
+미스틱 심포니의 효과가 부여됩니다.
+*/
+ MSG_ID_ED1 = 0xed1,
+/*20200212 to latest
+미스틱 심포니의 효과가 사라집니다.
+*/
+ MSG_ID_ED2 = 0xed2,
+/*20200212 to latest
+마법 저항력이 감소했습니다.
+*/
+ MSG_ID_ED3 = 0xed3,
+/*20200212 to latest
+게페니아 녹턴의 효과가 해제 되었습니다.
+*/
+ MSG_ID_ED4 = 0xed4,
+/*20200212 to latest
+물리 저항력이 감소했습니다.
+*/
+ MSG_ID_ED5 = 0xed5,
+/*20200212 to latest
+마인워커 랩소디 상태가 해제되었습니다.
+*/
+ MSG_ID_ED6 = 0xed6,
+/*20200212 to latest
+물리 저항력이 증가했습니다.
+*/
+ MSG_ID_ED7 = 0xed7,
+/*20200212 to latest
+뮤지컬 인터루드 상태가 해제되었습니다.
+*/
+ MSG_ID_ED8 = 0xed8,
+/*20200212 to latest
+특성 마법 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_ED9 = 0xed9,
+/*20200212 to latest
+저녁 노을의 세레나데 효과가 해제되었습니다.
+*/
+ MSG_ID_EDA = 0xeda,
+/*20200212 to latest
+특성 물리 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_EDB = 0xedb,
+/*20200212 to latest
+ 프론테라의 행진곡 효과가 해제되었습니다.
+*/
+ MSG_ID_EDC = 0xedc,
+/*20200212 to latest
+바람의 분노가 시전자에게 흘러 들어옵니다.
+*/
+ MSG_ID_EDD = 0xedd,
+/*20200212 to latest
+캘러미티 가일 상태가 해제되었습니다.
+*/
+ MSG_ID_EDE = 0xede,
+/*20200212 to latest
+바람에 의해 약점과 모습이 드러납니다.
+*/
+ MSG_ID_EDF = 0xedf,
+/*20200212 to latest
+윈드 사인 효과가 사라집니다.
+*/
+ MSG_ID_EE0 = 0xee0,
+#endif
+#if PACKETVER >= 20200304
+/*20200304 to latest
+E X P : %.1f%% ( basic 100.0%% %s %.1f%%)
+EXP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE1 = 0xee1,
+/*20200304 to latest
+DROP : %.1f%% ( basic 100.0%% %s %.1f%%)
+DROP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE2 = 0xee2,
+/*20200304 to latest
+DEATH : %.1f%% ( basic 100.0%% %s %.1f%%)
+DEATH: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE3 = 0xee3,
+#endif
};
#endif /* MAP_MESSAGES_RE_H */
diff --git a/src/map/messages_zero.h b/src/map/messages_zero.h
index 55c0329ee..babe9384c 100644
--- a/src/map/messages_zero.h
+++ b/src/map/messages_zero.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
/* This file is autogenerated, please do not commit manual changes
-Latest version: 20200129
+Latest version: 20200304
*/
enum clif_messages {
@@ -18605,6 +18605,102 @@ Search
*/
MSG_ID_ECD = 0xecd,
#endif
+#if PACKETVER >= 20200212
+/*20200212 to latest
+검색
+Search
+*/
+ MSG_ID_ECE = 0xece,
+/*20200212 to latest
+합주를 혼자 사용할 수 있습니다.
+*/
+ MSG_ID_ECF = 0xecf,
+/*20200212 to latest
+크바시르의 지혜가 사라집니다.
+*/
+ MSG_ID_ED0 = 0xed0,
+/*20200212 to latest
+미스틱 심포니의 효과가 부여됩니다.
+*/
+ MSG_ID_ED1 = 0xed1,
+/*20200212 to latest
+미스틱 심포니의 효과가 사라집니다.
+*/
+ MSG_ID_ED2 = 0xed2,
+/*20200212 to latest
+마법 저항력이 감소했습니다.
+*/
+ MSG_ID_ED3 = 0xed3,
+/*20200212 to latest
+게페니아 녹턴의 효과가 해제 되었습니다.
+*/
+ MSG_ID_ED4 = 0xed4,
+/*20200212 to latest
+물리 저항력이 감소했습니다.
+*/
+ MSG_ID_ED5 = 0xed5,
+/*20200212 to latest
+마인워커 랩소디 상태가 해제되었습니다.
+*/
+ MSG_ID_ED6 = 0xed6,
+/*20200212 to latest
+물리 저항력이 증가했습니다.
+*/
+ MSG_ID_ED7 = 0xed7,
+/*20200212 to latest
+뮤지컬 인터루드 상태가 해제되었습니다.
+*/
+ MSG_ID_ED8 = 0xed8,
+/*20200212 to latest
+특성 마법 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_ED9 = 0xed9,
+/*20200212 to latest
+저녁 노을의 세레나데 효과가 해제되었습니다.
+*/
+ MSG_ID_EDA = 0xeda,
+/*20200212 to latest
+특성 물리 공격력과 이동 속도가 증가합니다.
+*/
+ MSG_ID_EDB = 0xedb,
+/*20200212 to latest
+ 프론테라의 행진곡 효과가 해제되었습니다.
+*/
+ MSG_ID_EDC = 0xedc,
+/*20200212 to latest
+바람의 분노가 시전자에게 흘러 들어옵니다.
+*/
+ MSG_ID_EDD = 0xedd,
+/*20200212 to latest
+캘러미티 가일 상태가 해제되었습니다.
+*/
+ MSG_ID_EDE = 0xede,
+/*20200212 to latest
+바람에 의해 약점과 모습이 드러납니다.
+*/
+ MSG_ID_EDF = 0xedf,
+/*20200212 to latest
+윈드 사인 효과가 사라집니다.
+*/
+ MSG_ID_EE0 = 0xee0,
+#endif
+#if PACKETVER >= 20200304
+/*20200304 to latest
+E X P : %.1f%% ( basic 100.0%% %s %.1f%%)
+EXP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE1 = 0xee1,
+/*20200304 to latest
+DROP : %.1f%% ( basic 100.0%% %s %.1f%%)
+DROP: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE2 = 0xee2,
+/*20200304 to latest
+DEATH : %.1f%% ( basic 100.0%% %s %.1f%%)
+DEATH: %.1f%% (basic: 100.0%%, %s: %.1f%%)
+*/
+ MSG_ID_EE3 = 0xee3,
+#endif
};
#endif /* MAP_MESSAGES_ZERO_H */
diff --git a/src/map/mob.c b/src/map/mob.c
index 0830e5a5a..51a32abd9 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -1462,7 +1462,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick)
// If master is BL_MOB and in battle, lock & chase to master's target instead, unless configured not to.
if ((battle_config.slave_chase_masters_chasetarget == 0 || (m_md != NULL && !mob->is_in_battle_state(m_md)))
&& map->search_freecell(&md->bl, bl->m, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 1)
- && unit->walktoxy(&md->bl, x, y, 0))
+ && unit->walk_toxy(&md->bl, x, y, 0) == 0)
return 1;
}
} else if (bl->m != md->bl.m && map_flag_gvg(md->bl.m)) {
@@ -1544,7 +1544,7 @@ static int mob_unlocktarget(struct mob_data *md, int64 tick)
unit->set_target(&md->ud, 0);
}
if(battle_config.official_cell_stack_limit && map->count_oncell(md->bl.m, md->bl.x, md->bl.y, BL_CHAR|BL_NPC, 0x1 | 0x2) > battle_config.official_cell_stack_limit) {
- unit->walktoxy(&md->bl, md->bl.x, md->bl.y, 8);
+ unit->walk_toxy(&md->bl, md->bl.x, md->bl.y, 8);
}
return 0;
@@ -1576,9 +1576,9 @@ static int mob_randomwalk(struct mob_data *md, int64 tick)
x+=md->bl.x;
y+=md->bl.y;
- if (((x != md->bl.x) || (y != md->bl.y)) && map->getcell(md->bl.m, &md->bl, x, y, CELL_CHKPASS) && unit->walktoxy(&md->bl, x, y, 8)) {
+ if ((x != md->bl.x || y != md->bl.y) && map->getcell(md->bl.m, &md->bl, x, y, CELL_CHKPASS) != 0
+ && unit->walk_toxy(&md->bl, x, y, 8) == 0)
break;
- }
}
if(i==retrycount){
md->move_fail_count++;
diff --git a/src/map/mob.h b/src/map/mob.h
index 8839809f2..4cfddc2cd 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -35,7 +35,7 @@ struct hplugin_data_store;
// 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 5000
+#define MAX_MOB_DB 22000
//The number of drops all mobs have and the max drop-slot that the steal skill will attempt to steal from.
#define MAX_MOB_DROP 10
diff --git a/src/map/npc.c b/src/map/npc.c
index e66888a74..40ec380ee 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1799,6 +1799,7 @@ static void npc_expanded_barter_fromsql(void)
) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
+ StrBuf->Destroy(&buf);
return;
}
@@ -3391,7 +3392,7 @@ static bool npc_viewisid(const char *viewid)
* @param class_ The NPC view class.
* @return A pointer to the created NPC data (ownership passed to the caller).
*/
-static struct npc_data *npc_create_npc(enum npc_subtype subtype, int m, int x, int y, uint8 dir, int class_)
+static struct npc_data *npc_create_npc(enum npc_subtype subtype, int m, int x, int y, enum unit_dir dir, int class_)
{
struct npc_data *nd;
diff --git a/src/map/npc.h b/src/map/npc.h
index 65c9796d9..1585a2bc8 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -95,7 +95,7 @@ struct npc_data {
int chat_id;
int touching_id;
int64 next_walktime;
- uint8 dir;
+ enum unit_dir dir;
uint8 area_size;
int clan_id;
@@ -281,7 +281,7 @@ struct npc_interface {
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 *(*create_npc) (enum npc_subtype subtype, int m, int x, int y, uint8 dir, int class_);
+ struct npc_data *(*create_npc) (enum npc_subtype subtype, int m, int x, int y, enum unit_dir dir, int class_);
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) (const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
const char *(*parse_shop) (const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
diff --git a/src/map/packets_keys_main.h b/src/map/packets_keys_main.h
index a72d9bf5f..e3a89827c 100644
--- a/src/map/packets_keys_main.h
+++ b/src/map/packets_keys_main.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -37,7 +37,7 @@
packetKeys(0x49357d72,0x22c370a1,0x5f836591);
#endif
-// 2010-11-23aRagexeRE, 2010-11-24aRagexeRE, 2010-11-24bRagexeRE, 2010-11-25aRagexeRE, 2010-11-26aRagexeRE, 2010-11-30aRagexeRE, 2010-12-07aRagexeRE, 2010-12-14aRagexeRE, 2010-12-21aRagexeRE, 2010-12-23aRagexeRE, 2010-12-28aRagexeRE, 2011-01-04aRagexeRE, 2011-01-05aRagexeRE, 2011-01-11aRagexeRE, 2011-01-18aRagexeRE, 2011-01-25aRagexeRE, 2011-01-26aRagexeRE, 2011-01-26bRagexeRE, 2011-01-31aRagexeRE, 2011-01-31bRagexeRE, 2011-01-31cRagexeRE, 2011-02-08aRagexeRE, 2011-02-15aRagexeRE, 2011-02-22aRagexeRE, 2011-02-23aRagexeRE, 2011-02-23bRagexeRE, 2011-02-24aRagexeRE, 2011-02-25aRagexeRE, 2011-02-28aRagexeRE, 2011-03-08aRagexeRE, 2011-03-09aRagexeRE, 2011-03-09bRagexeRE, 2011-03-09cRagexeRE, 2011-03-09dRagexeRE, 2011-03-15aRagexeRE, 2011-03-22aRagexeRE, 2011-03-29aRagexeRE, 2011-03-30aRagexeRE, 2011-03-30cRagexeRE, 2011-04-05aRagexeRE, 2011-04-12aRagexeRE, 2011-04-19aRagexeRE, 2011-04-20aRagexeRE, 2011-04-26aRagexeRE, 2011-04-27aRagexeRE, 2011-05-03aRagexeRE, 2011-05-11aRagexeRE, 2011-05-17bRagexeRE, 2011-05-24aRagexeRE, 2011-05-26aRagexeRE, 2011-05-31aRagexeRE, 2011-06-07aRagexeRE, 2011-06-08aRagexeRE, 2011-06-08bRagexeRE, 2011-06-08cRagexeRE, 2011-06-09aRagexeRE, 2011-06-14bRagexeRE, 2011-06-22aRagexeRE, 2011-06-28aRagexeRE, 2011-07-06aRagexeRE, 2011-07-13aRagexeRE, 2011-07-13bRagexeRE, 2011-07-13cRagexeRE, 2011-07-19aRagexeRE, 2011-07-26aRagexeRE, 2011-08-03aRagexeRE, 2011-08-03bRagexeRE, 2011-08-10aRagexeRE, 2013-12-23aRagexeRE, 2014-05-08aRagexe, 2014-05-08aRagexeRE, 2014-06-11eRagexe, 2015-02-25hRagexe, 2018-03-15aRagexe, 2018-03-21aRagexe, 2018-03-21aRagexeRE, 2018-03-28bRagexe, 2018-03-28bRagexeRE, 2018-04-04bRagexe, 2018-04-04cRagexeRE, 2018-04-18aRagexe, 2018-04-18bRagexeRE, 2018-04-25cRagexe, 2018-04-25cRagexeRE, 2018-05-02bRagexe, 2018-05-02bRagexeRE, 2018-05-02dRagexeRE, 2018-05-09aRagexe, 2018-05-16cRagexe, 2018-05-16cRagexeRE, 2018-05-23aRagexe, 2018-05-23aRagexeRE, 2018-05-30aRagexe, 2018-05-30bRagexeRE, 2018-05-30cRagexeRE, 2018-06-05bRagexe, 2018-06-05bRagexeRE, 2018-06-12aRagexeRE, 2018-06-12bRagexeRE, 2018-06-20cRagexe, 2018-06-20dRagexeRE, 2018-06-20eRagexe, 2018-06-20eRagexeRE, 2018-06-21aRagexe, 2018-06-21aRagexeRE, 2018-07-04aRagexe, 2018-07-04aRagexeRE, 2018-07-11aRagexeRE, 2018-07-18bRagexe, 2018-07-18bRagexeRE, 2018-07-18bRagexeRE1, 2018-07-18cRagexe, 2018-07-18cRagexeRE, 2018-08-01cRagexe, 2018-08-01cRagexeRE, 2018-08-08bRagexe, 2018-08-08bRagexeRE, 2018-08-22cRagexe, 2018-08-22cRagexeRE, 2018-08-29aRagexe, 2018-08-29aRagexeRE, 2018-08-29bRagexeRE, 2018-08-31aRagexe, 2018-09-12dRagexe, 2018-09-12dRagexeRE, 2018-09-19aRagexe, 2018-09-19aRagexeRE, 2018-10-02aRagexe, 2018-10-02aRagexeRE, 2018-10-02bRagexe, 2018-10-02bRagexeRE, 2018-10-17_02aRagexe, 2018-10-17_02aRagexeRE, 2018-10-17_03aRagexe, 2018-10-17_03aRagexeRE, 2018-10-17bRagexe, 2018-10-17bRagexeRE, 2018-10-24bRagexe, 2018-10-31aRagexe, 2018-10-31bRagexe, 2018-10-31cRagexeRE, 2018-11-07aRagexe, 2018-11-07aRagexeRE, 2018-11-14cRagexe, 2018-11-14cRagexeRE, 2018-11-14dRagexe, 2018-11-14dRagexeRE, 2018-11-21bRagexe, 2018-11-21cRagexeRE, 2018-11-28aRagexe, 2018-11-28aRagexeRE, 2018-11-28bRagexe, 2018-11-28cRagexe, 2018-12-05aRagexe, 2018-12-05bRagexeRE, 2018-12-12aRagexe, 2018-12-12aRagexeRE, 2018-12-12bRagexe, 2018-12-12bRagexeRE, 2018-12-19bRagexe, 2018-12-19bRagexeRE, 2018-12-26aRagexe, 2018-12-26aRagexeRE, 2019-01-09aRagexe, 2019-01-09bRagexeRE, 2019-01-16bRagexe, 2019-01-16bRagexeRE, 2019-01-16cRagexe, 2019-01-16cRagexeRE, 2019-01-23dRagexe, 2019-01-23dRagexeRE, 2019-02-13IRagexeRE, 2019-02-13bRagexe, 2019-02-13eRagexe, 2019-02-20aRagexeRE, 2019-02-27aRagexe, 2019-02-27bRagexeRE, 2019-02-28aRagexe, 2019-02-28aRagexeRE, 2019-03-06bRagexe, 2019-03-06bRagexeRE, 2019-03-06cRagexe, 2019-03-06cRagexeRE, 2019-03-13aRagexe, 2019-03-20aRagexe, 2019-03-20aRagexeRE, 2019-03-22aRagexe, 2019-03-22aRagexeRE, 2019-03-27bRagexe, 2019-03-27bRagexeRE, 2019-04-03aRagexe, 2019-04-03bRagexeRE, 2019-04-03cRagexeRE, 2019-04-17aRagexe, 2019-04-17cRagexeRE, 2019-04-18aRagexe, 2019-04-18aRagexeRE, 2019-05-08cRagexe, 2019-05-08dRagexeRE, 2019-05-08eRagexeRE, 2019-05-22bRagexe, 2019-05-22bRagexeRE, 2019-05-22cRagexe, 2019-05-22cRagexeRE, 2019-05-23aRagexe, 2019-05-29aRagexe, 2019-05-29bRagexeRE, 2019-05-29cRagexe, 2019-05-29cRagexeRE, 2019-05-30aRagexe, 2019-05-30aRagexeRE, 2019-06-05JRagexeRE, 2019-06-05KRagexe, 2019-06-05LRagexeRE, 2019-06-05fRagexe, 2019-06-05hRagexeRE, 2019-06-19bRagexe, 2019-06-19cRagexeRE, 2019-06-19eRagexe, 2019-06-19hRagexe, 2019-06-26bRagexeRE, 2019-07-03aRagexe, 2019-07-03bRagexeRE, 2019-07-17aRagexe, 2019-07-17cRagexeRE, 2019-07-17dRagexe, 2019-07-17dRagexeRE, 2019-07-24aRagexe, 2019-07-24bRagexeRE, 2019-07-31bRagexe, 2019-07-31bRagexeRE, 2019-08-02aRagexe, 2019-08-02aRagexeRE, 2019-08-07aRagexe, 2019-08-07dRagexeRE, 2019-08-21aRagexe, 2019-08-21cRagexeRE, 2019-08-21dRagexeRE, 2019-08-28aRagexe, 2019-08-28aRagexeRE, 2019-09-04aRagexe, 2019-09-04bRagexe, 2019-09-04bRagexeRE, 2019-09-18bRagexe, 2019-09-18cRagexeRE, 2019-09-25aRagexe, 2019-09-25aRagexeRE, 2019-09-25bRagexe, 2019-09-25bRagexeRE, 2019-10-02bRagexeRE, 2019-10-02cRagexe, 2019-10-02dRagexe, 2019-10-02dRagexeRE, 2019-10-02dRagexeRE_2, 2019-10-16fRagexe, 2019-10-16fRagexeRE, 2019-10-16gRagexe, 2019-10-16gRagexeRE, 2019-10-18aRagexe, 2019-10-23aRagexe, 2019-10-23aRagexeRE, 2019-10-30bRagexeRE, 2019-10-30cRagexe, 2019-11-06aRagexe, 2019-11-06bRagexeRE, 2019-11-07aRagexe, 2019-11-07aRagexeRE, 2019-11-13cRagexe, 2019-11-13eRagexe, 2019-11-13eRagexeRE, 2019-11-20aRagexe, 2019-11-20cRagexeRE, 2019-11-20dRagexe, 2019-11-27aRagexe, 2019-11-27aRagexeRE, 2019-11-27bRagexe, 2019-12-04aRagexe, 2019-12-04aRagexeRE, 2019-12-04bRagexe, 2019-12-04bRagexeRE, 2019-12-04cRagexeRE, 2019-12-11aRagexe, 2019-12-11fRagexeRE, 2019-12-18bRagexe, 2019-12-18bRagexeRE, 2019-12-24aRagexe, 2019-12-24aRagexeRE, 2019-12-24bRagexe, 2019-12-24bRagexeRE, 2020-01-08aRagexe, 2020-01-08bRagexeRE, 2020-01-22cRagexe, 2020-01-22cRagexeRE, 2020-01-29bRagexe, 2020-01-30aRagexe, 2020-02-05aRagexe, 2020-02-05aRagexeRE, 2020-02-06aRagexe
+// 2010-11-23aRagexeRE, 2010-11-24aRagexeRE, 2010-11-24bRagexeRE, 2010-11-25aRagexeRE, 2010-11-26aRagexeRE, 2010-11-30aRagexeRE, 2010-12-07aRagexeRE, 2010-12-14aRagexeRE, 2010-12-21aRagexeRE, 2010-12-23aRagexeRE, 2010-12-28aRagexeRE, 2011-01-04aRagexeRE, 2011-01-05aRagexeRE, 2011-01-11aRagexeRE, 2011-01-18aRagexeRE, 2011-01-25aRagexeRE, 2011-01-26aRagexeRE, 2011-01-26bRagexeRE, 2011-01-31aRagexeRE, 2011-01-31bRagexeRE, 2011-01-31cRagexeRE, 2011-02-08aRagexeRE, 2011-02-15aRagexeRE, 2011-02-22aRagexeRE, 2011-02-23aRagexeRE, 2011-02-23bRagexeRE, 2011-02-24aRagexeRE, 2011-02-25aRagexeRE, 2011-02-28aRagexeRE, 2011-03-08aRagexeRE, 2011-03-09aRagexeRE, 2011-03-09bRagexeRE, 2011-03-09cRagexeRE, 2011-03-09dRagexeRE, 2011-03-15aRagexeRE, 2011-03-22aRagexeRE, 2011-03-29aRagexeRE, 2011-03-30aRagexeRE, 2011-03-30cRagexeRE, 2011-04-05aRagexeRE, 2011-04-12aRagexeRE, 2011-04-19aRagexeRE, 2011-04-20aRagexeRE, 2011-04-26aRagexeRE, 2011-04-27aRagexeRE, 2011-05-03aRagexeRE, 2011-05-11aRagexeRE, 2011-05-17bRagexeRE, 2011-05-24aRagexeRE, 2011-05-26aRagexeRE, 2011-05-31aRagexeRE, 2011-06-07aRagexeRE, 2011-06-08aRagexeRE, 2011-06-08bRagexeRE, 2011-06-08cRagexeRE, 2011-06-09aRagexeRE, 2011-06-14bRagexeRE, 2011-06-22aRagexeRE, 2011-06-28aRagexeRE, 2011-07-06aRagexeRE, 2011-07-13aRagexeRE, 2011-07-13bRagexeRE, 2011-07-13cRagexeRE, 2011-07-19aRagexeRE, 2011-07-26aRagexeRE, 2011-08-03aRagexeRE, 2011-08-03bRagexeRE, 2011-08-10aRagexeRE, 2013-12-23aRagexeRE, 2014-05-08aRagexe, 2014-05-08aRagexeRE, 2014-06-11eRagexe, 2015-02-25hRagexe, 2018-03-15aRagexe, 2018-03-21aRagexe, 2018-03-21aRagexeRE, 2018-03-28bRagexe, 2018-03-28bRagexeRE, 2018-04-04bRagexe, 2018-04-04cRagexeRE, 2018-04-18aRagexe, 2018-04-18bRagexeRE, 2018-04-25cRagexe, 2018-04-25cRagexeRE, 2018-05-02bRagexe, 2018-05-02bRagexeRE, 2018-05-02dRagexeRE, 2018-05-09aRagexe, 2018-05-16cRagexe, 2018-05-16cRagexeRE, 2018-05-23aRagexe, 2018-05-23aRagexeRE, 2018-05-30aRagexe, 2018-05-30bRagexeRE, 2018-05-30cRagexeRE, 2018-06-05bRagexe, 2018-06-05bRagexeRE, 2018-06-12aRagexeRE, 2018-06-12bRagexeRE, 2018-06-20cRagexe, 2018-06-20dRagexeRE, 2018-06-20eRagexe, 2018-06-20eRagexeRE, 2018-06-21aRagexe, 2018-06-21aRagexeRE, 2018-07-04aRagexe, 2018-07-04aRagexeRE, 2018-07-11aRagexeRE, 2018-07-18bRagexe, 2018-07-18bRagexeRE, 2018-07-18bRagexeRE1, 2018-07-18cRagexe, 2018-07-18cRagexeRE, 2018-08-01cRagexe, 2018-08-01cRagexeRE, 2018-08-08bRagexe, 2018-08-08bRagexeRE, 2018-08-22cRagexe, 2018-08-22cRagexeRE, 2018-08-29aRagexe, 2018-08-29aRagexeRE, 2018-08-29bRagexeRE, 2018-08-31aRagexe, 2018-09-12dRagexe, 2018-09-12dRagexeRE, 2018-09-19aRagexe, 2018-09-19aRagexeRE, 2018-10-02aRagexe, 2018-10-02aRagexeRE, 2018-10-02bRagexe, 2018-10-02bRagexeRE, 2018-10-17_02aRagexe, 2018-10-17_02aRagexeRE, 2018-10-17_03aRagexe, 2018-10-17_03aRagexeRE, 2018-10-17bRagexe, 2018-10-17bRagexeRE, 2018-10-24bRagexe, 2018-10-31aRagexe, 2018-10-31bRagexe, 2018-10-31cRagexeRE, 2018-11-07aRagexe, 2018-11-07aRagexeRE, 2018-11-14cRagexe, 2018-11-14cRagexeRE, 2018-11-14dRagexe, 2018-11-14dRagexeRE, 2018-11-21bRagexe, 2018-11-21cRagexeRE, 2018-11-28aRagexe, 2018-11-28aRagexeRE, 2018-11-28bRagexe, 2018-11-28cRagexe, 2018-12-05aRagexe, 2018-12-05bRagexeRE, 2018-12-12aRagexe, 2018-12-12aRagexeRE, 2018-12-12bRagexe, 2018-12-12bRagexeRE, 2018-12-19bRagexe, 2018-12-19bRagexeRE, 2018-12-26aRagexe, 2018-12-26aRagexeRE, 2019-01-09aRagexe, 2019-01-09bRagexeRE, 2019-01-16bRagexe, 2019-01-16bRagexeRE, 2019-01-16cRagexe, 2019-01-16cRagexeRE, 2019-01-23dRagexe, 2019-01-23dRagexeRE, 2019-02-13IRagexeRE, 2019-02-13bRagexe, 2019-02-13eRagexe, 2019-02-20aRagexeRE, 2019-02-27aRagexe, 2019-02-27bRagexeRE, 2019-02-28aRagexe, 2019-02-28aRagexeRE, 2019-03-06bRagexe, 2019-03-06bRagexeRE, 2019-03-06cRagexe, 2019-03-06cRagexeRE, 2019-03-13aRagexe, 2019-03-20aRagexe, 2019-03-20aRagexeRE, 2019-03-22aRagexe, 2019-03-22aRagexeRE, 2019-03-27bRagexe, 2019-03-27bRagexeRE, 2019-04-03aRagexe, 2019-04-03bRagexeRE, 2019-04-03cRagexeRE, 2019-04-17aRagexe, 2019-04-17cRagexeRE, 2019-04-18aRagexe, 2019-04-18aRagexeRE, 2019-05-08cRagexe, 2019-05-08dRagexeRE, 2019-05-08eRagexeRE, 2019-05-22bRagexe, 2019-05-22bRagexeRE, 2019-05-22cRagexe, 2019-05-22cRagexeRE, 2019-05-23aRagexe, 2019-05-29aRagexe, 2019-05-29bRagexeRE, 2019-05-29cRagexe, 2019-05-29cRagexeRE, 2019-05-30aRagexe, 2019-05-30aRagexeRE, 2019-06-05JRagexeRE, 2019-06-05KRagexe, 2019-06-05LRagexeRE, 2019-06-05fRagexe, 2019-06-05hRagexeRE, 2019-06-19bRagexe, 2019-06-19cRagexeRE, 2019-06-19eRagexe, 2019-06-19hRagexe, 2019-06-26bRagexeRE, 2019-07-03aRagexe, 2019-07-03bRagexeRE, 2019-07-17aRagexe, 2019-07-17cRagexeRE, 2019-07-17dRagexe, 2019-07-17dRagexeRE, 2019-07-24aRagexe, 2019-07-24bRagexeRE, 2019-07-31bRagexe, 2019-07-31bRagexeRE, 2019-08-02aRagexe, 2019-08-02aRagexeRE, 2019-08-07aRagexe, 2019-08-07dRagexeRE, 2019-08-21aRagexe, 2019-08-21cRagexeRE, 2019-08-21dRagexeRE, 2019-08-28aRagexe, 2019-08-28aRagexeRE, 2019-09-04aRagexe, 2019-09-04bRagexe, 2019-09-04bRagexeRE, 2019-09-18bRagexe, 2019-09-18cRagexeRE, 2019-09-25aRagexe, 2019-09-25aRagexeRE, 2019-09-25bRagexe, 2019-09-25bRagexeRE, 2019-10-02bRagexeRE, 2019-10-02cRagexe, 2019-10-02dRagexe, 2019-10-02dRagexeRE, 2019-10-02dRagexeRE_2, 2019-10-16fRagexe, 2019-10-16fRagexeRE, 2019-10-16gRagexe, 2019-10-16gRagexeRE, 2019-10-18aRagexe, 2019-10-23aRagexe, 2019-10-23aRagexeRE, 2019-10-30bRagexeRE, 2019-10-30cRagexe, 2019-11-06aRagexe, 2019-11-06bRagexeRE, 2019-11-07aRagexe, 2019-11-07aRagexeRE, 2019-11-13cRagexe, 2019-11-13eRagexe, 2019-11-13eRagexeRE, 2019-11-20aRagexe, 2019-11-20cRagexeRE, 2019-11-20dRagexe, 2019-11-27aRagexe, 2019-11-27aRagexeRE, 2019-11-27bRagexe, 2019-12-04aRagexe, 2019-12-04aRagexeRE, 2019-12-04bRagexe, 2019-12-04bRagexeRE, 2019-12-04cRagexeRE, 2019-12-11aRagexe, 2019-12-11fRagexeRE, 2019-12-18bRagexe, 2019-12-18bRagexeRE, 2019-12-24aRagexe, 2019-12-24aRagexeRE, 2019-12-24bRagexe, 2019-12-24bRagexeRE, 2020-01-08aRagexe, 2020-01-08bRagexeRE, 2020-01-22cRagexe, 2020-01-22cRagexeRE, 2020-01-29bRagexe, 2020-01-30aRagexe, 2020-02-05aRagexe, 2020-02-05aRagexeRE, 2020-02-06aRagexe, 2020-02-12aRagexe, 2020-02-12aRagexeRE, 2020-02-19dRagexe, 2020-02-19eRagexeRE, 2020-03-04aRagexe, 2020-03-04aRagexeRE, 2020-03-18bRagexe, 2020-04-01bRagexe
#if PACKETVER == 20101123 || \
PACKETVER == 20101124 || \
PACKETVER == 20101125 || \
@@ -186,7 +186,12 @@
PACKETVER == 20200129 || \
PACKETVER == 20200130 || \
PACKETVER == 20200205 || \
- PACKETVER >= 20200206
+ PACKETVER == 20200206 || \
+ PACKETVER == 20200212 || \
+ PACKETVER == 20200219 || \
+ PACKETVER == 20200304 || \
+ PACKETVER == 20200318 || \
+ PACKETVER >= 20200401
packetKeys(0x00000000,0x00000000,0x00000000);
#endif
diff --git a/src/map/packets_keys_zero.h b/src/map/packets_keys_zero.h
index 90d226c92..f189032d3 100644
--- a/src/map/packets_keys_zero.h
+++ b/src/map/packets_keys_zero.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,7 +30,7 @@
/* This file is autogenerated, please do not commit manual changes */
-// 2017-10-18aRagexe_zero, 2017-10-19aRagexe_zero, 2017-10-23aRagexe_zero, 2017-10-23bRagexe_zero, 2017-10-23cRagexe_zero, 2017-10-24aRagexe_2_zero, 2017-10-24aRagexe_zero, 2017-10-25bRagexe_zero, 2017-10-27aRagexe_zero, 2017-10-27bRagexe_zero, 2017-10-30aRagexe_zero, 2017-10-31aRagexe_zero, 2017-11-09aRagexe_zero, 2017-11-13aRagexe_zero, 2017-11-13bRagexe_zero, 2018-03-15aRagexe_zero, 2018-03-21aRagexe_zero, 2018-03-21bRagexe_zero, 2018-03-28_1aRagexe_zero, 2018-03-28cRagexe_zero, 2018-04-11aRagexe_zero, 2018-04-25_3aRagexe_zero, 2018-05-09_3aRagexe_zero, 2018-05-23aRagexe_zero, 2018-06-05bRagexe_zero, 2018-06-05cRagexe_zero, 2018-06-27aRagexe_zero, 2018-07-03aRagexe_zero, 2018-07-11_2aRagexe_zero, 2018-07-25_2aRagexe_zero, 2018-08-01aRagexe_zero, 2018-08-08_2aRagexe_zero, 2018-08-22aRagexe_zero, 2018-08-29aRagexe_zero, 2018-09-05aRagexe_zero, 2018-09-12aRagexe_zero, 2018-09-19aRagexe_zero, 2018-09-28aRagexe_zero, 2018-10-10_2aRagexe_zero, 2018-10-24_2aRagexe_zero, 2018-11-14aRagexe_zero, 2018-11-20aRagexe_zero, 2018-11-28aRagexe_zero, 2018-12-12aRagexe_zero, 2018-12-19aRagexe_zero, 2018-12-26_2aRagexe_zero, 2019-01-16_2aRagexe_zero, 2019-01-17_1aRagexe_zero, 2019-01-30_2aRagexe_zero, 2019-02-13aRagexe_zero, 2019-02-20aRagexe_zero, 2019-02-27aRagexe_zero, 2019-03-13aRagexe_zero, 2019-03-27_2aRagexe_zero, 2019-03-27_3aRagexe_zero, 2019-04-03aRagexe_zero, 2019-04-10bRagexe_zero, 2019-04-24aRagexe_zero, 2019-05-02aRagexe_zero, 2019-05-08_2aRagexe_zero, 2019-05-08aRagexe_zero, 2019-05-15aRagexe_zero, 2019-05-29aRagexe_zero, 2019-05-30aRagexe_zero, 2019-06-05_2aRagexe_zero, 2019-06-26_2aRagexe_zero, 2019-06-26_3aRagexe_zero, 2019-07-09aRagexe_zero, 2019-07-10_3aRagexe_zero, 2019-07-17aRagexe_zero, 2019-07-24aRagexe_zero, 2019-08-14_3aRagexe_zero, 2019-08-28_2aRagexe_zero, 2019-08-28_3aRagexe_zero, 2019-09-11aRagexe_zero, 2019-09-18_2aRagexe_zero, 2019-09-18aRagexe_zero, 2019-09-25_3aRagexe_zero, 2019-09-25_5aRagexe_zero, 2019-10-08_2aRagexe_zero, 2019-10-23_2aRagexe_zero, 2019-11-06aRagexe_zero, 2019-11-13aRagexe_zero, 2019-11-27_2aRagexe_zero, 2019-11-27aRagexe_zero, 2019-12-04aRagexe_zero, 2019-12-11_2aRagexe_zero, 2019-12-24_4aRagexe_zero, 2019-12-24_5aRagexe_zero, 2020-01-15_2aRagexe_zero, 2020-01-15aRagexe_zero, 2020-01-29_2aRagexe_zero, 2020-01-29aRagexe_zero
+// 2017-10-18aRagexe_zero, 2017-10-19aRagexe_zero, 2017-10-23aRagexe_zero, 2017-10-23bRagexe_zero, 2017-10-23cRagexe_zero, 2017-10-24aRagexe_2_zero, 2017-10-24aRagexe_zero, 2017-10-25bRagexe_zero, 2017-10-27aRagexe_zero, 2017-10-27bRagexe_zero, 2017-10-30aRagexe_zero, 2017-10-31aRagexe_zero, 2017-11-09aRagexe_zero, 2017-11-13aRagexe_zero, 2017-11-13bRagexe_zero, 2018-03-15aRagexe_zero, 2018-03-21aRagexe_zero, 2018-03-21bRagexe_zero, 2018-03-28_1aRagexe_zero, 2018-03-28cRagexe_zero, 2018-04-11aRagexe_zero, 2018-04-25_3aRagexe_zero, 2018-05-09_3aRagexe_zero, 2018-05-23aRagexe_zero, 2018-06-05bRagexe_zero, 2018-06-05cRagexe_zero, 2018-06-27aRagexe_zero, 2018-07-03aRagexe_zero, 2018-07-11_2aRagexe_zero, 2018-07-25_2aRagexe_zero, 2018-08-01aRagexe_zero, 2018-08-08_2aRagexe_zero, 2018-08-22aRagexe_zero, 2018-08-29aRagexe_zero, 2018-09-05aRagexe_zero, 2018-09-12aRagexe_zero, 2018-09-19aRagexe_zero, 2018-09-28aRagexe_zero, 2018-10-10_2aRagexe_zero, 2018-10-24_2aRagexe_zero, 2018-11-14aRagexe_zero, 2018-11-20aRagexe_zero, 2018-11-28aRagexe_zero, 2018-12-12aRagexe_zero, 2018-12-19aRagexe_zero, 2018-12-26_2aRagexe_zero, 2019-01-16_2aRagexe_zero, 2019-01-17_1aRagexe_zero, 2019-01-30_2aRagexe_zero, 2019-02-13aRagexe_zero, 2019-02-20aRagexe_zero, 2019-02-27aRagexe_zero, 2019-03-13aRagexe_zero, 2019-03-27_2aRagexe_zero, 2019-03-27_3aRagexe_zero, 2019-04-03aRagexe_zero, 2019-04-10bRagexe_zero, 2019-04-24aRagexe_zero, 2019-05-02aRagexe_zero, 2019-05-08_2aRagexe_zero, 2019-05-08aRagexe_zero, 2019-05-15aRagexe_zero, 2019-05-29aRagexe_zero, 2019-05-30aRagexe_zero, 2019-06-05_2aRagexe_zero, 2019-06-26_2aRagexe_zero, 2019-06-26_3aRagexe_zero, 2019-07-09aRagexe_zero, 2019-07-10_3aRagexe_zero, 2019-07-17aRagexe_zero, 2019-07-24aRagexe_zero, 2019-08-14_3aRagexe_zero, 2019-08-28_2aRagexe_zero, 2019-08-28_3aRagexe_zero, 2019-09-11aRagexe_zero, 2019-09-18_2aRagexe_zero, 2019-09-18aRagexe_zero, 2019-09-25_3aRagexe_zero, 2019-09-25_5aRagexe_zero, 2019-10-08_2aRagexe_zero, 2019-10-23_2aRagexe_zero, 2019-11-06aRagexe_zero, 2019-11-13aRagexe_zero, 2019-11-27_2aRagexe_zero, 2019-11-27aRagexe_zero, 2019-12-04aRagexe_zero, 2019-12-11_2aRagexe_zero, 2019-12-24_4aRagexe_zero, 2019-12-24_5aRagexe_zero, 2020-01-15_2aRagexe_zero, 2020-01-15aRagexe_zero, 2020-01-29_2aRagexe_zero, 2020-01-29aRagexe_zero, 2020-02-12aRagexe_zero, 2020-02-26aRagexe_zero, 2020-02-26bRagexe_zero, 2020-03-04aRagexe_zero, 2020-03-18_2aRagexe_zero, 2020-04-01_2aRagexe_zero
#if PACKETVER == 20171018 || \
PACKETVER == 20171019 || \
PACKETVER == 20171023 || \
@@ -105,7 +105,12 @@
PACKETVER == 20191211 || \
PACKETVER == 20191224 || \
PACKETVER == 20200115 || \
- PACKETVER >= 20200129
+ PACKETVER == 20200129 || \
+ PACKETVER == 20200212 || \
+ PACKETVER == 20200226 || \
+ PACKETVER == 20200304 || \
+ PACKETVER == 20200318 || \
+ PACKETVER >= 20200401
packetKeys(0x00000000,0x00000000,0x00000000);
#endif
diff --git a/src/map/packets_shuffle_main.h b/src/map/packets_shuffle_main.h
index 2d7f1d6ec..beedc950f 100644
--- a/src/map/packets_shuffle_main.h
+++ b/src/map/packets_shuffle_main.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -9794,7 +9794,7 @@
packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 14
#endif
-// 2019-09-04aRagexe, 2019-09-04bRagexe, 2019-09-18bRagexe, 2019-09-25aRagexe, 2019-09-25bRagexe, 2019-10-02cRagexe, 2019-10-02dRagexe, 2019-10-16fRagexe, 2019-10-16gRagexe, 2019-10-18aRagexe, 2019-10-23aRagexe, 2019-10-30cRagexe, 2019-11-06aRagexe, 2019-11-07aRagexe, 2019-11-13cRagexe, 2019-11-13eRagexe, 2019-11-20aRagexe, 2019-11-20dRagexe, 2019-11-27aRagexe, 2019-11-27bRagexe, 2019-12-04aRagexe, 2019-12-04bRagexe, 2019-12-11aRagexe, 2019-12-18bRagexe, 2019-12-24aRagexe, 2019-12-24bRagexe, 2020-01-08aRagexe, 2020-01-22cRagexe, 2020-01-29bRagexe, 2020-01-30aRagexe, 2020-02-05aRagexe, 2020-02-06aRagexe
+// 2019-09-04aRagexe, 2019-09-04bRagexe, 2019-09-18bRagexe, 2019-09-25aRagexe, 2019-09-25bRagexe, 2019-10-02cRagexe, 2019-10-02dRagexe, 2019-10-16fRagexe, 2019-10-16gRagexe, 2019-10-18aRagexe, 2019-10-23aRagexe, 2019-10-30cRagexe, 2019-11-06aRagexe, 2019-11-07aRagexe, 2019-11-13cRagexe, 2019-11-13eRagexe, 2019-11-20aRagexe, 2019-11-20dRagexe, 2019-11-27aRagexe, 2019-11-27bRagexe, 2019-12-04aRagexe, 2019-12-04bRagexe, 2019-12-11aRagexe, 2019-12-18bRagexe, 2019-12-24aRagexe, 2019-12-24bRagexe, 2020-01-08aRagexe, 2020-01-22cRagexe, 2020-01-29bRagexe, 2020-01-30aRagexe, 2020-02-05aRagexe, 2020-02-06aRagexe, 2020-02-12aRagexe, 2020-02-19dRagexe, 2020-03-04aRagexe, 2020-03-18bRagexe, 2020-04-01bRagexe
#if PACKETVER == 20190904 || \
PACKETVER == 20190918 || \
PACKETVER == 20190925 || \
@@ -9817,7 +9817,12 @@
PACKETVER == 20200129 || \
PACKETVER == 20200130 || \
PACKETVER == 20200205 || \
- PACKETVER == 20200206
+ PACKETVER == 20200206 || \
+ PACKETVER == 20200212 || \
+ PACKETVER == 20200219 || \
+ PACKETVER == 20200304 || \
+ PACKETVER == 20200318 || \
+ PACKETVER == 20200401
packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
diff --git a/src/map/packets_shuffle_re.h b/src/map/packets_shuffle_re.h
index 757cfee55..490d517fd 100644
--- a/src/map/packets_shuffle_re.h
+++ b/src/map/packets_shuffle_re.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -9744,7 +9744,7 @@
packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 14
#endif
-// 2019-09-04bRagexeRE, 2019-09-18cRagexeRE, 2019-09-25aRagexeRE, 2019-09-25bRagexeRE, 2019-10-02bRagexeRE, 2019-10-02dRagexeRE, 2019-10-02dRagexeRE_2, 2019-10-16fRagexeRE, 2019-10-16gRagexeRE, 2019-10-23aRagexeRE, 2019-10-30bRagexeRE, 2019-11-06bRagexeRE, 2019-11-07aRagexeRE, 2019-11-13eRagexeRE, 2019-11-20cRagexeRE, 2019-11-27aRagexeRE, 2019-12-04aRagexeRE, 2019-12-04bRagexeRE, 2019-12-04cRagexeRE, 2019-12-11fRagexeRE, 2019-12-18bRagexeRE, 2019-12-24aRagexeRE, 2019-12-24bRagexeRE, 2020-01-08bRagexeRE, 2020-01-22cRagexeRE, 2020-02-05aRagexeRE
+// 2019-09-04bRagexeRE, 2019-09-18cRagexeRE, 2019-09-25aRagexeRE, 2019-09-25bRagexeRE, 2019-10-02bRagexeRE, 2019-10-02dRagexeRE, 2019-10-02dRagexeRE_2, 2019-10-16fRagexeRE, 2019-10-16gRagexeRE, 2019-10-23aRagexeRE, 2019-10-30bRagexeRE, 2019-11-06bRagexeRE, 2019-11-07aRagexeRE, 2019-11-13eRagexeRE, 2019-11-20cRagexeRE, 2019-11-27aRagexeRE, 2019-12-04aRagexeRE, 2019-12-04bRagexeRE, 2019-12-04cRagexeRE, 2019-12-11fRagexeRE, 2019-12-18bRagexeRE, 2019-12-24aRagexeRE, 2019-12-24bRagexeRE, 2020-01-08bRagexeRE, 2020-01-22cRagexeRE, 2020-02-05aRagexeRE, 2020-02-12aRagexeRE, 2020-02-19eRagexeRE, 2020-03-04aRagexeRE
#if PACKETVER == 20190904 || \
PACKETVER == 20190918 || \
PACKETVER == 20190925 || \
@@ -9763,7 +9763,10 @@
PACKETVER == 20191224 || \
PACKETVER == 20200108 || \
PACKETVER == 20200122 || \
- PACKETVER == 20200205
+ PACKETVER == 20200205 || \
+ PACKETVER == 20200212 || \
+ PACKETVER == 20200219 || \
+ PACKETVER == 20200304
packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
diff --git a/src/map/packets_shuffle_zero.h b/src/map/packets_shuffle_zero.h
index 602264a8f..15936f854 100644
--- a/src/map/packets_shuffle_zero.h
+++ b/src/map/packets_shuffle_zero.h
@@ -2,8 +2,8 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2020 Hercules Dev Team
- * Copyright (C) 2018-2020 Andrei Karas (4144)
+ * Copyright (C) 2013-2020 Hercules Dev Team
+ * Copyright (C) 2018-2020 Andrei Karas (4144)
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -803,7 +803,7 @@
packet(0x083c,clif->pSearchStoreInfoListItemClick,2,6,10); // CZ_SSILIST_ITEM_CLICK // 14
#endif
-// 2019-08-28_2aRagexe_zero, 2019-08-28_3aRagexe_zero, 2019-09-11aRagexe_zero, 2019-09-18_2aRagexe_zero, 2019-09-18aRagexe_zero, 2019-09-25_3aRagexe_zero, 2019-09-25_5aRagexe_zero, 2019-10-08_2aRagexe_zero, 2019-10-23_2aRagexe_zero, 2019-11-06aRagexe_zero, 2019-11-13aRagexe_zero, 2019-11-27_2aRagexe_zero, 2019-11-27aRagexe_zero, 2019-12-04aRagexe_zero, 2019-12-11_2aRagexe_zero, 2019-12-24_4aRagexe_zero, 2019-12-24_5aRagexe_zero, 2020-01-15_2aRagexe_zero, 2020-01-15aRagexe_zero, 2020-01-29_2aRagexe_zero, 2020-01-29aRagexe_zero
+// 2019-08-28_2aRagexe_zero, 2019-08-28_3aRagexe_zero, 2019-09-11aRagexe_zero, 2019-09-18_2aRagexe_zero, 2019-09-18aRagexe_zero, 2019-09-25_3aRagexe_zero, 2019-09-25_5aRagexe_zero, 2019-10-08_2aRagexe_zero, 2019-10-23_2aRagexe_zero, 2019-11-06aRagexe_zero, 2019-11-13aRagexe_zero, 2019-11-27_2aRagexe_zero, 2019-11-27aRagexe_zero, 2019-12-04aRagexe_zero, 2019-12-11_2aRagexe_zero, 2019-12-24_4aRagexe_zero, 2019-12-24_5aRagexe_zero, 2020-01-15_2aRagexe_zero, 2020-01-15aRagexe_zero, 2020-01-29_2aRagexe_zero, 2020-01-29aRagexe_zero, 2020-02-12aRagexe_zero, 2020-02-26aRagexe_zero, 2020-02-26bRagexe_zero, 2020-03-04aRagexe_zero, 2020-03-18_2aRagexe_zero, 2020-04-01_2aRagexe_zero
#if PACKETVER == 20190828 || \
PACKETVER == 20190911 || \
PACKETVER == 20190918 || \
@@ -817,7 +817,12 @@
PACKETVER == 20191211 || \
PACKETVER == 20191224 || \
PACKETVER == 20200115 || \
- PACKETVER == 20200129
+ PACKETVER == 20200129 || \
+ PACKETVER == 20200212 || \
+ PACKETVER == 20200226 || \
+ PACKETVER == 20200304 || \
+ PACKETVER == 20200318 || \
+ PACKETVER == 20200401
packet(0x0202,clif->pFriendsListAdd,2); // CZ_ADD_FRIENDS // 26
packet(0x022d,clif->pHomMenu,2,4); // CZ_COMMAND_MER // 5
packet(0x023b,clif->pStoragePassword,0); // CZ_ACK_STORE_PASSWORD // 36
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index b604c77b8..ca2fb8aef 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -3779,7 +3779,7 @@ struct PACKET_ZC_SE_CASHSHOP_OPEN {
} __attribute__((packed));
DEFINE_PACKET_HEADER(ZC_SE_CASHSHOP_OPEN, 0x0b6e);
// for ragexeRE in some version this packet unused [4144]
-#elif PACKETVER_MAIN_NUM >= 20101123 || PACKETVER_RE_NUM >= 20120328 || PACKETVER_ZERO_NUM >= defined(PACKETVER_ZERO)
+#elif PACKETVER_MAIN_NUM >= 20101123 || PACKETVER_RE_NUM >= 20120328 || defined(PACKETVER_ZERO)
struct PACKET_ZC_SE_CASHSHOP_OPEN {
int16 packetType;
uint32 cashPoints;
@@ -3819,9 +3819,15 @@ struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub {
uint32 index;
uint32 zeny;
uint32 currency_count;
- struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 currencies[];
+ // Workaround for fix Visual Studio bug (error C2233). Here should be currencies[]
+ struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2 currencies[1];
} __attribute__((packed));
+// Workaround check for Visual Studio bug (error C2233)
+STATIC_ASSERT(sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2[1]) ==
+ sizeof(struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub2),
+ "Wrong PACKET_ZC_NPC_EXPANDED_BARTER_OPEN_sub size");
+
struct PACKET_ZC_NPC_EXPANDED_BARTER_OPEN {
int16 packetType;
int16 packetLength;
diff --git a/src/map/pc.c b/src/map/pc.c
index c96e957c7..90282209b 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -998,20 +998,23 @@ static bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data
return false; // Job Change Fail
}
-/*=================================================
- * Checks if the player can equip the item at index n in inventory.
- * Returns 0 (no) or 1 (yes).
- *------------------------------------------------*/
+/**
+ * Checks if a character can equip an item.
+ *
+ * @param sd The related character.
+ * @param n The item's inventory index.
+ * @retval 0 Character can't equip the item.
+ * @retval 1 Character can equip the item.
+ *
+ **/
static int pc_isequip(struct map_session_data *sd, int n)
{
- struct item_data *item;
-
nullpo_ret(sd);
Assert_ret(n >= 0 && n < sd->status.inventorySize);
- item = sd->inventory_data[n];
+ struct item_data *item = sd->inventory_data[n];
- if(item == NULL)
+ if (item == NULL)
return 0;
#if PACKETVER <= 20100707
@@ -1019,31 +1022,34 @@ static int pc_isequip(struct map_session_data *sd, int n)
return 0;
#endif
- if(pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT))
+ if (pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT))
return 1;
- if (item->elv && sd->status.base_level < item->elv) {
+ if (item->elv != 0 && sd->status.base_level < item->elv) {
#if PACKETVER >= 20100525
clif->msgtable(sd, MSG_CANNOT_EQUIP_ITEM_LEVEL);
#endif
return 0;
}
- if (item->elvmax && sd->status.base_level > item->elvmax) {
+
+ if (item->elvmax != 0 && sd->status.base_level > item->elvmax) {
#if PACKETVER >= 20100525
clif->msgtable(sd, MSG_CANNOT_EQUIP_ITEM_LEVEL);
#endif
return 0;
}
- if(item->sex != 2 && sd->status.sex != item->sex)
+
+ if (item->sex != SEX_SERVER && sd->status.sex != item->sex)
return 0;
- if ( item->equip & EQP_AMMO ) {
- if (sd->state.active && !pc_iscarton(sd) && (sd->job & MAPID_THIRDMASK) == MAPID_GENETIC) { // check if sc data is already loaded.
+ if ((item->equip & EQP_AMMO) != 0) {
+ if (sd->state.active != 0 && !pc_iscarton(sd) && (sd->job & MAPID_THIRDMASK) == MAPID_GENETIC) { // Check if sc data is already loaded.
#if PACKETVER_RE_NUM >= 20090529 || PACKETVER_MAIN_NUM >= 20090603 || defined(PACKETVER_ZERO)
clif->msgtable(sd, MSG_USESKILL_FAIL_CART);
#endif
return 0;
}
+
if (!pc_ismadogear(sd) && (sd->job & MAPID_THIRDMASK) == MAPID_MECHANIC) {
#if PACKETVER_RE_NUM >= 20090226 || PACKETVER_MAIN_NUM >= 20090304 || defined(PACKETVER_ZERO)
clif->msgtable(sd, MSG_USESKILL_FAIL_MADOGEAR);
@@ -1051,76 +1057,85 @@ static int pc_isequip(struct map_session_data *sd, int n)
return 0;
}
}
- if (sd->sc.count) {
- if(item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_NOEQUIPWEAPON]) // Also works with left-hand weapons [DracoRPG]
+ if ((battle_config.unequip_restricted_equipment & 1) != 0) {
+ for (int i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++)
+ if (map->list[sd->bl.m].zone->disabled_items[i] == item->nameid)
+ return 0;
+ }
+
+ if ((battle_config.unequip_restricted_equipment & 2) != 0 && !itemdb_isspecial(sd->status.inventory[n].card[0])) {
+ for (int slot = 0; slot < item->slot; slot++)
+ for (int i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++)
+ if (map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].card[slot])
+ return 0;
+ }
+
+ if (sd->sc.count != 0) {
+ if ((item->equip & EQP_ARMS) != 0 && item->type == IT_WEAPON && sd->sc.data[SC_NOEQUIPWEAPON] != NULL) // Also works with left-hand weapons. [DracoRPG]
return 0;
- if(item->equip & EQP_SHIELD && item->type == IT_ARMOR && sd->sc.data[SC_NOEQUIPSHIELD])
+
+ if ((item->equip & EQP_SHIELD) != 0 && item->type == IT_ARMOR && sd->sc.data[SC_NOEQUIPSHIELD] != NULL)
return 0;
- if(item->equip & EQP_ARMOR && sd->sc.data[SC_NOEQUIPARMOR])
+
+ if ((item->equip & EQP_ARMOR) != 0 && sd->sc.data[SC_NOEQUIPARMOR] != NULL)
return 0;
- if(item->equip & EQP_HEAD_TOP && sd->sc.data[SC_NOEQUIPHELM])
+
+ if ((item->equip & EQP_HEAD_TOP) != 0 && sd->sc.data[SC_NOEQUIPHELM] != NULL)
return 0;
- if(item->equip & EQP_ACC && sd->sc.data[SC__STRIPACCESSARY])
+
+ if ((item->equip & EQP_ACC) != 0 && sd->sc.data[SC__STRIPACCESSARY] != NULL)
return 0;
- if(item->equip && sd->sc.data[SC_KYOUGAKU])
+
+ if (item->equip != 0 && sd->sc.data[SC_KYOUGAKU] != NULL)
return 0;
- if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_SUPERNOVICE) {
- //Spirit of Super Novice equip bonuses. [Skotlex]
- if (sd->status.base_level > 90 && item->equip & EQP_HELM)
- return 1; //Can equip all helms
-
- if (sd->status.base_level > 96 && item->equip & EQP_ARMS && item->type == IT_WEAPON)
- switch (item->subtype) { //In weapons, the look determines type of weapon.
- case W_DAGGER: //Level 4 Knives are equippable.. this means all knives, I'd guess?
- case W_1HSWORD: //All 1H swords
- case W_1HAXE: //All 1H Axes
- case W_MACE: //All 1H Maces
- case W_STAFF: //All 1H Staves
+ if (sd->sc.data[SC_SOULLINK] != NULL && sd->sc.data[SC_SOULLINK]->val2 == SL_SUPERNOVICE) { // Spirit of Super Novice equip bonuses. [Skotlex]
+ if (sd->status.base_level > 90 && (item->equip & EQP_HELM) != 0)
+ return 1; // Can equip all helms.
+
+ if (sd->status.base_level > 96 && (item->equip & EQP_ARMS) != 0 && item->type == IT_WEAPON) {
+ switch (item->subtype) { // In weapons, the look determines type of weapon.
+ case W_DAGGER: // Level 4 Knives are equippable.. this means all knives, I'd guess?
+ case W_1HSWORD: // All 1H swords.
+ case W_1HAXE: // All 1H axes.
+ case W_MACE: // All 1H maces.
+ case W_STAFF: // All 1H staffs.
return 1;
}
+ }
}
}
- //Not equipable by class. [Skotlex]
- if (((1ULL<<(sd->job & MAPID_BASEMASK)) & item->class_base[(sd->job & JOBL_2_1) != 0 ? 1 : ((sd->job & JOBL_2_2) != 0 ? 2 : 0)]) == 0)
+
+ uint64 mask_job = 1ULL << (sd->job & MAPID_BASEMASK);
+ uint64 mask_item = item->class_base[((sd->job & JOBL_2_1) != 0) ? 1 : (((sd->job & JOBL_2_2) != 0) ? 2 : 0)];
+
+ if ((mask_job & mask_item) == 0) // Not equipable by class. [Skotlex]
return 0;
- //Not usable by upper class. [Inkfish]
- while( 1 ) {
+
+ // Not usable by upper class. [Inkfish]
+ while (1) {
if ((item->class_upper & ITEMUPPER_NORMAL) != 0) {
- if ((sd->job & (JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) == 0)
+ if ((sd->job & (JOBL_UPPER | JOBL_THIRD | JOBL_BABY)) == 0)
break;
}
+
if ((item->class_upper & ITEMUPPER_UPPER) != 0) {
- if ((sd->job & (JOBL_UPPER|JOBL_THIRD)) != 0)
+ if ((sd->job & (JOBL_UPPER | JOBL_THIRD)) != 0)
break;
}
+
if ((item->class_upper & ITEMUPPER_BABY) != 0) {
if ((sd->job & JOBL_BABY) != 0)
break;
}
+
if ((item->class_upper & ITEMUPPER_THIRD) != 0) {
if ((sd->job & JOBL_THIRD) != 0)
break;
}
- return 0;
- }
- if ( battle_config.unequip_restricted_equipment & 1 ) {
- int i;
- for ( i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++ )
- if ( map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].nameid )
- return 0;
- }
-
- if ( battle_config.unequip_restricted_equipment & 2 ) {
- if ( !itemdb_isspecial( sd->status.inventory[n].card[0] ) ) {
- int i, slot;
- for ( slot = 0; slot < MAX_SLOTS; slot++ )
- for ( i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++ )
- if ( map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].card[slot] )
- return 0;
- }
+ return 0;
}
return 1;
@@ -5280,10 +5295,6 @@ static int pc_useitem(struct map_session_data *sd, int n)
if(sd->catch_target_class != -1) //Abort pet catching.
sd->catch_target_class = -1;
- // Removes abracadabra/randomize spell flag for delayed consume items or item doesn't get consumed
- if (sd->inventory_data[n]->flag.delay_consume)
- sd->state.abra_flag = 0;
-
amount = sd->status.inventory[n].amount;
//Check if the item is to be consumed immediately [Skotlex]
if (sd->inventory_data[n]->flag.delay_consume || sd->inventory_data[n]->flag.keepafteruse)
@@ -5322,21 +5333,22 @@ static int pc_useitem(struct map_session_data *sd, int n)
}
/**
- * Sets state flags and helper variables, used by itemskill() script command, to 0.
+ * Unsets a character's auto-cast related data.
*
* @param sd The character's session data.
* @return 0 if parameter sd is NULL, otherwise 1.
*/
-static int pc_itemskill_clear(struct map_session_data *sd)
+static int pc_autocast_clear(struct map_session_data *sd)
{
nullpo_ret(sd);
- sd->itemskill_id = 0;
- sd->itemskill_lv = 0;
- sd->state.itemskill_conditions_checked = 0;
- sd->state.itemskill_no_conditions = 0;
- sd->state.itemskill_no_casttime = 0;
- sd->state.itemskill_castonself = 0;
+ sd->autocast.type = AUTOCAST_NONE;
+ sd->autocast.skill_id = 0;
+ sd->autocast.skill_lv = 0;
+ sd->autocast.itemskill_conditions_checked = false;
+ sd->autocast.itemskill_check_conditions = false;
+ sd->autocast.itemskill_instant_cast = false;
+ sd->autocast.itemskill_cast_on_self = false;
return 1;
}
@@ -5688,242 +5700,295 @@ static int pc_steal_coin(struct map_session_data *sd, struct block_list *target,
return 0;
}
-/*==========================================
- * Set's a player position.
- * Return values:
- * 0 - Success.
- * 1 - Invalid map index.
- * 2 - Map not in this map-server, and failed to locate alternate map-server.
- *------------------------------------------*/
+/**
+ * Sets a character's position.
+ *
+ * @param sd The related character.
+ * @param map_index The target map's index.
+ * @param x The target x-coordinate.
+ * @param y The target y-coordinate.
+ * @param clrtype The unit clear type, which should be used.
+ * @retval 0 Success.
+ * @retval 1 Invalid map index.
+ * @retval 2 Map not in this map-server, and failed to locate alternative map-server.
+ * @retval 3 No character data. (Parameter sd is a NULL pointer.)
+ * @retval 4 Character is jailed.
+ *
+ **/
static int pc_setpos(struct map_session_data *sd, unsigned short map_index, int x, int y, enum clr_type clrtype)
{
- int16 m;
+ nullpo_retr(3, sd);
- nullpo_ret(sd);
+ int map_id = map->mapindex2mapid(map_index);
- if( !map_index || !mapindex_id2name(map_index) || ( m = map->mapindex2mapid(map_index) ) == -1 ) {
- ShowDebug("pc_setpos: Passed mapindex(%d) is invalid!\n", map_index);
+ if (map_index == 0 || !mapindex_id2name(map_index) || map_id == INDEX_NOT_FOUND) {
+ ShowDebug("pc_setpos: Passed mapindex %d is invalid!\n", map_index);
return 1;
}
- if( pc_isdead(sd) ) { //Revive dead people before warping them
+ if (pc_isdead(sd)) { // Revive dead character before warping.
pc->setstand(sd);
- pc->setrestartvalue(sd,1);
+ pc->setrestartvalue(sd, 1);
}
- if( map->list[m].flag.src4instance ) {
- struct party_data *p;
+ if (map->list[map_id].flag.src4instance != 0) {
bool stop = false;
- int i = 0, j = 0;
- if( sd->instances ) {
- for( i = 0; i < sd->instances; i++ ) {
- 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 )
+ if (sd->instances != 0) {
+ int i, j = 0;
+
+ for (i = 0; i < sd->instances; i++) {
+ 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 == map_id
+ && !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 = instance->list[sd->instance[i]].map[j];
- map_index = map_id2index(m);
+
+ if (i != sd->instances) {
+ map_id = instance->list[sd->instance[i]].map[j];
+ map_index = map_id2index(map_id);
stop = true;
}
}
- if ( !stop && sd->status.party_id && (p = party->search(sd->status.party_id)) != NULL && p->instances ) {
- for( i = 0; i < p->instances; i++ ) {
- 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 )
+
+ struct party_data *p = party->search(sd->status.party_id);
+
+ if (!stop && sd->status.party_id != 0 && p != NULL && p->instances != 0) {
+ int i, j = 0;
+
+ for (i = 0; i < p->instances; i++) {
+ 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 == map_id
+ && !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 = instance->list[p->instance[i]].map[j];
- map_index = map_id2index(m);
+
+ if (i != p->instances) {
+ map_id = instance->list[p->instance[i]].map[j];
+ map_index = map_id2index(map_id);
stop = true;
}
}
- if ( !stop && sd->status.guild_id && sd->guild && sd->guild->instances ) {
- for( i = 0; i < sd->guild->instances; i++ ) {
- 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 )
+
+ if (!stop && sd->status.guild_id != 0 && sd->guild != NULL && sd->guild->instances != 0) {
+ int i, j = 0;
+
+ for (i = 0; i < sd->guild->instances; i++) {
+ 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 == map_id
+ && !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 = instance->list[sd->guild->instance[i]].map[j];
- map_index = map_id2index(m);
- //stop = true; Uncomment if adding new checks
+
+ if (i != sd->guild->instances) {
+ map_id = instance->list[sd->guild->instance[i]].map[j];
+ map_index = map_id2index(map_id);
+ //stop = true; Uncomment when 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;
+ // We hit an instance. If empty we populate the spawn data.
+ if (map->list[map_id].instance_id >= 0 && instance->list[map->list[map_id].instance_id].respawn.map == 0
+ && instance->list[map->list[map_id].instance_id].respawn.x == 0
+ && instance->list[map->list[map_id].instance_id].respawn.y == 0) {
+ instance->list[map->list[map_id].instance_id].respawn.map = map_index;
+ instance->list[map->list[map_id].instance_id].respawn.x = x;
+ instance->list[map->list[map_id].instance_id].respawn.y = y;
}
}
- sd->state.changemap = (sd->mapindex != map_index);
+ sd->state.changemap = (sd->mapindex != map_index) ? 1 : 0;
sd->state.warping = 1;
sd->state.workinprogress = 0;
- if( sd->state.changemap ) { // Misc map-changing settings
- int i;
+
+ if (sd->state.changemap != 0) { // Miscellaneous map-changing settings.
sd->state.pmap = sd->bl.m;
- for (i = 0; i < VECTOR_LENGTH(sd->script_queues); i++) {
+ for (int i = 0; i < VECTOR_LENGTH(sd->script_queues); i++) {
struct script_queue *queue = script->queue(VECTOR_INDEX(sd->script_queues, i));
- if (queue && queue->event_mapchange[0] != '\0') {
- pc->setregstr(sd, script->add_variable("@Queue_Destination_Map$"), map->list[m].name);
+
+ if (queue != NULL && queue->event_mapchange[0] != '\0') {
+ pc->setregstr(sd, script->add_variable("@Queue_Destination_Map$"), map->list[map_id].name);
npc->event(sd, queue->event_mapchange, 0);
}
}
- 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!
+ if (map->list[map_id].cell == (struct mapcell *)0xdeadbeaf)
+ map->cellfromcache(&map->list[map_id]);
+
+ if (sd->sc.count != 0) { // Cancel some map related stuff.
+ if (sd->sc.data[SC_JAILED] != NULL)
+ return 4; // You may not get out!
+
status_change_end(&sd->bl, SC_CASH_BOSS_ALARM, INVALID_TIMER);
status_change_end(&sd->bl, SC_WARM, INVALID_TIMER);
status_change_end(&sd->bl, SC_SUN_COMFORT, INVALID_TIMER);
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_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]) {
+
+ if (sd->sc.data[SC_KNOWLEDGE] != NULL) {
struct status_change_entry *sce = sd->sc.data[SC_KNOWLEDGE];
+
if (sce->timer != INVALID_TIMER)
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);
+
+ 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);
status_change_end(&sd->bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
}
- for( i = 0; i < EQI_MAX; i++ ) {
- if( sd->equip_index[ i ] >= 0 )
- if( !pc->isequip( sd , sd->equip_index[ i ] ) )
- pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE);
+
+ for (int i = 0; i < EQI_MAX; i++) {
+ if (sd->equip_index[i] >= 0 && pc->isequip(sd , sd->equip_index[i]) == 0)
+ pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE);
}
- if (battle_config.clear_unit_onwarp&BL_PC)
+
+ if ((battle_config.clear_unit_onwarp & BL_PC) != 0)
skill->clear_unitgroup(&sd->bl);
- party->send_dot_remove(sd); //minimap dot fix [Kevin]
+
+ party->send_dot_remove(sd); // Minimap dot fix. [Kevin]
guild->send_dot_remove(sd);
bg->send_dot_remove(sd);
- if (sd->regen.state.gc)
+
+ if (sd->regen.state.gc != 0)
sd->regen.state.gc = 0;
- // make sure vending is allowed here
- if (sd->state.vending && map->list[m].flag.novending) {
- clif->message (sd->fd, msg_sd(sd,276)); // "You can't open a shop on this map"
+
+ // Make sure that vending is allowed here.
+ if (sd->state.vending != 0 && map->list[map_id].flag.novending != 0) {
+ clif->message(sd->fd, msg_sd(sd, 276)); // "You can't open a shop on this map"
vending->close(sd);
}
- if (sd->mapindex != 0) {
- // Only if the character is already on a map
- if (map->list[sd->bl.m].channel) {
- channel->leave(map->list[sd->bl.m].channel,sd);
- }
- }
+ if (sd->mapindex != 0 && map->list[sd->bl.m].channel != NULL) // Only if the character is already on a map.
+ channel->leave(map->list[sd->bl.m].channel, sd);
}
- if( m < 0 ) {
+ if (map_id < 0) {
uint32 ip;
uint16 port;
- //if can't find any map-servers, just abort setting position.
- if(!sd->mapindex || map->mapname2ipport(map_index,&ip,&port))
+
+ // If can't find any map-servers, just abort setting position.
+ if (sd->mapindex == 0 || map->mapname2ipport(map_index, &ip, &port) != 0)
return 2;
- if (sd->npc_id)
+ if (sd->npc_id != 0)
npc->event_dequeue(sd);
+
npc->script_event(sd, NPCE_LOGOUT);
- //remove from map, THEN change x/y coordinates
- unit->remove_map_pc(sd,clrtype);
+
+ // Remove from map, THEN change x/y coordinates.
+ unit->remove_map_pc(sd, clrtype);
+
if (battle_config.player_warp_keep_direction == 0)
- sd->ud.dir = 0; // makes character face north
+ sd->ud.dir = 0; /// Make character facing north.
+
sd->mapindex = map_index;
- sd->bl.x=x;
- sd->bl.y=y;
+ 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, port);
- //Free session data from this map server [Kevin]
+ // Free session data from this map server. [Kevin]
unit->free_pc(sd);
return 0;
}
- 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 || x >= map->list[map_id].xs || y < 0 || y >= map->list[map_id].ys) { // Invalid coordinates. Randomize them.
+ 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 = 0;
+ y = 0;
}
- if( x == 0 && y == 0 ) {// pick a random walkable cell
+ if (x == 0 && y == 0) { // Pick a random walkable cell.
do {
- x=rnd()%(map->list[m].xs-2)+1;
- y=rnd()%(map->list[m].ys-2)+1;
- } while(map->getcell(m, &sd->bl, x, y, CELL_CHKNOPASS));
+ x = rnd() % (map->list[map_id].xs - 2) + 1;
+ y = rnd() % (map->list[map_id].ys - 2) + 1;
+ } while(map->getcell(map_id, &sd->bl, x, y, CELL_CHKNOPASS) != 0);
}
- if (sd->state.vending && map->getcell(m, &sd->bl, x, y, CELL_CHKNOVENDING)) {
- clif->message (sd->fd, msg_sd(sd,204)); // "You can't open a shop on this cell."
+ if (sd->state.vending != 0 && map->getcell(map_id, &sd->bl, x, y, CELL_CHKNOVENDING) != 0) {
+ clif->message(sd->fd, msg_sd(sd, 204)); // "You can't open a shop on this cell."
vending->close(sd);
}
if (battle_config.player_warp_keep_direction == 0)
- sd->ud.dir = 0; // makes character face north
+ sd->ud.dir = 0; // Make character facing north.
- if(sd->bl.prev != NULL){
- 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;
+ if (sd->bl.prev != NULL) {
+ unit->remove_map_pc(sd, clrtype);
+ clif->changemap(sd, map_id, x, y); // [MouseJstr]
+ } else if (sd->state.active != 0) {
+ sd->state.rewarp = 1; // Tag character for re-warping after map-loading is done. [Skotlex]
+ }
sd->mapindex = map_index;
- sd->bl.m = m;
- sd->bl.x = sd->ud.to_x = x;
- sd->bl.y = sd->ud.to_y = y;
+ sd->bl.m = map_id;
+ sd->bl.x = x;
+ sd->bl.y = y;
+ sd->ud.to_x = x;
+ sd->ud.to_y = y;
- if( sd->status.guild_id > 0 && map->list[m].flag.gvg_castle ) { // Increased guild castle regen [Valaris]
+ if (sd->status.guild_id > 0 && map->list[map_id].flag.gvg_castle != 0) { // Double regeneration in guild castle. [Valaris]
struct guild_castle *gc = guild->mapindex2gc(sd->mapindex);
- if(gc && gc->guild_id == sd->status.guild_id)
+
+ if (gc != NULL && gc->guild_id == sd->status.guild_id)
sd->regen.state.gc = 1;
}
- if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 ) {
- sd->pd->bl.m = m;
- sd->pd->bl.x = sd->pd->ud.to_x = x;
- sd->pd->bl.y = sd->pd->ud.to_y = y;
+ if (sd->status.pet_id > 0 && sd->pd != NULL && sd->pd->pet.intimate > PET_INTIMACY_NONE) {
+ sd->pd->bl.m = map_id;
+ sd->pd->bl.x = x;
+ sd->pd->bl.y = y;
+ sd->pd->ud.to_x = x;
+ sd->pd->ud.to_y = y;
sd->pd->ud.dir = sd->ud.dir;
}
- if( homun_alive(sd->hd) ) {
- sd->hd->bl.m = m;
- sd->hd->bl.x = sd->hd->ud.to_x = x;
- sd->hd->bl.y = sd->hd->ud.to_y = y;
+ if (homun_alive(sd->hd)) {
+ sd->hd->bl.m = map_id;
+ sd->hd->bl.x = x;
+ sd->hd->bl.y = y;
+ sd->hd->ud.to_x = x;
+ sd->hd->ud.to_y = y;
sd->hd->ud.dir = sd->ud.dir;
}
- if( sd->md ) {
- sd->md->bl.m = m;
- sd->md->bl.x = sd->md->ud.to_x = x;
- sd->md->bl.y = sd->md->ud.to_y = y;
+ if (sd->md != NULL) {
+ sd->md->bl.m = map_id;
+ sd->md->bl.x = x;
+ sd->md->bl.y = y;
+ sd->md->ud.to_x = x;
+ 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);
+ // Given autotrades have no clients. You have to trigger this manually, otherwise they get stuck in memory limbo. (bugreport:7495)
+ if (sd->state.autotrade != 0)
+ clif->pLoadEndAck(0, sd);
return 0;
}
@@ -8003,163 +8068,177 @@ static void pc_damage(struct map_session_data *sd, struct block_list *src, unsig
}
}
-/*==========================================
- * Invoked when a player has negative current hp
- *------------------------------------------*/
+/**
+ * Invoked when a character died.
+ *
+ * @param sd The died character.
+ * @param src The unit which caused the death.
+ * @retval 0 Death canceled.
+ * @retval 1 Standard death.
+ * @retval 9 Died in PVP/GVG/BG.
+ *
+ **/
static int pc_dead(struct map_session_data *sd, struct block_list *src)
{
- int i=0,j=0;
- int64 tick = timer->gettick();
+ nullpo_ret(sd);
- nullpo_retr(0, sd);
+ for (int i = 0; i < MAX_PC_DEVOTION; i++) {
+ if (sd->devotion[i] != 0) {
+ struct map_session_data *devsd = map->id2sd(sd->devotion[i]);
- for (j = 0; j < MAX_PC_DEVOTION; j++) {
- if (sd->devotion[j]) {
- struct map_session_data *devsd = map->id2sd(sd->devotion[j]);
- if (devsd)
+ if (devsd != NULL)
status_change_end(&devsd->bl, SC_DEVOTION, INVALID_TIMER);
- sd->devotion[j] = 0;
+
+ sd->devotion[i] = 0;
}
}
- if(sd->status.pet_id > 0 && sd->pd) {
+ if (sd->status.pet_id > 0 && sd->pd != NULL) {
struct pet_data *pd = sd->pd;
- if( !map->list[sd->bl.m].flag.noexppenalty ) {
+
+ if (map->list[sd->bl.m].flag.noexppenalty == 0) {
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);
+ clif->send_petdata(sd, sd->pd, 1, pd->pet.intimate);
}
- if( sd->pd->target_id ) // Unlock all targets...
+
+ if (sd->pd->target_id != 0) // Unlock all targets.
pet->unlocktarget(sd->pd);
}
- if (sd->status.hom_id > 0){
- if(battle_config.homunculus_auto_vapor && sd->hd)
- homun->vaporize(sd, HOM_ST_REST, true);
- }
+ if (sd->status.hom_id > 0 && sd->hd != NULL && battle_config.homunculus_auto_vapor != 0)
+ homun->vaporize(sd, HOM_ST_REST, true);
- if( sd->md )
- mercenary->delete(sd->md, 3); // Your mercenary soldier has ran away.
+ if (sd->md != NULL)
+ mercenary->delete(sd->md, 3); // Your mercenary soldier ran away.
- if( sd->ed )
+ if (sd->ed != NULL)
elemental->delete(sd->ed, 0);
- // Leave duel if you die [LuzZza]
- if(battle_config.duel_autoleave_when_die) {
- if(sd->duel_group > 0)
+ if (battle_config.duel_autoleave_when_die != 0) { // Leave duel if character died. [LuzZza]
+ if (sd->duel_group > 0)
duel->leave(sd->duel_group, sd);
- if(sd->duel_invite > 0)
+ if (sd->duel_invite > 0)
duel->reject(sd->duel_invite, sd);
}
- if (sd->npc_id && sd->st && sd->st->state != RUN)
+ if (sd->npc_id != 0 && sd->st != NULL && sd->st->state != RUN)
npc->event_dequeue(sd);
- pc_setglobalreg(sd,script->add_variable("PC_DIE_COUNTER"),sd->die_counter+1);
- pc->setparam(sd, SP_KILLERRID, src?src->id:0);
+ pc_setglobalreg(sd, script->add_variable("PC_DIE_COUNTER"), sd->die_counter + 1);
+ pc->setparam(sd, SP_KILLERRID, (src != NULL) ? src->id : 0);
- if( sd->bg_id ) {/* TODO: purge when bgqueue is deemed ok */
- struct battleground_data *bgd;
- if( (bgd = bg->team_search(sd->bg_id)) != NULL && bgd->die_event[0] )
+ if (sd->bg_id != 0) { //TODO: Purge when bgqueue is deemed ok.
+ struct battleground_data *bgd = bg->team_search(sd->bg_id);
+
+ if (bgd != NULL && bgd->die_event[0] != '\0')
npc->event(sd, bgd->die_event, 0);
}
- for (i = 0; i < VECTOR_LENGTH(sd->script_queues); i++ ) {
+ for (int i = 0; i < VECTOR_LENGTH(sd->script_queues); i++) {
struct script_queue *queue = script->queue(VECTOR_INDEX(sd->script_queues, i));
- if (queue && queue->event_death[0] != '\0')
+
+ if (queue != NULL && queue->event_death[0] != '\0')
npc->event(sd, queue->event_death, 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) && sd->state.dialog) {
- if (sd->state.using_fake_npc) {
+ // Clear anything NPC-related if character died while interacting with one.
+ if ((sd->npc_id != 0 || sd->npc_shopid != 0) && sd->state.dialog != 0) {
+ if (sd->state.using_fake_npc != 0) {
clif->clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
sd->state.using_fake_npc = 0;
}
- if (sd->state.menu_or_input)
+
+ if (sd->state.menu_or_input != 0)
sd->state.menu_or_input = 0;
- if (sd->npc_menu)
+
+ if (sd->npc_menu != 0)
sd->npc_menu = 0;
sd->npc_id = 0;
sd->npc_shopid = 0;
- if (sd->st && sd->st->state != END)
+
+ if (sd->st != NULL && sd->st->state != END)
sd->st->state = END;
}
- /* e.g. not killed through pc->damage */
- if( pc_issit(sd) ) {
+ // E.g. not killed through pc->damage().
+ if (pc_issit(sd))
clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_SIT));
- }
pc_setdead(sd);
-
clif->party_dead_notification(sd);
- //Reset menu skills/item skills
- if (sd->skillitem)
- sd->skillitem = sd->skillitemlv = 0;
- if (sd->menuskill_id)
- sd->menuskill_id = sd->menuskill_val = 0;
- //Reset ticks.
- sd->hp_loss.tick = sd->sp_loss.tick = sd->hp_regen.tick = sd->sp_regen.tick = 0;
+ pc->autocast_clear(sd); // Unset auto-cast data.
- if ( sd->spiritball )
+ if (sd->menuskill_id != 0) { // Reset menu skills.
+ sd->menuskill_id = 0;
+ sd->menuskill_val = 0;
+ }
+
+ // Reset ticks.
+ sd->hp_loss.tick = 0;
+ sd->sp_loss.tick = 0;
+ sd->hp_regen.tick = 0;
+ sd->sp_regen.tick = 0;
+
+ if (sd->spiritball != 0)
pc->delspiritball(sd, sd->spiritball, 0);
+
if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0)
pc->del_charm(sd, sd->charm_count, sd->charm_type);
+ int64 tick = timer->gettick();
+
if (src != NULL) {
switch (src->type) {
- case BL_MOB:
- {
- struct mob_data *md = BL_UCAST(BL_MOB, src);
- if (md->target_id==sd->bl.id)
- mob->unlocktarget(md,tick);
- if (battle_config.mobs_level_up && md->status.hp
- && md->level < pc->maxbaselv(sd)
- && !md->guardian_data && md->special_state.ai == AI_NONE// Guardians/summons should not level. [Skotlex]
- ) {
- // monster level up [Valaris]
- clif->misceffect(&md->bl,0);
- md->level++;
- status_calc_mob(md, SCO_NONE);
- status_percent_heal(src,10,0);
-
- if( battle_config.show_mob_info&4 )
- {// update name with new level
- clif->blname_ack(0, &md->bl);
- }
- }
- src = battle->get_master(src); // Maybe Player Summon
+ case BL_MOB: {
+ struct mob_data *md = BL_UCAST(BL_MOB, src);
+
+ if (md->target_id == sd->bl.id)
+ mob->unlocktarget(md, tick);
+
+ if (battle_config.mobs_level_up != 0 && md->status.hp != 0 && md->level < pc->maxbaselv(sd)
+ && md->guardian_data == NULL && md->special_state.ai == AI_NONE) { // Guardians/summons should not level up. [Skotlex]
+ /// Monster level up. [Valaris]
+ clif->misceffect(&md->bl, 0);
+ md->level++;
+ status_calc_mob(md, SCO_NONE);
+ status_percent_heal(src, 10, 0);
+
+ if ((battle_config.show_mob_info & 4) != 0)
+ clif->blname_ack(0, &md->bl); // Update name with new level.
}
+
+ src = battle->get_master(src); // Maybe character summon.
break;
- case BL_PET: //Pass on to master...
- src = &BL_UCAST(BL_PET, src)->msd->bl;
+ }
+ case BL_PET:
+ src = &BL_UCAST(BL_PET, src)->msd->bl; // Pass on to master.
break;
- case BL_HOM:
- src = &BL_UCAST(BL_HOM, src)->master->bl;
+ case BL_HOM:
+ src = &BL_UCAST(BL_HOM, src)->master->bl; // Pass on to master.
break;
- case BL_MER:
- src = &BL_UCAST(BL_MER, src)->master->bl;
+ case BL_MER:
+ src = &BL_UCAST(BL_MER, src)->master->bl; // Pass on to master.
break;
}
}
if (src != NULL && src->type == BL_PC) {
struct map_session_data *ssd = BL_UCAST(BL_PC, src);
+
pc->setparam(ssd, SP_KILLEDRID, sd->bl.id);
npc->script_event(ssd, NPCE_KILLPC);
+ achievement->validate_pc_kill(ssd, sd);
- achievement->validate_pc_kill(ssd, sd); // Achievements [Smokexyz/Hercules]
-
- if (battle_config.pk_mode&2) {
+ if ((battle_config.pk_mode & 2) != 0) {
ssd->status.manner -= 5;
- if(ssd->status.manner < 0)
- sc_start(NULL,src,SC_NOCHAT,100,0,0);
+
+ if (ssd->status.manner < 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 ^^;
@@ -8171,14 +8250,15 @@ static int pc_dead(struct map_session_data *sd, struct block_list *src)
// If player killed was more evil
sd->status.karma--;
ssd->status.karma--;
- }
- else if (sd->status.karma < ssd->status.karma) // If player killed was more good
+ } else if (sd->status.karma < ssd->status.karma) { // If player killed was more good
ssd->status.karma++;
+ }
// or the PK System way...
if (sd->status.karma > 0) // player killed is dishonourable?
ssd->status.karma--; // honour points earned
+
sd->status.karma++; // honour points lost
// To-do: Receive exp on certain occasions
@@ -8186,137 +8266,156 @@ static int pc_dead(struct map_session_data *sd, struct block_list *src)
}
}
- if( battle_config.bone_drop==2
- || (battle_config.bone_drop==1 && map->list[sd->bl.m].flag.pvp)
- ) {
+ if (battle_config.bone_drop == 2 || (battle_config.bone_drop == 1 && map->list[sd->bl.m].flag.pvp != 0)) {
struct item item_tmp;
- memset(&item_tmp,0,sizeof(item_tmp));
- item_tmp.nameid=ITEMID_SKULL_;
- item_tmp.identify=1;
- item_tmp.card[0]=CARD0_CREATE;
- 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);
+
+ memset(&item_tmp, 0, sizeof(item_tmp));
+ item_tmp.nameid = ITEMID_SKULL_;
+ item_tmp.identify = 1;
+ item_tmp.card[0] = CARD0_CREATE;
+ item_tmp.card[1] = 0;
+ item_tmp.card[2] = GetWord(sd->status.char_id, 0);
+ item_tmp.card[3] = GetWord(sd->status.char_id, 1);
map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0, false);
}
- // activate Steel body if a super novice dies at 99+% exp [celest]
- if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && !sd->state.snovice_dead_flag) {
+ // Activate Steel Body if a Super Novice dies at 99+% EXP. [celest]
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->state.snovice_dead_flag == 0) {
uint64 next = pc->nextbaseexp(sd);
- if( next == 0 ) next = pc->thisbaseexp(sd);
+
+ if (next == 0)
+ next = pc->thisbaseexp(sd);
+
if (get_percentage64(sd->status.base_exp, next) >= 99) {
sd->state.snovice_dead_flag = 1;
pc->setstand(sd);
status_percent_heal(&sd->bl, 100, 100);
clif->resurrection(&sd->bl, 1);
- if(battle_config.pc_invincible_time)
+
+ if (battle_config.pc_invincible_time != 0)
pc->setinvincibletimer(sd, battle_config.pc_invincible_time);
- sc_start(NULL,&sd->bl,status->skill2sc(MO_STEELBODY),100,1,skill->get_time(MO_STEELBODY,1));
- if(map_flag_gvg2(sd->bl.m))
+
+ 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
- && pc->isDeathPenaltyJob(sd->job)
- && !map->list[sd->bl.m].flag.noexppenalty && !map_flag_gvg2(sd->bl.m)
- && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_CASH_DEATHPENALTY]
- && !pc->auto_exp_insurance(sd)
- ) {
+ if (battle_config.death_penalty_type != 0 && pc->isDeathPenaltyJob(sd->job) && !map_flag_gvg2(sd->bl.m)
+ && map->list[sd->bl.m].flag.noexppenalty == 0 && sd->sc.data[SC_BABY] == NULL
+ && sd->sc.data[SC_CASH_DEATHPENALTY] == NULL && !pc->auto_exp_insurance(sd)) {
if (battle_config.death_penalty_base > 0) {
unsigned int base_penalty = 0;
+ int rate = battle_config.death_penalty_base;
+
switch (battle_config.death_penalty_type) {
- case 1:
- base_penalty = (unsigned int) apply_percentrate64(pc->nextbaseexp(sd), battle_config.death_penalty_base, 10000);
- break;
- case 2:
- base_penalty = (unsigned int) apply_percentrate64(sd->status.base_exp, battle_config.death_penalty_base, 10000);
- break;
+ case 1:
+ base_penalty = (unsigned int)apply_percentrate64(pc->nextbaseexp(sd), rate, 10000);
+ break;
+ case 2:
+ base_penalty = (unsigned int)apply_percentrate64(sd->status.base_exp, rate, 10000);
+ break;
}
if (base_penalty != 0) {
- 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;
+ if (battle_config.pk_mode != 0 && src != NULL && src->type == BL_PC)
+ base_penalty *= 2;
+
+ if (sd->status.mod_death != 100)
+ base_penalty *= sd->status.mod_death / 100;
+
sd->status.base_exp -= min(sd->status.base_exp, base_penalty);
- clif->updatestatus(sd,SP_BASEEXP);
+ clif->updatestatus(sd, SP_BASEEXP);
}
}
- if(battle_config.death_penalty_job > 0) {
+ if (battle_config.death_penalty_job > 0) {
unsigned int job_penalty = 0;
+ int rate = battle_config.death_penalty_job;
switch (battle_config.death_penalty_type) {
- case 1:
- job_penalty = (unsigned int) apply_percentrate64(pc->nextjobexp(sd), battle_config.death_penalty_job, 10000);
- break;
- case 2:
- job_penalty = (unsigned int) apply_percentrate64(sd->status.job_exp, battle_config.death_penalty_job, 10000);
- break;
+ case 1:
+ job_penalty = (unsigned int)apply_percentrate64(pc->nextjobexp(sd), rate, 10000);
+ break;
+ case 2:
+ job_penalty = (unsigned int)apply_percentrate64(sd->status.job_exp, rate, 10000);
+ break;
}
if (job_penalty != 0) {
- if (battle_config.pk_mode && src && src->type==BL_PC)
- job_penalty*=2;
- if( sd->status.mod_death != 100 )
- job_penalty = job_penalty * sd->status.mod_death / 100;
+ if (battle_config.pk_mode != 0 && src != NULL && src->type == BL_PC)
+ job_penalty *= 2;
+
+ if (sd->status.mod_death != 100)
+ job_penalty *= sd->status.mod_death / 100;
+
sd->status.job_exp -= min(sd->status.job_exp, job_penalty);
- clif->updatestatus(sd,SP_JOBEXP);
+ clif->updatestatus(sd, SP_JOBEXP);
}
}
- if (battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty) {
+ if (battle_config.zeny_penalty > 0 && map->list[sd->bl.m].flag.nozenypenalty == 0) {
int zeny_penalty = apply_percentrate(sd->status.zeny, battle_config.zeny_penalty, 10000);
+
if (zeny_penalty != 0)
pc->payzeny(sd, zeny_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL);
}
}
- 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)
+ if (map->list[sd->bl.m].flag.pvp_nightmaredrop != 0) {
+ // Moved this outside so it works when PVP isn't enabled and during pk mode. [Ancyker]
+ for (int i = 0; i < map->list[sd->bl.m].drop_list_count; i++) {
+ int id = map->list[sd->bl.m].drop_list[i].drop_id;
+ int type = map->list[sd->bl.m].drop_list[i].drop_type;
+ int per = map->list[sd->bl.m].drop_list[i].drop_per;
+
+ if (id == 0)
continue;
- if(id == -1){
- int eq_num = 0, eq_n[MAX_INVENTORY], k;
- memset(eq_n,0,sizeof(eq_n));
- for(i = 0; i < sd->status.inventorySize; i++) {
- if( (type == 1 && !sd->status.inventory[i].equip)
- || (type == 2 && sd->status.inventory[i].equip)
- || type == 3)
- {
+
+ if (id == -1) {
+ int eq_num = 0;
+ int eq_n[MAX_INVENTORY];
+
+ memset(eq_n, 0, sizeof(eq_n));
+
+ for (int j = 0; j < sd->status.inventorySize; j++) {
+ bool is_equipped = (sd->status.inventory[j].equip != 0);
+
+ if ((type == 1 && !is_equipped) || (type == 2 && is_equipped) || type == 3) {
+ int k;
+
ARR_FIND(0, sd->status.inventorySize, k, eq_n[k] <= 0);
+
if (k < sd->status.inventorySize)
- eq_n[k] = i;
+ eq_n[k] = j;
eq_num++;
}
}
- if(eq_num > 0){
- int n = eq_n[rnd()%eq_num];
- if(rnd()%10000 < per){
- if(sd->status.inventory[n].equip)
+
+ if (eq_num > 0) {
+ int n = eq_n[rnd() % eq_num];
+
+ if (rnd() % 10000 < per) {
+ if (sd->status.inventory[n].equip != 0)
pc->unequipitem(sd, n, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
- pc->dropitem(sd,n,1);
+
+ pc->dropitem(sd, n, 1);
}
}
- }
- else if(id > 0){
- for( i = 0; i < sd->status.inventorySize; i++) {
- if(sd->status.inventory[i].nameid == id
- && rnd()%10000 < per
- && ((type == 1 && !sd->status.inventory[i].equip)
- || (type == 2 && sd->status.inventory[i].equip)
- || type == 3) ){
- if(sd->status.inventory[i].equip)
- pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
- pc->dropitem(sd,i,1);
+ } else if (id > 0) {
+ for (int j = 0; j < sd->status.inventorySize; j++) {
+ bool is_equipped = (sd->status.inventory[j].equip != 0);
+
+ if (((type == 1 && !is_equipped) || (type == 2 && is_equipped) || type == 3)
+ && sd->status.inventory[j].nameid == id && rnd() % 10000 < per) {
+ if (is_equipped)
+ pc->unequipitem(sd, j, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
+
+ pc->dropitem(sd, j, 1);
break;
}
}
@@ -8324,46 +8423,51 @@ static 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)
- ) {
+ // Remove autotrade to prevent autotrading from save point.
+ if ((map->list[sd->bl.m].flag.pvp != 0 || map->list[sd->bl.m].flag.gvg != 0)
+ && (sd->state.standalone != 0 || sd->state.autotrade != 0)) {
sd->state.autotrade = 0;
sd->state.standalone = 0;
- pc->autotrade_update(sd,PAUC_REMOVE);
+ pc->autotrade_update(sd, PAUC_REMOVE);
map->quit(sd);
}
- // pvp
- // disable certain pvp functions on pk_mode [Valaris]
- if( map->list[sd->bl.m].flag.pvp && !battle_config.pk_mode && !map->list[sd->bl.m].flag.pvp_nocalcrank ) {
+ // Disable certain PVP functions on pk_mode. [Valaris]
+ if (map->list[sd->bl.m].flag.pvp != 0 && battle_config.pk_mode == 0
+ && map->list[sd->bl.m].flag.pvp_nocalcrank == 0) {
sd->pvp_point -= 5;
sd->pvp_lost++;
+
if (src != NULL && src->type == BL_PC) {
struct map_session_data *ssd = BL_UCAST(BL_PC, src);
+
ssd->pvp_point++;
ssd->pvp_won++;
}
- if( sd->pvp_point < 0 )
- {
- timer->add(tick+1, pc->respawn_timer,sd->bl.id,0);
+
+ if (sd->pvp_point < 0) {
+ timer->add(tick + 1, pc->respawn_timer, sd->bl.id, 0);
return 1|8;
}
}
- //GvG
- if( map_flag_gvg2(sd->bl.m) ) {
- timer->add(tick+1, pc->respawn_timer, sd->bl.id, 0);
+
+ // GVG
+ 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 ) {
+ }
+
+ if (sd->bg_id != 0) {
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);
+
+ if (bgd != NULL && 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 )
+ // Reset "can log out" tick.
+ if (battle_config.prevent_logout != 0)
sd->canlog_tick = timer->gettick() - battle_config.prevent_logout;
return 1;
@@ -8786,6 +8890,10 @@ static int pc_itemheal(struct map_session_data *sd, int itemid, int hp, int sp)
// 2014 Halloween Event : Pumpkin Bonus
if ( sd->sc.data[SC_MTF_PUMPKIN] && itemid == ITEMID_PUMPKIN )
hp += (int)(hp * sd->sc.data[SC_MTF_PUMPKIN]->val1/100);
+
+ // Activation Potion
+ if (sd->sc.data[SC_VITALIZE_POTION] != NULL)
+ hp += hp * sd->sc.data[SC_VITALIZE_POTION]->val3 / 100;
}
if(sp) {
bonus = 100 + (sd->battle_status.int_<<1)
@@ -10144,141 +10252,163 @@ static void pc_equipitem_pos(struct map_session_data *sd, struct item_data *id,
}
}
-/*==========================================
- * Equip item on player sd at req_pos from inventory index n
- * Return:
- * 0 = fail
- * 1 = success
- *------------------------------------------*/
+/**
+ * Attempts to equip an item.
+ *
+ * @param sd The related character.
+ * @param n The item's inventory index.
+ * @param req_pos The equipment slot, where the item should be equipped. (See enum equip_pos.)
+ * @return 0 on failure, 1 on success.
+ *
+ **/
static int pc_equipitem(struct map_session_data *sd, int n, int req_pos)
{
- int i,pos,flag=0,iflag;
- struct item_data *id;
-
nullpo_ret(sd);
if (n < 0 || n >= sd->status.inventorySize) {
- clif->equipitemack(sd,0,0,EIA_FAIL);
+ clif->equipitemack(sd, 0, 0, EIA_FAIL);
return 0;
}
- if( DIFF_TICK(sd->canequip_tick,timer->gettick()) > 0 )
- {
- clif->equipitemack(sd,n,0,EIA_FAIL);
+ // If the character is in berserk mode, the item can't be equipped.
+ if (sd->sc.count != 0 && (sd->sc.data[SC_BERSERK] != NULL || sd->sc.data[SC_NO_SWITCH_EQUIP] != NULL)) {
+ clif->equipitemack(sd, n, 0, EIA_FAIL);
return 0;
}
- id = sd->inventory_data[n];
- pos = pc->equippoint(sd,n); //With a few exceptions, item should go in all specified slots.
+ if (battle_config.battle_log != 0)
+ ShowInfo("equip %d(%d) %x:%x\n", sd->status.inventory[n].nameid, n, sd->status.inventory[n].equip,
+ (unsigned int)req_pos);
- if(battle_config.battle_log)
- ShowInfo("equip %d(%d) %x:%x\n", sd->status.inventory[n].nameid, n, (unsigned int)(id ? id->equip : 0), (unsigned int)req_pos);
- if(!pc->isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || (sd->status.inventory[n].attribute & ATTR_BROKEN) != 0 ) { // [Valaris]
- // FIXME: pc->isequip: equip level failure uses 2 instead of 0
- clif->equipitemack(sd,n,0,EIA_FAIL); // fail
+ if (DIFF_TICK(sd->canequip_tick, timer->gettick()) > 0) {
+ clif->equipitemack(sd, n, 0, EIA_FAIL);
return 0;
}
- if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP])
- {
- clif->equipitemack(sd,n,0,EIA_FAIL); // fail
+ int pos = pc->equippoint(sd, n); // With a few exceptions, item should go in all specified slots.
+
+ if (pc->isequip(sd,n) == 0 || (pos & req_pos) == 0 || sd->status.inventory[n].equip != 0
+ || (sd->status.inventory[n].attribute & ATTR_BROKEN) != 0) {
+ clif->equipitemack(sd, n, 0, EIA_FAIL);
return 0;
+ }
+
+ if (sd->inventory_data[n]->flag.bindonequip != 0 && sd->status.inventory[n].bound == 0) {
+ sd->status.inventory[n].bound = IBT_CHARACTER;
+ clif->notify_bounditem(sd, n);
}
- /* 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;
- } 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) {
- //Update skill-block range database when weapon range changes. [Skotlex]
- i = sd->equip_index[EQI_HAND_R];
- if (i < 0 || !sd->inventory_data[i]) //No data, or no weapon equipped
+ 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;
+ } else if (pos == EQP_ARMS && sd->inventory_data[n]->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 && sd->inventory_data[n]->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;
+ }
+
+ int flag = 0;
+
+ // Update skill-block range database when weapon range changes. [Skotlex]
+ if ((pos & EQP_HAND_R) != 0 && (battle_config.use_weapon_skill_range & BL_PC) != 0) {
+ int idx = sd->equip_index[EQI_HAND_R];
+
+ if (idx < 0 || sd->inventory_data[idx] == NULL) // No data, or no weapon equipped.
flag = 1;
else
- flag = id->range != sd->inventory_data[i]->range;
+ flag = (sd->inventory_data[n]->range != sd->inventory_data[idx]->range) ? 1 : 0;
}
- for(i=0;i<EQI_MAX;i++) {
- if(pos & pc->equip_pos[i]) {
- if(sd->equip_index[i] >= 0) //Slot taken, remove item from there.
+ for (int i = 0; i < EQI_MAX; i++) {
+ if ((pos & pc->equip_pos[i]) != 0) {
+ if (sd->equip_index[i] >= 0) // Slot taken, remove item from there.
pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE);
sd->equip_index[i] = n;
}
}
- if(pos==EQP_AMMO){
- clif->arrowequip(sd,n);
- clif->arrow_fail(sd,3);
+ if (pos == EQP_AMMO) {
+ clif->arrowequip(sd, n);
+ clif->arrow_fail(sd, 3);
+ } else {
+ clif->equipitemack(sd, n, pos, EIA_SUCCESS);
}
- else
- clif->equipitemack(sd,n,pos,EIA_SUCCESS);
- sd->status.inventory[n].equip=pos;
+ sd->status.inventory[n].equip = pos;
+ pc->equipitem_pos(sd, sd->inventory_data[n], n, pos);
+ pc->checkallowskill(sd); // Check if status changes should be halted.
- pc->equipitem_pos(sd, id, n, pos);
+ int iflag = sd->npc_item_flag;
- pc->checkallowskill(sd); //Check if status changes should be halted.
- iflag = sd->npc_item_flag;
+ // Check for combos. (MUST be done before status->calc_pc()!)
+ if (sd->inventory_data[n]->combos_count != 0)
+ pc->checkcombo(sd, sd->inventory_data[n]);
- /* check for combos (MUST be before status_calc_pc) */
- if( id->combos_count )
- pc->checkcombo(sd,id);
- if(itemdb_isspecial(sd->status.inventory[n].card[0]))
- ; //No cards
- else {
- for( i = 0; i < id->slot; i++ ) {
- struct item_data *data;
- if (!sd->status.inventory[n].card[i])
+ if (!itemdb_isspecial(sd->status.inventory[n].card[0])) {
+ for (int i = 0; i < sd->inventory_data[n]->slot; i++) {
+ if (sd->status.inventory[n].card[i] == 0)
continue;
- if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
- if( data->combos_count )
- pc->checkcombo(sd,data);
- }
+
+ struct item_data *data = itemdb->exists(sd->status.inventory[n].card[i]);
+
+ if (data != NULL && data->combos_count != 0)
+ pc->checkcombo(sd, data);
}
}
- status_calc_pc(sd,SCO_NONE);
- if (flag) //Update skill data
+ status_calc_pc(sd, SCO_NONE);
+
+ if (flag != 0) // Update skill data.
clif->skillinfoblock(sd);
+
+ // Execute equip script. [Skotlex]
+ struct item_data *equip_data = sd->inventory_data[n];
+ struct map_zone_data *zone = map->list[sd->bl.m].zone;
+ int dis_items_cnt = zone->disabled_items_count;
- //OnEquip script [Skotlex]
- if (id->equip_script)
- script->run_item_equip_script(sd, id, npc->fake_nd->bl.id);
+ if (equip_data->equip_script != NULL) {
+ int idx;
- if(itemdb_isspecial(sd->status.inventory[n].card[0]))
- ; //No cards
- else {
- for( i = 0; i < id->slot; i++ ) {
- struct item_data *data;
- if (!sd->status.inventory[n].card[i])
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == equip_data->nameid);
+
+ if (idx == dis_items_cnt)
+ script->run_item_equip_script(sd, equip_data, npc->fake_nd->bl.id);
+ }
+
+ struct item *equip = &sd->status.inventory[n];
+
+ if (!itemdb_isspecial(equip->card[0])) {
+ for (int slot = 0; slot < equip_data->slot; slot++) {
+ if (equip->card[slot] == 0)
continue;
- if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
- if (data->equip_script)
- script->run_item_equip_script(sd, data, npc->fake_nd->bl.id);
+
+ struct item_data *card_data = itemdb->exists(equip->card[slot]);
+
+ if (card_data != NULL && card_data->equip_script != NULL) {
+ int idx;
+
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == card_data->nameid);
+
+ if (idx == dis_items_cnt)
+ script->run_item_equip_script(sd, card_data, npc->fake_nd->bl.id);
}
}
}
+
sd->npc_item_flag = iflag;
return 1;
@@ -10350,19 +10480,17 @@ static void pc_unequipitem_pos(struct map_session_data *sd, int n, int pos)
}
}
-/*==========================================
- * Called when attemting to unequip an item from player
- * type: @see enum pc_unequipitem_flag
- * Return:
- * 0 = fail
- * 1 = success
- *------------------------------------------*/
+/**
+ * Attempts to unequip an item.
+ *
+ * @param sd The related character.
+ * @param n The item's inventory index.
+ * @param flag Modifier for additional actions. (See enum pc_unequipitem_flag.)
+ * @return 0 on failure, 1 on success.
+ *
+ **/
static int pc_unequipitem(struct map_session_data *sd, int n, int flag)
{
- int i, iflag;
- bool status_calc = false;
- int pos;
-
nullpo_ret(sd);
if (n < 0 || n >= sd->status.inventorySize) {
@@ -10370,127 +10498,128 @@ static int pc_unequipitem(struct map_session_data *sd, int n, int flag)
return 0;
}
- // if player is berserk then cannot unequip
- if (!(flag & PCUNEQUIPITEM_FORCE) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP])) {
+ // If the character is in berserk mode, the item can't be unequipped.
+ if (sd->sc.count != 0 && (sd->sc.data[SC_BERSERK] != NULL || sd->sc.data[SC_NO_SWITCH_EQUIP] != NULL)
+ && (flag & PCUNEQUIPITEM_FORCE) == 0) {
clif->unequipitemack(sd, n, 0, UIA_FAIL);
return 0;
}
- if (!(flag & PCUNEQUIPITEM_FORCE) && sd->sc.count && sd->sc.data[SC_KYOUGAKU]) {
+ if ((flag & PCUNEQUIPITEM_FORCE) == 0 && sd->sc.count != 0 && sd->sc.data[SC_KYOUGAKU] != NULL) {
clif->unequipitemack(sd, n, 0, UIA_FAIL);
return 0;
}
- if (battle_config.battle_log)
+ if (battle_config.battle_log != 0)
ShowInfo("unequip %d %x:%x\n", n, (unsigned int)(pc->equippoint(sd, n)), sd->status.inventory[n].equip);
- if (sd->status.inventory[n].equip == 0) { //Nothing to unequip
+ if (sd->status.inventory[n].equip == 0) { // Nothing to unequip.
clif->unequipitemack(sd, n, 0, UIA_FAIL);
return 0;
}
- for (i = 0; i < EQI_MAX; i++) {
- if (sd->status.inventory[n].equip & pc->equip_pos[i])
+ for (int i = 0; i < EQI_MAX; i++) {
+ if ((sd->status.inventory[n].equip & pc->equip_pos[i]) != 0)
sd->equip_index[i] = -1;
}
- pos = sd->status.inventory[n].equip;
- pc->unequipitem_pos(sd, n, pos);
+ int pos = sd->status.inventory[n].equip;
+ pc->unequipitem_pos(sd, n, pos);
clif->unequipitemack(sd, n, pos, UIA_SUCCESS);
- if ((pos & EQP_ARMS) &&
- sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST && (sd->sc.data[SC_TK_SEVENWIND] == NULL || sd->sc.data[SC_ASPERSIO] != NULL)) //Check for seven wind (but not level seven!)
+ if ((pos & EQP_ARMS) != 0 && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST
+ && (sd->sc.data[SC_TK_SEVENWIND] == NULL || sd->sc.data[SC_ASPERSIO] != NULL)) { // Check for Seven Wind. (But not level seven!)
skill->enchant_elemental_end(&sd->bl, -1);
+ }
- if (pos & EQP_ARMOR) {
- // On Armor Change...
+ if ((pos & EQP_ARMOR) != 0) {
status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER);
status_change_end(&sd->bl, SC_ARMOR_RESIST, INVALID_TIMER);
}
#ifdef RENEWAL
- if (battle->bc->bow_unequip_arrow && pos&EQP_ARMS && sd->equip_index[EQI_AMMO] > 0)
+ if (battle->bc->bow_unequip_arrow != 0 && (pos & EQP_ARMS) != 0 && sd->equip_index[EQI_AMMO] > 0)
pc->unequipitem(sd, sd->equip_index[EQI_AMMO], PCUNEQUIPITEM_FORCE);
#endif
- if( sd->state.autobonus&pos )
- sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish]
+ if ((sd->state.autobonus & pos) != 0) // Check for activated autobonus. [Inkfish]
+ sd->state.autobonus &= ~sd->status.inventory[n].equip;
sd->status.inventory[n].equip = 0;
- iflag = sd->npc_item_flag;
- /* check for combos (MUST be before status_calc_pc) */
+ bool status_calc = false;
+ int iflag = sd->npc_item_flag;
+
+ // Check for combos. (MUST be done before status->calc_pc()!)
if (sd->inventory_data[n] != NULL) {
- if (sd->inventory_data[n]->combos_count) {
- if (pc->removecombo(sd, sd->inventory_data[n]))
- status_calc = true;
- }
- if (itemdb_isspecial(sd->status.inventory[n].card[0]) == false) {
- for (i = 0; i < sd->inventory_data[n]->slot; i++) {
- struct item_data *data;
+ if (sd->inventory_data[n]->combos_count != 0 && pc->removecombo(sd, sd->inventory_data[n]) != 0)
+ status_calc = true;
+
+ if (!itemdb_isspecial(sd->status.inventory[n].card[0])) {
+ for (int i = 0; i < sd->inventory_data[n]->slot; i++) {
if (sd->status.inventory[n].card[i] == 0)
continue;
- if ((data = itemdb->exists(sd->status.inventory[n].card[i])) != NULL) {
- if (data->combos_count) {
- if (pc->removecombo(sd, data))
- status_calc = true;
- }
- }
+
+ struct item_data *data = itemdb->exists(sd->status.inventory[n].card[i]);
+
+ if (data != NULL && data->combos_count != 0 && pc->removecombo(sd, data) != 0)
+ status_calc = true;
}
}
- /* Item Options checking */
- for (i = 0; i < MAX_ITEM_OPTIONS; i++) {
- struct itemdb_option *ito = NULL;
- int16 item_option = sd->status.inventory[n].option[i].index;
- if (item_option <= 0)
+ // Check item options.
+ for (int i = 0; i < MAX_ITEM_OPTIONS; i++) {
+ if (sd->status.inventory[n].option[i].index <= 0)
continue;
- if ((ito = itemdb->option_exists(sd->status.inventory[n].option[i].index)) == NULL)
+
+ if (itemdb->option_exists(sd->status.inventory[n].option[i].index) == NULL)
continue;
status_calc = true;
}
}
- if (flag & PCUNEQUIPITEM_RECALC || status_calc) {
+ if ((flag & PCUNEQUIPITEM_RECALC) != 0 || status_calc) {
pc->checkallowskill(sd);
status_calc_pc(sd, SCO_NONE);
}
- if (sd->sc.data[SC_CRUCIS] && battle->check_undead(sd->battle_status.race, sd->battle_status.def_ele) == false)
+ if (sd->sc.data[SC_CRUCIS] != NULL && !battle->check_undead(sd->battle_status.race, sd->battle_status.def_ele))
status_change_end(&sd->bl, SC_CRUCIS, INVALID_TIMER);
- //OnUnEquip script [Skotlex]
+ // Execute unequip script. [Skotlex]
if (sd->inventory_data[n] != NULL) {
- if (sd->inventory_data[n]->unequip_script != NULL) {
- if (battle_config.unequip_restricted_equipment & 1) {
- ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, i, map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].nameid);
- if (i == map->list[sd->bl.m].zone->disabled_items_count)
- script->run_item_unequip_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id);
- }
- else
- script->run_item_unequip_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id);
+ struct item_data *equip_data = sd->inventory_data[n];
+ struct map_zone_data *zone = map->list[sd->bl.m].zone;
+ int dis_items_cnt = zone->disabled_items_count;
+
+ if (equip_data->unequip_script != NULL) {
+ int idx;
+
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == equip_data->nameid);
+
+ if (idx == dis_items_cnt)
+ script->run_item_unequip_script(sd, equip_data, npc->fake_nd->bl.id);
}
- if (itemdb_isspecial(sd->status.inventory[n].card[0]) == false) {
- for (i = 0; i < sd->inventory_data[n]->slot; i++) {
- struct item_data *data = NULL;
- if (sd->status.inventory[n].card[i] == 0)
+
+ struct item *equip = &sd->status.inventory[n];
+
+ if (!itemdb_isspecial(equip->card[0])) {
+ for (int slot = 0; slot < equip_data->slot; slot++) {
+ if (equip->card[slot] == 0)
continue;
- if ((data = itemdb->exists(sd->status.inventory[n].card[i])) != NULL) {
- if (data->unequip_script) {
- if (battle_config.unequip_restricted_equipment & 2) {
- int j;
- ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, j, map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[n].card[i]);
- if (j == map->list[sd->bl.m].zone->disabled_items_count)
- script->run_item_unequip_script(sd, data, npc->fake_nd->bl.id);
- } else {
- script->run_item_unequip_script(sd, data, npc->fake_nd->bl.id);
- }
- }
- }
+ struct item_data *card_data = itemdb->exists(equip->card[slot]);
+
+ if (card_data != NULL && card_data->unequip_script != NULL) {
+ int idx;
+ ARR_FIND(0, dis_items_cnt, idx, zone->disabled_items[idx] == card_data->nameid);
+
+ if (idx == dis_items_cnt)
+ script->run_item_unequip_script(sd, card_data, npc->fake_nd->bl.id);
+ }
}
}
}
@@ -12682,7 +12811,7 @@ void pc_defaults(void)
pc->unequipitem_pos = pc_unequipitem_pos;
pc->checkitem = pc_checkitem;
pc->useitem = pc_useitem;
- pc->itemskill_clear = pc_itemskill_clear;
+ pc->autocast_clear = pc_autocast_clear;
pc->skillatk_bonus = pc_skillatk_bonus;
pc->skillheal_bonus = pc_skillheal_bonus;
diff --git a/src/map/pc.h b/src/map/pc.h
index 007c08f20..2699b7882 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -173,6 +173,17 @@ struct pc_combos {
int id; /* this combo id */
};
+/** Auto-cast related data. **/
+struct autocast_data {
+ enum autocast_type type; // The auto-cast type.
+ int skill_id; // The auto-cast skill ID.
+ int skill_lv; // The auto-cast skill level.
+ bool itemskill_conditions_checked; // Used by itemskill() script command, to prevent second check of conditions after target was selected.
+ bool itemskill_check_conditions; // Used by itemskill() script command, to check skill conditions and consume them.
+ bool itemskill_instant_cast; // Used by itemskill() script command, to cast skill instantaneously.
+ bool itemskill_cast_on_self; // Used by itemskill() script command, to forcefully cast skill on invoking character.
+};
+
struct map_session_data {
struct block_list bl;
struct unit_data ud;
@@ -181,6 +192,7 @@ struct map_session_data {
struct status_change sc;
struct regen_data regen;
struct regen_data_sub sregen, ssregen;
+ struct autocast_data autocast;
//NOTE: When deciding to add a flag to state or special_state, take into consideration that state is preserved in
//status_calc_pc, while special_state is recalculated in each call. [Skotlex]
struct {
@@ -194,8 +206,6 @@ struct map_session_data {
unsigned int rest : 1;
unsigned int storage_flag : 2; // @see enum storage_flag
unsigned int snovice_dead_flag : 1; //Explosion spirits on death: 0 off, 1 used.
- unsigned int abra_flag : 2; // Abracadabra bugfix by Aru
- unsigned int autocast : 1; // Autospell flag [Inkfish]
unsigned int autotrade : 2; //By Fantik
unsigned int showdelay :1;
unsigned int showexp :1;
@@ -240,10 +250,6 @@ struct map_session_data {
unsigned int refine_ui : 1;
unsigned int npc_unloaded : 1; ///< The player is talking with an unloaded NPCs (respawned tombstones)
unsigned int lapine_ui : 1;
- unsigned int itemskill_conditions_checked : 1; // Used by itemskill() script command, to prevent second check of conditions after target was selected.
- unsigned int itemskill_no_conditions : 1; // Used by itemskill() script command, to ignore skill conditions and don't consume them.
- unsigned int itemskill_no_casttime : 1; // Used by itemskill() script command, to cast skill instantaneously.
- unsigned int itemskill_castonself : 1; // Used by itemskill() script command, to forcefully cast skill on invoking character.
} state;
struct {
unsigned char no_weapon_damage, no_magic_damage, no_misc_damage;
@@ -298,7 +304,6 @@ struct map_session_data {
int followtimer; // [MouseJstr]
int followtarget;
time_t emotionlasttime; // to limit flood with emotion packets
- int skillitem,skillitemlv;
uint16 skill_id_old,skill_lv_old;
uint16 skill_id_dance,skill_lv_dance;
short cook_mastery; // range: [0,1999] [Inkfish]
@@ -648,15 +653,6 @@ END_ZEROED_BLOCK;
bool achievements_received;
// Title
VECTOR_DECL(int) title_ids;
-
- /*
- * itemskill_conditions_checked/itemskill_no_conditions/itemskill_no_casttime/itemskill_castonself abuse prevention.
- * If a skill, casted by itemskill() script command, is aborted while target selection,
- * the map server gets no notification where these states could be unset.
- * Thus we need this helper variables to prevent abusing these states for next skill cast.
- */
- int itemskill_id;
- int itemskill_lv;
};
#define EQP_WEAPON EQP_HAND_R
@@ -1035,7 +1031,7 @@ END_ZEROED_BLOCK; /* End */
void (*unequipitem_pos) (struct map_session_data *sd, int n, int pos);
int (*checkitem) (struct map_session_data *sd);
int (*useitem) (struct map_session_data *sd,int n);
- int (*itemskill_clear) (struct map_session_data *sd);
+ int (*autocast_clear) (struct map_session_data *sd);
int (*skillatk_bonus) (struct map_session_data *sd, uint16 skill_id);
int (*skillheal_bonus) (struct map_session_data *sd, uint16 skill_id);
diff --git a/src/map/pet.c b/src/map/pet.c
index f20de2650..620779765 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -60,62 +60,101 @@ struct pet_interface *pet;
#define MIN_PETTHINKTIME 100
+/**
+ * Gets a pet's hunger value, depending it's hunger level.
+ * This value is only used in clif_parse_LoadEndAck() when calling clif_pet_emotion().
+ *
+ * @param pd The pet.
+ * @return The pet's hunger value.
+ *
+ **/
static int pet_hungry_val(struct pet_data *pd)
{
nullpo_ret(pd);
- if(pd->pet.hungry > 90)
+ if (pd->pet.hungry > PET_HUNGER_SATISFIED)
return 4;
- else if(pd->pet.hungry > 75)
+ else if (pd->pet.hungry > PET_HUNGER_NEUTRAL)
return 3;
- else if(pd->pet.hungry > 25)
+ else if (pd->pet.hungry > PET_HUNGER_HUNGRY)
return 2;
- else if(pd->pet.hungry > 10)
+ else if (pd->pet.hungry > PET_HUNGER_VERY_HUNGRY)
return 1;
else
return 0;
}
-static void pet_set_intimate(struct pet_data *pd, int value)
+/**
+ * Sets a pet's hunger value.
+ *
+ * @param pd The pet.
+ * @param value The pet's new hunger value.
+ *
+ **/
+static void pet_set_hunger(struct pet_data *pd, int value)
{
- int intimate;
- struct map_session_data *sd;
+ nullpo_retv(pd);
+
+ pd->pet.hungry = cap_value(value, PET_HUNGER_STARVING, PET_HUNGER_STUFFED);
+}
+/**
+ * Sets a pet's intimacy value.
+ * Deletes the pet if its intimacy value reaches PET_INTIMACY_NONE (0).
+ *
+ * @param pd The pet.
+ * @param value The pet's new intimacy value.
+ *
+ **/
+static void pet_set_intimate(struct pet_data *pd, int value)
+{
nullpo_retv(pd);
- intimate = pd->pet.intimate;
- sd = pd->msd;
+ nullpo_retv(pd->msd);
+
+ pd->pet.intimate = cap_value(value, PET_INTIMACY_NONE, PET_INTIMACY_MAX);
- pd->pet.intimate = value;
+ struct map_session_data *sd = pd->msd;
- 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,SCO_NONE);
+ status_calc_pc(sd, SCO_NONE);
- /* Pet is lost, delete the egg */
- if (value <= 0) {
+ if (pd->pet.intimate == PET_INTIMACY_NONE) { /// Pet is lost. Delete the egg.
int i;
- ARR_FIND(0, sd->status.inventorySize, i, sd->status.inventory[i].card[0] == CARD0_PET &&
- pd->pet.pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2]));
+ ARR_FIND(0, sd->status.inventorySize, i, sd->status.inventory[i].card[0] == CARD0_PET
+ && pd->pet.pet_id == MakeDWord(sd->status.inventory[i].card[1],
+ sd->status.inventory[i].card[2]));
- if (i != sd->status.inventorySize) {
+ if (i != sd->status.inventorySize)
pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG);
- }
}
}
+/**
+ * Creates a pet egg.
+ *
+ * @param sd The character who tries to create the pet egg.
+ * @param item_id The pet egg's item ID.
+ * @return 0 on failure, 1 on success.
+ *
+ **/
static int pet_create_egg(struct map_session_data *sd, int item_id)
{
- int pet_id = pet->search_petDB_index(item_id, PET_EGG);
nullpo_ret(sd);
- if (pet_id < 0) return 0; //No pet egg here.
- if (!pc->inventoryblank(sd)) return 0; // Inventory full
+
+ int pet_id = pet->search_petDB_index(item_id, PET_EGG);
+
+ if (pet_id == INDEX_NOT_FOUND) // No pet egg here.
+ return 0;
+
+ if (pc->inventoryblank(sd) == 0) // Inventory full.
+ return 0;
+
sd->catch_target_class = pet->db[pet_id].class_;
- intif->create_pet(sd->status.account_id, sd->status.char_id,
- pet->db[pet_id].class_,
- mob->db(pet->db[pet_id].class_)->lv,
- pet->db[pet_id].EggID, 0,
- (short)pet->db[pet_id].intimate,
- 100, 0, 1, pet->db[pet_id].jname);
+ intif->create_pet(sd->status.account_id, sd->status.char_id, pet->db[pet_id].class_,
+ mob->db(pet->db[pet_id].class_)->lv, pet->db[pet_id].EggID, 0,
+ (short)pet->db[pet_id].intimate, PET_HUNGER_STUFFED,
+ 0, 1, pet->db[pet_id].jname);
+
return 1;
}
@@ -162,48 +201,42 @@ static int pet_attackskill(struct pet_data *pd, int target_id)
return 0;
}
+/**
+ * Checks if a pet can attack a target.
+ *
+ * @param sd The pet's master.
+ * @param bl The pet's target.
+ * @param type 0 - Support master when attacking. Not 0 - Support master when being attacked.
+ * @return 0 on failure, 1 on success.
+ *
+ **/
static int pet_target_check(struct map_session_data *sd, struct block_list *bl, int type)
{
- struct pet_data *pd;
- int rate;
-
nullpo_ret(sd);
- pd = sd->pd;
+ nullpo_ret(sd->pd);
+ nullpo_ret(bl);
+ Assert_ret(sd->pd->msd == NULL || sd->pd->msd->pd == sd->pd);
- Assert_ret(pd->msd == 0 || pd->msd->pd == pd);
+ struct pet_data *pd = sd->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))
- return 0;
+ if ((type == 0 && pd->petDB->attack_rate == 0) || (type != 0 && pd->petDB->defence_attack_rate == 0))
+ return 0; // If base rate is 0, there's nothing to do.
- if( pd->bl.m != bl->m
- || !check_distance_bl(&pd->bl, bl, pd->db->range2))
+ if (bl->type != BL_MOB || bl->prev == NULL || pd->pet.intimate < battle_config.pet_support_min_friendly
+ || pd->pet.hungry <= PET_HUNGER_STARVING || pd->pet.class_ == status->get_class(bl)
+ || pd->bl.m != bl->m || !check_distance_bl(&pd->bl, bl, pd->db->range2)
+ || status->check_skilluse(&pd->bl, bl, 0, 0) == 0) {
return 0;
+ }
- if (!status->check_skilluse(&pd->bl, bl, 0, 0))
- return 0;
+ int rate = ((type == 0) ? pd->petDB->attack_rate : pd->petDB->defence_attack_rate) * pd->rate_fix / 1000;
- if(!type) {
- rate = pd->petDB->attack_rate;
- rate = rate * pd->rate_fix/1000;
- if(pd->petDB->attack_rate > 0 && rate <= 0)
- rate = 1;
- } else {
- rate = pd->petDB->defence_attack_rate;
- rate = rate * pd->rate_fix/1000;
- if(pd->petDB->defence_attack_rate > 0 && rate <= 0)
- rate = 1;
- }
- if(rnd()%10000 < rate)
- {
- if(pd->target_id == 0 || rnd()%10000 < pd->petDB->change_target_rate)
- pd->target_id = bl->id;
- }
+ if (rnd() % 10000 < max(rate, 1) && (pd->target_id == 0 || rnd() % 10000 < pd->petDB->change_target_rate))
+ pd->target_id = bl->id;
return 0;
}
+
/*==========================================
* Pet SC Check [Skotlex]
*------------------------------------------*/
@@ -226,59 +259,72 @@ static int pet_sc_check(struct map_session_data *sd, int type)
return 0;
}
+/**
+ * Updates a pet's hunger value and timer and updates the pet's intimacy value if starving.
+ *
+ * @param tid The timer ID.
+ * @param tick The base amount of ticks to add to the pet's hunger timer. (The timer's current ticks when calling this fuction.)
+ * @param id The pet master's account ID.
+ * @param data Unused.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
static int pet_hungry(int tid, int64 tick, int id, intptr_t data)
{
- struct map_session_data *sd;
- struct pet_data *pd;
- int interval;
+ struct map_session_data *sd = map->id2sd(id);
- sd=map->id2sd(id);
- if(!sd)
+ if (sd == NULL || sd->status.pet_id == 0 || sd->pd == NULL)
return 1;
- if(!sd->status.pet_id || !sd->pd)
- return 1;
+ struct pet_data *pd = sd->pd;
- pd = sd->pd;
- if(pd->pet_hungry_timer != tid){
- ShowError("pet_hungry_timer %d != %d\n",pd->pet_hungry_timer,tid);
+ /**
+ * If HungerDelay is 0, there's nothing to do.
+ * Actually this shouldn't happen, since the timer wasn't added in pet_data_init(), but just to be sure...
+ *
+ **/
+ if (pd->petDB->hungry_delay == 0) {
+ pet->hungry_timer_delete(pd);
return 0;
}
+
+ if (pd->pet_hungry_timer != tid) {
+ ShowError("pet_hungry: pet_hungry_timer %d != %d\n", pd->pet_hungry_timer, tid);
+ return 1;
+ }
+
pd->pet_hungry_timer = INVALID_TIMER;
- if (pd->pet.intimate <= 0)
- return 1; //You lost the pet already, the rest is irrelevant.
+ if (pd->pet.intimate <= PET_INTIMACY_NONE)
+ return 1; // You lost the pet already, the rest is irrelevant.
+
+ pet->set_hunger(pd, pd->pet.hungry - pd->petDB->hunger_decrement);
- pd->pet.hungry--;
- /* Pet Autofeed */
- if (battle_config.feature_enable_pet_autofeed != 0) {
- if (pd->petDB->autofeed == 1 && pd->pet.autofeed == 1 && pd->pet.hungry <= 25) {
+ // Pet auto-feed.
+ if (battle_config.feature_enable_pet_autofeed == 1) {
+ if (pd->petDB->autofeed == 1 && pd->pet.autofeed == 1 && pd->pet.hungry <= PET_HUNGER_HUNGRY)
pet->food(sd, pd);
- }
}
- if( pd->pet.hungry < 0 )
- {
+ int interval = pd->petDB->hungry_delay;
+
+ if (pd->pet.hungry == PET_HUNGER_STARVING) {
pet_stop_attack(pd);
- pd->pet.hungry = 0;
- pet->set_intimate(pd, pd->pet.intimate - battle_config.pet_hungry_friendly_decrease);
- if( pd->pet.intimate <= 0 )
- {
- pd->pet.intimate = 0;
+ pet->set_intimate(pd, pd->pet.intimate - pd->petDB->starving_decrement);
+
+ if (pd->pet.intimate == PET_INTIMACY_NONE)
pd->status.speed = pd->db->status.speed;
- }
+
status_calc_pet(pd, SCO_NONE);
- clif->send_petdata(sd,pd,1,pd->pet.intimate);
+ clif->send_petdata(sd, pd, 1, pd->pet.intimate);
+
+ if (pd->petDB->starving_delay > 0)
+ interval = pd->petDB->starving_delay;
}
- clif->send_petdata(sd,pd,2,pd->pet.hungry);
- 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 = timer->add(tick+interval,pet->hungry,sd->bl.id,0);
+ clif->send_petdata(sd, pd, 2, pd->pet.hungry);
+ interval *= battle_config.pet_hungry_delay_rate / 100;
+ pd->pet_hungry_timer = timer->add(tick + max(interval, 1), pet->hungry, sd->bl.id, 0);
return 0;
}
@@ -315,21 +361,31 @@ static int pet_hungry_timer_delete(struct pet_data *pd)
return 1;
}
+/**
+ * Makes a pet start performing/dancing.
+ *
+ * @param sd Unused.
+ * @param pd The pet.
+ * @return 0 on failure, 1 on success.
+ *
+ **/
static int pet_performance(struct map_session_data *sd, struct pet_data *pd)
{
+ nullpo_ret(pd);
+
int val;
- nullpo_retr(1, pd);
- if (pd->pet.intimate > 900)
- val = (pd->petDB->s_perfor > 0)? 4:3;
- else if(pd->pet.intimate > 750) //TODO: this is way too high
+ if (pd->pet.intimate > PET_INTIMACY_LOYAL)
+ val = (pd->petDB->s_perfor > 0) ? 4 : 3;
+ else if (pd->pet.intimate > PET_INTIMACY_CORDIAL) //TODO: This is way too high.
val = 2;
else
val = 1;
- pet_stop_walking(pd,STOPWALKING_FLAG_NONE | (2000<<8)); // Stop walking for 2000ms
- clif->send_petdata(NULL, pd, 4, rnd()%val + 1);
- pet->lootitem_drop(pd,NULL);
+ pet_stop_walking(pd, STOPWALKING_FLAG_NONE | (2000 << 8)); // Stop walking for 2 seconds.
+ clif->send_petdata(NULL, pd, 4, rnd() % val + 1);
+ pet->lootitem_drop(pd, NULL);
+
return 1;
}
@@ -377,78 +433,80 @@ static int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
return 1;
}
+/**
+ * Initializes a pet.
+ *
+ * @param sd The pet's master.
+ * @param petinfo The pet's status data.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
static 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);
nullpo_retr(1, petinfo);
- Assert_retr(1, sd->status.pet_id == 0 || sd->pd == 0 || sd->pd->msd == sd);
+ Assert_retr(1, sd->status.pet_id == 0 || sd->pd == NULL || sd->pd->msd == sd);
- if(sd->status.account_id != petinfo->account_id || sd->status.char_id != petinfo->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 != petinfo->pet_id) {
- if (sd->status.pet_id) {
- //Wrong pet?? Set incubate to no and send it back for saving.
+ if (sd->status.pet_id != 0) { // Wrong pet? Set incubate to no and send it back for saving.
petinfo->incubate = 1;
- intif->save_petdata(sd->status.account_id,petinfo);
+ 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 = petinfo->pet_id;
+
+ sd->status.pet_id = petinfo->pet_id; // The pet_id value was lost? Odd... Restore it.
}
- i = pet->search_petDB_index(petinfo->class_,PET_CLASS);
- if(i < 0) {
+ int i = pet->search_petDB_index(petinfo->class_, PET_CLASS);
+
+ if (i == INDEX_NOT_FOUND) {
sd->status.pet_id = 0;
return 1;
}
+
+ struct pet_data *pd;
+
CREATE(pd, struct pet_data, 1);
- pd->bl.type = BL_PET;
- pd->bl.id = npc->get_new_npc_id();
+ memcpy(&pd->pet, petinfo, sizeof(struct s_pet));
sd->pd = pd;
-
pd->msd = sd;
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_);
+ pd->db = mob->db(pd->petDB->class_);
+ pd->bl.type = BL_PET;
+ pd->bl.id = npc->get_new_npc_id();
+ status->set_viewdata(&pd->bl, pd->petDB->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);
pd->bl.x = pd->ud.to_x;
pd->bl.y = pd->ud.to_y;
-
map->addiddb(&pd->bl);
- status_calc_pet(pd,SCO_FIRST);
-
+ status_calc_pet(pd, SCO_FIRST);
pd->last_thinktime = timer->gettick();
pd->state.skillbonus = 0;
- if( battle_config.pet_status_support )
- script->run_pet(pet->db[i].pet_script,0,sd->bl.id,0);
+ if (pd->petDB->pet_script != NULL && battle_config.pet_status_support == 1)
+ script->run_pet(pd->petDB->pet_script, 0, sd->bl.id, 0);
- if( pd->petDB ) {
- if( pd->petDB->equip_script )
- status_calc_pc(sd,SCO_NONE);
+ if (pd->petDB->equip_script != NULL)
+ 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;
+ pd->pet_hungry_timer = INVALID_TIMER;
+
+ if (pd->petDB->hungry_delay > 0) {
+ int interval = pd->petDB->hungry_delay * battle_config.pet_hungry_delay_rate / 100;
+ pd->pet_hungry_timer = timer->add(timer->gettick() + max(interval, 1), pet->hungry, sd->bl.id, 0);
}
- if( interval <= 0 )
- interval = 1;
- pd->pet_hungry_timer = timer->add(timer->gettick() + interval, pet->hungry, sd->bl.id, 0);
return 0;
}
@@ -563,57 +621,66 @@ static int pet_catch_process1(struct map_session_data *sd, int target_class)
return 0;
}
+/**
+ * Begins the actual process of catching a monster.
+ *
+ * @param sd The character who tries to catch the monster.
+ * @param target_id The monster ID of the pet, which the character tries to catch.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
static int pet_catch_process2(struct map_session_data *sd, int target_id)
{
- struct mob_data *md = NULL;
- struct block_list *bl = NULL;
- int i = 0, pet_catch_rate = 0;
-
nullpo_retr(1, sd);
- bl = map->id2bl(target_id); // TODO: Why does this not use map->id2md?
- md = BL_CAST(BL_MOB, bl);
- if (md == NULL || md->bl.prev == NULL) {
- // Invalid inputs/state, abort capture.
- clif->pet_roulette(sd,0);
+ struct mob_data *md = BL_CAST(BL_MOB, map->id2bl(target_id)); //TODO: Why does this not use map->id2md?
+
+ if (md == NULL || md->bl.prev == NULL) { // Invalid inputs/state, abort capture.
+ clif->pet_roulette(sd, 0);
sd->catch_target_class = -1;
sd->itemid = -1;
sd->itemindex = -1;
return 1;
}
- //FIXME: delete taming item here, if this was an item-invoked capture and the item was flagged as delay-consume [ultramage]
+ //FIXME: Delete taming item here, if this was an item-invoked capture and the item was flagged as delay-consume. [ultramage]
- 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))
+ // 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) == 0)
sd->catch_target_class = md->class_;
- if(i < 0 || sd->catch_target_class != md->class_) {
- clif->emotion(&md->bl, E_AG); //mob will do /ag if wrong lure is used on them.
- clif->pet_roulette(sd,0);
+
+ int i = pet->search_petDB_index(md->class_, PET_CLASS);
+
+ if (i == INDEX_NOT_FOUND || sd->catch_target_class != md->class_) {
+ clif->emotion(&md->bl, E_AG); // Mob will do /ag if wrong lure is used on it.
+ clif->pet_roulette(sd, 0);
sd->catch_target_class = -1;
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;
+ int pet_catch_rate;
+ int capture = pet->db[i].capture;
+ int mob_hp_perc = get_percentage(md->status.hp, md->status.max_hp);
+
+ if (battle_config.pet_catch_rate_official_formula == 1) {
+ pet_catch_rate = capture * (100 - mob_hp_perc) / 100 + capture;
+ } else {
+ int lvl_diff_mod = (sd->status.base_level - md->level) * 30;
+ int char_luk_mod = sd->battle_status.luk * 20;
+ pet_catch_rate = (capture + lvl_diff_mod + char_luk_mod) * (200 - mob_hp_perc) / 100;
+ }
- if(pet_catch_rate < 1) pet_catch_rate = 1;
- if(battle->bc->pet_catch_rate != 100)
- pet_catch_rate = (pet_catch_rate*battle->bc->pet_catch_rate)/100;
+ pet_catch_rate = cap_value(pet_catch_rate, 1, 10000) * battle_config.pet_catch_rate / 100;
- if(rnd()%10000 < pet_catch_rate)
- {
- unit->remove_map(&md->bl,CLR_OUTSIGHT,ALC_MARK);
+ if (rnd() % 10000 < pet_catch_rate) {
+ 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);
-
+ 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, PET_HUNGER_STUFFED, 0, 1, pet->db[i].jname);
achievement->validate_taming(sd, pet->db[i].class_);
- }
- else
- {
- clif->pet_roulette(sd,0);
+ } else {
+ clif->pet_roulette(sd, 0);
sd->catch_target_class = -1;
}
@@ -670,42 +737,52 @@ static bool pet_get_egg(int account_id, int pet_class, int pet_id)
return true;
}
+/**
+ * Performs selected pet menu option.
+ *
+ * @param sd The pet's master.
+ * @param menunum The selected menu option.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
static int pet_menu(struct map_session_data *sd, int menunum)
{
- struct item_data *egg_id;
- nullpo_ret(sd);
- if (sd->pd == NULL)
- return 1;
+ nullpo_retr(1, sd);
+ nullpo_retr(1, sd->pd);
- //You lost the pet already.
- if(!sd->status.pet_id || sd->pd->pet.intimate <= 0 || sd->pd->pet.incubate)
- return 1;
+ if (sd->status.pet_id == 0 || sd->pd->pet.intimate <= PET_INTIMACY_NONE || sd->pd->pet.incubate != 0)
+ return 1; // You lost the pet already.
+
+ struct item_data *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&ITR_NODROP) && !pc->inventoryblank(sd)) {
- clif->message(sd->fd, msg_sd(sd,451)); // You can't return your pet because your inventory is full.
+ if (egg_id != NULL) {
+ if ((egg_id->flag.trade_restriction & ITR_NODROP) != 0 && pc->inventoryblank(sd) == 0) {
+ clif->message(sd->fd, msg_sd(sd, 451)); // You can't return your pet because your inventory is full.
return 1;
}
}
- switch(menunum) {
- case 0:
- clif->send_petstatus(sd);
- break;
- case 1:
- pet->food(sd, sd->pd);
- break;
- case 2:
- pet->performance(sd, sd->pd);
- break;
- case 3:
- pet->return_egg(sd, sd->pd);
- break;
- case 4:
- pet->unequipitem(sd, sd->pd);
- break;
+ switch (menunum) {
+ case 0:
+ clif->send_petstatus(sd);
+ break;
+ case 1:
+ pet->food(sd, sd->pd);
+ break;
+ case 2:
+ pet->performance(sd, sd->pd);
+ break;
+ case 3:
+ pet->return_egg(sd, sd->pd);
+ break;
+ case 4:
+ pet->unequipitem(sd, sd->pd);
+ break;
+ default: ;
+ ShowError("pet_menu: Unexpected menu option: %d\n", menunum);
+ return 1;
}
+
return 0;
}
@@ -830,49 +907,56 @@ static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd)
return 0;
}
+/**
+ * Feeds a pet and updates its intimacy value.
+ *
+ * @param sd The pet's master.
+ * @param pd The pet.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
static int pet_food(struct map_session_data *sd, struct pet_data *pd)
{
- int i, food_id;
-
+ nullpo_retr(1, sd);
nullpo_retr(1, pd);
- food_id = pd->petDB->FoodID;
- i = pc->search_inventory(sd, food_id);
- if(i == INDEX_NOT_FOUND) {
- clif->pet_food(sd, food_id, 0);
+
+ int i = pc->search_inventory(sd, pd->petDB->FoodID);
+
+ if (i == INDEX_NOT_FOUND) {
+ clif->pet_food(sd, pd->petDB->FoodID, 0);
return 1;
}
+
pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME);
- 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
- 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 + add_intimate);
- }
- if (pd->pet.intimate <= 0) {
- pd->pet.intimate = 0;
+ int intimacy = 0;
+
+ if (pd->pet.hungry >= PET_HUNGER_STUFFED)
+ intimacy -= pd->petDB->r_full; // Decrease intimacy by OverFeedDecrement.
+ else if (pd->pet.hungry > PET_HUNGER_SATISFIED)
+ intimacy -= pd->petDB->r_full / 2; // Decrease intimacy by 50% of OverFeedDecrement.
+ else if (pd->pet.hungry > PET_HUNGER_NEUTRAL)
+ intimacy -= pd->petDB->r_full * 5 / 100; // Decrease intimacy by 5% of OverFeedDecrement.
+ else if (pd->pet.hungry > PET_HUNGER_HUNGRY)
+ intimacy += pd->petDB->r_hungry * 75 / 100; // Increase intimacy by 75% of FeedIncrement.
+ else if (pd->pet.hungry > PET_HUNGER_VERY_HUNGRY)
+ intimacy += pd->petDB->r_hungry; // Increase intimacy by FeedIncrement.
+ else
+ intimacy += pd->petDB->r_hungry / 2; // Increase intimacy by 50% of FeedIncrement.
+
+ intimacy *= battle_config.pet_friendly_rate / 100;
+ pet->set_intimate(pd, pd->pet.intimate + intimacy);
+
+ if (pd->pet.intimate == PET_INTIMACY_NONE) {
pet_stop_attack(pd);
pd->status.speed = pd->db->status.speed;
- } else if (pd->pet.intimate > 1000) {
- pd->pet.intimate = 1000;
}
- status_calc_pet(pd, SCO_NONE);
- pd->pet.hungry += pd->petDB->fullness;
- if( pd->pet.hungry > 100 )
- pd->pet.hungry = 100;
- clif->send_petdata(sd,pd,2,pd->pet.hungry);
- clif->send_petdata(sd,pd,1,pd->pet.intimate);
- clif->pet_food(sd,pd->petDB->FoodID,1);
+ status_calc_pet(pd, SCO_NONE);
+ pet->set_hunger(pd, pd->pet.hungry + pd->petDB->fullness);
+ clif->send_petdata(sd, pd, 2, pd->pet.hungry);
+ clif->send_petdata(sd, pd, 1, pd->pet.intimate);
+ clif->pet_food(sd, pd->petDB->FoodID, 1);
return 0;
}
@@ -891,7 +975,8 @@ static int pet_randomwalk(struct pet_data *pd, int64 tick)
int r=rnd();
int x=pd->bl.x+r%(d*2+1)-d;
int y=pd->bl.y+r/(d*2+1)%(d*2+1)-d;
- if(map->getcell (pd->bl.m, &pd->bl, x, y, CELL_CHKPASS) && unit->walktoxy(&pd->bl, x, y, 0)) {
+ if (map->getcell(pd->bl.m, &pd->bl, x, y, CELL_CHKPASS) != 0
+ && unit->walk_toxy(&pd->bl, x, y, 0) == 0) {
pd->move_fail_count=0;
break;
}
@@ -918,117 +1003,128 @@ static int pet_randomwalk(struct pet_data *pd, int64 tick)
return 0;
}
+/**
+ * Performs pet's AI actions. (Moving, attacking, etc.)
+ *
+ * @param pd The pet.
+ * @param sd The pet's master.
+ * @param tick Timestamp of last support.
+ * @return Always 0.
+ *
+ **/
static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick)
{
- struct block_list *target = NULL;
nullpo_ret(pd);
+ nullpo_ret(pd->bl.prev);
+ nullpo_ret(sd);
+ nullpo_ret(sd->bl.prev);
- if(pd->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL)
+ if (DIFF_TICK(tick, pd->last_thinktime) < MIN_PETTHINKTIME)
return 0;
- if(DIFF_TICK(tick,pd->last_thinktime) < MIN_PETTHINKTIME)
- return 0;
- pd->last_thinktime=tick;
+ pd->last_thinktime = tick;
- if(pd->ud.attacktimer != INVALID_TIMER || pd->ud.skilltimer != INVALID_TIMER || pd->bl.m != sd->bl.m)
+ if (pd->ud.attacktimer != INVALID_TIMER || pd->ud.skilltimer != INVALID_TIMER || pd->bl.m != sd->bl.m)
return 0;
- if(pd->ud.walktimer != INVALID_TIMER && pd->ud.walkpath.path_pos <= 2)
- return 0; //No thinking when you just started to walk.
+ if (pd->ud.walktimer != INVALID_TIMER && pd->ud.walkpath.path_pos <= 2)
+ return 0; // No thinking when you just started to walk.
- if(pd->pet.intimate <= 0) {
- //Pet should just... well, random walk.
- pet->randomwalk(pd,tick);
+ if (pd->pet.intimate <= PET_INTIMACY_NONE) {
+ pet->randomwalk(pd, tick); // Pet should just... well, random walk.
return 0;
}
- if (!check_distance_bl(&sd->bl, &pd->bl, pd->db->range3)) {
- //Master too far, chase.
- if(pd->target_id)
+ if (!check_distance_bl(&sd->bl, &pd->bl, pd->db->range3)) { // Master too far away. Chase him.
+ if (pd->target_id != 0)
pet->unlocktarget(pd);
- if(pd->ud.walktimer != INVALID_TIMER && pd->ud.target == sd->bl.id)
- return 0; //Already walking to him
+
+ 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)
- return 0; //Can't move yet.
- 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);
+ return 0; // Can't move yet.
+
+ pd->status.speed = max(sd->battle_status.speed / 2, MIN_WALK_SPEED);
+
+ if (unit->walktobl(&pd->bl, &sd->bl, 3, 0) == 0)
+ pet->randomwalk(pd, tick);
+
return 0;
}
- //Return speed to normal.
- if (pd->status.speed != pd->petDB->speed) {
+ if (pd->status.speed != pd->petDB->speed) { // Reset speed to normal.
if (pd->ud.walktimer != INVALID_TIMER)
- return 0; //Wait until the pet finishes walking back to master.
+ return 0; // Wait until the pet finishes walking back to master.
+
pd->status.speed = pd->petDB->speed;
- pd->ud.state.change_walk_target = pd->ud.state.speed_changed = 1;
+ pd->ud.state.speed_changed = 1;
+ pd->ud.state.change_walk_target = 1;
}
- if (pd->target_id) {
- 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)
- ) {
+ struct block_list *target = NULL;
+
+ if (pd->target_id != 0) {
+ target = map->id2bl(pd->target_id);
+
+ if (target == NULL || pd->bl.m != target->m || status->isdead(target) == 1
+ || !check_distance_bl(&pd->bl, target, pd->db->range3)) {
target = NULL;
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.
- map->foreachinrange(pet->ai_sub_hard_lootsearch,&pd->bl,
- pd->db->range2/2, BL_ITEM,pd,&target);
+ if (target == NULL && pd->loot != NULL && pd->msd != NULL && 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.
+ map->foreachinrange(pet->ai_sub_hard_lootsearch, &pd->bl, pd->db->range2 / 2, BL_ITEM, pd, &target);
}
- if (!target) {
- //Just walk around.
+ if (target == NULL) { // Just walk around.
if (check_distance_bl(&sd->bl, &pd->bl, 3))
- return 0; //Already next to master.
+ return 0; // Already next to master.
- 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
+ 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);
+
+ if (unit->walk_toxy(&pd->bl, pd->ud.to_x, pd->ud.to_y, 0) != 0)
+ pet->randomwalk(pd, tick);
return 0;
}
- if(pd->ud.target == target->id &&
- (pd->ud.attacktimer != INVALID_TIMER || pd->ud.walktimer != INVALID_TIMER))
- return 0; //Target already locked.
+ if (pd->ud.target == target->id && (pd->ud.attacktimer != INVALID_TIMER || pd->ud.walktimer != INVALID_TIMER))
+ return 0; // Target already locked.
+
+ if (target->type != BL_ITEM) { // Target is enemy. Chase or attack it.
+ if (!battle->check_range(&pd->bl, target, pd->status.rhw.range)) { // Chase enemy.
+ if (unit->walktobl(&pd->bl, target, pd->status.rhw.range, 2) == 0) // Enemy is unreachable.
+ pet->unlocktarget(pd);
- 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.
return 0;
}
- //Continuous attack.
- 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.
+
+ unit->attack(&pd->bl, pd->target_id, 1); // Start/continue attacking.
+ } else { // Target is item. Attempt looting.
+ if (!check_distance_bl(&pd->bl, target, 1)) { // Item is out of range.
+ if (unit->walktobl(&pd->bl, target, 1, 1) == 0) // Item is unreachable.
pet->unlocktarget(pd);
+
return 0;
- } else{
+ }
+
+ if (pd->loot->count < pd->loot->max) {
struct flooritem_data *fitem = BL_UCAST(BL_ITEM, 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;
- map->clearflooritem(target);
- }
- //Target is unlocked regardless of whether it was picked or not.
- pet->unlocktarget(pd);
+
+ 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;
+ map->clearflooritem(target);
}
+
+ pet->unlocktarget(pd); // Target is unlocked regardless of whether the item was picked or not.
}
+
return 0;
}
@@ -1142,45 +1238,54 @@ static int pet_lootitem_drop(struct pet_data *pd, struct map_session_data *sd)
return 1;
}
-/*==========================================
- * pet bonus giving skills [Valaris] / Rewritten by [Skotlex]
- *------------------------------------------*/
+/**
+ * Applies pet's stat bonuses to its master. (See petskillbonus() script command.)
+ *
+ * @param tid The timer ID
+ * @param tick The base amount of ticks to add to the pet's bonus timer. (The timer's current ticks when calling this fuction.)
+ * @param id The pet's master's account ID.
+ * @param data Unused.
+ * @return 1 on failure, 0 on success.
+ *
+ **/
static 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 duration = 0;
+ struct map_session_data *sd = map->id2sd(id);
- if(sd == NULL || sd->pd==NULL || sd->pd->bonus == NULL)
+ if (sd == NULL || sd->pd == NULL || sd->pd->bonus == NULL)
return 1;
- pd=sd->pd;
+ struct pet_data *pd = sd->pd;
- if(pd->bonus->timer != tid) {
- ShowError("pet_skill_bonus_timer %d != %d\n",pd->bonus->timer,tid);
+ if (pd->bonus->timer != tid) {
+ ShowError("pet_skill_bonus_timer %d != %d\n", pd->bonus->timer, tid);
pd->bonus->timer = INVALID_TIMER;
- return 0;
+ return 1;
}
- // determine the time for the next timer
- if (pd->state.skillbonus && pd->bonus->delay > 0) {
+ int bonus;
+ int duration;
+
+ // Determine the time for the next timer.
+ if (pd->state.skillbonus == 1 && pd->bonus->delay > 0) {
bonus = 0;
- duration = pd->bonus->delay*1000; // the duration until pet bonuses will be reactivated again
- } else if (pd->pet.intimate) {
+ duration = pd->bonus->delay * 1000; // The duration until pet bonuses will be reactivated again.
+ } else if (pd->pet.intimate > PET_INTIMACY_NONE) {
bonus = 1;
- duration = pd->bonus->duration*1000; // the duration for pet bonuses to be in effect
- } else { //Lost pet...
+ duration = pd->bonus->duration * 1000; // The duration for pet bonuses to be in effect.
+ } else { // Lost pet...
pd->bonus->timer = INVALID_TIMER;
- return 0;
+ return 1;
}
if (pd->state.skillbonus != bonus) {
pd->state.skillbonus = bonus;
status_calc_pc(sd, SCO_NONE);
}
- // wait for the next timer
- pd->bonus->timer=timer->add(tick+duration,pet->skill_bonus_timer,sd->bl.id,0);
+
+ // Wait for the next timer.
+ pd->bonus->timer = timer->add(tick + duration, pet->skill_bonus_timer, sd->bl.id, 0);
+
return 0;
}
@@ -1326,115 +1431,155 @@ static int pet_read_db_libconfig(const char *filename, bool ignore_missing)
return count;
}
+/**
+ * Reads a single pet from DB.
+ *
+ * @param it The libconfig settings block, which contains the pet's data.
+ * @param n The pet's index in pet->db[].
+ * @param source The pet DB's file name.
+ * @return 0 on failure, the pet's ID on success.
+ *
+ **/
static int pet_read_db_sub(struct config_setting_t *it, int n, const char *source)
{
- struct config_setting_t *t = NULL;
- struct item_data *data = NULL;
- const char *str = NULL;
- int i32 = 0;
-
nullpo_ret(it);
nullpo_ret(source);
Assert_ret(n >= 0 && n < MAX_PET_DB);
- if (!libconfig->setting_lookup_int(it, "Id", &i32)) {
+ int i32 = 0;
+
+ if (libconfig->setting_lookup_int(it, "Id", &i32) == CONFIG_FALSE) {
ShowWarning("pet_read_db_sub: Missing Id in \"%s\", entry #%d, skipping.\n", source, n);
return 0;
}
- pet->db[n].class_ = i32;
- if (!libconfig->setting_lookup_string(it, "SpriteName", &str) || !*str ) {
- ShowWarning("pet_read_db_sub: Missing SpriteName in pet %d of \"%s\", skipping.\n", pet->db[n].class_, source);
+ if (mob->db_checkid(i32) == 0) {
+ ShowWarning("pet_read_db_sub: Invalid Id in \"%s\", entry #%d, skipping.\n", source, n);
return 0;
}
- safestrncpy(pet->db[n].name, str, sizeof(pet->db[n].name));
- if (!libconfig->setting_lookup_string(it, "Name", &str) || !*str) {
- ShowWarning("pet_read_db_sub: Missing Name in pet %d of \"%s\", skipping.\n", pet->db[n].class_, source);
+ pet->db[n].class_ = i32;
+ safestrncpy(pet->db[n].name, mob->db(i32)->sprite, sizeof(pet->db[n].name));
+
+ const char *str;
+
+ if (libconfig->setting_lookup_string(it, "Name", &str) == CONFIG_FALSE || *str == '\0') {
+ ShowWarning("pet_read_db_sub: Missing Name in pet %d of \"%s\", skipping.\n",
+ pet->db[n].class_, source);
return 0;
}
+
safestrncpy(pet->db[n].jname, str, sizeof(pet->db[n].jname));
- if (libconfig->setting_lookup_string(it, "TamingItem", &str)) {
- if (!(data = itemdb->name2id(str))) {
- ShowWarning("pet_read_db_sub: Invalid item '%s' in pet %d of \"%s\", defaulting to 0.\n", str, pet->db[n].class_, source);
- } else {
- pet->db[n].itemID = data->nameid;
- }
+ if (libconfig->setting_lookup_string(it, "EggItem", &str) == CONFIG_FALSE || *str == '\0') {
+ ShowWarning("pet_read_db_sub: Missing EggItem in pet %d of \"%s\", skipping.\n",
+ pet->db[n].class_, source);
+ return 0;
}
- if (libconfig->setting_lookup_string(it, "EggItem", &str)) {
- if (!(data = itemdb->name2id(str))) {
- ShowWarning("pet_read_db_sub: Invalid item '%s' in pet %d of \"%s\", defaulting to 0.\n", str, pet->db[n].class_, source);
- } else {
- pet->db[n].EggID = data->nameid;
- }
+ struct item_data *data;
+
+ if ((data = itemdb->name2id(str)) == NULL) {
+ ShowWarning("pet_read_db_sub: Invalid EggItem '%s' in pet %d of \"%s\", skipping.\n",
+ str, pet->db[n].class_, source);
+ return 0;
}
- if (libconfig->setting_lookup_string(it, "AccessoryItem", &str)) {
- if (!(data = itemdb->name2id(str))) {
- ShowWarning("pet_read_db_sub: Invalid item '%s' in pet %d of \"%s\", defaulting to 0.\n", str, pet->db[n].class_, source);
- } else {
- pet->db[n].AcceID = data->nameid;
- }
+ pet->db[n].EggID = data->nameid;
+
+ if (libconfig->setting_lookup_string(it, "TamingItem", &str) == CONFIG_TRUE) {
+ if ((data = itemdb->name2id(str)) == NULL)
+ ShowWarning("pet_read_db_sub: Invalid TamingItem '%s' in pet %d of \"%s\", defaulting to 0.\n",
+ str, pet->db[n].class_, source);
+ else
+ pet->db[n].itemID = data->nameid;
}
- if (libconfig->setting_lookup_string(it, "FoodItem", &str)) {
- if (!(data = itemdb->name2id(str))) {
- ShowWarning("pet_read_db_sub: Invalid item '%s' in pet %d of \"%s\", defaulting to 0.\n", str, pet->db[n].class_, source);
- } else {
+ pet->db[n].FoodID = 537;
+
+ if (libconfig->setting_lookup_string(it, "FoodItem", &str) == CONFIG_TRUE) {
+ if ((data = itemdb->name2id(str)) == NULL)
+ ShowWarning("pet_read_db_sub: Invalid FoodItem '%s' in pet %d of \"%s\", defaulting to Pet_Food (ID=537).\n",
+ str, pet->db[n].class_, source);
+ else
pet->db[n].FoodID = data->nameid;
- }
}
- if (libconfig->setting_lookup_int(it, "FoodEffectiveness", &i32))
- pet->db[n].fullness = i32;
+ if (libconfig->setting_lookup_string(it, "AccessoryItem", &str) == CONFIG_TRUE) {
+ if ((data = itemdb->name2id(str)) == NULL)
+ ShowWarning("pet_read_db_sub: Invalid AccessoryItem '%s' in pet %d of \"%s\", defaulting to 0.\n",
+ str, pet->db[n].class_, source);
+ else
+ pet->db[n].AcceID = data->nameid;
+ }
- if (libconfig->setting_lookup_int(it, "HungerDelay", &i32))
- pet->db[n].hungry_delay = i32 * 1000;
+ int ret = libconfig->setting_lookup_int(it, "FoodEffectiveness", &i32);
+ pet->db[n].fullness = (ret == CONFIG_FALSE) ? 80 : cap_value(i32, 1, PET_HUNGER_STUFFED);
- if ((t = libconfig->setting_get_member(it, "Intimacy"))) {
- if (config_setting_is_group(t)) {
- pet->read_db_sub_intimacy(n, t);
- }
- }
- if (pet->db[n].r_hungry <= 0)
- pet->db[n].r_hungry = 1;
+ ret = libconfig->setting_lookup_int(it, "HungerDelay", &i32);
+ pet->db[n].hungry_delay = (ret == CONFIG_FALSE) ? 60000 : cap_value(1000 * i32, 0, INT_MAX);
- if (libconfig->setting_lookup_int(it, "CaptureRate", &i32))
- pet->db[n].capture = i32;
+ ret = libconfig->setting_lookup_int(it, "HungerDecrement", &i32);
+ pet->db[n].hunger_decrement = (ret == CONFIG_FALSE) ? 1 : cap_value(i32, PET_HUNGER_STARVING, PET_HUNGER_STUFFED - 1);
- if (libconfig->setting_lookup_int(it, "Speed", &i32))
- pet->db[n].speed = i32;
+ if (pet->db[n].hunger_decrement == PET_HUNGER_STARVING)
+ pet->db[n].hungry_delay = 0;
- if ((t = libconfig->setting_get_member(it, "SpecialPerformance")) && (i32 = libconfig->setting_get_bool(t)))
- pet->db[n].s_perfor = (char)i32;
+ /**
+ * Preventively set default intimacy values here, just in case that 'Intimacy' block is not defined,
+ * or pet_read_db_sub_intimacy() fails execution.
+ *
+ **/
+ pet->db[n].intimate = PET_INTIMACY_NEUTRAL;
+ pet->db[n].r_hungry = 10;
+ pet->db[n].r_full = 100;
+ pet->db[n].die = 20;
+ pet->db[n].starving_delay = min(20000, pet->db[n].hungry_delay);
+ pet->db[n].starving_decrement = 20;
- if ((t = libconfig->setting_get_member(it, "TalkWithEmotes")) && (i32 = libconfig->setting_get_bool(t)))
- pet->db[n].talk_convert_class = i32;
+ struct config_setting_t *t;
- if (libconfig->setting_lookup_int(it, "AttackRate", &i32))
- pet->db[n].attack_rate = i32;
+ if ((t = libconfig->setting_get_member(it, "Intimacy")) != NULL && config_setting_is_group(t))
+ pet->read_db_sub_intimacy(n, t);
- if (libconfig->setting_lookup_int(it, "DefendRate", &i32))
- pet->db[n].defence_attack_rate = i32;
+ ret = libconfig->setting_lookup_int(it, "CaptureRate", &i32);
+ pet->db[n].capture = (ret == CONFIG_FALSE) ? 1000 : cap_value(i32, 1, 10000);
- if (libconfig->setting_lookup_int(it, "ChangeTargetRate", &i32))
- pet->db[n].change_target_rate = i32;
+ ret = libconfig->setting_lookup_int(it, "Speed", &i32);
+ pet->db[n].speed = (ret == CONFIG_FALSE) ? DEFAULT_WALK_SPEED : cap_value(i32, MIN_WALK_SPEED, MAX_WALK_SPEED);
- // Pet Evolution
- if ((t = libconfig->setting_get_member(it, "Evolve")) && config_setting_is_group(t)) {
- pet->read_db_sub_evolution(t, n);
+ if ((t = libconfig->setting_get_member(it, "SpecialPerformance")) != NULL
+ && (i32 = libconfig->setting_get_bool(t)) != 0) {
+ pet->db[n].s_perfor = (char)i32;
}
- if ((t = libconfig->setting_get_member(it, "AutoFeed")) && (i32 = libconfig->setting_get_bool(t)))
+ if ((t = libconfig->setting_get_member(it, "TalkWithEmotes")) != NULL
+ && (i32 = libconfig->setting_get_bool(t)) != 0) {
+ pet->db[n].talk_convert_class = i32;
+ }
+
+ ret = libconfig->setting_lookup_int(it, "AttackRate", &i32);
+ pet->db[n].attack_rate = (ret == CONFIG_FALSE) ? 300 : cap_value(i32, 0, 10000);
+
+ ret = libconfig->setting_lookup_int(it, "DefendRate", &i32);
+ pet->db[n].defence_attack_rate = (ret == CONFIG_FALSE) ? 300 : cap_value(i32, 0, 10000);
+
+ ret = libconfig->setting_lookup_int(it, "ChangeTargetRate", &i32);
+ pet->db[n].change_target_rate = (ret == CONFIG_FALSE) ? 800 : cap_value(i32, 0, 10000);
+
+ if ((t = libconfig->setting_get_member(it, "AutoFeed")) != NULL && (i32 = libconfig->setting_get_bool(t)) != 0)
pet->db[n].autofeed = i32;
- if (libconfig->setting_lookup_string(it, "PetScript", &str))
- pet->db[n].pet_script = *str ? script->parse(str, source, -pet->db[n].class_, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ pet->db[n].pet_script = NULL;
+ if (libconfig->setting_lookup_string(it, "PetScript", &str) == CONFIG_TRUE && *str != '\0')
+ pet->db[n].pet_script = script->parse(str, source, -pet->db[n].class_, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL);
+
+ pet->db[n].equip_script = NULL;
+ if (libconfig->setting_lookup_string(it, "EquipScript", &str) == CONFIG_TRUE && *str != '\0')
+ pet->db[n].equip_script = script->parse(str, source, -pet->db[n].class_, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL);
- if (libconfig->setting_lookup_string(it, "EquipScript", &str))
- pet->db[n].equip_script = *str ? script->parse(str, source, -pet->db[n].class_, SCRIPT_IGNORE_EXTERNAL_BRACKETS, NULL) : NULL;
+ if ((t = libconfig->setting_get_member(it, "Evolve")) != NULL && config_setting_is_group(t))
+ pet->read_db_sub_evolution(t, n);
return pet->db[n].class_;
}
@@ -1514,24 +1659,41 @@ static void pet_read_db_sub_evolution(struct config_setting_t *t, int n)
}
}
+/**
+ * Reads a pet's intimacy data from DB.
+ *
+ * @param idx The pet's index in pet->db[].
+ * @param t The libconfig settings block, which contains the pet's intimacy data.
+ * @return false on failure, true on success.
+ *
+ **/
static bool pet_read_db_sub_intimacy(int idx, struct config_setting_t *t)
{
+ nullpo_retr(false, t);
+ Assert_retr(false, idx >= 0 && idx < MAX_PET_DB);
+
int i32 = 0;
- nullpo_retr(false, t);
- Assert_ret(idx >= 0 && idx < MAX_PET_DB);
+ if (libconfig->setting_lookup_int(t, "Initial", &i32) == CONFIG_TRUE)
+ pet->db[idx].intimate = cap_value(i32, PET_INTIMACY_AWKWARD, PET_INTIMACY_MAX);
+
+ if (libconfig->setting_lookup_int(t, "FeedIncrement", &i32) == CONFIG_TRUE)
+ pet->db[idx].r_hungry = cap_value(i32, PET_INTIMACY_AWKWARD, PET_INTIMACY_MAX);
+
+ if (libconfig->setting_lookup_int(t, "OverFeedDecrement", &i32) == CONFIG_TRUE)
+ pet->db[idx].r_full = cap_value(i32, PET_INTIMACY_NONE, PET_INTIMACY_MAX);
- if (libconfig->setting_lookup_int(t, "Initial", &i32))
- pet->db[idx].intimate = i32;
+ if (libconfig->setting_lookup_int(t, "OwnerDeathDecrement", &i32) == CONFIG_TRUE)
+ pet->db[idx].die = cap_value(i32, PET_INTIMACY_NONE, PET_INTIMACY_MAX);
- if (libconfig->setting_lookup_int(t, "FeedIncrement", &i32))
- pet->db[idx].r_hungry = i32;
+ if (libconfig->setting_lookup_int(t, "StarvingDelay", &i32) == CONFIG_TRUE)
+ pet->db[idx].starving_delay = cap_value(1000 * i32, 0, pet->db[idx].hungry_delay);
- if (libconfig->setting_lookup_int(t, "OverFeedDecrement", &i32))
- pet->db[idx].r_full = i32;
+ if (libconfig->setting_lookup_int(t, "StarvingDecrement", &i32) == CONFIG_TRUE)
+ pet->db[idx].starving_decrement = cap_value(i32, PET_INTIMACY_NONE, PET_INTIMACY_MAX);
- if (libconfig->setting_lookup_int(t, "OwnerDeathDecrement", &i32))
- pet->db[idx].die = i32;
+ if (pet->db[idx].starving_decrement == PET_INTIMACY_NONE)
+ pet->db[idx].starving_delay = 0;
return true;
}
@@ -1625,6 +1787,7 @@ void pet_defaults(void)
pet->final = do_final_pet;
pet->hungry_val = pet_hungry_val;
+ pet->set_hunger = pet_set_hunger;
pet->set_intimate = pet_set_intimate;
pet->create_egg = pet_create_egg;
pet->unlocktarget = pet_unlocktarget;
diff --git a/src/map/pet.h b/src/map/pet.h
index e0a5529a6..fa37e896a 100644
--- a/src/map/pet.h
+++ b/src/map/pet.h
@@ -57,6 +57,9 @@ struct s_pet_db {
int defence_attack_rate;
int change_target_rate;
int autofeed;
+ int hunger_decrement;
+ int starving_delay;
+ int starving_decrement;
struct script_code *equip_script;
struct script_code *pet_script;
@@ -143,6 +146,7 @@ struct pet_interface {
int (*final) (void);
/* */
int (*hungry_val) (struct pet_data *pd);
+ void (*set_hunger) (struct pet_data *pd, int value);
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);
diff --git a/src/map/script.c b/src/map/script.c
index c1eb2e8b7..3d5534a47 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -11001,31 +11001,29 @@ static BUILDIN(itemskill)
if (sd == NULL || sd->ud.skilltimer != INVALID_TIMER)
return true;
- sd->skillitem = script_isstringtype(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2);
- sd->skillitemlv = script_getnum(st, 3);
- sd->state.itemskill_conditions_checked = 0; // Skill casting items will check the conditions prior to the target selection in AEGIS. Thus we need a flag to prevent checking them twice.
+ pc->autocast_clear(sd);
+ sd->autocast.type = AUTOCAST_ITEM;
+ sd->autocast.skill_id = script_isstringtype(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2);
+ sd->autocast.skill_lv = script_getnum(st, 3);
int flag = script_hasdata(st, 4) ? script_getnum(st, 4) : ISF_NONE;
- sd->state.itemskill_no_conditions = ((flag & ISF_IGNORECONDITIONS) == ISF_IGNORECONDITIONS) ? 1 : 0; // Unset in pc_itemskill_clear().
+ sd->autocast.itemskill_check_conditions = ((flag & ISF_CHECKCONDITIONS) == ISF_CHECKCONDITIONS);
- if (sd->state.itemskill_no_conditions == 0) {
- if (skill->check_condition_castbegin(sd, sd->skillitem, sd->skillitemlv) == 0
- || skill->check_condition_castend(sd, sd->skillitem, sd->skillitemlv) == 0) {
+ if (sd->autocast.itemskill_check_conditions) {
+ if (skill->check_condition_castbegin(sd, sd->autocast.skill_id, sd->autocast.skill_lv) == 0
+ || skill->check_condition_castend(sd, sd->autocast.skill_id, sd->autocast.skill_lv) == 0) {
+ pc->autocast_clear(sd);
return true;
}
- sd->state.itemskill_conditions_checked = 1; // Unset in pc_itemskill_clear().
+ sd->autocast.itemskill_conditions_checked = true;
}
- sd->state.itemskill_no_casttime = ((flag & ISF_INSTANTCAST) == ISF_INSTANTCAST) ? 1 : 0; // Unset in pc_itemskill_clear().
- sd->state.itemskill_castonself = ((flag & ISF_CASTONSELF) == ISF_CASTONSELF) ? 1 : 0; // Unset in pc_itemskill_clear().
+ sd->autocast.itemskill_instant_cast = ((flag & ISF_INSTANTCAST) == ISF_INSTANTCAST);
+ sd->autocast.itemskill_cast_on_self = ((flag & ISF_CASTONSELF) == ISF_CASTONSELF);
- // itemskill_conditions_checked/itemskill_no_conditions/itemskill_no_casttime/itemskill_castonself abuse prevention. Unset in pc_itemskill_clear().
- sd->itemskill_id = sd->skillitem;
- sd->itemskill_lv = sd->skillitemlv;
-
- clif->item_skill(sd, sd->skillitem, sd->skillitemlv);
+ clif->item_skill(sd, sd->autocast.skill_id, sd->autocast.skill_lv);
return true;
}
@@ -14780,24 +14778,34 @@ static BUILDIN(getitemslots)
return true;
}
-// TODO: add matk here if needed
-
-/*==========================================
- * Returns some values of an item [Lupus]
- * Price, Weight, etc...
- *------------------------------------------*/
+/**
+ * Returns various information about an item.
+ *
+ * @code{.herc}
+ * getiteminfo(<item ID>, <type>);
+ * getiteminfo("<item name>", <type>);
+ * @endcode
+ *
+ **/
static BUILDIN(getiteminfo)
{
- int item_id = script_getnum(st, 2);
- int n = script_getnum(st, 3);
- struct item_data *it = itemdb->exists(item_id);
+ struct item_data *it;
+
+ if (script_isstringtype(st, 2)) { /// Item name.
+ const char *name = script_getstr(st, 2);
+ it = itemdb->search_name(name);
+ } else { /// Item ID.
+ it = itemdb->exists(script_getnum(st, 2));
+ }
if (it == NULL) {
script_pushint(st, -1);
return true;
}
- switch (n) {
+ int type = script_getnum(st, 3);
+
+ switch (type) {
case ITEMINFO_BUYPRICE:
script_pushint(st, it->value_buy);
break;
@@ -14909,16 +14917,24 @@ static BUILDIN(getiteminfo)
case ITEMINFO_STACK_AMOUNT:
script_pushint(st, it->stack.amount);
break;
- case ITEMINFO_STACK_FLAG:
- {
- int stack_flag = 0;
- if (it->stack.inventory != 0) stack_flag |= 1;
- if (it->stack.cart != 0) stack_flag |= 2;
- if (it->stack.storage != 0) stack_flag |= 4;
- if (it->stack.guildstorage != 0) stack_flag |= 8;
- script_pushint(st, stack_flag);
- }
+ case ITEMINFO_STACK_FLAG: {
+ int stack_flag = 0;
+
+ if (it->stack.inventory != 0)
+ stack_flag |= 1;
+
+ if (it->stack.cart != 0)
+ stack_flag |= 2;
+
+ if (it->stack.storage != 0)
+ stack_flag |= 4;
+
+ if (it->stack.guildstorage != 0)
+ stack_flag |= 8;
+
+ script_pushint(st, stack_flag);
break;
+ }
case ITEMINFO_ITEM_USAGE_FLAG:
script_pushint(st, it->item_usage.flag);
break;
@@ -14928,11 +14944,21 @@ static BUILDIN(getiteminfo)
case ITEMINFO_GM_LV_TRADE_OVERRIDE:
script_pushint(st, it->gm_lv_trade_override);
break;
+ case ITEMINFO_ID:
+ script_pushint(st, it->nameid);
+ break;
+ case ITEMINFO_AEGISNAME:
+ script_pushstrcopy(st, it->name);
+ break;
+ case ITEMINFO_NAME:
+ script_pushstrcopy(st, it->jname);
+ break;
default:
- ShowError("buildin_getiteminfo: Invalid item type %d.\n", n);
- script_pushint(st,-1);
+ ShowError("buildin_getiteminfo: Invalid item info type %d.\n", type);
+ script_pushint(st, -1);
return false;
}
+
return true;
}
@@ -16558,7 +16584,7 @@ static BUILDIN(npcwalkto)
} else {
status_calc_npc(nd, SCO_NONE);
}
- unit->walktoxy(&nd->bl, x, y, 0);
+ unit->walk_toxy(&nd->bl, x, y, 0);
}
return true;
@@ -19237,12 +19263,14 @@ static BUILDIN(pcblockmove)
static BUILDIN(setpcblock)
{
- struct map_session_data *sd = script->rid2sd(st);
+ struct map_session_data *sd = script_hasdata(st, 4) ? script->id2sd(st, script_getnum(st, 4)) : script->rid2sd(st);
enum pcblock_action_flag type = script_getnum(st, 2);
int state = (script_getnum(st, 3) > 0) ? 1 : 0;
- if (sd == NULL)
+ if (sd == NULL) {
+ script_pushint(st, 0);
return true;
+ }
if ((type & PCBLOCK_MOVE) != 0)
sd->block_action.move = state;
@@ -19271,12 +19299,13 @@ static BUILDIN(setpcblock)
if ((type & PCBLOCK_NPC) != 0)
sd->block_action.npc = state;
+ script_pushint(st, 1);
return true;
}
static BUILDIN(checkpcblock)
{
- struct map_session_data *sd = script->rid2sd(st);
+ struct map_session_data *sd = script_hasdata(st, 2) ? script->id2sd(st, script_getnum(st, 2)) : script->rid2sd(st);
int retval = PCBLOCK_NONE;
if (sd == NULL) {
@@ -19385,26 +19414,25 @@ static BUILDIN(getunittype)
/**
* Sets real-time unit data for a game object.
- * Setunitdata <GUID>,<DataType>,<Val1>{,<Val2>,<Val3>}
+ *
+ * @code{.herc}
+ * setunitdata <GUID>, <DataType>, <Val1>{, <Val2>, <Val3>}
+ * @endcode
+ *
* @param1 GUID GID of the unit.
* @param2 DataType Type of Data to be set for the unit.
* @param3 Value#1 Value to be passed as change in data.
* @param4 Value#2 Optional int value to be passed for certain data types.
* @param5 Value#3 Optional int value to be passed for certain data types.
* @return 1 on success, 0 on failure.
-
- Note: Please make this script command only modify ONE INTEGER value.
- If need to modify string type data, or having multiple arguments, please
- introduce a new script command.
- */
+ *
+ * Note: Please make this script command only modify ONE INTEGER value.
+ * If need to modify string type data, or having multiple arguments, please introduce a new script command.
+ *
+ **/
static BUILDIN(setunitdata)
{
- struct block_list *bl = NULL;
- const char *mapname = NULL, *udtype = NULL;
- int type = 0, val = 0, val2 = 0, val3 = 0;
- struct map_session_data *tsd = NULL;
-
- bl = map->id2bl(script_getnum(st, 2));
+ struct block_list *bl = map->id2bl(script_getnum(st, 2));
if (bl == NULL) {
ShowWarning("buildin_setunitdata: Error in finding object with given GID %d!\n", script_getnum(st, 2));
@@ -19412,22 +19440,26 @@ static BUILDIN(setunitdata)
return false;
}
- type = script_getnum(st, 3);
+ int type = script_getnum(st, 3);
- /* type bounds */
+ // Type bounds.
if (type < UDT_SIZE || type >= UDT_MAX) { // Note: UDT_TYPE is not valid here
ShowError("buildin_setunitdata: Invalid unit data type %d provided.\n", type);
script_pushint(st, 0);
return false;
}
- /* Mandatory Argument 3. Subject to deprecate. */
+ const char *mapname = NULL;
+ int val = 0;
+
+ // Mandatory argument #3. Subject to deprecate.
if (type == UDT_MAPIDXY) {
if (!script_isstringtype(st, 4)) {
ShowError("buildin_setunitdata: Invalid data type for argument #3.\n");
script_pushint(st, 0);
return false;
}
+
mapname = script_getstr(st, 4);
} else {
if (script_isstringtype(st, 4)) {
@@ -19435,68 +19467,87 @@ static BUILDIN(setunitdata)
script_pushint(st, 0);
return false;
}
+
val = script_getnum(st, 4);
}
-/* checks if value is out of bounds. */
+
+/****************************************************************************************************
+ * Define temporary macros. [BEGIN]
+ ****************************************************************************************************/
+
+// Checks if value is out of bounds.
#define setunitdata_check_bounds(arg, min, max) \
do { \
if (script_getnum(st, (arg)) < (min) || script_getnum(st, (arg)) > (max)) { \
- ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d, max: %d)\n", script_getnum(st, (arg)), (arg)-1, (min), (max)); \
+ ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d, max: %d)\n", \
+ script_getnum(st, (arg)), (arg) - 1, (min), (max)); \
script_pushint(st, 0); \
return false; \
} \
} while(0);
-/* checks if value is out of bounds. */
+
+// Checks if value is too low.
#define setunitdata_check_min(arg, min) \
do { \
if (script_getnum(st, (arg)) < (min)) { \
- ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d)\n", script_getnum(st, (arg)), (arg)-1, (min)); \
+ ShowError("buildin_setunitdata: Invalid value %d for argument #%d. (min: %d)\n", \
+ script_getnum(st, (arg)), (arg) - 1, (min)); \
script_pushint(st, 0); \
return false; \
} \
} while(0);
-/* checks if the argument doesn't exist, if required.
- * also checks if the argument exists, if not required. */
+
+// Checks if the argument doesn't exist, if required. Also checks if the argument exists, if not required.
#define setunitdata_assert_arg(arg, required) \
do { \
if (required && !script_hasdata(st, (arg))) { \
- ShowError("buildin_setunitdata: Type %d reqires argument #%d.\n", type, (arg)-1); \
+ ShowError("buildin_setunitdata: Type %d reqires argument #%d.\n", type, (arg) - 1); \
script_pushint(st, 0); \
return false; \
} else if (!required && script_hasdata(st, arg)) { \
- ShowError("buildin_setunitdata: Argument %d is not required for type %d.\n", (arg)-1, type); \
+ ShowError("buildin_setunitdata: Argument %d is not required for type %d.\n", (arg) - 1, type); \
script_pushint(st, 0); \
return false; \
} \
} while (0);
-/* checks if the data is an integer. */
+
+// Checks if the data is an integer.
#define setunitdata_check_int(arg) \
do { \
setunitdata_assert_arg((arg), true); \
if (script_isstringtype(st, (arg))) { \
- ShowError("buildin_setunitdata: Argument #%d expects integer, string given.\n", (arg)-1); \
+ ShowError("buildin_setunitdata: Argument #%d expects integer, string given.\n", (arg) - 1); \
script_pushint(st, 0); \
return false; \
} \
} while(0);
-/* checks if the data is a string. */
+
+// Checks if the data is a string.
#define setunitdata_check_string(arg) \
do { \
setunitdata_assert_arg((arg), true); \
if (script_isinttype(st, (arg))) { \
- ShowError("buildin_setunitdata: Argument #%d expects string, integer given.\n", (arg)-1); \
+ ShowError("buildin_setunitdata: Argument #%d expects string, integer given.\n", (arg) - 1); \
script_pushint(st, 0); \
return false; \
} \
} while(0);
+/****************************************************************************************************
+ * Define temporary macros. [END]
+ ****************************************************************************************************/
+
if (type != UDT_MAPIDXY && type != UDT_WALKTOXY) {
setunitdata_assert_arg(5, false);
setunitdata_assert_arg(6, false);
}
- switch (type)
- {
+ int val2 = 0;
+ int val3 = 0;
+
+ struct map_session_data *tsd = NULL;
+
+ switch (type) {
case UDT_SIZE:
setunitdata_check_bounds(4, SZ_SMALL, SZ_BIG);
break;
@@ -19522,30 +19573,36 @@ static BUILDIN(setunitdata)
case UDT_MASTERAID:
setunitdata_check_min(4, 0);
tsd = map->id2sd(val);
+
if (tsd == NULL) {
- ShowWarning("buildin_setunitdata: Account ID %d not found for master change!\n",val);
+ ShowWarning("buildin_setunitdata: Account ID %d not found for master change!\n", val);
script_pushint(st, 0);
return false;
}
+
break;
case UDT_MASTERCID:
setunitdata_check_min(4, 0);
tsd = map->charid2sd(val);
+
if (tsd == NULL) {
- ShowWarning("buildin_setunitdata: Character ID %d not found for master change!\n",val);
+ ShowWarning("buildin_setunitdata: Character ID %d not found for master change!\n", val);
script_pushint(st, 0);
return false;
}
+
break;
case UDT_MAPIDXY:
- if ((val = map->mapname2mapid(mapname)) == -1) {
+ if ((val = map->mapname2mapid(mapname)) == INDEX_NOT_FOUND) {
ShowError("buildin_setunitdata: Non-existent map %s provided.\n", mapname);
+ script_pushint(st, 0);
return false;
}
+
setunitdata_check_int(5);
setunitdata_check_int(6);
- setunitdata_check_bounds(5, 0, MAX_MAP_SIZE/2);
- setunitdata_check_bounds(6, 0, MAX_MAP_SIZE/2);
+ setunitdata_check_bounds(5, 0, MAX_MAP_SIZE / 2);
+ setunitdata_check_bounds(6, 0, MAX_MAP_SIZE / 2);
val2 = script_getnum(st, 5);
val3 = script_getnum(st, 6);
break;
@@ -19553,8 +19610,8 @@ static BUILDIN(setunitdata)
setunitdata_assert_arg(6, false);
setunitdata_check_int(5);
val2 = script_getnum(st, 5);
- setunitdata_check_bounds(4, 0, MAX_MAP_SIZE/2);
- setunitdata_check_bounds(5, 0, MAX_MAP_SIZE/2);
+ setunitdata_check_bounds(4, 0, MAX_MAP_SIZE / 2);
+ setunitdata_check_bounds(5, 0, MAX_MAP_SIZE / 2);
break;
case UDT_SPEED:
setunitdata_check_bounds(4, 0, MAX_WALK_SPEED);
@@ -19609,7 +19666,7 @@ static BUILDIN(setunitdata)
setunitdata_check_bounds(4, 0, SHRT_MAX);
break;
case UDT_HUNGER:
- setunitdata_check_bounds(4, 0, 99);
+ setunitdata_check_bounds(4, PET_HUNGER_STARVING, PET_HUNGER_STUFFED); // Pets and Homunculi have the same hunger value bounds.
break;
case UDT_RACE:
case UDT_ELETYPE:
@@ -19617,19 +19674,20 @@ static BUILDIN(setunitdata)
setunitdata_check_bounds(4, 0, CHAR_MAX);
break;
case UDT_GROUP:
- {
setunitdata_check_bounds(4, 0, INT_MAX);
+
struct unit_data *ud = unit->bl2ud2(bl);
+
if (ud == NULL) {
ShowError("buildin_setunitdata: ud is NULL!\n");
script_pushint(st, 0);
return false;
}
+
ud->groupId = script_getnum(st, 4);
clif->blname_ack(0, bl); // Send update to client.
script_pushint(st, 1);
return true;
- }
case UDT_DAMAGE_TAKEN_RATE:
setunitdata_check_bounds(4, 1, INT_MAX);
break;
@@ -19637,67 +19695,81 @@ static BUILDIN(setunitdata)
break;
}
+/****************************************************************************************************
+ * Undefine temporary macros. [BEGIN]
+ ****************************************************************************************************/
+
#undef setunitdata_check_bounds
+#undef setunitdata_check_min
#undef setunitdata_assert_arg
#undef setunitdata_check_int
#undef setunitdata_check_string
- /* Set the values */
+/****************************************************************************************************
+ * Undefine temporary macros. [END]
+ ****************************************************************************************************/
+
+ // Set the values.
switch (bl->type) {
- case BL_MOB:
- {
+ case BL_MOB: {
struct mob_data *md = BL_UCAST(BL_MOB, bl);
- nullpo_retr(false, md);
- switch (type)
- {
+ if (md == NULL) {
+ ShowError("buildin_setunitdata: Can't find monster for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ switch (type) {
case UDT_SIZE:
- md->status.size = (unsigned char) val;
+ md->status.size = (unsigned char)val;
break;
case UDT_LEVEL:
md->level = val;
- if (battle_config.show_mob_info & 4)
+
+ if ((battle_config.show_mob_info & 4) != 0)
clif->blname_ack(0, &md->bl);
+
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
clif->blname_ack(0, &md->bl);
break;
case UDT_MAXHP:
- md->status.max_hp = (unsigned int) val;
+ md->status.max_hp = (unsigned int)val;
clif->blname_ack(0, &md->bl);
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
- md->status.max_sp = (unsigned int) val;
+ md->status.max_sp = (unsigned int)val;
break;
case UDT_MASTERAID:
md->master_id = val;
break;
case UDT_MAPIDXY:
- unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT);
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
break;
case UDT_WALKTOXY:
- if (!unit->walktoxy(bl, (short) val, (short) val2, 2))
- unit->movepos(bl, (short) val, (short) val2, 0, 0);
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
break;
case UDT_SPEED:
- md->status.speed = (unsigned short) val;
+ md->status.speed = (unsigned short)val;
status->calc_misc(bl, &md->status, md->level);
break;
case UDT_MODE:
- md->status.mode = (enum e_mode) val;
+ md->status.mode = (enum e_mode)val;
break;
case UDT_AI:
- md->special_state.ai = (enum ai) val;
+ md->special_state.ai = (enum ai)val;
break;
case UDT_SCOPTION:
- md->sc.option = (unsigned int) val;
+ md->sc.option = (unsigned int)val;
break;
case UDT_SEX:
- md->vd->sex = (char) val;
+ md->vd->sex = (char)val;
break;
case UDT_CLASS:
mob->class_change(md, val);
@@ -19727,118 +19799,121 @@ static BUILDIN(setunitdata)
clif->changelook(bl, LOOK_WEAPON, val);
break;
case UDT_LOOKDIR:
- unit->setdir(bl, (uint8) val);
+ unit->set_dir(bl, (enum unit_dir)val);
break;
case UDT_CANMOVETICK:
md->ud.canmove_tick = val;
break;
case UDT_STR:
- md->status.str = (unsigned short) val;
+ md->status.str = (unsigned short)val;
status->calc_misc(bl, &md->status, md->level);
break;
case UDT_AGI:
- md->status.agi = (unsigned short) val;
+ md->status.agi = (unsigned short)val;
status->calc_misc(bl, &md->status, md->level);
break;
case UDT_VIT:
- md->status.vit = (unsigned short) val;
+ md->status.vit = (unsigned short)val;
status->calc_misc(bl, &md->status, md->level);
break;
case UDT_INT:
- md->status.int_ = (unsigned short) val;
+ md->status.int_ = (unsigned short)val;
status->calc_misc(bl, &md->status, md->level);
break;
case UDT_DEX:
- md->status.dex = (unsigned short) val;
+ md->status.dex = (unsigned short)val;
status->calc_misc(bl, &md->status, md->level);
break;
case UDT_LUK:
- md->status.luk = (unsigned short) val;
+ md->status.luk = (unsigned short)val;
status->calc_misc(bl, &md->status, md->level);
break;
case UDT_ATKRANGE:
- md->status.rhw.range = (unsigned short) val;
+ md->status.rhw.range = (unsigned short)val;
break;
case UDT_ATKMIN:
- md->status.rhw.atk = (unsigned short) val;
+ md->status.rhw.atk = (unsigned short)val;
break;
case UDT_ATKMAX:
- md->status.rhw.atk2 = (unsigned short) val;
+ md->status.rhw.atk2 = (unsigned short)val;
break;
case UDT_MATKMIN:
- md->status.matk_min = (unsigned short) val;
+ md->status.matk_min = (unsigned short)val;
break;
case UDT_MATKMAX:
- md->status.matk_max = (unsigned short) val;
+ md->status.matk_max = (unsigned short)val;
break;
case UDT_DEF:
- md->status.def = (defType) val;
+ md->status.def = (defType)val;
break;
case UDT_MDEF:
- md->status.mdef = (defType) val;
+ md->status.mdef = (defType)val;
break;
case UDT_HIT:
- md->status.hit = (short) val;
+ md->status.hit = (short)val;
break;
case UDT_FLEE:
- md->status.flee = (short) val;
+ md->status.flee = (short)val;
break;
case UDT_PDODGE:
- md->status.flee2 = (short) val;
+ md->status.flee2 = (short)val;
break;
case UDT_CRIT:
- md->status.cri = (short) val;
+ md->status.cri = (short)val;
break;
case UDT_RACE:
- md->status.race = (unsigned char) val;
+ md->status.race = (unsigned char)val;
break;
case UDT_ELETYPE:
- md->status.def_ele = (unsigned char) val;
+ md->status.def_ele = (unsigned char)val;
break;
case UDT_ELELEVEL:
- md->status.ele_lv = (unsigned char) val;
+ md->status.ele_lv = (unsigned char)val;
break;
case UDT_AMOTION:
- md->status.amotion = (unsigned short) val;
+ md->status.amotion = (unsigned short)val;
break;
case UDT_ADELAY:
- md->status.adelay = (unsigned short) val;
+ md->status.adelay = (unsigned short)val;
break;
case UDT_DMOTION:
- md->status.dmotion = (unsigned short) val;
+ md->status.dmotion = (unsigned short)val;
break;
case UDT_DAMAGE_TAKEN_RATE:
- md->dmg_taken_rate = (int) val;
+ md->dmg_taken_rate = (int)val;
break;
default:
- ShowWarning("buildin_setunitdata: Invalid data type '%s' for mob unit.\n", udtype);
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for mob unit.\n", type);
script_pushint(st, 0);
return false;
}
- }
+
break;
- case BL_HOM:
- {
+ }
+ case BL_HOM: {
struct homun_data *hd = BL_UCAST(BL_HOM, bl);
- nullpo_retr(false, hd);
+ if (hd == NULL) {
+ ShowError("buildin_setunitdata: Can't find Homunculus for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
- switch (type)
- {
+ switch (type) {
case UDT_SIZE:
- hd->base_status.size = (unsigned char) val;
+ hd->base_status.size = (unsigned char)val;
break;
case UDT_LEVEL:
- hd->homunculus.level = (short) val;
+ hd->homunculus.level = (short)val;
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXHP:
hd->homunculus.max_hp = val;
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
hd->homunculus.max_sp = val;
@@ -19848,634 +19923,645 @@ static BUILDIN(setunitdata)
hd->master = tsd;
break;
case UDT_MAPIDXY:
- unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT);
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
break;
case UDT_WALKTOXY:
- if (!unit->walktoxy(bl, (short) val, (short) val2, 2))
- unit->movepos(bl, (short) val, (short) val2, 0, 0);
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
break;
case UDT_SPEED:
- hd->base_status.speed = (unsigned short) val;
+ hd->base_status.speed = (unsigned short)val;
status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
break;
case UDT_LOOKDIR:
- unit->setdir(bl, (unsigned char) val);
+ unit->set_dir(bl, (enum unit_dir)val);
break;
case UDT_CANMOVETICK:
hd->ud.canmove_tick = val;
break;
case UDT_STR:
- hd->base_status.str = (unsigned short) val;
+ hd->base_status.str = (unsigned short)val;
status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
break;
case UDT_AGI:
- hd->base_status.agi = (unsigned short) val;
+ hd->base_status.agi = (unsigned short)val;
status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
break;
case UDT_VIT:
- hd->base_status.vit = (unsigned short) val;
+ hd->base_status.vit = (unsigned short)val;
status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
break;
case UDT_INT:
- hd->base_status.int_ = (unsigned short) val;
+ hd->base_status.int_ = (unsigned short)val;
status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
break;
case UDT_DEX:
- hd->base_status.dex = (unsigned short) val;
+ hd->base_status.dex = (unsigned short)val;
status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
break;
case UDT_LUK:
- hd->base_status.luk = (unsigned short) val;
+ hd->base_status.luk = (unsigned short)val;
status->calc_misc(bl, &hd->base_status, hd->homunculus.level);
break;
case UDT_ATKRANGE:
- hd->base_status.rhw.range = (unsigned short) val;
+ hd->base_status.rhw.range = (unsigned short)val;
break;
case UDT_ATKMIN:
- hd->base_status.rhw.atk = (unsigned short) val;
+ hd->base_status.rhw.atk = (unsigned short)val;
break;
case UDT_ATKMAX:
- hd->base_status.rhw.atk2 = (unsigned short) val;
+ hd->base_status.rhw.atk2 = (unsigned short)val;
break;
case UDT_MATKMIN:
- hd->base_status.matk_min = (unsigned short) val;
+ hd->base_status.matk_min = (unsigned short)val;
break;
case UDT_MATKMAX:
- hd->base_status.matk_max = (unsigned short) val;
+ hd->base_status.matk_max = (unsigned short)val;
break;
case UDT_DEF:
- hd->base_status.def = (defType) val;
+ hd->base_status.def = (defType)val;
break;
case UDT_MDEF:
- hd->base_status.mdef = (defType) val;
+ hd->base_status.mdef = (defType)val;
break;
case UDT_HIT:
- hd->base_status.hit = (short) val;
+ hd->base_status.hit = (short)val;
break;
case UDT_FLEE:
- hd->base_status.flee = (short) val;
+ hd->base_status.flee = (short)val;
break;
case UDT_PDODGE:
- hd->base_status.flee2 = (short) val;
+ hd->base_status.flee2 = (short)val;
break;
case UDT_CRIT:
- hd->base_status.cri = (short) val;
+ hd->base_status.cri = (short)val;
break;
case UDT_RACE:
- hd->base_status.race = (unsigned char) val;
+ hd->base_status.race = (unsigned char)val;
break;
case UDT_ELETYPE:
- hd->base_status.def_ele = (unsigned char) val;
+ hd->base_status.def_ele = (unsigned char)val;
break;
case UDT_ELELEVEL:
- hd->base_status.ele_lv = (unsigned char) val;
+ hd->base_status.ele_lv = (unsigned char)val;
break;
case UDT_AMOTION:
- hd->base_status.amotion = (unsigned short) val;
+ hd->base_status.amotion = (unsigned short)val;
break;
case UDT_ADELAY:
- hd->base_status.adelay = (unsigned short) val;
+ hd->base_status.adelay = (unsigned short)val;
break;
case UDT_DMOTION:
- hd->base_status.dmotion = (unsigned short) val;
+ hd->base_status.dmotion = (unsigned short)val;
break;
case UDT_HUNGER:
- hd->homunculus.hunger = (short) val;
+ hd->homunculus.hunger = (short)val;
clif->send_homdata(hd->master, SP_HUNGRY, hd->homunculus.hunger);
break;
case UDT_INTIMACY:
- homun->add_intimacy(hd, (unsigned int) val);
+ homun->add_intimacy(hd, (unsigned int)val);
clif->send_homdata(hd->master, SP_INTIMATE, hd->homunculus.intimacy / 100);
break;
default:
- ShowWarning("buildin_setunitdata: Invalid data type '%s' for homunculus unit.\n", udtype);
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for homunculus unit.\n", type);
script_pushint(st, 0);
return false;
}
- clif->send_homdata(hd->master, SP_ACK, 0); // send homun data
- }
+ clif->send_homdata(hd->master, SP_ACK, 0); // Send Homunculus data.
break;
- case BL_PET:
- {
+ }
+ case BL_PET: {
struct pet_data *pd = BL_UCAST(BL_PET, bl);
- nullpo_retr(false, pd);
+ if (pd == NULL) {
+ ShowError("buildin_setunitdata: Can't find pet for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
- switch (type)
- {
+ switch (type) {
case UDT_SIZE:
- pd->status.size = (unsigned char) val;
+ pd->status.size = (unsigned char)val;
break;
case UDT_LEVEL:
- pd->pet.level = (short) val;
+ pd->pet.level = (short)val;
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXHP:
- pd->status.max_hp = (unsigned int) val;
+ pd->status.max_hp = (unsigned int)val;
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
- pd->status.max_sp = (unsigned int) val;
+ pd->status.max_sp = (unsigned int)val;
break;
case UDT_MASTERAID:
pd->pet.account_id = val;
pd->msd = tsd;
break;
case UDT_MAPIDXY:
- unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT);
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
break;
case UDT_WALKTOXY:
- if (!unit->walktoxy(bl, (short) val, (short) val2, 2))
- unit->movepos(bl, (short) val, (short) val2, 0, 0);
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
break;
case UDT_SPEED:
- pd->status.speed = (unsigned short) val;
+ pd->status.speed = (unsigned short)val;
status->calc_misc(bl, &pd->status, pd->pet.level);
break;
case UDT_LOOKDIR:
- unit->setdir(bl, (unsigned char) val);
+ unit->set_dir(bl, (enum unit_dir)val);
break;
case UDT_CANMOVETICK:
pd->ud.canmove_tick = val;
break;
case UDT_STR:
- pd->status.str = (unsigned short) val;
+ pd->status.str = (unsigned short)val;
status->calc_misc(bl, &pd->status, pd->pet.level);
break;
case UDT_AGI:
- pd->status.agi = (unsigned short) val;
+ pd->status.agi = (unsigned short)val;
status->calc_misc(bl, &pd->status, pd->pet.level);
break;
case UDT_VIT:
- pd->status.vit = (unsigned short) val;
+ pd->status.vit = (unsigned short)val;
status->calc_misc(bl, &pd->status, pd->pet.level);
break;
case UDT_INT:
- pd->status.int_ = (unsigned short) val;
+ pd->status.int_ = (unsigned short)val;
status->calc_misc(bl, &pd->status, pd->pet.level);
break;
case UDT_DEX:
- pd->status.dex = (unsigned short) val;
+ pd->status.dex = (unsigned short)val;
status->calc_misc(bl, &pd->status, pd->pet.level);
break;
case UDT_LUK:
- pd->status.luk = (unsigned short) val;
+ pd->status.luk = (unsigned short)val;
status->calc_misc(bl, &pd->status, pd->pet.level);
break;
case UDT_ATKRANGE:
- pd->status.rhw.range = (unsigned short) val;
+ pd->status.rhw.range = (unsigned short)val;
break;
case UDT_ATKMIN:
- pd->status.rhw.atk = (unsigned short) val;
+ pd->status.rhw.atk = (unsigned short)val;
break;
case UDT_ATKMAX:
- pd->status.rhw.atk2 = (unsigned short) val;
+ pd->status.rhw.atk2 = (unsigned short)val;
break;
case UDT_MATKMIN:
- pd->status.matk_min = (unsigned short) val;
+ pd->status.matk_min = (unsigned short)val;
break;
case UDT_MATKMAX:
- pd->status.matk_max = (unsigned short) val;
+ pd->status.matk_max = (unsigned short)val;
break;
case UDT_DEF:
- pd->status.def = (defType) val;
+ pd->status.def = (defType)val;
break;
case UDT_MDEF:
- pd->status.mdef = (defType) val;
+ pd->status.mdef = (defType)val;
break;
case UDT_HIT:
- pd->status.hit = (short) val;
+ pd->status.hit = (short)val;
break;
case UDT_FLEE:
- pd->status.flee = (short) val;
+ pd->status.flee = (short)val;
break;
case UDT_PDODGE:
- pd->status.flee2 = (short) val;
+ pd->status.flee2 = (short)val;
break;
case UDT_CRIT:
- pd->status.cri = (short) val;
+ pd->status.cri = (short)val;
break;
case UDT_RACE:
- pd->status.race = (unsigned char) val;
+ pd->status.race = (unsigned char)val;
break;
case UDT_ELETYPE:
- pd->status.def_ele = (unsigned char) val;
+ pd->status.def_ele = (unsigned char)val;
break;
case UDT_ELELEVEL:
- pd->status.ele_lv = (unsigned char) val;
+ pd->status.ele_lv = (unsigned char)val;
break;
case UDT_AMOTION:
- pd->status.amotion = (unsigned short) val;
+ pd->status.amotion = (unsigned short)val;
break;
case UDT_ADELAY:
- pd->status.adelay = (unsigned short) val;
+ pd->status.adelay = (unsigned short)val;
break;
case UDT_DMOTION:
- pd->status.dmotion = (unsigned short) val;
+ pd->status.dmotion = (unsigned short)val;
break;
case UDT_INTIMACY:
pet->set_intimate(pd, val);
clif->send_petdata(pd->msd, pd, 1, pd->pet.intimate);
break;
case UDT_HUNGER:
- pd->pet.hungry = (short) val;
+ pet->set_hunger(pd, val);
break;
default:
- ShowWarning("buildin_setunitdata: Invalid data type '%s' for pet unit.\n", udtype);
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for pet unit.\n", type);
script_pushint(st, 0);
return false;
}
- clif->send_petstatus(pd->msd); // send pet data
- }
+
+ clif->send_petstatus(pd->msd); // Send pet data.
break;
- case BL_MER:
- {
+ }
+ case BL_MER: {
struct mercenary_data *mc = BL_UCAST(BL_MER, bl);
- nullpo_retr(false, mc);
+ if (mc == NULL) {
+ ShowError("buildin_setunitdata: Can't find mercenary for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
- switch (type)
- {
+ switch (type) {
case UDT_SIZE:
- mc->base_status.size = (unsigned char) val;
+ mc->base_status.size = (unsigned char)val;
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXHP:
- mc->base_status.max_hp = (unsigned int) val;
+ mc->base_status.max_hp = (unsigned int)val;
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
- mc->base_status.max_sp = (unsigned int) val;
+ mc->base_status.max_sp = (unsigned int)val;
break;
case UDT_MASTERCID:
mc->mercenary.char_id = val;
break;
case UDT_MAPIDXY:
- unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT);
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
break;
case UDT_WALKTOXY:
- if (!unit->walktoxy(bl, (short) val, (short) val2, 2))
- unit->movepos(bl, (short) val, (short) val2, 0, 0);
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
break;
case UDT_SPEED:
- mc->base_status.size = (unsigned char) val;
+ mc->base_status.size = (unsigned char)val;
status->calc_misc(bl, &mc->base_status, mc->db->lv);
break;
case UDT_LOOKDIR:
- unit->setdir(bl, (unsigned char) val);
+ unit->set_dir(bl, (enum unit_dir)val);
break;
case UDT_CANMOVETICK:
mc->ud.canmove_tick = val;
break;
case UDT_STR:
- mc->base_status.str = (unsigned short) val;
+ mc->base_status.str = (unsigned short)val;
status->calc_misc(bl, &mc->base_status, mc->db->lv);
break;
case UDT_AGI:
- mc->base_status.agi = (unsigned short) val;
+ mc->base_status.agi = (unsigned short)val;
status->calc_misc(bl, &mc->base_status, mc->db->lv);
break;
case UDT_VIT:
- mc->base_status.vit = (unsigned short) val;
+ mc->base_status.vit = (unsigned short)val;
status->calc_misc(bl, &mc->base_status, mc->db->lv);
break;
case UDT_INT:
- mc->base_status.int_ = (unsigned short) val;
+ mc->base_status.int_ = (unsigned short)val;
status->calc_misc(bl, &mc->base_status, mc->db->lv);
break;
case UDT_DEX:
- mc->base_status.dex = (unsigned short) val;
+ mc->base_status.dex = (unsigned short)val;
status->calc_misc(bl, &mc->base_status, mc->db->lv);
break;
case UDT_LUK:
- mc->base_status.luk = (unsigned short) val;
+ mc->base_status.luk = (unsigned short)val;
status->calc_misc(bl, &mc->base_status, mc->db->lv);
break;
case UDT_ATKRANGE:
- mc->base_status.rhw.range = (unsigned short) val;
+ mc->base_status.rhw.range = (unsigned short)val;
break;
case UDT_ATKMIN:
- mc->base_status.rhw.atk = (unsigned short) val;
+ mc->base_status.rhw.atk = (unsigned short)val;
break;
case UDT_ATKMAX:
- mc->base_status.rhw.atk2 = (unsigned short) val;
+ mc->base_status.rhw.atk2 = (unsigned short)val;
break;
case UDT_MATKMIN:
- mc->base_status.matk_min = (unsigned short) val;
+ mc->base_status.matk_min = (unsigned short)val;
break;
case UDT_MATKMAX:
- mc->base_status.matk_max = (unsigned short) val;
+ mc->base_status.matk_max = (unsigned short)val;
break;
case UDT_DEF:
- mc->base_status.def = (defType) val;
+ mc->base_status.def = (defType)val;
break;
case UDT_MDEF:
- mc->base_status.mdef = (defType) val;
+ mc->base_status.mdef = (defType)val;
break;
case UDT_HIT:
- mc->base_status.hit = (short) val;
+ mc->base_status.hit = (short)val;
break;
case UDT_FLEE:
- mc->base_status.flee = (short) val;
+ mc->base_status.flee = (short)val;
break;
case UDT_PDODGE:
- mc->base_status.flee2 = (short) val;
+ mc->base_status.flee2 = (short)val;
break;
case UDT_CRIT:
- mc->base_status.cri = (short) val;
+ mc->base_status.cri = (short)val;
break;
case UDT_RACE:
- mc->base_status.race = (unsigned char) val;
+ mc->base_status.race = (unsigned char)val;
break;
case UDT_ELETYPE:
- mc->base_status.def_ele = (unsigned char) val;
+ mc->base_status.def_ele = (unsigned char)val;
break;
case UDT_ELELEVEL:
- mc->base_status.ele_lv = (unsigned char) val;
+ mc->base_status.ele_lv = (unsigned char)val;
break;
case UDT_AMOTION:
- mc->base_status.amotion = (unsigned short) val;
+ mc->base_status.amotion = (unsigned short)val;
break;
case UDT_ADELAY:
- mc->base_status.adelay = (unsigned short) val;
+ mc->base_status.adelay = (unsigned short)val;
break;
case UDT_DMOTION:
- mc->base_status.dmotion = (unsigned short) val;
+ mc->base_status.dmotion = (unsigned short)val;
break;
case UDT_MERC_KILLCOUNT:
- mc->mercenary.kill_count = (unsigned int) val;
+ mc->mercenary.kill_count = (unsigned int)val;
break;
case UDT_LIFETIME:
- mc->mercenary.life_time = (unsigned int) val;
+ mc->mercenary.life_time = (unsigned int)val;
break;
default:
- ShowWarning("buildin_setunitdata: Invalid data type '%s' for mercenary unit.\n", udtype);
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for mercenary unit.\n", type);
script_pushint(st, 0);
return false;
}
+ // Send mercenary data.
clif->mercenary_info(map->charid2sd(mc->mercenary.char_id));
clif->mercenary_skillblock(map->charid2sd(mc->mercenary.char_id));
- }
break;
- case BL_ELEM:
- {
+ }
+ case BL_ELEM: {
struct elemental_data *ed = BL_UCAST(BL_ELEM, bl);
- nullpo_retr(false, ed);
+ if (ed == NULL) {
+ ShowError("buildin_setunitdata: Can't find Elemental for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
- switch (type)
- {
+ switch (type) {
case UDT_SIZE:
- ed->base_status.size = (unsigned char) val;
+ ed->base_status.size = (unsigned char)val;
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXHP:
- ed->base_status.max_hp = (unsigned int) val;
+ ed->base_status.max_hp = (unsigned int)val;
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
- ed->base_status.max_sp = (unsigned int) val;
+ ed->base_status.max_sp = (unsigned int)val;
break;
case UDT_MASTERCID:
ed->elemental.char_id = val;
break;
case UDT_MAPIDXY:
- unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT);
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
break;
case UDT_WALKTOXY:
- if (!unit->walktoxy(bl, (short) val, (short) val2, 2))
- unit->movepos(bl, (short) val, (short) val2, 0, 0);
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
break;
case UDT_SPEED:
- ed->base_status.speed = (unsigned short) val;
+ ed->base_status.speed = (unsigned short)val;
status->calc_misc(bl, &ed->base_status, ed->db->lv);
break;
case UDT_LOOKDIR:
- unit->setdir(bl, (unsigned char) val);
+ unit->set_dir(bl, (enum unit_dir)val);
break;
case UDT_CANMOVETICK:
ed->ud.canmove_tick = val;
break;
case UDT_STR:
- ed->base_status.str = (unsigned short) val;
+ ed->base_status.str = (unsigned short)val;
status->calc_misc(bl, &ed->base_status, ed->db->lv);
break;
case UDT_AGI:
- ed->base_status.agi = (unsigned short) val;
+ ed->base_status.agi = (unsigned short)val;
status->calc_misc(bl, &ed->base_status, ed->db->lv);
break;
case UDT_VIT:
- ed->base_status.vit = (unsigned short) val;
+ ed->base_status.vit = (unsigned short)val;
status->calc_misc(bl, &ed->base_status, ed->db->lv);
break;
case UDT_INT:
- ed->base_status.int_ = (unsigned short) val;
+ ed->base_status.int_ = (unsigned short)val;
status->calc_misc(bl, &ed->base_status, ed->db->lv);
break;
case UDT_DEX:
- ed->base_status.dex = (unsigned short) val;
+ ed->base_status.dex = (unsigned short)val;
status->calc_misc(bl, &ed->base_status, ed->db->lv);
break;
case UDT_LUK:
- ed->base_status.luk = (unsigned short) val;
+ ed->base_status.luk = (unsigned short)val;
status->calc_misc(bl, &ed->base_status, ed->db->lv);
break;
case UDT_ATKRANGE:
- ed->base_status.rhw.range = (unsigned short) val;
+ ed->base_status.rhw.range = (unsigned short)val;
break;
case UDT_ATKMIN:
- ed->base_status.rhw.atk = (unsigned short) val;
+ ed->base_status.rhw.atk = (unsigned short)val;
break;
case UDT_ATKMAX:
- ed->base_status.rhw.atk2 = (unsigned short) val;
+ ed->base_status.rhw.atk2 = (unsigned short)val;
break;
case UDT_MATKMIN:
- ed->base_status.matk_min = (unsigned short) val;
+ ed->base_status.matk_min = (unsigned short)val;
break;
case UDT_MATKMAX:
- ed->base_status.matk_max = (unsigned short) val;
+ ed->base_status.matk_max = (unsigned short)val;
break;
case UDT_DEF:
- ed->base_status.def = (defType) val;
+ ed->base_status.def = (defType)val;
break;
case UDT_MDEF:
- ed->base_status.mdef = (defType) val;
+ ed->base_status.mdef = (defType)val;
break;
case UDT_HIT:
- ed->base_status.hit = (short) val;
+ ed->base_status.hit = (short)val;
break;
case UDT_FLEE:
- ed->base_status.flee = (short) val;
+ ed->base_status.flee = (short)val;
break;
case UDT_PDODGE:
- ed->base_status.flee2 = (short) val;
+ ed->base_status.flee2 = (short)val;
break;
case UDT_CRIT:
- ed->base_status.cri = (short) val;
+ ed->base_status.cri = (short)val;
break;
case UDT_RACE:
- ed->base_status.race = (unsigned char) val;
+ ed->base_status.race = (unsigned char)val;
break;
case UDT_ELETYPE:
- ed->base_status.def_ele = (unsigned char) val;
+ ed->base_status.def_ele = (unsigned char)val;
break;
case UDT_ELELEVEL:
- ed->base_status.ele_lv = (unsigned char) val;
+ ed->base_status.ele_lv = (unsigned char)val;
break;
case UDT_AMOTION:
- ed->base_status.amotion = (unsigned short) val;
+ ed->base_status.amotion = (unsigned short)val;
break;
case UDT_ADELAY:
- ed->base_status.adelay = (unsigned short) val;
+ ed->base_status.adelay = (unsigned short)val;
break;
case UDT_DMOTION:
- ed->base_status.dmotion = (unsigned short) val;
+ ed->base_status.dmotion = (unsigned short)val;
break;
case UDT_LIFETIME:
ed->elemental.life_time = val;
break;
default:
- ShowWarning("buildin_setunitdata: Invalid data type '%s' for elemental unit.\n", udtype);
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for elemental unit.\n", type);
script_pushint(st, 0);
return false;
}
- clif->elemental_info(ed->master);
- }
+
+ clif->elemental_info(ed->master); // Send Elemental data.
break;
- case BL_NPC:
- {
+ }
+ case BL_NPC: {
struct npc_data *nd = BL_UCAST(BL_NPC, bl);
- nullpo_retr(false, nd);
+ if (nd == NULL) {
+ ShowError("buildin_setunitdata: Can't find NPC for GID %d!\n", script_getnum(st, 2));
+ script_pushint(st, 0);
+ return false;
+ }
- switch (type)
- {
+ switch (type) {
case UDT_SIZE:
- nd->status.size = (unsigned char) val;
+ nd->status.size = (unsigned char)val;
break;
case UDT_LEVEL:
- nd->level = (unsigned short) val;
+ nd->level = (unsigned short)val;
break;
case UDT_HP:
- status->set_hp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_hp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXHP:
- nd->status.max_hp = (unsigned int) val;
+ nd->status.max_hp = (unsigned int)val;
break;
case UDT_SP:
- status->set_sp(bl, (unsigned int) val, STATUS_HEAL_DEFAULT);
+ status->set_sp(bl, (unsigned int)val, STATUS_HEAL_DEFAULT);
break;
case UDT_MAXSP:
- nd->status.max_sp = (unsigned int) val;
+ nd->status.max_sp = (unsigned int)val;
break;
case UDT_MAPIDXY:
- unit->warp(bl, (short) val, (short) val2, (short) val3, CLR_TELEPORT);
+ unit->warp(bl, (short)val, (short)val2, (short)val3, CLR_TELEPORT);
break;
case UDT_WALKTOXY:
- if (!unit->walktoxy(bl, (short) val, (short) val2, 2))
- unit->movepos(bl, (short) val, (short) val2, 0, 0);
+ if (unit->walk_toxy(bl, (short)val, (short)val2, 2) != 0)
+ unit->movepos(bl, (short)val, (short)val2, 0, 0);
break;
case UDT_CLASS:
- npc->setclass(nd, (short) val);
+ npc->setclass(nd, (short)val);
break;
case UDT_SPEED:
- nd->speed = (short) val;
+ nd->speed = (short)val;
status->calc_misc(bl, &nd->status, nd->level);
break;
case UDT_LOOKDIR:
- unit->setdir(bl, (unsigned char) val);
+ unit->set_dir(bl, (enum unit_dir)val);
break;
case UDT_STR:
- nd->status.str = (unsigned short) val;
+ nd->status.str = (unsigned short)val;
status->calc_misc(bl, &nd->status, nd->level);
break;
case UDT_AGI:
- nd->status.agi = (unsigned short) val;
+ nd->status.agi = (unsigned short)val;
status->calc_misc(bl, &nd->status, nd->level);
break;
case UDT_VIT:
- nd->status.vit = (unsigned short) val;
+ nd->status.vit = (unsigned short)val;
status->calc_misc(bl, &nd->status, nd->level);
break;
case UDT_INT:
- nd->status.int_ = (unsigned short) val;
+ nd->status.int_ = (unsigned short)val;
status->calc_misc(bl, &nd->status, nd->level);
break;
case UDT_DEX:
- nd->status.dex = (unsigned short) val;
+ nd->status.dex = (unsigned short)val;
status->calc_misc(bl, &nd->status, nd->level);
break;
case UDT_LUK:
- nd->status.luk = (unsigned short) val;
+ nd->status.luk = (unsigned short)val;
status->calc_misc(bl, &nd->status, nd->level);
break;
case UDT_STATPOINT:
- nd->stat_point = (unsigned short) val;
+ nd->stat_point = (unsigned short)val;
break;
case UDT_ATKRANGE:
- nd->status.rhw.range = (unsigned short) val;
+ nd->status.rhw.range = (unsigned short)val;
break;
case UDT_ATKMIN:
- nd->status.rhw.atk = (unsigned short) val;
+ nd->status.rhw.atk = (unsigned short)val;
break;
case UDT_ATKMAX:
- nd->status.rhw.atk2 = (unsigned short) val;
+ nd->status.rhw.atk2 = (unsigned short)val;
break;
case UDT_MATKMIN:
- nd->status.matk_min = (unsigned short) val;
+ nd->status.matk_min = (unsigned short)val;
break;
case UDT_MATKMAX:
- nd->status.matk_max = (unsigned short) val;
+ nd->status.matk_max = (unsigned short)val;
break;
case UDT_DEF:
- nd->status.def = (defType) val;
+ nd->status.def = (defType)val;
break;
case UDT_MDEF:
- nd->status.mdef = (defType) val;
+ nd->status.mdef = (defType)val;
break;
case UDT_HIT:
- nd->status.hit = (short) val;
+ nd->status.hit = (short)val;
break;
case UDT_FLEE:
- nd->status.flee = (short) val;
+ nd->status.flee = (short)val;
break;
case UDT_PDODGE:
- nd->status.flee2 = (short) val;
+ nd->status.flee2 = (short)val;
break;
case UDT_CRIT:
- nd->status.cri = (short) val;
+ nd->status.cri = (short)val;
break;
case UDT_RACE:
- nd->status.race = (unsigned char) val;
+ nd->status.race = (unsigned char)val;
break;
case UDT_ELETYPE:
- nd->status.def_ele = (unsigned char) val;
+ nd->status.def_ele = (unsigned char)val;
break;
case UDT_ELELEVEL:
- nd->status.ele_lv = (unsigned char) val;
+ nd->status.ele_lv = (unsigned char)val;
break;
case UDT_AMOTION:
- nd->status.amotion = (unsigned short) val;
+ nd->status.amotion = (unsigned short)val;
break;
case UDT_ADELAY:
- nd->status.adelay = (unsigned short) val;
+ nd->status.adelay = (unsigned short)val;
break;
case UDT_DMOTION:
- nd->status.dmotion = (unsigned short) val;
+ nd->status.dmotion = (unsigned short)val;
break;
case UDT_SEX:
nd->vd.sex = (char)val;
@@ -20512,19 +20598,21 @@ static BUILDIN(setunitdata)
clif->changelook(bl, LOOK_BODY2, val);
break;
default:
- ShowWarning("buildin_setunitdata: Invalid data type '%s' for NPC unit.\n", udtype);
+ ShowWarning("buildin_setunitdata: Invalid data type '%d' for NPC unit.\n", type);
script_pushint(st, 0);
return false;
}
- }
+
break;
+ }
default:
ShowError("buildin_setunitdata: Unknown object!\n");
script_pushint(st, 0);
return false;
- } // end of bl->type switch
+ } // End of bl->type switch.
script_pushint(st, 1);
+
return true;
}
@@ -21121,7 +21209,10 @@ static BUILDIN(unitwalk)
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.
+ if (unit->walk_toxy(bl, x, y, 0) == 0) // We'll use harder calculations.
+ script_pushint(st, 1);
+ else
+ script_pushint(st, 0);
}
else {
int target_id = script_getnum(st, 3);
@@ -21131,6 +21222,38 @@ static BUILDIN(unitwalk)
return true;
}
+/**
+ * Checks if a unit is walking.
+ *
+ * Returns 1 if unit is walking, 0 if unit is not walking and -1 on error.
+ *
+ * @code{.herc}
+ * unitiswalking({<GID>});
+ * @endcode
+ *
+ **/
+static BUILDIN(unitiswalking)
+{
+ int gid = script_hasdata(st, 2) ? script_getnum(st, 2) : st->rid;
+ struct block_list *bl = map->id2bl(gid);
+
+ if (bl == NULL) {
+ ShowWarning("buildin_unitiswalking: Error in finding object for GID %d!\n", gid);
+ script_pushint(st, -1);
+ return false;
+ }
+
+ if (unit->bl2ud(bl) == NULL) {
+ ShowWarning("buildin_unitiswalking: Error in finding unit_data for GID %d!\n", gid);
+ script_pushint(st, -1);
+ return false;
+ }
+
+ script_pushint(st, unit->is_walking(bl));
+
+ return true;
+}
+
/// Kills the unit
///
/// unitkill <unit_id>;
@@ -21364,7 +21487,10 @@ static BUILDIN(unitskilluseid)
} else {
status_calc_npc(nd, SCO_NONE);
}
+ } else if (bl->type == BL_PC) {
+ pc->autocast_clear(BL_UCAST(BL_PC, bl));
}
+
unit->skilluse_id(bl, target_id, skill_id, skill_lv);
}
@@ -21400,7 +21526,10 @@ static BUILDIN(unitskillusepos)
} else {
status_calc_npc(nd, SCO_NONE);
}
+ } else if (bl->type == BL_PC) {
+ pc->autocast_clear(BL_UCAST(BL_PC, bl));
}
+
unit->skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv);
}
@@ -23250,7 +23379,6 @@ static BUILDIN(progressbar_unit)
}
static BUILDIN(pushpc)
{
- uint8 dir;
int cells, dx, dy;
struct map_session_data* sd;
@@ -23259,14 +23387,14 @@ static BUILDIN(pushpc)
return true;
}
- dir = script_getnum(st,2);
- cells = script_getnum(st,3);
+ enum unit_dir dir = script_getnum(st, 2);
+ cells = script_getnum(st,3);
- if (dir > 7) {
+ if (dir >= UNIT_DIR_MAX) {
ShowWarning("buildin_pushpc: Invalid direction %d specified.\n", dir);
script->reportsrc(st);
- dir%= 8; // trim spin-over
+ dir %= UNIT_DIR_MAX; // trim spin-over
}
if(!cells)
@@ -23275,10 +23403,11 @@ static BUILDIN(pushpc)
}
else if(cells<0)
{// pushing backwards
- dir = (dir+4)%8; // turn around
- cells = -cells;
+ dir = unit_get_opposite_dir(dir);
+ cells = -cells;
}
+ Assert_retr(false, dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
dx = dirx[dir];
dy = diry[dir];
@@ -26970,7 +27099,7 @@ static void script_parse_builtin(void)
BUILDIN_DEF(setnpcdisplay,"sv??"),
BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine.
BUILDIN_DEF(strcmp,"ss"),
- BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info
+ BUILDIN_DEF(getiteminfo,"vi"), //[Lupus] returns Items Buy / sell Price, etc info
BUILDIN_DEF(setiteminfo,"iii"), //[Lupus] set Items Buy / sell Price, etc info
BUILDIN_DEF(getequipcardid,"ii"), //[Lupus] returns CARD ID or other info from CARD slot N of equipped item
BUILDIN_DEF(getequippedoptioninfo, "i"),
@@ -27020,8 +27149,8 @@ static void script_parse_builtin(void)
BUILDIN_DEF(pcfollow,"ii"),
BUILDIN_DEF(pcstopfollow,"i"),
BUILDIN_DEF_DEPRECATED(pcblockmove,"ii"), // Deprecated 2018-05-04
- BUILDIN_DEF(setpcblock, "ii"),
- BUILDIN_DEF(checkpcblock, ""),
+ BUILDIN_DEF(setpcblock, "ii?"),
+ BUILDIN_DEF(checkpcblock, "?"),
// <--- [zBuffer] List of player cont commands
// [zBuffer] List of mob control commands --->
BUILDIN_DEF(getunittype,"i"),
@@ -27033,6 +27162,7 @@ static void script_parse_builtin(void)
BUILDIN_DEF(getunittitle,"i"),
BUILDIN_DEF(setunittitle,"is"),
BUILDIN_DEF(unitwalk,"ii?"),
+ BUILDIN_DEF(unitiswalking, "?"),
BUILDIN_DEF(unitkill,"i"),
BUILDIN_DEF(unitwarp,"isii"),
BUILDIN_DEF(unitattack,"iv?"),
@@ -27615,6 +27745,9 @@ static void script_hardcoded_constants(void)
script->set_constant("ITEMINFO_ITEM_USAGE_FLAG", ITEMINFO_ITEM_USAGE_FLAG, false, false);
script->set_constant("ITEMINFO_ITEM_USAGE_OVERRIDE", ITEMINFO_ITEM_USAGE_OVERRIDE, false, false);
script->set_constant("ITEMINFO_GM_LV_TRADE_OVERRIDE", ITEMINFO_GM_LV_TRADE_OVERRIDE, false, false);
+ script->set_constant("ITEMINFO_ID", ITEMINFO_ID, false, false);
+ script->set_constant("ITEMINFO_AEGISNAME", ITEMINFO_AEGISNAME, false, false);
+ script->set_constant("ITEMINFO_NAME", ITEMINFO_NAME, false, false);
script->constdb_comment("getmercinfo options");
script->set_constant("MERCINFO_ID,", MERCINFO_ID, false, false);
@@ -27642,6 +27775,23 @@ static void script_hardcoded_constants(void)
script->set_constant("PETINFO_EVO_EGGID", PETINFO_EVO_EGGID, false, false);
script->set_constant("PETINFO_AUTOFEED", PETINFO_AUTOFEED, false, false);
+ script->constdb_comment("Pet hunger levels");
+ script->set_constant("PET_HUNGER_STARVING", PET_HUNGER_STARVING, false, false);
+ script->set_constant("PET_HUNGER_VERY_HUNGRY", PET_HUNGER_VERY_HUNGRY, false, false);
+ script->set_constant("PET_HUNGER_HUNGRY", PET_HUNGER_HUNGRY, false, false);
+ script->set_constant("PET_HUNGER_NEUTRAL", PET_HUNGER_NEUTRAL, false, false);
+ script->set_constant("PET_HUNGER_SATISFIED", PET_HUNGER_SATISFIED, false, false);
+ script->set_constant("PET_HUNGER_STUFFED", PET_HUNGER_STUFFED, false, false);
+
+ script->constdb_comment("Pet intimacy levels");
+ script->set_constant("PET_INTIMACY_NONE", PET_INTIMACY_NONE, false, false);
+ script->set_constant("PET_INTIMACY_AWKWARD", PET_INTIMACY_AWKWARD, false, false);
+ script->set_constant("PET_INTIMACY_SHY", PET_INTIMACY_SHY, false, false);
+ script->set_constant("PET_INTIMACY_NEUTRAL", PET_INTIMACY_NEUTRAL, false, false);
+ script->set_constant("PET_INTIMACY_CORDIAL", PET_INTIMACY_CORDIAL, false, false);
+ script->set_constant("PET_INTIMACY_LOYAL", PET_INTIMACY_LOYAL, false, false);
+ script->set_constant("PET_INTIMACY_MAX", PET_INTIMACY_MAX, false, false);
+
script->constdb_comment("monster skill states");
script->set_constant("MSS_ANY", MSS_ANY, false, false);
script->set_constant("MSS_IDLE", MSS_IDLE, false, false);
@@ -27858,10 +28008,17 @@ static void script_hardcoded_constants(void)
script->constdb_comment("itemskill option flags");
script->set_constant("ISF_NONE", ISF_NONE, false, false);
- script->set_constant("ISF_IGNORECONDITIONS", ISF_IGNORECONDITIONS, false, false);
+ script->set_constant("ISF_CHECKCONDITIONS", ISF_CHECKCONDITIONS, false, false);
script->set_constant("ISF_INSTANTCAST", ISF_INSTANTCAST, false, false);
script->set_constant("ISF_CASTONSELF", ISF_CASTONSELF, false, false);
+ script->constdb_comment("Item Bound Types");
+ script->set_constant("IBT_ANY", IBT_NONE, false, false); // for *checkbound()
+ script->set_constant("IBT_ACCOUNT", IBT_ACCOUNT, false, false);
+ script->set_constant("IBT_GUILD", IBT_GUILD, false, false);
+ script->set_constant("IBT_PARTY", IBT_PARTY, false, false);
+ script->set_constant("IBT_CHARACTER", IBT_CHARACTER, false, false);
+
script->constdb_comment("Renewal");
#ifdef RENEWAL
script->set_constant("RENEWAL", 1, false, false);
diff --git a/src/map/script.h b/src/map/script.h
index 857d22c61..511497a66 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -484,6 +484,9 @@ enum script_iteminfo_types {
ITEMINFO_ITEM_USAGE_FLAG,
ITEMINFO_ITEM_USAGE_OVERRIDE,
ITEMINFO_GM_LV_TRADE_OVERRIDE,
+ ITEMINFO_ID,
+ ITEMINFO_AEGISNAME,
+ ITEMINFO_NAME,
ITEMINFO_MAX
};
@@ -569,7 +572,7 @@ enum mado_type {
**/
enum itemskill_flag {
ISF_NONE = 0x00,
- ISF_IGNORECONDITIONS = 0x01, // Ignore skill conditions and don't consume them.
+ ISF_CHECKCONDITIONS = 0x01, // Check skill conditions and consume them.
ISF_INSTANTCAST = 0x02, // Cast skill instantaneously.
ISF_CASTONSELF = 0x04, // Forcefully cast skill on invoking character without showing the target selection cursor.
};
diff --git a/src/map/skill.c b/src/map/skill.c
index a8dbefbd7..3dccf7a9e 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -935,6 +935,8 @@ static int skill_calc_heal(struct block_list *src, struct block_list *target, ui
hp -= hp * 20/100;
if(sc->data[SC_HEALPLUS] && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN)
hp += hp * sc->data[SC_HEALPLUS]->val1/100; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish]
+ if (sc->data[SC_VITALIZE_POTION] != NULL && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN)
+ hp += hp * sc->data[SC_VITALIZE_POTION]->val3 / 100;
if(sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2)
hp += hp / 10;
if (sc->data[SC_VITALITYACTIVATION])
@@ -1010,14 +1012,14 @@ static int skillnotok(uint16 skill_id, struct map_session_data *sd)
if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL))
return 0; // can do any damn thing they want
- if( skill_id == AL_TELEPORT && sd->skillitem == skill_id && sd->skillitemlv > 2 )
- return 0; // Teleport lv 3 bypasses this check.[Inkfish]
+ if (skill_id == AL_TELEPORT && sd->autocast.type == AUTOCAST_ITEM && sd->autocast.skill_lv > 2)
+ return 0; // Teleport level 3 and higher bypasses this check if cast by itemskill() script commands.
// Epoque:
// This code will compare the player's attack motion value which is influenced by ASPD before
// 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 &&
+ if (sd->autocast.type == AUTOCAST_NONE && sd->canskill_tick != 0 &&
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;
@@ -1032,7 +1034,7 @@ static int skillnotok(uint16 skill_id, struct map_session_data *sd)
* It has been confirmed on a official server (thanks to Yommy) that item-cast skills bypass all the restrictions below
* Also, without this check, an exploit where an item casting + healing (or any other kind buff) isn't deleted after used on a restricted map
**/
- if( sd->skillitem == skill_id )
+ if (sd->autocast.type == AUTOCAST_ITEM)
return 0;
if( sd->sc.data[SC_ALL_RIDING] )
@@ -1177,10 +1179,34 @@ static int skillnotok_mercenary(uint16 skill_id, struct mercenary_data *md)
return skill->not_ok(skill_id, md->master);
}
+/**
+ * Validates the plausibility of auto-cast related data and calls pc_autocast_clear() if necessary.
+ *
+ * @param sd The character who cast the skill.
+ * @param skill_id The cast skill's ID.
+ * @param skill_lv The cast skill's level. (clif_parse_UseSkillMap() passes 0.)
+ *
+ **/
+static void skill_validate_autocast_data(struct map_session_data *sd, int skill_id, int skill_lv)
+{
+ nullpo_retv(sd);
+
+ // Determine if called by clif_parse_UseSkillMap().
+ bool use_skill_map = (skill_lv == 0 && (skill_id == AL_WARP || skill_id == AL_TELEPORT));
+
+ if (sd->autocast.type == AUTOCAST_NONE)
+ pc->autocast_clear(sd); // No auto-cast type set. Preventively unset all auto-cast related data.
+ else if (sd->autocast.type == AUTOCAST_TEMP)
+ pc->autocast_clear(sd); // AUTOCAST_TEMP should have been unset straight after usage.
+ else if (sd->autocast.skill_id == 0 || skill_id == 0 || sd->autocast.skill_id != skill_id)
+ pc->autocast_clear(sd); // Implausible skill ID.
+ else if (sd->autocast.skill_lv == 0 || (!use_skill_map && (skill_lv == 0 || sd->autocast.skill_lv != skill_lv)))
+ pc->autocast_clear(sd); // Implausible skill level.
+}
+
static struct s_skill_unit_layout *skill_get_unit_layout(uint16 skill_id, uint16 skill_lv, struct block_list *src, int x, int y)
{
int pos = skill->get_unit_layout_type(skill_id,skill_lv);
- uint8 dir;
nullpo_retr(&skill->dbs->unit_layout[0], src);
if (pos < -1 || pos >= MAX_SKILL_UNIT_LAYOUT) {
@@ -1191,7 +1217,9 @@ static struct s_skill_unit_layout *skill_get_unit_layout(uint16 skill_id, uint16
if (pos != -1) // simple single-definition layout
return &skill->dbs->unit_layout[pos];
- dir = (src->x == x && src->y == y) ? 6 : map->calc_dir(src,x,y); // 6 - default aegis direction
+ enum unit_dir dir = UNIT_DIR_EAST; // default aegis direction
+ if (src->x != x || src->y != y)
+ dir = map->calc_dir(src, x, y);
if (skill_id == MG_FIREWALL)
return &skill->dbs->unit_layout [skill->firewall_unit_pos + dir];
@@ -2064,9 +2092,9 @@ static int skill_additional_effect(struct block_list *src, struct block_list *bl
temp = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id;
- sd->state.autocast = 1;
+ sd->autocast.type = AUTOCAST_TEMP;
notok = skill->not_ok(temp, sd);
- sd->state.autocast = 0;
+ sd->autocast.type = AUTOCAST_NONE;
if ( notok )
continue;
@@ -2117,11 +2145,12 @@ static int skill_additional_effect(struct block_list *src, struct block_list *bl
else if (temp == PF_SPIDERWEB) //Special case, due to its nature of coding.
type = CAST_GROUND;
- sd->state.autocast = 1;
+ sd->autocast.type = AUTOCAST_TEMP;
skill->consume_requirement(sd,temp,auto_skill_lv,1);
skill->toggle_magicpower(src, temp);
skill->castend_type(type, src, tbl, temp, auto_skill_lv, tick, 0);
- sd->state.autocast = 0;
+ sd->autocast.type = AUTOCAST_NONE;
+
//Set canact delay. [Skotlex]
ud = unit->bl2ud(src);
if (ud) {
@@ -2190,6 +2219,9 @@ static int skill_onskillusage(struct map_session_data *sd, struct block_list *bl
if( sd == NULL || !skill_id )
return 0;
+ // Preserve auto-cast type if bAutoSpellOnSkill was triggered by a skill which was cast by Abracadabra, Improvised Song or an item.
+ enum autocast_type ac_type = sd->autocast.type;
+
for( i = 0; i < ARRAYLENGTH(sd->autospell3) && sd->autospell3[i].flag; i++ ) {
if( sd->autospell3[i].flag != skill_id )
continue;
@@ -2199,9 +2231,9 @@ static int skill_onskillusage(struct map_session_data *sd, struct block_list *bl
temp = (sd->autospell3[i].id > 0) ? sd->autospell3[i].id : -sd->autospell3[i].id;
- sd->state.autocast = 1;
+ sd->autocast.type = AUTOCAST_TEMP;
notok = skill->not_ok(temp, sd);
- sd->state.autocast = 0;
+ sd->autocast.type = AUTOCAST_NONE;
if ( notok )
continue;
@@ -2247,14 +2279,16 @@ static int skill_onskillusage(struct map_session_data *sd, struct block_list *bl
!battle->check_range(&sd->bl, tbl, skill->get_range2(&sd->bl, temp,skill_lv) + (temp == RG_CLOSECONFINE?0:1)) )
continue;
- sd->state.autocast = 1;
sd->autospell3[i].lock = true;
+ sd->autocast.type = AUTOCAST_TEMP;
skill->consume_requirement(sd,temp,skill_lv,1);
skill->castend_type(type, &sd->bl, tbl, temp, skill_lv, tick, 0);
+ sd->autocast.type = AUTOCAST_NONE;
sd->autospell3[i].lock = false;
- sd->state.autocast = 0;
}
+ sd->autocast.type = ac_type;
+
if (sd->autobonus3[0].rate) {
for( i = 0; i < ARRAYLENGTH(sd->autobonus3); i++ ) {
if( rnd()%1000 >= sd->autobonus3[i].rate )
@@ -2401,6 +2435,9 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_
struct unit_data *ud;
int i, auto_skill_id, auto_skill_lv, type, notok;
+ // Preserve auto-cast type if bAutoSpellWhenHit was triggered during cast of a skill which was cast by Abracadabra, Improvised Song or an item.
+ enum autocast_type ac_type = dstsd->autocast.type;
+
for (i = 0; i < ARRAYLENGTH(dstsd->autospell2) && dstsd->autospell2[i].id; i++) {
if(!(dstsd->autospell2[i].flag&attack_type&BF_WEAPONMASK &&
@@ -2416,9 +2453,9 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_
if (attack_type&BF_LONG)
rate>>=1;
- dstsd->state.autocast = 1;
+ dstsd->autocast.type = AUTOCAST_TEMP;
notok = skill->not_ok(auto_skill_id, dstsd);
- dstsd->state.autocast = 0;
+ dstsd->autocast.type = AUTOCAST_NONE;
if ( notok )
continue;
@@ -2459,10 +2496,11 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_
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;
+ dstsd->autocast.type = AUTOCAST_TEMP;
skill->consume_requirement(dstsd,auto_skill_id,auto_skill_lv,1);
skill->castend_type(type, bl, tbl, auto_skill_id, auto_skill_lv, tick, 0);
- dstsd->state.autocast = 0;
+ dstsd->autocast.type = AUTOCAST_NONE;
+
// Set canact delay. [Skotlex]
ud = unit->bl2ud(bl);
if (ud) {
@@ -2474,6 +2512,8 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_
}
}
}
+
+ dstsd->autocast.type = ac_type;
}
//Autobonus when attacked
@@ -2626,11 +2666,11 @@ static int skill_strip_equip(struct block_list *bl, unsigned short where, int ra
/*=========================================================================
* Used to knock back players, monsters, traps, etc
* 'count' is the number of squares to knock back
- * 'direction' indicates the way OPPOSITE to the knockback direction (or -1 for default behavior)
+ * 'direction' indicates the way OPPOSITE to the knockback direction (or UNIT_DIR_UNDEFINED for default behavior)
* if 'flag&0x1', position update packets must not be sent.
* if 'flag&0x2', skill blown ignores players' special_state.no_knockback
*/
-static int skill_blown(struct block_list *src, struct block_list *target, int count, int8 dir, int flag)
+static int skill_blown(struct block_list *src, struct block_list *target, int count, enum unit_dir dir, int flag)
{
int dx = 0, dy = 0;
struct status_change *tsc = status->get_sc(target);
@@ -2672,10 +2712,10 @@ static int skill_blown(struct block_list *src, struct block_list *target, int co
break;
}
- if (dir == -1) // <optimized>: do the computation here instead of outside
+ if (dir == UNIT_DIR_UNDEFINED) // <optimized>: do the computation here instead of outside
dir = map->calc_dir(target, src->x, src->y); // direction from src to target, reversed
- if (dir >= 0 && dir < 8) {
+ if (dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX) {
// take the reversed 'direction' and reverse it
dx = -dirx[dir];
dy = -diry[dir];
@@ -3297,7 +3337,7 @@ static int skill_attack(int attack_type, struct block_list *src, struct block_li
//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)) {
- int8 dir = -1; // default
+ enum unit_dir dir = UNIT_DIR_UNDEFINED; // default
switch(skill_id) {//direction
case MG_FIREWALL:
case PR_SANCTUARY:
@@ -3310,13 +3350,13 @@ static int skill_attack(int attack_type, struct block_list *src, struct block_li
// This ensures the storm randomly pushes instead of exactly a cell backwards per official mechanics.
case WZ_STORMGUST:
if(!battle_config.stormgust_knockback)
- dir = rnd()%8;
+ dir = rnd() % UNIT_DIR_MAX;
break;
case WL_CRIMSONROCK:
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
+ dir = UNIT_DIR_EAST; // Official servers push target to the West
break;
default:
dir = skill->attack_dir_unknown(&attack_type, src, dsrc, bl, &skill_id, &skill_lv, &tick, &flag);
@@ -3337,8 +3377,12 @@ static int skill_attack(int attack_type, struct block_list *src, struct block_li
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 (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
+ dir_x = dirx[unit_get_opposite_dir(dir)];
+ dir_y = diry[unit_get_opposite_dir(dir)];
if (map->getcell(bl->m, bl, 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);
}
@@ -3498,10 +3542,12 @@ static int skill_attack_copy_unknown(int *attack_type, struct block_list *src, s
static int skill_attack_dir_unknown(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)
{
- return -1;
+ return UNIT_DIR_UNDEFINED;
}
-static void skill_attack_blow_unknown(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 *type, struct Damage *dmg, int64 *damage, int8 *dir)
+static void skill_attack_blow_unknown(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 *type,
+ struct Damage *dmg, int64 *damage, enum unit_dir *dir)
{
nullpo_retv(bl);
nullpo_retv(dmg);
@@ -3512,7 +3558,7 @@ static void skill_attack_blow_unknown(int *attack_type, struct block_list *src,
if (!dmg->blewcount && bl->type == BL_SKILL && *damage > 0){
struct skill_unit *su = BL_UCAST(BL_SKILL, bl);
if (su->group && su->group->skill_id == HT_BLASTMINE)
- skill->blown(src, bl, 3, -1, 0);
+ skill->blown(src, bl, 3, UNIT_DIR_UNDEFINED, 0);
}
}
@@ -4190,11 +4236,6 @@ static void skill_castend_type(int type, struct block_list *src, struct block_li
skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, flag);
break;
}
-
- struct map_session_data *sd = BL_CAST(BL_PC, src);
-
- if (sd != NULL)
- pc->itemskill_clear(sd);
}
/*==========================================
@@ -4406,7 +4447,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
case KN_CHARGEATK: {
bool path_exists = path->search_long(NULL, src, src->m, src->x, src->y, bl->x, bl->y,CELL_CHKWALL);
unsigned int dist = distance_bl(src, bl);
- uint8 dir = map->calc_dir(bl, src->x, src->y);
+ enum unit_dir dir = map->calc_dir(bl, src->x, src->y);
// teleport to target (if not on WoE grounds)
if( !map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground && unit->movepos(src, bl->x, bl->y, 0, 1) )
@@ -4418,7 +4459,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
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->set_dir(src, unit_get_opposite_dir(dir));
}
}
@@ -4457,12 +4498,13 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
case RG_BACKSTAP:
{
- 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) {
+ enum unit_dir dir = map->calc_dir(src, bl->x, bl->y);
+ enum unit_dir t_dir = unit->getdir(bl);
+ if ((!check_distance_bl(src, bl, 0) && map->check_dir(dir, t_dir) == 0) || 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);
+ dir = unit_get_opposite_dir(dir); // change direction [Celest]
+ unit->set_dir(bl, dir);
}
else if (sd)
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0);
@@ -4489,7 +4531,6 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
{
short x, y, i = 2; // Move 2 cells for Issen(from target)
struct block_list *mbl = bl;
- short dir = 0;
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
@@ -4511,13 +4552,13 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
status->set_hp(src, 1, STATUS_HEAL_DEFAULT);
#endif // RENEWAL
}
- 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;
+ enum unit_dir dir = map->calc_dir(src, bl->x, bl->y);
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
+ x = i * dirx[dir];
+ y = i * diry[dir];
if ((mbl == src || (!map_flag_gvg2(src->m) && !map->list[src->m].flag.battleground))) { // only NJ_ISSEN don't have slide effect in GVG
if (!(unit->movepos(src, mbl->x+x, mbl->y+y, 1, 1))) {
// The cell is not reachable (wall, object, ...), move next to the target
@@ -4744,12 +4785,12 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
if(idb_exists(skill->bowling_db, bl->id))
break;
// Random direction
- dir = rnd()%8;
+ dir = rnd() % UNIT_DIR_MAX;
} else {
// Create an empty list of already hit targets
db_clear(skill->bowling_db);
// Direction is walkpath
- dir = (unit->getdir(src)+4)%8;
+ dir = unit_get_opposite_dir(unit->getdir(src));
}
// Add current target to the list of already hit targets
idb_put(skill->bowling_db, bl->id, bl);
@@ -4758,6 +4799,10 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
ty = bl->y;
for(i=0;i<c;i++) {
// Target coordinates (get changed even if knockback fails)
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
tx -= dirx[dir];
ty -= diry[dir];
// If target cell is a wall then break
@@ -4786,18 +4831,24 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
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], UNIT_DIR_UNDEFINED, 0);
} else {
- int x=bl->x,y=bl->y,i,dir;
- dir = map->calc_dir(bl,src->x,src->y);
+ int x = bl->x;
+ int y = bl->y;
+ int i;
+ enum unit_dir 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], UNIT_DIR_UNDEFINED, 0);
for (i=0;i<4;i++) {
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);
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
x += dirx[dir];
y += diry[dir];
}
@@ -5019,7 +5070,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
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->blown(src, bl, 6, UNIT_DIR_UNDEFINED, 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);
}
@@ -5027,7 +5078,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
case RK_PHANTOMTHRUST:
{
struct map_session_data *tsd = BL_CAST(BL_PC, bl);
- unit->setdir(src,map->calc_dir(src, bl->x, bl->y));
+ unit->set_dir(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);
@@ -5041,16 +5092,13 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
case KO_JYUMONJIKIRI:
case GC_DARKILLUSION:
{
- short x, y;
- short dir = map->calc_dir(bl, src->x, src->y);
-
- if ( dir < 4 ) {
- x = bl->x + 2 * (dir > 0) - 3 * (dir > 0);
- y = bl->y + 1 - (dir / 2) - (dir > 2);
- } else {
- x = bl->x + 2 * (dir > 4) - 1 * (dir > 4);
- y = bl->y + (dir / 6) - 1 + (dir > 6);
+ enum unit_dir dir = map->calc_dir(bl, src->x, src->y);
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
}
+ short x = bl->x + dirx[dir];
+ short y = bl->y + diry[dir];
if ( unit->movepos(src, x, y, 1, 1) ) {
clif->slide(src, x, y);
@@ -5207,14 +5255,16 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag|ELE_DARK);
break;
case RA_WUGSTRIKE:
- 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 = map->calc_dir(bl, src->x, src->y);
-
- 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]);
+ if (sd != NULL && pc_isridingwug(sd)) {
+ enum unit_dir dir = map->calc_dir(bl, src->x, src->y);
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
+ short x = bl->x + dirx[dir];
+ short y = bl->y + diry[dir];
+ if (unit->movepos(src, x, y, 1, 1) != 0) {
+ clif->slide(src, x, y);
clif->fixpos(src);
skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
}
@@ -5657,8 +5707,9 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data)
}
if(ud->skill_id == RG_BACKSTAP) {
- 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)) {
+ enum unit_dir dir = map->calc_dir(src, target->x, target->y);
+ enum unit_dir t_dir = unit->getdir(target);
+ if (check_distance_bl(src, target, 0) || map->check_dir(dir, t_dir) != 0) {
break;
}
}
@@ -5775,7 +5826,7 @@ static int skill_castend_id(int tid, int64 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, STOPWALKING_FLAG_FIXPOS);
- if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) )
+ if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
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);
@@ -5844,7 +5895,7 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data)
}
if( sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish]
- sd->skillitem = sd->skillitemlv = 0;
+ pc->autocast_clear(sd);
if (ud->skilltimer == INVALID_TIMER) {
if(md) md->skill_idx = -1;
@@ -5854,7 +5905,7 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data)
// Asura Strike caster doesn't look to their target in the end
if (src->id != target->id && !is_asura)
- unit->setdir(src, map->calc_dir(src, target->x, target->y));
+ unit->set_dir(src, map->calc_dir(src, target->x, target->y));
map->freeblock_unlock();
return 1;
@@ -5877,25 +5928,13 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data)
}
if (target && target->m == src->m) {
//Move character to target anyway.
- int dir, x, y;
+ enum unit_dir dir = map->calc_dir(src, target->x, target->y);
+ Assert_ret(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
int dist = 3; // number of cells that asura caster will walk
+ int x = dist * dirx[dir];
+ int y = dist * diry[dir];
- dir = map->calc_dir(src,target->x,target->y);
- if (dir > 0 && dir < 4)
- x = -dist;
- else if (dir > 4)
- x = dist;
- else
- x = 0;
-
- if (dir > 2 && dir < 6)
- y = -dist;
- else if (dir == 7 || dir < 2)
- y = dist;
- else
- y = 0;
-
- if (unit->movepos(src, src->x + x, src->y + y, 1, 1) == 1) {
+ if (unit->movepos(src, src->x + x, src->y + y, 1, 1) != 0) {
//Display movement + animation.
clif->slide(src, src->x, src->y);
clif->spiritball(src);
@@ -5905,14 +5944,14 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data)
}
}
- if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) )
+ if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
ud->canact_tick = tick;
ud->skill_id = ud->skill_lv = ud->skilltarget = 0;
//You can't place a skill failed packet here because it would be
//sent in ALL cases, even cases where skill_check_condition fails
//which would lead to double 'skill failed' messages u.u [Skotlex]
if(sd)
- sd->skillitem = sd->skillitemlv = 0;
+ pc->autocast_clear(sd);
else if(md)
md->skill_idx = -1;
return 0;
@@ -6294,9 +6333,9 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
if (sd) {
// player-casted
- sd->state.abra_flag = 1;
- sd->skillitem = abra_skill_id;
- sd->skillitemlv = abra_skill_lv;
+ sd->autocast.type = AUTOCAST_ABRA;
+ sd->autocast.skill_id = abra_skill_id;
+ sd->autocast.skill_lv = abra_skill_lv;
clif->item_skill(sd, abra_skill_id, abra_skill_lv);
} else {
// mob-casted
@@ -7425,7 +7464,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
map->freeblock_unlock();
return 1;
}
- if( sd->skillitem != skill_id )
+ if (sd->autocast.type == AUTOCAST_NONE)
status_zap(src, 0, skill->get_sp(skill_id, skill_lv)); // consume sp only if succeeded
}
break;
@@ -7462,7 +7501,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
break;
}
- if( sd->state.autocast || ( (sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1 ) || skill_lv == 3 )
+ if (sd->autocast.type == AUTOCAST_TEMP || ((sd->autocast.skill_id == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1) || skill_lv == 3)
{
if( skill_lv == 1 )
pc->randomwarp(sd,CLR_TELEPORT);
@@ -7835,7 +7874,9 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
case TK_HIGHJUMP:
{
- int x,y, dir = unit->getdir(src);
+ int x;
+ int y;
+ enum unit_dir dir = unit->getdir(src);
//Fails on noteleport maps, except for GvG and BG maps [Skotlex]
if( map->list[src->m].flag.noteleport
@@ -8084,11 +8125,19 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
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):map->calc_dir(src,bl->x,bl->y); //If cast on self, run forward, else run away.
+ enum unit_dir dir;
+ if (bl == src) //If cast on self, run forward, else run away.
+ dir = unit->getdir(src);
+ else
+ dir = map->calc_dir(src, bl->x, bl->y);
+ if (Assert_chk(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX)) {
+ map->freeblock_unlock(); // unblock before assert-returning
+ return 0;
+ }
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)
+ if (unit->walk_toxy(src, src->x + skill_lv * -dirx[dir], src->y + skill_lv * -diry[dir], 2) == 0
+ && md != NULL)
md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the AI.
}
break;
@@ -9449,7 +9498,9 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
case NC_F_SIDESLIDE:
case NC_B_SIDESLIDE:
{
- uint8 dir = (skill_id == NC_F_SIDESLIDE) ? (unit->getdir(src)+4)%8 : unit->getdir(src);
+ enum unit_dir dir = unit->getdir(src);
+ if (skill_id == NC_F_SIDESLIDE)
+ dir = unit_get_opposite_dir(dir);
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);
@@ -10024,9 +10075,9 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
clif->skill_nodamage (src, bl, skill_id, skill_lv, 1);
if (sd != NULL) {
- sd->state.abra_flag = 2;
- sd->skillitem = improv_skill_id;
- sd->skillitemlv = improv_skill_lv;
+ sd->autocast.type = AUTOCAST_IMPROVISE;
+ sd->autocast.skill_id = improv_skill_id;
+ sd->autocast.skill_lv = improv_skill_lv;
clif->item_skill(sd, improv_skill_id, improv_skill_lv);
} else {
struct unit_data *ud = unit->bl2ud(src);
@@ -10795,7 +10846,7 @@ static int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
if (ud->walktimer != INVALID_TIMER)
unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);
- if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) )
+ if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv);
if (sd) { //Cooldown application
int i, cooldown = skill->get_cooldown(ud->skill_id, ud->skill_lv);
@@ -10824,10 +10875,10 @@ static int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
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]
- sd->skillitem = sd->skillitemlv = 0;
+ if (sd != NULL && sd->autocast.skill_id != AL_WARP) // Warp-Portal thru items will clear data in skill_castend_map. [Inkfish]
+ pc->autocast_clear(sd);
- unit->setdir(src, map->calc_dir(src, ud->skillx, ud->skilly));
+ unit->set_dir(src, map->calc_dir(src, ud->skillx, ud->skilly));
if (ud->skilltimer == INVALID_TIMER) {
if (md) md->skill_idx = -1;
@@ -10839,11 +10890,11 @@ static int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
return 1;
} while(0);
- if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) )
+ if (sd == NULL || sd->autocast.skill_id != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) != 0)
ud->canact_tick = tick;
ud->skill_id = ud->skill_lv = 0;
if(sd)
- sd->skillitem = sd->skillitemlv = 0;
+ pc->autocast_clear(sd);
else if(md)
md->skill_idx = -1;
return 0;
@@ -10973,7 +11024,7 @@ static int skill_castend_map(struct map_session_data *sd, uint16 skill_id, const
}
}
- lv = sd->skillitem==skill_id?sd->skillitemlv:pc->checkskill(sd,skill_id);
+ lv = (sd->autocast.type > AUTOCAST_TEMP) ? sd->autocast.skill_lv : pc->checkskill(sd, skill_id);
wx = sd->menuskill_val>>16;
wy = sd->menuskill_val&0xffff;
@@ -10996,7 +11047,7 @@ static int skill_castend_map(struct map_session_data *sd, uint16 skill_id, const
}
skill->consume_requirement(sd,sd->menuskill_id,lv,2);
- sd->skillitem = sd->skillitemlv = 0; // Clear data that's skipped in 'skill_castend_pos' [Inkfish]
+ pc->autocast_clear(sd); // Clear data which was skipped in skill_castend_pos().
if((group=skill->unitsetting(&sd->bl,skill_id,lv,wx,wy,0))==NULL) {
skill_failed(sd);
@@ -11606,17 +11657,16 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill
case WL_EARTHSTRAIN:
{
- int i, wave = skill_lv + 4, dir = map->calc_dir(src,x,y);
+ int i;
+ int wave = skill_lv + 4;
+ enum unit_dir dir = map->calc_dir(src, x, y);
+ Assert_ret(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
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++ )
- {
- switch( dir ){
- case 0: case 1: case 7: sy = y + i; break;
- case 3: case 4: case 5: sy = y - i; break;
- case 2: sx = x - i; break;
- case 6: sx = x + i; break;
- }
+ for (i = 1; i <= wave; i++) {
+ sy = y + i * diry[dir];
+ if (dir == UNIT_DIR_WEST || dir == UNIT_DIR_EAST)
+ sx = x + i * dirx[dir];
skill->addtimerskill(src,timer->gettick() + (140 * i),0,sx,sy,skill_id,skill_lv,dir,flag&2);
}
}
@@ -13835,12 +13885,14 @@ static int skill_check_condition_char_sub(struct block_list *bl, va_list ap)
} else {
switch(skill_id) {
- case PR_BENEDICTIO: {
- 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->job & MAPID_BASEMASK) == MAPID_ACOLYTE && (dir == 2 || dir == 6) //Must be standing to the left/right of Priest.
- && sd->status.sp >= 10)
+ case PR_BENEDICTIO:
+ {
+ enum unit_dir dir = map->calc_dir(&sd->bl, tsd->bl.x, tsd->bl.y);
+ dir = (unit->getdir(&sd->bl) + dir) % UNIT_DIR_MAX; //This adjusts dir to account for the direction the sd is facing.
+ if ((tsd->job & MAPID_BASEMASK) == MAPID_ACOLYTE && (dir == UNIT_DIR_WEST || dir == UNIT_DIR_EAST) //Must be standing to the left/right of Priest.
+ && sd->status.sp >= 10) {
p_sd[(*c)++]=tsd->bl.id;
+ }
return 1;
}
case AB_ADORAMUS:
@@ -13994,22 +14046,6 @@ static bool skill_is_combo(int skill_id)
return false;
}
-/**
- * Checks if a skill is casted by an item (itemskill() script command).
- *
- * @param sd The charcater's session data.
- * @param skill_id The skill's ID.
- * @param skill_lv The skill's level.
- * @return true if skill is casted by an item, otherwise false.
- */
-static bool skill_is_item_skill(struct map_session_data *sd, int skill_id, int skill_lv)
-{
- nullpo_retr(false, sd);
-
- return (sd->skillitem == skill_id && sd->skillitemlv == skill_lv
- && sd->itemskill_id == skill_id && sd->itemskill_lv == skill_lv);
-}
-
static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv)
{
struct status_data *st;
@@ -14024,13 +14060,13 @@ static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 s
if (sd->chat_id != 0)
return 0;
- if ((sd->state.itemskill_conditions_checked == 1 || sd->state.itemskill_no_conditions == 1)
- && skill->is_item_skill(sd, skill_id, skill_lv)) {
+ if (((sd->autocast.itemskill_conditions_checked || !sd->autocast.itemskill_check_conditions)
+ && sd->autocast.type == AUTOCAST_ITEM) || sd->autocast.type == AUTOCAST_IMPROVISE) {
return 1;
}
- if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id) {
- //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex]
+ if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->autocast.type != AUTOCAST_ITEM) {
+ // GMs don't override the AUTOCAST_ITEM check, otherwise they can use items without them being consumed!
sd->state.arrow_atk = skill->get_ammotype(skill_id)?1:0; //Need to do arrow state check.
sd->spiritball_old = sd->spiritball; //Need to do Spiritball check.
return 1;
@@ -14061,30 +14097,7 @@ static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 s
if( !sc->count )
sc = NULL;
- if( sd->skillitem == 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 ||
- sd->inventory_data[i] == NULL ||
- sd->status.inventory[i].amount < 1
- ) {
- //Something went wrong, item exploit?
- sd->itemid = sd->itemindex = -1;
- return 0;
- }
-
- //Consume
- sd->itemid = sd->itemindex = -1;
- if (sd->status.inventory[i].expire_time == 0 && sd->inventory_data[i]->flag.delay_consume == 1) // Rental usable items are not consumed until expiration
- pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME);
- }
- }
-
- if (pc_is90overweight(sd) && sd->skillitem != skill_id) { /// Skill casting items ignore the overweight restriction. [Kenpachi]
+ if (pc_is90overweight(sd) && sd->autocast.type != AUTOCAST_ITEM) { // Skill casting items ignore the overweight restriction.
clif->skill_fail(sd, skill_id, USESKILL_FAIL_WEIGHTOVER, 0, 0);
return 0;
}
@@ -14955,7 +14968,7 @@ static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 s
return 0;
}
- if (require.sp > 0 && st->sp < (unsigned int)require.sp && sd->skillitem != skill_id) { /// Skill casting items and Hocus-Pocus skills don't consume SP. [Kenpachi]
+ if (require.sp > 0 && st->sp < (unsigned int)require.sp && sd->autocast.type == AUTOCAST_NONE) { // Auto-cast skills don't consume SP.
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SP_INSUFFICIENT, 0, 0);
return 0;
}
@@ -15013,13 +15026,13 @@ static int skill_check_condition_castend(struct map_session_data *sd, uint16 ski
if (sd->chat_id != 0)
return 0;
- if ((sd->state.itemskill_conditions_checked == 1 || sd->state.itemskill_no_conditions == 1)
- && skill->is_item_skill(sd, skill_id, skill_lv)) {
+ if (((sd->autocast.itemskill_conditions_checked || !sd->autocast.itemskill_check_conditions)
+ && sd->autocast.type == AUTOCAST_ITEM) || sd->autocast.type == AUTOCAST_IMPROVISE) {
return 1;
}
- if( pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id ) {
- //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex]
+ if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->autocast.type != AUTOCAST_ITEM) {
+ // GMs don't override the AUTOCAST_ITEM check, otherwise they can use items without them being consumed!
sd->state.arrow_atk = skill->get_ammotype(skill_id)?1:0; //Need to do arrow state check.
sd->spiritball_old = sd->spiritball; //Need to do Spiritball check.
return 1;
@@ -15046,7 +15059,7 @@ static int skill_check_condition_castend(struct map_session_data *sd, uint16 ski
break;
}
- if (pc_is90overweight(sd) && sd->skillitem != skill_id) { /// Skill casting items ignore the overweight restriction. [Kenpachi]
+ if (pc_is90overweight(sd) && sd->autocast.type != AUTOCAST_ITEM) { // Skill casting items ignore the overweight restriction.
clif->skill_fail(sd, skill_id, USESKILL_FAIL_WEIGHTOVER, 0, 0);
return 0;
}
@@ -15152,10 +15165,8 @@ static int skill_check_condition_castend(struct map_session_data *sd, uint16 ski
clif->messagecolor_self(sd->fd, COLOR_RED, e_msg);
return 0;
}
- if (!(require.ammo&1<<sd->inventory_data[i]->subtype)) { //Ammo type check. Send the "wrong weapon type" message
- //which is the closest we have to wrong ammo type. [Skotlex]
- clif->arrow_fail(sd,0); //Haplo suggested we just send the equip-arrows message instead. [Skotlex]
- //clif->skill_fail(sd, skill_id, USESKILL_FAIL_THIS_WEAPON, 0, 0);
+ if ((require.ammo & (1 << sd->inventory_data[i]->subtype)) == 0 || !battle->check_arrows(sd)) { // Ammo type check.
+ clif->arrow_fail(sd, 0); // "Please equip the proper ammunition first."
return 0;
}
}
@@ -15219,8 +15230,10 @@ static int skill_consume_requirement(struct map_session_data *sd, uint16 skill_i
nullpo_ret(sd);
- if (sd->state.itemskill_no_conditions == 1 && skill->is_item_skill(sd, skill_id, skill_lv))
+ if ((!sd->autocast.itemskill_check_conditions && sd->autocast.type == AUTOCAST_ITEM)
+ || sd->autocast.type == AUTOCAST_IMPROVISE) {
return 1;
+ }
req = skill->get_requirement(sd,skill_id,skill_lv);
@@ -15236,7 +15249,7 @@ static int skill_consume_requirement(struct map_session_data *sd, uint16 skill_i
break;
default:
- if (sd->state.autocast == 1 || sd->skillitem == skill_id) /// Skill casting items and Hocus-Pocus skills don't consume SP. [Kenpachi]
+ if (sd->autocast.type != AUTOCAST_NONE) // Auto-cast skills don't consume SP.
req.sp = 0;
break;
@@ -15724,6 +15737,8 @@ static int skill_castfix_sc(struct block_list *bl, int time)
}
if (sc->data[SC_POEMBRAGI])
time -= time * sc->data[SC_POEMBRAGI]->val2 / 100;
+ if (sc->data[SC_SKF_CAST] != NULL)
+ time -= time * sc->data[SC_SKF_CAST]->val1 / 100;
if (sc->data[SC_IZAYOI])
time -= time * 50 / 100;
}
@@ -15825,6 +15840,8 @@ static int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id,
}
if (sc->data[SC_MYSTICSCROLL])
VARCAST_REDUCTION(sc->data[SC_MYSTICSCROLL]->val1);
+ if (sc->data[SC_SKF_CAST] != NULL)
+ VARCAST_REDUCTION(sc->data[SC_SKF_CAST]->val1);
// Fixed cast reduction bonuses
if( sc->data[SC__LAZINESS] )
@@ -15976,11 +15993,11 @@ struct square {
int val2[5];
};
-static void skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int16 y)
+static void skill_brandishspear_first(struct square *tc, enum unit_dir dir, int16 x, int16 y)
{
nullpo_retv(tc);
- if(dir == 0){
+ if (dir == UNIT_DIR_NORTH) {
tc->val1[0]=x-2;
tc->val1[1]=x-1;
tc->val1[2]=x;
@@ -15991,7 +16008,7 @@ static void skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int
tc->val2[2]=
tc->val2[3]=
tc->val2[4]=y-1;
- } else if(dir==2){
+ } else if (dir == UNIT_DIR_WEST) {
tc->val1[0]=
tc->val1[1]=
tc->val1[2]=
@@ -16002,7 +16019,7 @@ static void skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int
tc->val2[2]=y;
tc->val2[3]=y-1;
tc->val2[4]=y-2;
- } else if(dir==4){
+ } else if (dir == UNIT_DIR_SOUTH) {
tc->val1[0]=x-2;
tc->val1[1]=x-1;
tc->val1[2]=x;
@@ -16013,7 +16030,7 @@ static void skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int
tc->val2[2]=
tc->val2[3]=
tc->val2[4]=y+1;
- } else if(dir==6){
+ } else if (dir == UNIT_DIR_EAST) {
tc->val1[0]=
tc->val1[1]=
tc->val1[2]=
@@ -16024,7 +16041,7 @@ static void skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int
tc->val2[2]=y;
tc->val2[3]=y-1;
tc->val2[4]=y-2;
- } else if(dir==1){
+ } else if (dir == UNIT_DIR_NORTHWEST) {
tc->val1[0]=x-1;
tc->val1[1]=x;
tc->val1[2]=x+1;
@@ -16035,7 +16052,7 @@ static void skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int
tc->val2[2]=y-1;
tc->val2[3]=y;
tc->val2[4]=y+1;
- } else if(dir==3){
+ } else if (dir == UNIT_DIR_SOUTHWEST) {
tc->val1[0]=x+3;
tc->val1[1]=x+2;
tc->val1[2]=x+1;
@@ -16046,7 +16063,7 @@ static void skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int
tc->val2[2]=y+1;
tc->val2[3]=y+2;
tc->val2[4]=y+3;
- } else if(dir==5){
+ } else if (dir == UNIT_DIR_SOUTHEAST) {
tc->val1[0]=x+1;
tc->val1[1]=x;
tc->val1[2]=x-1;
@@ -16057,7 +16074,7 @@ static void skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int
tc->val2[2]=y+1;
tc->val2[3]=y;
tc->val2[4]=y-1;
- } else if(dir==7){
+ } else if (dir == UNIT_DIR_NORTHEAST) {
tc->val1[0]=x-3;
tc->val1[1]=x-2;
tc->val1[2]=x-1;
@@ -16072,36 +16089,27 @@ static void skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int
}
-static void skill_brandishspear_dir(struct square *tc, uint8 dir, int are)
+static void skill_brandishspear_dir(struct square *tc, enum unit_dir dir, int are)
{
- int c;
nullpo_retv(tc);
+ Assert_retv(dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
- for( c = 0; c < 5; c++ ) {
- switch( dir ) {
- case 0: tc->val2[c]+=are; break;
- case 1: tc->val1[c]-=are; tc->val2[c]+=are; break;
- case 2: tc->val1[c]-=are; break;
- case 3: tc->val1[c]-=are; tc->val2[c]-=are; break;
- case 4: tc->val2[c]-=are; break;
- case 5: tc->val1[c]+=are; tc->val2[c]-=are; break;
- case 6: tc->val1[c]+=are; break;
- case 7: tc->val1[c]+=are; tc->val2[c]+=are; break;
- }
+ for (int c = 0; c < 5; c++) {
+ tc->val1[c] += dirx[dir] * are;
+ tc->val2[c] += diry[dir] * are;
}
}
static 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;
struct square tc;
int x, y;
nullpo_retv(bl);
x = bl->x;
y = bl->y;
- dir = map->calc_dir(src, x, y);
+ enum unit_dir dir = map->calc_dir(src, x, y);
skill->brandishspear_first(&tc,dir,x,y);
skill->brandishspear_dir(&tc,dir,4);
skill->area_temp[1] = bl->id;
@@ -21627,7 +21635,6 @@ void skill_defaults(void)
skill->cast_fix_sc = skill_castfix_sc;
skill->vf_cast_fix = skill_vfcastfix;
skill->delay_fix = skill_delay_fix;
- skill->is_item_skill = skill_is_item_skill;
skill->check_condition_castbegin = skill_check_condition_castbegin;
skill->check_condition_castend = skill_check_condition_castend;
skill->consume_requirement = skill_consume_requirement;
@@ -21653,6 +21660,7 @@ void skill_defaults(void)
skill->not_ok_hom = skillnotok_hom;
skill->not_ok_hom_unknown = skillnotok_hom_unknown;
skill->not_ok_mercenary = skillnotok_mercenary;
+ skill->validate_autocast_data = skill_validate_autocast_data;
skill->chastle_mob_changetarget = skill_chastle_mob_changetarget;
skill->can_produce_mix = skill_can_produce_mix;
skill->produce_mix = skill_produce_mix;
diff --git a/src/map/skill.h b/src/map/skill.h
index eff9ed7fc..65195dc75 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -23,6 +23,7 @@
#include "map/map.h" // struct block_list
#include "map/status.h" // enum sc_type
+#include "map/unitdefines.h" // enum unit_dir
#include "common/hercules.h"
#include "common/db.h"
#include "common/mmo.h" // MAX_SKILL_DB, struct square
@@ -1723,6 +1724,15 @@ enum {
UNT_MAX = 0x190
};
+/** Constants to identify the auto-cast type. **/
+enum autocast_type {
+ AUTOCAST_NONE = 0,
+ AUTOCAST_TEMP, // Used when type is only required during the execution of the calling instance. (For example bAutoSpell* skills.)
+ AUTOCAST_ABRA, // Used for Abracadabra (Hocus pocus).
+ AUTOCAST_IMPROVISE, // Used for Improvised Song.
+ AUTOCAST_ITEM, // Used for itemskill() script command.
+};
+
/**
* Structures
**/
@@ -2002,7 +2012,7 @@ struct skill_interface {
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 (*blown) (struct block_list* src, struct block_list* target, int count, enum unit_dir 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);
@@ -2019,7 +2029,6 @@ struct skill_interface {
int (*cast_fix_sc) ( struct block_list *bl, int time);
int (*vf_cast_fix) ( struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv);
int (*delay_fix) ( struct block_list *bl, uint16 skill_id, uint16 skill_lv);
- bool (*is_item_skill) (struct map_session_data *sd, int skill_id, int 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);
@@ -2045,6 +2054,7 @@ struct skill_interface {
int (*not_ok_hom) (uint16 skill_id, struct homun_data *hd);
int (*not_ok_hom_unknown) (uint16 skill_id, struct homun_data *hd);
int (*not_ok_mercenary) (uint16 skill_id, struct mercenary_data *md);
+ void (*validate_autocast_data) (struct map_session_data *sd, int skill_id, int skill_lv);
int (*chastle_mob_changetarget) (struct block_list *bl,va_list ap);
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 );
@@ -2085,8 +2095,8 @@ struct skill_interface {
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);
+ void (*brandishspear_first) (struct square *tc, enum unit_dir dir, int16 x, int16 y);
+ void (*brandishspear_dir) (struct square* tc, enum unit_dir dir, int are);
int (*get_fixed_cast) (int skill_id, int skill_lv);
int (*sit_count) (struct block_list *bl, va_list ap);
int (*sit_in) (struct block_list *bl, va_list ap);
@@ -2163,7 +2173,7 @@ struct skill_interface {
void (*attack_display_unknown) (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 *type, struct Damage *dmg, int64 *damage);
int (*attack_copy_unknown) (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_dir_unknown) (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);
- void (*attack_blow_unknown) (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 *type, struct Damage *dmg, int64 *damage, int8 *dir);
+ void (*attack_blow_unknown) (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 *type, struct Damage *dmg, int64 *damage, enum unit_dir *dir);
void (*attack_post_unknown) (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);
bool (*timerskill_dead_unknown) (struct block_list *src, struct unit_data *ud, struct skill_timerskill *skl);
void (*timerskill_target_unknown) (int tid, int64 tick, struct block_list *src, struct block_list *target, struct unit_data *ud, struct skill_timerskill *skl);
diff --git a/src/map/status.c b/src/map/status.c
index 1f0f31119..d3e85e5be 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -801,21 +801,21 @@ static void initChangeTables(void)
set_sc_with_vfx( GN_ILLUSIONDOPING , SC_ILLUSIONDOPING , SCB_HIT );
// Storing the target job rather than simply SC_SOULLINK simplifies code later on.
- status->dbs->Skill2SCTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST,
- status->dbs->Skill2SCTable[SL_MONK] = (sc_type)MAPID_MONK,
- status->dbs->Skill2SCTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR,
- status->dbs->Skill2SCTable[SL_SAGE] = (sc_type)MAPID_SAGE,
- status->dbs->Skill2SCTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER,
- status->dbs->Skill2SCTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE,
- status->dbs->Skill2SCTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT,
- status->dbs->Skill2SCTable[SL_WIZARD] = (sc_type)MAPID_WIZARD,
- status->dbs->Skill2SCTable[SL_PRIEST] = (sc_type)MAPID_PRIEST,
- status->dbs->Skill2SCTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER,
- status->dbs->Skill2SCTable[SL_ROGUE] = (sc_type)MAPID_ROGUE,
- status->dbs->Skill2SCTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN,
- status->dbs->Skill2SCTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH,
- status->dbs->Skill2SCTable[SL_HUNTER] = (sc_type)MAPID_HUNTER,
- status->dbs->Skill2SCTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER,
+ status->dbs->Skill2SCTable[skill->get_index(SL_ALCHEMIST)] = (sc_type)MAPID_ALCHEMIST,
+ status->dbs->Skill2SCTable[skill->get_index(SL_MONK)] = (sc_type)MAPID_MONK,
+ status->dbs->Skill2SCTable[skill->get_index(SL_STAR)] = (sc_type)MAPID_STAR_GLADIATOR,
+ status->dbs->Skill2SCTable[skill->get_index(SL_SAGE)] = (sc_type)MAPID_SAGE,
+ status->dbs->Skill2SCTable[skill->get_index(SL_CRUSADER)] = (sc_type)MAPID_CRUSADER,
+ status->dbs->Skill2SCTable[skill->get_index(SL_SUPERNOVICE)] = (sc_type)MAPID_SUPER_NOVICE,
+ status->dbs->Skill2SCTable[skill->get_index(SL_KNIGHT)] = (sc_type)MAPID_KNIGHT,
+ status->dbs->Skill2SCTable[skill->get_index(SL_WIZARD)] = (sc_type)MAPID_WIZARD,
+ status->dbs->Skill2SCTable[skill->get_index(SL_PRIEST)] = (sc_type)MAPID_PRIEST,
+ status->dbs->Skill2SCTable[skill->get_index(SL_BARDDANCER)] = (sc_type)MAPID_BARDDANCER,
+ status->dbs->Skill2SCTable[skill->get_index(SL_ROGUE)] = (sc_type)MAPID_ROGUE,
+ status->dbs->Skill2SCTable[skill->get_index(SL_ASSASIN)] = (sc_type)MAPID_ASSASSIN,
+ status->dbs->Skill2SCTable[skill->get_index(SL_BLACKSMITH)] = (sc_type)MAPID_BLACKSMITH,
+ status->dbs->Skill2SCTable[skill->get_index(SL_HUNTER)] = (sc_type)MAPID_HUNTER,
+ status->dbs->Skill2SCTable[skill->get_index(SL_SOULLINKER)] = (sc_type)MAPID_SOUL_LINKER,
// Other SC which are not necessarily associated to skills.
status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION1] |= SCB_ASPD;
@@ -884,6 +884,13 @@ static void initChangeTables(void)
status->dbs->ChangeFlagTable[SC_PHI_DEMON] |= SCB_ALL;
status->dbs->ChangeFlagTable[SC_MAGIC_CANDY] |= SCB_MATK | SCB_ALL;
status->dbs->ChangeFlagTable[SC_MYSTICPOWDER] |= SCB_FLEE | SCB_LUK;
+ status->dbs->ChangeFlagTable[SC_POPECOOKIE] |= SCB_BASE | SCB_BATK | SCB_MATK;
+ status->dbs->ChangeFlagTable[SC_VITALIZE_POTION] |= SCB_BATK | SCB_MATK;
+ status->dbs->ChangeFlagTable[SC_SKF_MATK] |= SCB_MATK;
+ status->dbs->ChangeFlagTable[SC_SKF_ATK] |= SCB_BATK;
+ status->dbs->ChangeFlagTable[SC_SKF_ASPD] |= SCB_ASPD;
+ status->dbs->ChangeFlagTable[SC_SKF_CAST] |= SCB_NONE;
+ status->dbs->ChangeFlagTable[SC_ALMIGHTY] |= SCB_BATK | SCB_MATK;
// Cash Items
status->dbs->ChangeFlagTable[SC_FOOD_STR_CASH] |= SCB_STR;
@@ -1584,7 +1591,7 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ
}
if( skill_id ) {
- if (src != NULL && (sd == NULL || sd->skillitem == 0)) {
+ if (src != NULL && (sd == NULL || sd->autocast.type != AUTOCAST_ITEM)) {
// Items that cast skills using 'itemskill' will not be handled by map_zone_db.
int i;
@@ -1628,7 +1635,7 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ
if (src != NULL
&& map->getcell(src->m, src, src->x, src->y, CELL_CHKLANDPROTECTOR)
&& !(st->mode&MD_BOSS)
- && (src->type != BL_PC || sd->skillitem != skill_id))
+ && (src->type != BL_PC || sd->autocast.type != AUTOCAST_ITEM))
return 0;
break;
default:
@@ -1707,7 +1714,7 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ
return 0; //Can't amp out of Wand of Hermode :/ [Skotlex]
}
- if (skill_id != 0 /* Do not block item-casted skills.*/ && (src->type != BL_PC || sd->skillitem != skill_id)) {
+ if (skill_id != 0 /* Do not block item-casted skills.*/ && (src->type != BL_PC || sd->autocast.type != AUTOCAST_ITEM)) {
//Skills blocked through status changes...
if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through
sc->data[SC_SILENCE] ||
@@ -2572,12 +2579,16 @@ static int status_calc_pc_(struct map_session_data *sd, enum e_status_calc_opt o
status->calc_pc_additional(sd, opt);
- if( sd->pd ) { // Pet Bonus
+ if (sd->pd != NULL) { // 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 )
- 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);
+
+ if (pd->petDB != NULL && pd->petDB->equip_script != NULL)
+ script->run(pd->petDB->equip_script, 0, sd->bl.id, 0);
+
+ if (pd->pet.intimate > PET_INTIMACY_NONE && pd->state.skillbonus == 1 && pd->bonus != NULL
+ && (battle_config.pet_equip_required == 0 || pd->pet.equip > 0)) {
+ pc->bonus(sd, pd->bonus->type, pd->bonus->val);
+ }
}
//param_bonus now holds card bonuses.
@@ -3038,6 +3049,18 @@ static int status_calc_pc_(struct map_session_data *sd, enum e_status_calc_opt o
sd->subele[ELE_EARTH] += i;
sd->subele[ELE_FIRE] -= i;
}
+ if (sc->data[SC_POPECOOKIE] != NULL) {
+ i = sc->data[SC_POPECOOKIE]->val3;
+ sd->subele[ELE_WATER] += i;
+ sd->subele[ELE_EARTH] += i;
+ sd->subele[ELE_FIRE] += i;
+ sd->subele[ELE_WIND] += i;
+ sd->subele[ELE_POISON] += i;
+ sd->subele[ELE_HOLY] += i;
+ sd->subele[ELE_DARK] += i;
+ sd->subele[ELE_GHOST] += i;
+ sd->subele[ELE_UNDEAD] += i;
+ }
if (sc->data[SC_MTF_MLEATKED])
sd->subele[ELE_NEUTRAL] += sc->data[SC_MTF_MLEATKED]->val1;
if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3)
@@ -4801,6 +4824,10 @@ static int status_calc_batk(struct block_list *bl, struct status_change *sc, int
/* some statuses that are hidden in the status window */
if(sc->data[SC_PLUSATTACKPOWER])
batk += sc->data[SC_PLUSATTACKPOWER]->val1;
+ if (sc->data[SC_POPECOOKIE] != NULL)
+ batk += batk * sc->data[SC_POPECOOKIE]->val1 / 100;
+ if (sc->data[SC_VITALIZE_POTION] != NULL)
+ batk += batk * sc->data[SC_VITALIZE_POTION]->val1 / 100;
return cap_value(batk, battle_config.batk_min, battle_config.batk_max);
}
#ifndef RENEWAL
@@ -4880,6 +4907,10 @@ static int status_calc_batk(struct block_list *bl, struct status_change *sc, int
batk += batk * sc->data[SC_2011RWC]->val2 / 100;
if (sc->data[SC_STEAMPACK])
batk += sc->data[SC_STEAMPACK]->val1;
+ if (sc->data[SC_SKF_ATK] != NULL)
+ batk += sc->data[SC_SKF_ATK]->val1;
+ if (sc->data[SC_ALMIGHTY] != NULL)
+ batk += sc->data[SC_ALMIGHTY]->val1;
if (sc->data[SC_SHRIMP])
batk += batk * sc->data[SC_SHRIMP]->val2 / 100;
@@ -5020,6 +5051,10 @@ static int status_calc_matk(struct block_list *bl, struct status_change *sc, int
/* some statuses that are hidden in the status window */
if (sc->data[SC_MINDBREAKER])
matk += matk * sc->data[SC_MINDBREAKER]->val2 / 100;
+ if (sc->data[SC_POPECOOKIE] != NULL)
+ matk += matk * sc->data[SC_POPECOOKIE]->val2 / 100;
+ if (sc->data[SC_VITALIZE_POTION] != NULL)
+ matk += matk * sc->data[SC_VITALIZE_POTION]->val2 / 100;
return cap_value(matk, battle_config.matk_min, battle_config.matk_max);
}
@@ -5077,6 +5112,10 @@ static int status_calc_matk(struct block_list *bl, struct status_change *sc, int
matk += matk * sc->data[SC_2011RWC]->val2 / 100;
if (sc->data[SC_MAGIC_CANDY])
matk += sc->data[SC_MAGIC_CANDY]->val1;
+ if (sc->data[SC_SKF_MATK] != NULL)
+ matk += sc->data[SC_SKF_MATK]->val1;
+ if (sc->data[SC_ALMIGHTY] != NULL)
+ matk += sc->data[SC_ALMIGHTY]->val2;
return cap_value(matk, battle_config.matk_min, battle_config.matk_max);
}
@@ -5901,6 +5940,8 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s
bonus += sc->data[SC_BATTLESCROLL]->val1;
if (sc->data[SC_STEAMPACK])
bonus += sc->data[SC_STEAMPACK]->val2;
+ if (sc->data[SC_SKF_ASPD] != NULL)
+ bonus += sc->data[SC_SKF_ASPD]->val1;
}
return (bonus + pots);
@@ -6068,6 +6109,8 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
aspd_rate += sc->data[SC_BATTLESCROLL]->val1 * 10;
if (sc->data[SC_STEAMPACK])
aspd_rate += sc->data[SC_STEAMPACK]->val2 * 10;
+ if (sc->data[SC_SKF_ASPD] != NULL)
+ aspd_rate -= sc->data[SC_SKF_ASPD]->val1 * 10;
return (short)cap_value(aspd_rate,0,SHRT_MAX);
}
diff --git a/src/map/status.h b/src/map/status.h
index ada18bc0a..d5cb3da75 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -854,6 +854,13 @@ typedef enum sc_type {
SC_RESIST_PROPERTY_WIND,
SC_CLIENT_ONLY_EQUIP_ARROW,
SC_MADOGEAR,
+ SC_POPECOOKIE,
+ SC_VITALIZE_POTION,
+ SC_SKF_MATK,
+ SC_SKF_ATK,
+ SC_SKF_ASPD,
+ SC_SKF_CAST,
+ SC_ALMIGHTY,
#ifndef SC_MAX
SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
#endif
diff --git a/src/map/unit.c b/src/map/unit.c
index 29a01aea7..d484056f9 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -57,6 +57,7 @@
#include "common/showmsg.h"
#include "common/socket.h"
#include "common/timer.h"
+#include "common/utils.h"
#include <stdio.h>
#include <stdlib.h>
@@ -71,20 +72,69 @@ struct unit_interface *unit;
/**
* 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
+ *
+ * __Warning:__ if bl->type is not known or NULL,
+ * an assertion will be triggered and NULL returned.
+ * @param bl block_list to process, it is expected to be not NULL.
* @return a pointer to the given object's unit_data
**/
static struct unit_data *unit_bl2ud(struct block_list *bl)
{
- if (bl == NULL) return NULL;
- if (bl->type == BL_PC) return &BL_UCAST(BL_PC, bl)->ud;
- if (bl->type == BL_MOB) return &BL_UCAST(BL_MOB, bl)->ud;
- if (bl->type == BL_PET) return &BL_UCAST(BL_PET, bl)->ud;
- if (bl->type == BL_NPC) return BL_UCAST(BL_NPC, bl)->ud;
- if (bl->type == BL_HOM) return &BL_UCAST(BL_HOM, bl)->ud;
- if (bl->type == BL_MER) return &BL_UCAST(BL_MER, bl)->ud;
- if (bl->type == BL_ELEM) return &BL_UCAST(BL_ELEM, bl)->ud;
- return NULL;
+ Assert_retr(NULL, bl != NULL);
+ switch (bl->type) {
+ case BL_PC:
+ return &BL_UCAST(BL_PC, bl)->ud;
+ case BL_MOB:
+ return &BL_UCAST(BL_MOB, bl)->ud;
+ case BL_PET:
+ return &BL_UCAST(BL_PET, bl)->ud;
+ case BL_NPC:
+ return BL_UCAST(BL_NPC, bl)->ud;
+ case BL_HOM:
+ return &BL_UCAST(BL_HOM, bl)->ud;
+ case BL_MER:
+ return &BL_UCAST(BL_MER, bl)->ud;
+ case BL_ELEM:
+ return &BL_UCAST(BL_ELEM, bl)->ud;
+ case BL_SKILL: // No assertion to not spam the server console when attacking a skill type unit such as Ice Wall.
+ return NULL;
+ default:
+ Assert_retr(NULL, false);
+ }
+}
+
+/**
+ * Returns the const unit_data for the given const block_list. If the object is using
+ * shared unit_data (i.e. in case of BL_NPC), it returns the shared data.
+ *
+ * __Warning:__ if bl->type is not known or NULL,
+ * an assertion will be triggered and NULL returned.
+ * @param bl block_list to process, it is expected to be not NULL.
+ * @return a pointer to the given object's unit_data
+ **/
+static const struct unit_data *unit_cbl2ud(const struct block_list *bl)
+{
+ Assert_retr(NULL, bl != NULL);
+ switch (bl->type) {
+ case BL_PC:
+ return &BL_UCCAST(BL_PC, bl)->ud;
+ case BL_MOB:
+ return &BL_UCCAST(BL_MOB, bl)->ud;
+ case BL_PET:
+ return &BL_UCCAST(BL_PET, bl)->ud;
+ case BL_NPC:
+ return BL_UCCAST(BL_NPC, bl)->ud;
+ case BL_HOM:
+ return &BL_UCCAST(BL_HOM, bl)->ud;
+ case BL_MER:
+ return &BL_UCCAST(BL_MER, bl)->ud;
+ case BL_ELEM:
+ return &BL_UCCAST(BL_ELEM, bl)->ud;
+ case BL_SKILL: // No assertion to not spam the server console when attacking a skill type unit such as Ice Wall.
+ return NULL;
+ default:
+ Assert_retr(NULL, false);
+ }
}
/**
@@ -105,42 +155,46 @@ static struct unit_data *unit_bl2ud2(struct block_list *bl)
return unit->bl2ud(bl);
}
-static int unit_walktoxy_sub(struct block_list *bl)
+/**
+ * TODO: understand purpose of this function
+ * @param bl block_list to process
+ * @return 0: success, 1: fail, 2: nullpointer
+ */
+static int unit_walk_toxy_sub(struct block_list *bl)
{
- int i;
- struct walkpath_data wpd;
- struct unit_data *ud = NULL;
-
- nullpo_retr(1, bl);
- ud = unit->bl2ud(bl);
- if(ud == NULL) return 0;
+ nullpo_retr(2, bl);
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL)
+ return 2;
- memset(&wpd, 0, sizeof(wpd));
+ struct walkpath_data wpd = {0};
- if( !path->search(&wpd,bl,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) )
- return 0;
+ if (!path->search(&wpd, bl, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, ud->state.walk_easy, CELL_CHKNOPASS))
+ return 1;
#ifdef OFFICIAL_WALKPATH
- if( !path->search_long(NULL, bl, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, CELL_CHKNOPASS) // Check if there is an obstacle between
- && wpd.path_len > 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;
+ if (bl->type != BL_NPC // If type is an NPC, disregard.
+ && !path->search_long(NULL, bl, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, CELL_CHKNOPASS) // Check if there is an obstacle between
+ && wpd.path_len > 14) { // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
+ return 1;
+ }
#endif
- memcpy(&ud->walkpath,&wpd,sizeof(wpd));
+ ud->walkpath = wpd;
- if (ud->target_to && ud->chaserange>1) {
- //Generally speaking, the walk path is already to an adjacent tile
- //so we only need to shorten the path if the range is greater than 1.
+ if (ud->target_to != 0 && ud->chaserange > 1) {
+ // Generally speaking, the walk path is already to an adjacent tile
+ // so we only need to shorten the path if the range is greater than 1.
- //Trim the last part of the path to account for range,
- //but always move at least one cell when requested to move.
- for (i = (ud->chaserange*10)-10; i > 0 && ud->walkpath.path_len>1;) {
- uint8 dir;
+ // Trim the last part of the path to account for range,
+ // but always move at least one cell when requested to move.
+ for (int i = ud->chaserange * 10 - 10; i > 0 && ud->walkpath.path_len > 1;) {
+ enum unit_dir dir;
ud->walkpath.path_len--;
dir = ud->walkpath.path[ud->walkpath.path_len];
- if (dir&1)
- i -= MOVE_COST*20; //When chasing, units will target a diamond-shaped area in range [Playtester]
+ Assert_retr(1, dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
+ if (unit_is_diagonal_dir(dir))
+ i -= MOVE_COST * 20; // When chasing, units will target a diamond-shaped area in range [Playtester]
else
i -= MOVE_COST;
ud->to_x -= dirx[dir];
@@ -148,7 +202,7 @@ static int unit_walktoxy_sub(struct block_list *bl)
}
}
- ud->state.change_walk_target=0;
+ ud->state.change_walk_target = 0;
if (bl->type == BL_PC) {
struct map_session_data *sd = BL_UCAST(BL_PC, bl);
@@ -157,15 +211,17 @@ static int unit_walktoxy_sub(struct block_list *bl)
}
clif->move(ud);
- 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)*MOVE_DIAGONAL_COST/MOVE_COST;
+ int timer_delay;
+ if (ud->walkpath.path_pos >= ud->walkpath.path_len)
+ timer_delay = -1;
+ else if ((ud->walkpath.path[ud->walkpath.path_pos] & 1) != 0)
+ timer_delay = status->get_speed(bl) * MOVE_DIAGONAL_COST / MOVE_COST;
else
- i = status->get_speed(bl);
- if( i > 0)
- ud->walktimer = timer->add(timer->gettick()+i,unit->walktoxy_timer,bl->id,i);
- return 1;
+ timer_delay = status->get_speed(bl);
+
+ if (timer_delay > 0)
+ ud->walktimer = timer->add(timer->gettick() + timer_delay, unit->walk_toxy_timer, bl->id, 0); //TODO: check if unit->walk_toxy_timer uses any intptr data
+ return 0;
}
/**
@@ -173,289 +229,282 @@ static int unit_walktoxy_sub(struct block_list *bl)
* @param tid: Timer ID
* @param tick: Unused
* @param id: ID of bl to do the action
- * @param data: Not used
- * @return 1: Success 0: Fail (No valid bl)
+ * @param data: Unused
+ * @return 0: success, 1: fail, 2: nullpointer
*/
-static int unit_step_timer(int tid, int64 tick, int id, intptr_t data)
+static int unit_steptimer(int tid, int64 tick, int id, intptr_t data)
{
- struct block_list *bl;
- struct unit_data *ud;
- int target_id;
-
- bl = map->id2bl(id);
-
- if (!bl || bl->prev == NULL)
- return 0;
-
- ud = unit->bl2ud(bl);
-
- if(!ud)
- return 0;
+ struct block_list *bl = map->id2bl(id);
+ if (bl == NULL || bl->prev == NULL)
+ return 2;
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL)
+ return 2;
- if(ud->steptimer != tid) {
- ShowError("unit_step_timer mismatch %d != %d\n",ud->steptimer,tid);
- return 0;
+ if (ud->steptimer != tid) {
+ ShowError("unit_steptimer mismatch %d != %d\n", ud->steptimer, tid);
+ return 1;
}
ud->steptimer = INVALID_TIMER;
- if(!ud->stepaction)
- return 0;
+ if (!ud->stepaction)
+ return 1;
- //Set to false here because if an error occurs, it should not be executed again
+ // Set to false here because if an error occurs, it should not be executed again
ud->stepaction = false;
- if(!ud->target_to)
- return 0;
+ if (ud->target_to == 0)
+ return 1;
- //Flush target_to as it might contain map coordinates which should not be used by other functions
- target_id = ud->target_to;
+ // Flush target_to as it might contain map coordinates which should not be used by other functions
+ int target_id = ud->target_to;
ud->target_to = 0;
- //If stepaction is set then we remembered a client request that should be executed on the next step
- //Execute request now if target is in attack range
- if(ud->stepskill_id && skill->get_inf(ud->stepskill_id) & INF_GROUND_SKILL) {
- //Execute ground skill
+ // If stepaction is set then we remembered a client request that should be executed on the next step
+ // Execute request now if target is in attack range
+ if (ud->stepskill_id != 0 && (skill->get_inf(ud->stepskill_id) & INF_GROUND_SKILL) != 0) {
+ // Execute ground skill
struct map_data *md = &map->list[bl->m];
- unit->skilluse_pos(bl, target_id%md->xs, target_id/md->xs, ud->stepskill_id, ud->stepskill_lv);
+ unit->skilluse_pos(bl, target_id % md->xs, target_id / md->xs, ud->stepskill_id, ud->stepskill_lv);
} else {
- //If a player has target_id set and target is in range, attempt attack
+ // If a player has target_id set and target is in range, attempt attack
struct block_list *tbl = map->id2bl(target_id);
- if (!tbl || !status->check_visibility(bl, tbl)) {
- return 0;
- }
- if(ud->stepskill_id == 0) {
- //Execute normal attack
- unit->attack(bl, tbl->id, (ud->state.attack_continue) + 2);
- } else {
- //Execute non-ground skill
- unit->skilluse_id(bl, tbl->id, ud->stepskill_id, ud->stepskill_lv);
- }
+ nullpo_retr(2, tbl);
+ if (status->check_visibility(bl, tbl) == 0) // Target not visible
+ return 1;
+ if (ud->stepskill_id == 0)
+ unit->attack(bl, tbl->id, ud->state.attack_continue + 2); // Execute normal attack
+ else
+ unit->skilluse_id(bl, tbl->id, ud->stepskill_id, ud->stepskill_lv); // Execute non-ground skill
}
- return 1;
+ return 0;
}
-static int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data)
+/**
+ * Warps homunculus or mercenary towards his master in case he's too far away for 3 seconds.
+ * @param master_bl: block_list of master
+ * @param slave_bl: block_list of homunculus/mercenary master owns
+ * @return 0: success, 1: fail
+ */
+static int unit_warpto_master(struct block_list *master_bl, struct block_list *slave_bl)
{
- int i;
- int x,y,dx,dy;
- unsigned char icewall_walk_block;
- uint8 dir;
- struct block_list *bl;
- struct map_session_data *sd;
- struct mob_data *md;
- struct unit_data *ud;
- struct mercenary_data *mrd;
+ nullpo_retr(1, master_bl);
+ nullpo_retr(1, slave_bl);
+ int64 *masterteleport_timer;
+ struct homun_data *hd = BL_CAST(BL_HOM, slave_bl);
+ struct mercenary_data *md = BL_CAST(BL_MER, slave_bl);
+
+ bool check = true;
+ if (hd != NULL) {
+ masterteleport_timer = &hd->masterteleport_timer;
+ check = homun_alive(hd);
+ } else if (md != NULL) {
+ masterteleport_timer = &md->masterteleport_timer;
+ } else {
+ return 1;
+ }
- 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);
+ if (check && !check_distance_bl(master_bl, slave_bl, MAX_MER_DISTANCE)) {
+ if (*masterteleport_timer == 0) {
+ *masterteleport_timer = timer->gettick();
+ return 0;
+ } else if (DIFF_TICK(timer->gettick(), *masterteleport_timer) > 3000) {
+ unit->warp(slave_bl, master_bl->m, master_bl->x, master_bl->y, CLR_TELEPORT);
+ }
+ }
+ *masterteleport_timer = 0; // resets tick in case he isn't far anymore.
- if(ud == NULL) return 0;
+ return 0;
+}
+
+/**
+ * Timer for walking to target coordinates or object.
+ * @param tid: timer id
+ * @param tick: tick
+ * @param id: id of bl to do the action
+ * @param data: unused
+ * @return 0: success, 1: fail
+ */
+static int unit_walk_toxy_timer(int tid, int64 tick, int id, intptr_t data)
+{
+ struct block_list *bl = map->id2bl(id);
+ if (bl == NULL)
+ return 1;
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL)
+ return 1;
- if(ud->walktimer != tid){
+ if (ud->walktimer != tid) {
ShowError("unit_walk_timer mismatch %d != %d\n",ud->walktimer,tid);
- return 0;
+ return 1;
}
+
ud->walktimer = INVALID_TIMER;
- if (bl->prev == NULL) return 0; // Stop moved because it is missing from the block_list
- if(ud->walkpath.path_pos>=ud->walkpath.path_len)
- return 0;
+ if (bl->prev == NULL) // Stop moved because it is missing from the block_list.
+ return 1;
- if(ud->walkpath.path[ud->walkpath.path_pos]>=8)
+ if (ud->walkpath.path_pos >= ud->walkpath.path_len)
return 1;
- x = bl->x;
- y = bl->y;
- dir = ud->walkpath.path[ud->walkpath.path_pos];
+ enum unit_dir dir = ud->walkpath.path[ud->walkpath.path_pos];
+ Assert_retr(1, dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
+ int x = bl->x;
+ int y = bl->y;
+
ud->dir = dir;
- dx = dirx[(int)dir];
- dy = diry[(int)dir];
+ int dx = dirx[dir];
+ int dy = diry[dir];
- //Get icewall walk block depending on boss mode (players can't be trapped)
- if(md && md->status.mode&MD_BOSS)
- icewall_walk_block = battle_config.boss_icewall_walk_block;
- else if(md)
- icewall_walk_block = battle_config.mob_icewall_walk_block;
- else
- icewall_walk_block = 0;
+ // Get icewall walk block depending on boss mode (players can't be trapped)
+ unsigned char icewall_walk_block = 0;
+ struct mob_data *md = BL_CAST(BL_MOB, bl);
+ if (md != NULL) {
+ if ((md->status.mode & MD_BOSS) != 0)
+ icewall_walk_block = battle_config.boss_icewall_walk_block;
+ else
+ icewall_walk_block = battle_config.mob_icewall_walk_block;
+ }
- //Monsters will walk into an icewall from the west and south if they already started walking
+ // Monsters will walk into an icewall from the west and south if they already started walking
if (map->getcell(bl->m, bl, x + dx, y + dy, CELL_CHKNOPASS)
&& (icewall_walk_block == 0 || !map->getcell(bl->m, bl, x + dx, y + dy, CELL_CHKICEWALL) || dx < 0 || dy < 0))
- return unit->walktoxy_sub(bl);
+ return unit->walk_toxy_sub(bl);
- //Monsters can only leave icewalls to the west and south
- //But if movement fails more than icewall_walk_block times, they can ignore this rule
- if (md && md->walktoxy_fail_count < icewall_walk_block && map->getcell(bl->m, bl, x, y, CELL_CHKICEWALL) && (dx > 0 || dy > 0)) {
- //Needs to be done here so that rudeattack skills are invoked
+ // Monsters can only leave icewalls to the west and south
+ // But if movement fails more than icewall_walk_block times, they can ignore this rule
+ if (md != NULL && md->walktoxy_fail_count < icewall_walk_block && map->getcell(bl->m, bl, x, y, CELL_CHKICEWALL) != 0 && (dx > 0 || dy > 0)) {
+ // Needs to be done here so that rudeattack skills are invoked
md->walktoxy_fail_count++;
clif->fixpos(bl);
- //Monsters in this situation first use a chase skill, then unlock target and then use an idle skill
- if (!(++ud->walk_count%WALK_SKILL_INTERVAL))
+ // Monsters in this situation first use a chase skill, then unlock target and then use an idle skill
+ if ((++ud->walk_count % WALK_SKILL_INTERVAL) == 0)
mob->skill_use(md, tick, -1);
mob->unlocktarget(md, tick);
- if (!(++ud->walk_count%WALK_SKILL_INTERVAL))
+ if ((++ud->walk_count % WALK_SKILL_INTERVAL) != 0)
mob->skill_use(md, tick, -1);
- return 0;
+ return 1;
}
+ struct map_session_data *sd = BL_CAST(BL_PC, bl);
//Refresh view for all those we lose sight
- map->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl);
+ map->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, (sd != NULL ? BL_ALL : BL_PC), bl);
x += dx;
y += dy;
map->moveblock(bl, x, y, tick);
- ud->walk_count++; //walked cell counter, to be used for walk-triggered skills. [Skotlex]
+ 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; //map->moveblock has altered the object beyond what we expected (moved/warped it)
+ return 1; // 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
- map->foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl);
+ map->foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, (sd != NULL ? BL_ALL : BL_PC), bl);
ud->walktimer = INVALID_TIMER;
- if(sd) {
- if( sd->touching_id )
- npc->touchnext_areanpc(sd,false);
+ struct mercenary_data *mrd = BL_CAST(BL_MER, bl);
+ if (sd != NULL) {
+ if (sd->touching_id != 0)
+ npc->touchnext_areanpc(sd, false);
if (map->getcell(bl->m, bl, x, y, CELL_CHKNPC)) {
- npc->touch_areanpc(sd,bl->m,x,y);
+ 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
+ } else {
npc->untouch_areanpc(sd, bl->m, x, y);
-
- 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;
- }
- 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;
}
+
+ if (sd->md != NULL) // mercenary should be warped after being 3 seconds too far from the master [greenbox]
+ unit->warpto_master(bl, &sd->md->bl);
+ if (sd->hd != NULL)
+ unit->warpto_master(bl, &sd->hd->bl);
} else if (md) {
- //Movement was successful, reset walktoxy_fail_count
+ // Movement was successful, reset walktoxy_fail_count
md->walktoxy_fail_count = 0;
- if (map->getcell(bl->m, bl, x, y, CELL_CHKNPC)) {
- if( npc->touch_areanpc2(md) ) return 0; // Warped
- } else
+
+ if (map->getcell(bl->m, bl, x, y, CELL_CHKNPC) != 0 && npc->touch_areanpc2(md))
+ return 0; // Warped
+ else
md->areanpc_id = 0;
- if (md->min_chase > md->db->range3) md->min_chase--;
- //Walk skills are triggered regardless of target due to the idle-walk mob state.
- //But avoid triggering on stop-walk calls.
- if (tid != INVALID_TIMER
- && !(ud->walk_count%WALK_SKILL_INTERVAL)
- && map->list[bl->m].users > 0
- && mob->skill_use(md, tick, -1)
- ) {
+
+ if (md->min_chase > md->db->range3)
+ md->min_chase--;
+ // Walk skills are triggered regardless of target due to the idle-walk mob state.
+ // But avoid triggering on stop-walk calls.
+ if (tid != INVALID_TIMER && (ud->walk_count % WALK_SKILL_INTERVAL) == 0
+ && map->list[bl->m].users > 0 && mob->skill_use(md, tick, -1) == 1) {
+ // Walk skills are supposed to be used while walking
if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)
- && md->state.skillstate != MSS_WALK //Walk skills are supposed to be used while walking
- ) {
- //Skill used, abort walking
- clif->fixpos(bl); //Fix position as walk has been canceled.
- return 0;
+ && md->state.skillstate != MSS_WALK) {
+ // Skill used, abort walking
+ clif->fixpos(bl); // Fix position as walk has been canceled.
+ return 1;
}
- //Resend walk packet for proper Self Destruction display.
+ // Resend walk packet for proper Self Destruction display.
clif->move(ud);
}
- }
- else if( mrd && mrd->master )
- {
- if (!check_distance_bl(&mrd->master->bl, bl, MAX_MER_DISTANCE))
- {
- // mercenary should be warped after being 3 seconds too far from the master [greenbox]
- if (mrd->masterteleport_timer == 0)
- {
- mrd->masterteleport_timer = timer->gettick();
- }
- else if (DIFF_TICK(timer->gettick(), mrd->masterteleport_timer) > 3000)
- {
- mrd->masterteleport_timer = 0;
- unit->warp( bl, mrd->master->bl.m, mrd->master->bl.x, mrd->master->bl.y, CLR_TELEPORT );
- }
- }
- else
- {
- mrd->masterteleport_timer = 0;
- }
+ } else if (mrd != NULL && mrd->master != NULL) {
+ unit->warpto_master(&mrd->master->bl, bl);
}
- if(tid == INVALID_TIMER) //A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
+ if(tid == INVALID_TIMER) // A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
return 0;
- //If stepaction is set then we remembered a client request that should be executed on the next step
- if (ud->stepaction && ud->target_to) {
- //Delete old stepaction even if not executed yet, the latest command is what counts
- if(ud->steptimer != INVALID_TIMER) {
- timer->delete(ud->steptimer, unit->step_timer);
+ // If stepaction is set then we remembered a client request that should be executed on the next step
+ if (ud->stepaction && ud->target_to != 0) {
+ // Delete old stepaction even if not executed yet, the latest command is what counts
+ if (ud->steptimer != INVALID_TIMER) {
+ timer->delete(ud->steptimer, unit->steptimer);
ud->steptimer = INVALID_TIMER;
}
- //Delay stepactions by half a step (so they are executed at full step)
- if(ud->walkpath.path[ud->walkpath.path_pos]&1)
- i = status->get_speed(bl)*14/20;
+ // Delay stepactions by half a step (so they are executed at full step)
+ int timer_delay;
+ if ((ud->walkpath.path[ud->walkpath.path_pos] & 1) != 0)
+ timer_delay = status->get_speed(bl) * 14 / 20;
else
- i = status->get_speed(bl)/2;
- ud->steptimer = timer->add(tick+i, unit->step_timer, bl->id, 0);
+ timer_delay = status->get_speed(bl) / 2;
+ ud->steptimer = timer->add(tick + timer_delay, unit->steptimer, bl->id, 0);
}
- if(ud->state.change_walk_target) {
- if(unit->walktoxy_sub(bl)) {
- return 1;
- } else {
- clif->fixpos(bl);
+ if (ud->state.change_walk_target) {
+ if (unit->walk_toxy_sub(bl) == 0)
return 0;
- }
+ clif->fixpos(bl);
+ return 1;
}
+ int timer_delay;
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;
+ timer_delay = -1;
+ else if ((ud->walkpath.path[ud->walkpath.path_pos] & 1) != 0)
+ timer_delay = status->get_speed(bl) * 14 / 10;
else
- i = status->get_speed(bl);
+ timer_delay = status->get_speed(bl);
- if(i > 0) {
- ud->walktimer = timer->add(tick+i,unit->walktoxy_timer,id,i);
- if( md && DIFF_TICK(tick,md->dmgtick) < 3000 )//not required not damaged recently
+ if (timer_delay > 0) {
+ ud->walktimer = timer->add(tick + timer_delay, unit->walk_toxy_timer, id, 0);
+ if (md != NULL && 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, NULL, SC_RUN) || unit->run(bl, sd, SC_WUGDASH)) )
+ } else if (ud->state.running != 0) {
+ // Keep trying to run.
+ if (!(unit->run(bl, NULL, SC_RUN) || unit->run(bl, sd, SC_WUGDASH)))
ud->state.running = 0;
- } else if (!ud->stepaction && ud->target_to) {
- //Update target trajectory.
+ } else if (!ud->stepaction && ud->target_to != 0) {
+ // Update target trajectory.
struct block_list *tbl = map->id2bl(ud->target_to);
- if (!tbl || !status->check_visibility(bl, tbl)) {
- //Cancel chase.
+ if (tbl == NULL || status->check_visibility(bl, tbl) == 0) { // not visible
+ // Cancel chase.
ud->to_x = bl->x;
ud->to_y = bl->y;
- if (tbl && bl->type == BL_MOB && mob->warpchase(BL_UCAST(BL_MOB, bl), tbl))
+ if (tbl != NULL && bl->type == BL_MOB && mob->warpchase(BL_UCAST(BL_MOB, bl), tbl) != 0)
return 0;
ud->target_to = 0;
- return 0;
+ return 1;
}
if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange)) {
//Reached destination.
@@ -466,81 +515,106 @@ static int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data)
clif->fixpos(bl);
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? 1 : 0));
+ } else { // Update chase-path
+ unit->walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy | ud->state.attack_continue);
return 0;
}
} else {
- //Stopped walking. Update to_x and to_y to current location [Skotlex]
+ // Stopped walking. Update to_x and to_y to current location [Skotlex]
ud->to_x = bl->x;
ud->to_y = bl->y;
- if (battle_config.official_cell_stack_limit && map->count_oncell(bl->m, x, y, BL_CHAR|BL_NPC, 0x1 | 0x2) > battle_config.official_cell_stack_limit) {
- //Walked on occupied cell, call unit_walktoxy again
- if(ud->steptimer != INVALID_TIMER) {
- //Execute step timer on next step instead
- timer->delete(ud->steptimer, unit->step_timer);
+ if (battle_config.official_cell_stack_limit != 0 && map->count_oncell(bl->m, x, y, BL_CHAR | BL_NPC, 0x1 | 0x2) > battle_config.official_cell_stack_limit) {
+ // Walked on occupied cell, call unit->walk_toxy again
+ if (ud->steptimer != INVALID_TIMER) {
+ // Execute step timer on next step instead
+ timer->delete(ud->steptimer, unit->steptimer);
ud->steptimer = INVALID_TIMER;
}
- return unit->walktoxy(bl, x, y, 8);
+ return unit->walk_toxy(bl, x, y, 8);
}
}
return 0;
}
-static int unit_delay_walktoxy_timer(int tid, int64 tick, int id, intptr_t data)
+/**
+ * Timer for delayed execution of unit->walk_toxy once triggered
+ * @param tid: Timer ID, unused
+ * @param tick: Tick, unused
+ * @param id: ID of block_list to execute the action
+ * @param data: uint32 data cast to intptr_t with x-coord in lowest 16 bits and y-coord in highest 16 bits
+ * @return 0: success, 1: failure
+ */
+static int unit_delay_walk_toxy_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);
- return 1;
+ if (bl == NULL || bl->prev == NULL)
+ return 1;
+ short x = (short)GetWord((uint32)data, 0);
+ short y = (short)GetWord((uint32)data, 1);
+ unit->walk_toxy(bl, x, y, 0);
+ return 0;
}
-//flag parameter:
-//&1 -> 1/0 = easy/hard
-//&2 -> force walking
-//&4 -> Delay walking if the reason you can't walk is the canwalk delay
-//&8 -> Search for an unoccupied cell and cancel if none available
-static int unit_walktoxy(struct block_list *bl, short x, short y, int flag)
+/**
+ * Makes a unit walk to (x, y) coordinates
+ * @param bl: block_list of unit to move
+ * @param x: x-coordinate
+ * @param y: y-coordinate
+ * @param flag: flag paramater with following options:
+ * - `& 1` -> 1/0 = easy / hard
+ * - `& 2` -> Force walking
+ * - `& 4` -> Delay walking, if the reason you can't walk is the `canwalk delay`
+ * - `& 8` -> Search for an unoccupied cell and cancel if none available
+ * .
+ * @return 0: success, 1: failure
+ */
+static int unit_walk_toxy(struct block_list *bl, short x, short y, int flag)
{
+ // TODO: change flag to enum? [skyleo]
struct unit_data* ud = NULL;
struct status_change* sc = NULL;
struct walkpath_data wpd;
- nullpo_ret(bl);
+ nullpo_retr(1, bl);
ud = unit->bl2ud(bl);
- if( ud == NULL) return 0;
+ if (ud == NULL)
+ return 1;
- if (battle_config.check_occupied_cells && (flag&8) && !map->closest_freecell(bl->m, bl, &x, &y, BL_CHAR|BL_NPC, 1)) //This might change x and y
- return 0;
+ if ((flag & 8) != 0 && battle_config.check_occupied_cells != 0) {
+ if (!map->closest_freecell(bl->m, bl, &x, &y, BL_CHAR | BL_NPC, 1)) // This might change x and y
+ return 1;
+ }
- if (!path->search(&wpd, bl, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS)) // Count walk path cells
- return 0;
+ if (!path->search(&wpd, bl, bl->m, bl->x, bl->y, x, y, flag & 1, CELL_CHKNOPASS)) // Count walk path cells
+ return 1;
+ if (bl->type != BL_NPC) {
#ifdef OFFICIAL_WALKPATH
- if( !path->search_long(NULL, bl, 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;
+ // Check if there is an obstacle between
+ // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
+ if (!path->search_long(NULL, bl, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS)
+ && (wpd.path_len > (battle_config.max_walk_path / 17) * 14))
+ return 1;
#endif
- if ((wpd.path_len > battle_config.max_walk_path) && (bl->type != BL_NPC))
- return 0;
+ if (wpd.path_len > battle_config.max_walk_path)
+ return 1;
+ }
- if (flag&4 && DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0 &&
- DIFF_TICK(ud->canmove_tick, timer->gettick()) < 2000) {
+ if ((flag & 4) != 0 && 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;
+ timer->add(ud->canmove_tick + 1, unit->delay_walk_toxy_timer, bl->id,
+ (intptr_t)MakeDWord((uint16)x, (uint16)y));
+ return 0;
}
- if(!(flag&2) && (!(status_get_mode(bl)&MD_CANMOVE) || !unit->can_move(bl)))
- return 0;
+ if ((flag & 2) == 0 && ((status_get_mode(bl) & MD_CANMOVE) == 0 || unit->can_move(bl) == 0))
+ return 1;
- ud->state.walk_easy = flag&1;
+ ud->state.walk_easy = flag & 1;
ud->to_x = x;
ud->to_y = y;
unit->stop_attack(bl); //Sets target to 0
@@ -548,44 +622,63 @@ static int unit_walktoxy(struct block_list *bl, short x, short y, int flag)
unit->stop_stepaction(bl); // unit->walktoxy removes any remembered stepaction and resets ud->target_to
sc = status->get_sc(bl);
- if( sc ) {
- if( sc->data[SC_CONFUSION] || sc->data[SC__CHAOS] ) //Randomize the target position
+ if (sc != NULL) {
+ if (sc->data[SC_CONFUSION] != NULL || sc->data[SC__CHAOS] != NULL) // Randomize the target position
map->random_dir(bl, &ud->to_x, &ud->to_y);
- if( sc->data[SC_COMBOATTACK] )
+ if (sc->data[SC_COMBOATTACK] != NULL)
status_change_end(bl, SC_COMBOATTACK, INVALID_TIMER);
}
- if(ud->walktimer != 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->walk_toxy_sub
ud->state.change_walk_target = 1;
- return 1;
+ return 0;
}
- return unit->walktoxy_sub(bl);
+ return unit->walk_toxy_sub(bl);
}
-//To set Mob's CHASE/FOLLOW states (shouldn't be done if there's no path to reach)
-static inline void set_mobstate(struct block_list *bl, int flag)
+/**
+ * Sets CHASE / FOLLOW states, in case bl is a mob.
+ * WARNING: This shouldn't be done if there's no path to reach
+ * @param bl: block_list of mob
+ */
+static inline void set_mobstate(struct block_list *bl)
{
- struct mob_data* md = BL_CAST(BL_MOB,bl);
+ struct mob_data* md = BL_CAST(BL_MOB, bl);
- if( md && flag )
- md->state.skillstate = md->state.aggressive ? MSS_FOLLOW : MSS_RUSH;
+ if (md != NULL) {
+ if (md->state.aggressive != 0)
+ md->state.skillstate = MSS_FOLLOW;
+ else
+ md->state.skillstate = MSS_RUSH;
+ }
}
-static int unit_walktobl_sub(int tid, int64 tick, int id, intptr_t data)
+/**
+ * Timer used for when a unit can't walk towards its target yet due to it's canmove_tick,
+ * keeps retrying until it works or target changes.
+ * @param tid: Timer ID, unused
+ * @param tick: Tick, unused
+ * @param id: ID of block_list to execute the action
+ * @param data: ID of block_list to walk towards
+ * @return 0: success, 1: failure
+ */
+static int unit_walktobl_timer(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 (DIFF_TICK(ud->canmove_tick, tick) > 0) //Keep waiting?
- 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);
- }
+ if (bl == NULL)
+ return 1;
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL)
+ return 1;
+
+ if (ud->walktimer == INVALID_TIMER && ud->target == data) {
+ if (DIFF_TICK(ud->canmove_tick, tick) > 0) // Keep waiting?
+ timer->add(ud->canmove_tick + 1, unit->walktobl_timer, id, data);
+ else if (unit->can_move(bl) != 0 && unit->walk_toxy_sub(bl) == 0 && ud->state.attack_continue != 0)
+ set_mobstate(bl);
}
return 0;
}
@@ -629,23 +722,27 @@ static int unit_walktobl(struct block_list *bl, struct block_list *tbl, int rang
if(ud->walktimer != INVALID_TIMER) {
ud->state.change_walk_target = 1;
- set_mobstate(bl, flag&2);
+ if ((flag & 2) != 0)
+ set_mobstate(bl);
return 1;
}
if (DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0) {
//Can't move, wait a bit before invoking the movement.
- timer->add(ud->canmove_tick+1, unit->walktobl_sub, bl->id, ud->target);
+ timer->add(ud->canmove_tick + 1, unit->walktobl_timer, bl->id, ud->target);
return 1;
}
if(!unit->can_move(bl))
return 0;
- if (unit->walktoxy_sub(bl)) {
- set_mobstate(bl, flag&2);
+ if (unit->walk_toxy_sub(bl) == 0) {
+ if ((flag & 2) != 0)
+ set_mobstate(bl);
+
return 1;
}
+
return 0;
}
@@ -732,14 +829,14 @@ static bool unit_run(struct block_list *bl, struct map_session_data *sd, enum sc
return false;
}
- if( unit->walktoxy(bl, to_x, to_y, 1) )
+ if (unit->walk_toxy(bl, to_x, to_y, 1) == 0)
return true;
//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));
+ } while (--i > 0 && unit->walk_toxy(bl, to_x, to_y, 1) != 0);
if ( i == 0 ) {
unit->run_hit(bl, sc, sd, type);
@@ -752,19 +849,21 @@ static bool unit_run(struct block_list *bl, struct map_session_data *sd, enum sc
//Makes bl attempt to run dist cells away from target. Uses hard-paths.
static int unit_escape(struct block_list *bl, struct block_list *target, short dist)
{
- uint8 dir;
nullpo_ret(bl);
- dir = map->calc_dir(target, bl->x, bl->y);
+ enum unit_dir dir = map->calc_dir(target, bl->x, bl->y);
+ Assert_retr(1, dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
while (dist > 0 && map->getcell(bl->m, bl, 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) );
+ if (dist > 0 && unit->walk_toxy(bl, bl->x + dist * dirx[dir], bl->y + dist * diry[dir], 0) == 0)
+ return 1;
+ else
+ return 0;
}
//Instant warp function.
static 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;
struct map_session_data *sd = NULL;
@@ -783,7 +882,7 @@ static int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int eas
ud->to_x = dst_x;
ud->to_y = dst_y;
- dir = map->calc_dir(bl, dst_x, dst_y);
+ enum unit_dir dir = map->calc_dir(bl, dst_x, dst_y);
ud->dir = dir;
dx = dst_x - bl->x;
@@ -807,7 +906,7 @@ static int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int eas
} else
npc->untouch_areanpc(sd, bl->m, bl->x, bl->y);
- if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 )
+ if (sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > PET_INTIMACY_NONE)
{ // Check if pet needs to be teleported. [Skotlex]
int flag = 0;
struct block_list* pbl = &sd->pd->bl;
@@ -825,12 +924,18 @@ static int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int eas
return 1;
}
-static int unit_setdir(struct block_list *bl, unsigned char dir)
+/**
+ * Sets the facing direction of a unit
+ * @param bl: unit to modify
+ * @param dir: the facing direction @see enum unit_dir
+ * @return 0: success, 1: failure
+ */
+static int unit_set_dir(struct block_list *bl, enum unit_dir dir)
{
- struct unit_data *ud;
- nullpo_ret(bl );
- ud = unit->bl2ud(bl);
- if (!ud) return 0;
+ nullpo_retr(1, bl);
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud == NULL)
+ return 1;
ud->dir = dir;
if (bl->type == BL_PC)
BL_UCAST(BL_PC, bl)->head_dir = 0;
@@ -838,15 +943,20 @@ static int unit_setdir(struct block_list *bl, unsigned char dir)
return 0;
}
-static uint8 unit_getdir(struct block_list *bl)
+/**
+ * Get the facing direction of a unit
+ * @param bl: unit to request data from
+ * @return the facing direction @see enum unit_dir
+ */
+static enum unit_dir unit_getdir(const struct block_list *bl)
{
- struct unit_data *ud;
- nullpo_ret(bl);
+ nullpo_retr(UNIT_DIR_NORTH, bl);
- if( bl->type == BL_NPC )
+ if (bl->type == BL_NPC)
return BL_UCCAST(BL_NPC, bl)->dir;
- ud = unit->bl2ud(bl);
- if (!ud) return 0;
+ const struct unit_data *ud = unit->cbl2ud(bl);
+ if (ud == NULL)
+ return UNIT_DIR_NORTH;
return ud->dir;
}
@@ -1010,7 +1120,7 @@ static int unit_stop_walking(struct block_list *bl, int flag)
//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);
+ timer->delete(ud->walktimer, unit->walk_toxy_timer);
ud->walktimer = INVALID_TIMER;
ud->state.change_walk_target = 0;
tick = timer->gettick();
@@ -1018,7 +1128,7 @@ static int unit_stop_walking(struct block_list *bl, int flag)
|| (flag&STOPWALKING_FLAG_NEXTCELL && 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->walk_toxy_timer(INVALID_TIMER, tick, bl->id, ud->walkpath.path_pos);
}
if(flag&STOPWALKING_FLAG_FIXPOS)
@@ -1046,8 +1156,10 @@ static int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_
int ret = unit->skilluse_id2(src, target_id, skill_id, skill_lv, casttime, castcancel);
struct map_session_data *sd = BL_CAST(BL_PC, src);
- if (sd != NULL)
- pc->itemskill_clear(sd);
+ if (sd != NULL && ret == 0)
+ pc->autocast_clear(sd); // Error in unit_skilluse_id2().
+ else if (sd != NULL && ret != 0 && skill_id != SA_ABRACADABRA && skill_id != WM_RANDOMIZESPELL)
+ skill->validate_autocast_data(sd, skill_id, skill_lv);
return ret;
}
@@ -1235,7 +1347,7 @@ static int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int
} else {
unit->stop_walking(bl, STOPWALKING_FLAG_NEXTCELL);
if (ud->target)
- timer->add(ud->canmove_tick+1, unit->walktobl_sub, bl->id, ud->target);
+ timer->add(ud->canmove_tick + 1, unit->walktobl_timer, bl->id, ud->target);
}
}
}
@@ -1450,7 +1562,7 @@ static int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill
ud->target_to = target_id;
ud->stepskill_id = skill_id;
ud->stepskill_lv = skill_lv;
- return 0; // Attacking will be handled by unit_walktoxy_timer in this case
+ return 0; // Attacking will be handled by unit_walk_toxy_timer in this case
}
//Check range when not using skill on yourself or is a combo-skill during attack
@@ -1606,7 +1718,7 @@ static int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill
if (!ud->state.running) //need TK_RUN or WUGDASH handler to be done before that, see bugreport:6026
unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);// even though this is not how official works but this will do the trick. bugreport:6829
- if (sd != NULL && sd->state.itemskill_no_casttime == 1 && skill->is_item_skill(sd, skill_id, skill_lv))
+ if (sd != NULL && sd->autocast.itemskill_instant_cast && sd->autocast.type == AUTOCAST_ITEM)
casttime = 0;
// in official this is triggered even if no cast time.
@@ -1644,7 +1756,7 @@ static int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill
if( casttime <= 0 )
ud->state.skillcastcancel = 0;
- if( !sd || sd->skillitem != skill_id || skill->get_cast(skill_id,skill_lv) )
+ if (sd == NULL || sd->autocast.type < AUTOCAST_ABRA || skill->get_cast(skill_id, skill_lv) != 0)
ud->canact_tick = tick + casttime + 100;
if( sd )
{
@@ -1663,7 +1775,7 @@ static int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill
if( casttime > 0 ) {
if (src->id != target->id) // self-targeted skills shouldn't show different direction
- unit->setdir(src, map->calc_dir(src, target->x, target->y));
+ unit->set_dir(src, map->calc_dir(src, target->x, target->y));
ud->skilltimer = timer->add( tick+casttime, skill->castend_id, src->id, 0 );
if (sd && (pc->checkskill(sd, SA_FREECAST) > 0 || skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0))
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
@@ -1683,8 +1795,10 @@ static int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_
int ret = unit->skilluse_pos2(src, skill_x, skill_y, skill_id, skill_lv, casttime, castcancel);
struct map_session_data *sd = BL_CAST(BL_PC, src);
- if (sd != NULL)
- pc->itemskill_clear(sd);
+ if (sd != NULL && ret == 0)
+ pc->autocast_clear(sd); // Error in unit_skilluse_pos2().
+ else if (sd != NULL && ret != 0 && skill_id != SA_ABRACADABRA && skill_id != WM_RANDOMIZESPELL)
+ skill->validate_autocast_data(sd, skill_id, skill_lv);
return ret;
}
@@ -1757,7 +1871,7 @@ static int unit_skilluse_pos2(struct block_list *src, short skill_x, short skill
ud->target_to = (skill_x + skill_y*md->xs);
ud->stepskill_id = skill_id;
ud->stepskill_lv = skill_lv;
- return 0; // Attacking will be handled by unit_walktoxy_timer in this case
+ return 0; // Attacking will be handled by unit_walk_toxy_timer in this case
}
if( skill->get_state(ud->skill_id) == ST_MOVE_ENABLE ) {
@@ -1781,7 +1895,7 @@ static int unit_skilluse_pos2(struct block_list *src, short skill_x, short skill
}
ud->state.skillcastcancel = castcancel&&casttime>0?1:0;
- if( !sd || sd->skillitem != skill_id || skill->get_cast(skill_id,skill_lv) )
+ if (sd == NULL || sd->autocast.type < AUTOCAST_ABRA || skill->get_cast(skill_id, skill_lv) != 0)
ud->canact_tick = tick + casttime + 100;
#if 0
if (sd) {
@@ -1812,13 +1926,13 @@ static int unit_skilluse_pos2(struct block_list *src, short skill_x, short skill
unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);
- if (sd != NULL && sd->state.itemskill_no_casttime == 1 && skill->is_item_skill(sd, skill_id, skill_lv))
+ if (sd != NULL && sd->autocast.itemskill_instant_cast && sd->autocast.type == AUTOCAST_ITEM)
casttime = 0;
// in official this is triggered even if no cast time.
clif->useskill(src, src->id, 0, skill_x, skill_y, skill_id, skill_lv, casttime);
if( casttime > 0 ) {
- unit->setdir(src, map->calc_dir(src, skill_x, skill_y));
+ unit->set_dir(src, map->calc_dir(src, skill_x, skill_y));
ud->skilltimer = timer->add( tick+casttime, skill->castend_pos, src->id, 0 );
if ((sd && pc->checkskill(sd, SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0) {
status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD);
@@ -1897,7 +2011,7 @@ static void unit_stop_stepaction(struct block_list *bl)
return;
//Clear timer
- timer->delete(ud->steptimer, unit->step_timer);
+ timer->delete(ud->steptimer, unit->steptimer);
ud->steptimer = INVALID_TIMER;
}
@@ -1981,7 +2095,7 @@ static int unit_attack(struct block_list *src, int target_id, int continuous)
ud->target_to = ud->target;
ud->stepskill_id = 0;
ud->stepskill_lv = 0;
- return 0; // Attacking will be handled by unit_walktoxy_timer in this case
+ return 0; // Attacking will be handled by unit_walk_toxy_timer in this case
}
if(DIFF_TICK(ud->attackabletime, timer->gettick()) > 0)
@@ -2082,14 +2196,13 @@ static bool unit_can_reach_bl(struct block_list *bl, struct block_list *tbl, int
/*==========================================
* Calculates position of Pet/Mercenary/Homunculus/Elemental
*------------------------------------------*/
-static int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
+static int unit_calc_pos(struct block_list *bl, int tx, int ty, enum unit_dir dir)
{
int dx, dy, x, y;
struct unit_data *ud = unit->bl2ud(bl);
nullpo_ret(ud);
- if(dir > 7)
- return 1;
+ Assert_retr(1, dir >= UNIT_DIR_FIRST && dir < UNIT_DIR_MAX);
ud->to_x = tx;
ud->to_y = ty;
@@ -2106,7 +2219,7 @@ static int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
if (!unit->can_reach_pos(bl, x, y, 0)) {
int i;
for (i = 0; i < 12; i++) {
- int k = rnd()%8; // Pick a Random Dir
+ enum unit_dir k = rnd() % UNIT_DIR_MAX; // Pick a Random Dir
dx = -dirx[k] * 2;
dy = -diry[k] * 2;
x = tx + dx;
@@ -2272,7 +2385,7 @@ static int unit_attack_timer_sub(struct block_list *src, int tid, int64 tick)
}
if(ud->state.attack_continue) {
- unit->setdir(src, map->calc_dir(src, target->x, target->y));
+ unit->set_dir(src, map->calc_dir(src, target->x, target->y));
if( src->type == BL_PC )
pc->update_idle_time(sd, BCIDLE_ATTACK);
ud->attacktimer = timer->add(ud->attackabletime,unit->attack_timer,src->id,0);
@@ -2617,7 +2730,7 @@ static int unit_remove_map(struct block_list *bl, enum clr_type clrtype, const c
case BL_PET:
{
struct pet_data *pd = BL_UCAST(BL_PET, bl);
- if( pd->pet.intimate <= 0 && !(pd->msd && !pd->msd->state.active) ) {
+ if (pd->pet.intimate <= PET_INTIMACY_NONE && !(pd->msd && !pd->msd->state.active)) {
//If logging out, this is deleted on unit->free
clif->clearunit_area(bl,clrtype);
map->delblock(bl);
@@ -2831,7 +2944,7 @@ static int unit_free(struct block_list *bl, enum clr_type clrtype)
aFree (pd->loot);
pd->loot = NULL;
}
- if (pd->pet.intimate > 0) {
+ if (pd->pet.intimate > PET_INTIMACY_NONE) {
intif->save_petdata(pd->pet.account_id,&pd->pet);
} else {
//Remove pet.
@@ -2969,10 +3082,10 @@ static int do_init_unit(bool 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");
- timer->add_func_list(unit->step_timer,"unit_step_timer");
+ timer->add_func_list(unit->walk_toxy_timer, "unit_walk_toxy_timer");
+ timer->add_func_list(unit->walktobl_timer, "unit_walktobl_timer");
+ timer->add_func_list(unit->delay_walk_toxy_timer, "unit_delay_walk_toxy_timer");
+ timer->add_func_list(unit->steptimer, "unit_steptimer");
return 0;
}
@@ -2990,26 +3103,28 @@ void unit_defaults(void)
unit->final = do_final_unit;
/* */
unit->bl2ud = unit_bl2ud;
+ unit->cbl2ud = unit_cbl2ud;
unit->bl2ud2 = unit_bl2ud2;
unit->init_ud = unit_init_ud;
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->walk_toxy_timer = unit_walk_toxy_timer;
+ unit->walk_toxy_sub = unit_walk_toxy_sub;
+ unit->delay_walk_toxy_timer = unit_delay_walk_toxy_timer;
+ unit->walk_toxy = unit_walk_toxy;
+ unit->walktobl_timer = unit_walktobl_timer;
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->set_dir = unit_set_dir;
unit->getdir = unit_getdir;
unit->blown = unit_blown;
unit->warp = unit_warp;
+ unit->warpto_master = unit_warpto_master;
unit->stop_walking = unit_stop_walking;
unit->skilluse_id = unit_skilluse_id;
- unit->step_timer = unit_step_timer;
+ unit->steptimer = unit_steptimer;
unit->stop_stepaction = unit_stop_stepaction;
unit->is_walking = unit_is_walking;
unit->can_move = unit_can_move;
diff --git a/src/map/unit.h b/src/map/unit.h
index 5437a172a..3f288e0d3 100644
--- a/src/map/unit.h
+++ b/src/map/unit.h
@@ -24,6 +24,7 @@
#include "map/clif.h" // clr_type
#include "map/path.h" // struct walkpath_data
#include "map/skill.h" // 'MAX_SKILLTIMERSKILL, struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset
+#include "map/unitdefines.h" // enum unit_dir
#include "common/hercules.h"
struct map_session_data;
@@ -67,7 +68,7 @@ struct unit_data {
int64 attackabletime;
int64 canact_tick;
int64 canmove_tick;
- uint8 dir;
+ enum unit_dir dir;
unsigned char walk_count;
unsigned char target_count;
struct {
@@ -102,26 +103,28 @@ struct unit_interface {
int (*final) (void);
/* */
struct unit_data* (*bl2ud) (struct block_list *bl);
+ const struct unit_data* (*cbl2ud) (const struct block_list *bl);
struct unit_data* (*bl2ud2) (struct block_list *bl);
void (*init_ud) (struct unit_data *ud);
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 (*walk_toxy_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*walk_toxy_sub) (struct block_list *bl);
+ int (*delay_walk_toxy_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*walk_toxy) (struct block_list *bl, short x, short y, int flag);
+ int (*walktobl_timer) (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 (*set_dir) (struct block_list *bl, enum unit_dir dir);
+ enum unit_dir (*getdir) (const 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, enum clr_type type);
+ int (*warpto_master) (struct block_list *master_bl, struct block_list *slave_bl);
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 (*step_timer) (int tid, int64 tick, int id, intptr_t data);
+ int (*steptimer) (int tid, int64 tick, int id, intptr_t data);
void (*stop_stepaction) (struct block_list *bl);
int (*is_walking) (struct block_list *bl);
int (*can_move) (struct block_list *bl);
@@ -137,7 +140,7 @@ struct unit_interface {
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 (*calc_pos) (struct block_list *bl, int tx, int ty, enum unit_dir 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);
diff --git a/src/map/unitdefines.h b/src/map/unitdefines.h
new file mode 100644
index 000000000..0ee30998c
--- /dev/null
+++ b/src/map/unitdefines.h
@@ -0,0 +1,58 @@
+/**
+ * This file is part of Hercules.
+ * http://herc.ws - http://github.com/HerculesWS/Hercules
+ *
+ * Copyright (C) 2012-2019 Hercules Dev Team
+ * Copyright (C) Athena Dev Teams
+ *
+ * Hercules is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef MAP_UNITDEFINES_H
+#define MAP_UNITDEFINES_H
+
+/**
+ * Used for directions, @see unit_data.dir
+ */
+enum unit_dir {
+ UNIT_DIR_UNDEFINED = -1,
+ UNIT_DIR_FIRST = 0,
+ UNIT_DIR_NORTH = 0,
+ UNIT_DIR_NORTHWEST = 1,
+ UNIT_DIR_WEST = 2,
+ UNIT_DIR_SOUTHWEST = 3,
+ UNIT_DIR_SOUTH = 4,
+ UNIT_DIR_SOUTHEAST = 5,
+ UNIT_DIR_EAST = 6,
+ UNIT_DIR_NORTHEAST = 7,
+ UNIT_DIR_MAX = 8,
+ /* IMPORTANT: Changing the order would break the above macros
+ * and several usages of directions anywhere */
+};
+
+/* Returns the opposite of the facing direction */
+#define unit_get_opposite_dir(dir) ( ((dir) + 4) % UNIT_DIR_MAX )
+
+/* Returns true when direction is diagonal/combined (ex. UNIT_DIR_NORTHWEST, UNIT_DIR_SOUTHWEST, ...) */
+#define unit_is_diagonal_dir(dir) ( ((dir) % 2) == UNIT_DIR_NORTHWEST )
+
+/* Returns true if direction equals val or the opposite direction of val */
+#define unit_is_dir_or_opposite(dir, val) ( ((dir) % 4) == (val) )
+
+/* Returns the next direction after 90° CCW on a compass */
+#define unit_get_ccw90_dir(dir) ( ((dir) + 2) % UNIT_DIR_MAX )
+
+/* Returns a random diagonal direction */
+#define unit_get_rnd_diagonal_dir() ( UNIT_DIR_NORTHWEST + 2 * (rnd() % 4) )
+
+#endif /* MAP_UNITDEFINES_H */
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc
index 7996a59f9..b8aa5ae61 100644
--- a/src/plugins/HPMHooking/HPMHooking.Defs.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc
@@ -4734,10 +4734,10 @@ typedef uint32 (*HPMHOOK_pre_map_race_id2mask) (int *race);
typedef uint32 (*HPMHOOK_post_map_race_id2mask) (uint32 retVal___, int race);
typedef void (*HPMHOOK_pre_map_reloadnpc) (bool *clear);
typedef void (*HPMHOOK_post_map_reloadnpc) (bool clear);
-typedef int (*HPMHOOK_pre_map_check_dir) (int *s_dir, int *t_dir);
-typedef int (*HPMHOOK_post_map_check_dir) (int retVal___, int s_dir, int t_dir);
-typedef uint8 (*HPMHOOK_pre_map_calc_dir) (struct block_list **src, int16 *x, int16 *y);
-typedef uint8 (*HPMHOOK_post_map_calc_dir) (uint8 retVal___, struct block_list *src, int16 x, int16 y);
+typedef int (*HPMHOOK_pre_map_check_dir) (enum unit_dir *s_dir, enum unit_dir *t_dir);
+typedef int (*HPMHOOK_post_map_check_dir) (int retVal___, enum unit_dir s_dir, enum unit_dir t_dir);
+typedef enum unit_dir (*HPMHOOK_pre_map_calc_dir) (const struct block_list **src, int16 *x, int16 *y);
+typedef enum unit_dir (*HPMHOOK_post_map_calc_dir) (enum unit_dir retVal___, const struct block_list *src, int16 x, int16 y);
typedef int (*HPMHOOK_pre_map_random_dir) (struct block_list **bl, short **x, short **y);
typedef int (*HPMHOOK_post_map_random_dir) (int retVal___, struct block_list *bl, short *x, short *y);
typedef int (*HPMHOOK_pre_map_cleanup_sub) (struct block_list **bl, va_list ap);
@@ -5708,8 +5708,8 @@ typedef int (*HPMHOOK_pre_npc_parseview) (const char **w4, const char **start, c
typedef int (*HPMHOOK_post_npc_parseview) (int retVal___, const char *w4, const char *start, const char *buffer, const char *filepath);
typedef bool (*HPMHOOK_pre_npc_viewisid) (const char **viewid);
typedef bool (*HPMHOOK_post_npc_viewisid) (bool retVal___, const char *viewid);
-typedef struct npc_data* (*HPMHOOK_pre_npc_create_npc) (enum npc_subtype *subtype, int *m, int *x, int *y, uint8 *dir, int *class_);
-typedef struct npc_data* (*HPMHOOK_post_npc_create_npc) (struct npc_data* retVal___, enum npc_subtype subtype, int m, int x, int y, uint8 dir, int class_);
+typedef struct npc_data* (*HPMHOOK_pre_npc_create_npc) (enum npc_subtype *subtype, int *m, int *x, int *y, enum unit_dir *dir, int *class_);
+typedef struct npc_data* (*HPMHOOK_post_npc_create_npc) (struct npc_data* retVal___, enum npc_subtype subtype, int m, int x, int y, enum unit_dir dir, int class_);
typedef struct npc_data* (*HPMHOOK_pre_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);
typedef struct npc_data* (*HPMHOOK_post_npc_add_warp) (struct npc_data* retVal___, 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);
typedef const char* (*HPMHOOK_pre_npc_parse_warp) (const char **w1, const char **w2, const char **w3, const char **w4, const char **start, const char **buffer, const char **filepath, int **retval);
@@ -5830,6 +5830,10 @@ typedef int (*HPMHOOK_pre_npc_secure_timeout_timer) (int *tid, int64 *tick, int
typedef int (*HPMHOOK_post_npc_secure_timeout_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data);
#endif // MAP_NPC_H
#ifdef COMMON_NULLPO_H /* nullpo */
+typedef void (*HPMHOOK_pre_nullpo_init) (void);
+typedef void (*HPMHOOK_post_nullpo_init) (void);
+typedef void (*HPMHOOK_pre_nullpo_final) (void);
+typedef void (*HPMHOOK_post_nullpo_final) (void);
typedef void (*HPMHOOK_pre_nullpo_assert_report) (const char **file, int *line, const char **func, const char **targetname, const char **title);
typedef void (*HPMHOOK_post_nullpo_assert_report) (const char *file, int line, const char *func, const char *targetname, const char *title);
#endif // COMMON_NULLPO_H
@@ -6184,8 +6188,8 @@ typedef int (*HPMHOOK_pre_pc_checkitem) (struct map_session_data **sd);
typedef int (*HPMHOOK_post_pc_checkitem) (int retVal___, struct map_session_data *sd);
typedef int (*HPMHOOK_pre_pc_useitem) (struct map_session_data **sd, int *n);
typedef int (*HPMHOOK_post_pc_useitem) (int retVal___, struct map_session_data *sd, int n);
-typedef int (*HPMHOOK_pre_pc_itemskill_clear) (struct map_session_data **sd);
-typedef int (*HPMHOOK_post_pc_itemskill_clear) (int retVal___, struct map_session_data *sd);
+typedef int (*HPMHOOK_pre_pc_autocast_clear) (struct map_session_data **sd);
+typedef int (*HPMHOOK_post_pc_autocast_clear) (int retVal___, struct map_session_data *sd);
typedef int (*HPMHOOK_pre_pc_skillatk_bonus) (struct map_session_data **sd, uint16 *skill_id);
typedef int (*HPMHOOK_post_pc_skillatk_bonus) (int retVal___, struct map_session_data *sd, uint16 skill_id);
typedef int (*HPMHOOK_pre_pc_skillheal_bonus) (struct map_session_data **sd, uint16 *skill_id);
@@ -6496,6 +6500,8 @@ typedef int (*HPMHOOK_pre_pet_final) (void);
typedef int (*HPMHOOK_post_pet_final) (int retVal___);
typedef int (*HPMHOOK_pre_pet_hungry_val) (struct pet_data **pd);
typedef int (*HPMHOOK_post_pet_hungry_val) (int retVal___, struct pet_data *pd);
+typedef void (*HPMHOOK_pre_pet_set_hunger) (struct pet_data **pd, int *value);
+typedef void (*HPMHOOK_post_pet_set_hunger) (struct pet_data *pd, int value);
typedef void (*HPMHOOK_pre_pet_set_intimate) (struct pet_data **pd, int *value);
typedef void (*HPMHOOK_post_pet_set_intimate) (struct pet_data *pd, int value);
typedef int (*HPMHOOK_pre_pet_create_egg) (struct map_session_data **sd, int *item_id);
@@ -7298,8 +7304,8 @@ typedef int (*HPMHOOK_pre_skill_additional_effect) (struct block_list **src, str
typedef int (*HPMHOOK_post_skill_additional_effect) (int retVal___, struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int dmg_lv, int64 tick);
typedef int (*HPMHOOK_pre_skill_counter_additional_effect) (struct block_list **src, struct block_list **bl, uint16 *skill_id, uint16 *skill_lv, int *attack_type, int64 *tick);
typedef int (*HPMHOOK_post_skill_counter_additional_effect) (int retVal___, struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, int64 tick);
-typedef int (*HPMHOOK_pre_skill_blown) (struct block_list **src, struct block_list **target, int *count, int8 *dir, int *flag);
-typedef int (*HPMHOOK_post_skill_blown) (int retVal___, struct block_list *src, struct block_list *target, int count, int8 dir, int flag);
+typedef int (*HPMHOOK_pre_skill_blown) (struct block_list **src, struct block_list **target, int *count, enum unit_dir *dir, int *flag);
+typedef int (*HPMHOOK_post_skill_blown) (int retVal___, struct block_list *src, struct block_list *target, int count, enum unit_dir dir, int flag);
typedef int (*HPMHOOK_pre_skill_break_equip) (struct block_list **bl, unsigned short *where, int *rate, int *flag);
typedef int (*HPMHOOK_post_skill_break_equip) (int retVal___, struct block_list *bl, unsigned short where, int rate, int flag);
typedef int (*HPMHOOK_pre_skill_strip_equip) (struct block_list **bl, unsigned short *where, int *rate, int *lv, int *time);
@@ -7332,8 +7338,6 @@ typedef int (*HPMHOOK_pre_skill_vf_cast_fix) (struct block_list **bl, double *ti
typedef int (*HPMHOOK_post_skill_vf_cast_fix) (int retVal___, struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv);
typedef int (*HPMHOOK_pre_skill_delay_fix) (struct block_list **bl, uint16 *skill_id, uint16 *skill_lv);
typedef int (*HPMHOOK_post_skill_delay_fix) (int retVal___, struct block_list *bl, uint16 skill_id, uint16 skill_lv);
-typedef bool (*HPMHOOK_pre_skill_is_item_skill) (struct map_session_data **sd, int *skill_id, int *skill_lv);
-typedef bool (*HPMHOOK_post_skill_is_item_skill) (bool retVal___, struct map_session_data *sd, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_check_condition_castbegin) (struct map_session_data **sd, uint16 *skill_id, uint16 *skill_lv);
typedef int (*HPMHOOK_post_skill_check_condition_castbegin) (int retVal___, struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
typedef int (*HPMHOOK_pre_skill_check_condition_castend) (struct map_session_data **sd, uint16 *skill_id, uint16 *skill_lv);
@@ -7384,6 +7388,8 @@ typedef int (*HPMHOOK_pre_skill_not_ok_hom_unknown) (uint16 *skill_id, struct ho
typedef int (*HPMHOOK_post_skill_not_ok_hom_unknown) (int retVal___, uint16 skill_id, struct homun_data *hd);
typedef int (*HPMHOOK_pre_skill_not_ok_mercenary) (uint16 *skill_id, struct mercenary_data **md);
typedef int (*HPMHOOK_post_skill_not_ok_mercenary) (int retVal___, uint16 skill_id, struct mercenary_data *md);
+typedef void (*HPMHOOK_pre_skill_validate_autocast_data) (struct map_session_data **sd, int *skill_id, int *skill_lv);
+typedef void (*HPMHOOK_post_skill_validate_autocast_data) (struct map_session_data *sd, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_chastle_mob_changetarget) (struct block_list **bl, va_list ap);
typedef int (*HPMHOOK_post_skill_chastle_mob_changetarget) (int retVal___, struct block_list *bl, va_list ap);
typedef int (*HPMHOOK_pre_skill_can_produce_mix) (struct map_session_data **sd, int *nameid, int *trigger, int *qty);
@@ -7464,10 +7470,10 @@ typedef int (*HPMHOOK_pre_skill_check_condition_char_sub) (struct block_list **b
typedef int (*HPMHOOK_post_skill_check_condition_char_sub) (int retVal___, struct block_list *bl, va_list ap);
typedef int (*HPMHOOK_pre_skill_check_condition_mob_master_sub) (struct block_list **bl, va_list ap);
typedef int (*HPMHOOK_post_skill_check_condition_mob_master_sub) (int retVal___, struct block_list *bl, va_list ap);
-typedef void (*HPMHOOK_pre_skill_brandishspear_first) (struct square **tc, uint8 *dir, int16 *x, int16 *y);
-typedef void (*HPMHOOK_post_skill_brandishspear_first) (struct square *tc, uint8 dir, int16 x, int16 y);
-typedef void (*HPMHOOK_pre_skill_brandishspear_dir) (struct square **tc, uint8 *dir, int *are);
-typedef void (*HPMHOOK_post_skill_brandishspear_dir) (struct square *tc, uint8 dir, int are);
+typedef void (*HPMHOOK_pre_skill_brandishspear_first) (struct square **tc, enum unit_dir *dir, int16 *x, int16 *y);
+typedef void (*HPMHOOK_post_skill_brandishspear_first) (struct square *tc, enum unit_dir dir, int16 x, int16 y);
+typedef void (*HPMHOOK_pre_skill_brandishspear_dir) (struct square **tc, enum unit_dir *dir, int *are);
+typedef void (*HPMHOOK_post_skill_brandishspear_dir) (struct square *tc, enum unit_dir dir, int are);
typedef int (*HPMHOOK_pre_skill_get_fixed_cast) (int *skill_id, int *skill_lv);
typedef int (*HPMHOOK_post_skill_get_fixed_cast) (int retVal___, int skill_id, int skill_lv);
typedef int (*HPMHOOK_pre_skill_sit_count) (struct block_list **bl, va_list ap);
@@ -7608,8 +7614,8 @@ typedef int (*HPMHOOK_pre_skill_attack_copy_unknown) (int **attack_type, struct
typedef int (*HPMHOOK_post_skill_attack_copy_unknown) (int retVal___, 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);
typedef int (*HPMHOOK_pre_skill_attack_dir_unknown) (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);
typedef int (*HPMHOOK_post_skill_attack_dir_unknown) (int retVal___, 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);
-typedef void (*HPMHOOK_pre_skill_attack_blow_unknown) (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 **type, struct Damage **dmg, int64 **damage, int8 **dir);
-typedef void (*HPMHOOK_post_skill_attack_blow_unknown) (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 *type, struct Damage *dmg, int64 *damage, int8 *dir);
+typedef void (*HPMHOOK_pre_skill_attack_blow_unknown) (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 **type, struct Damage **dmg, int64 **damage, enum unit_dir **dir);
+typedef void (*HPMHOOK_post_skill_attack_blow_unknown) (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 *type, struct Damage *dmg, int64 *damage, enum unit_dir *dir);
typedef void (*HPMHOOK_pre_skill_attack_post_unknown) (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);
typedef void (*HPMHOOK_post_skill_attack_post_unknown) (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);
typedef bool (*HPMHOOK_pre_skill_timerskill_dead_unknown) (struct block_list **src, struct unit_data **ud, struct skill_timerskill **skl);
@@ -8288,22 +8294,24 @@ typedef int (*HPMHOOK_pre_unit_final) (void);
typedef int (*HPMHOOK_post_unit_final) (int retVal___);
typedef struct unit_data* (*HPMHOOK_pre_unit_bl2ud) (struct block_list **bl);
typedef struct unit_data* (*HPMHOOK_post_unit_bl2ud) (struct unit_data* retVal___, struct block_list *bl);
+typedef const struct unit_data* (*HPMHOOK_pre_unit_cbl2ud) (const struct block_list **bl);
+typedef const struct unit_data* (*HPMHOOK_post_unit_cbl2ud) (const struct unit_data* retVal___, const struct block_list *bl);
typedef struct unit_data* (*HPMHOOK_pre_unit_bl2ud2) (struct block_list **bl);
typedef struct unit_data* (*HPMHOOK_post_unit_bl2ud2) (struct unit_data* retVal___, struct block_list *bl);
typedef void (*HPMHOOK_pre_unit_init_ud) (struct unit_data **ud);
typedef void (*HPMHOOK_post_unit_init_ud) (struct unit_data *ud);
typedef int (*HPMHOOK_pre_unit_attack_timer) (int *tid, int64 *tick, int *id, intptr_t *data);
typedef int (*HPMHOOK_post_unit_attack_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data);
-typedef int (*HPMHOOK_pre_unit_walktoxy_timer) (int *tid, int64 *tick, int *id, intptr_t *data);
-typedef int (*HPMHOOK_post_unit_walktoxy_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data);
-typedef int (*HPMHOOK_pre_unit_walktoxy_sub) (struct block_list **bl);
-typedef int (*HPMHOOK_post_unit_walktoxy_sub) (int retVal___, struct block_list *bl);
-typedef int (*HPMHOOK_pre_unit_delay_walktoxy_timer) (int *tid, int64 *tick, int *id, intptr_t *data);
-typedef int (*HPMHOOK_post_unit_delay_walktoxy_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data);
-typedef int (*HPMHOOK_pre_unit_walktoxy) (struct block_list **bl, short *x, short *y, int *flag);
-typedef int (*HPMHOOK_post_unit_walktoxy) (int retVal___, struct block_list *bl, short x, short y, int flag);
-typedef int (*HPMHOOK_pre_unit_walktobl_sub) (int *tid, int64 *tick, int *id, intptr_t *data);
-typedef int (*HPMHOOK_post_unit_walktobl_sub) (int retVal___, int tid, int64 tick, int id, intptr_t data);
+typedef int (*HPMHOOK_pre_unit_walk_toxy_timer) (int *tid, int64 *tick, int *id, intptr_t *data);
+typedef int (*HPMHOOK_post_unit_walk_toxy_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data);
+typedef int (*HPMHOOK_pre_unit_walk_toxy_sub) (struct block_list **bl);
+typedef int (*HPMHOOK_post_unit_walk_toxy_sub) (int retVal___, struct block_list *bl);
+typedef int (*HPMHOOK_pre_unit_delay_walk_toxy_timer) (int *tid, int64 *tick, int *id, intptr_t *data);
+typedef int (*HPMHOOK_post_unit_delay_walk_toxy_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data);
+typedef int (*HPMHOOK_pre_unit_walk_toxy) (struct block_list **bl, short *x, short *y, int *flag);
+typedef int (*HPMHOOK_post_unit_walk_toxy) (int retVal___, struct block_list *bl, short x, short y, int flag);
+typedef int (*HPMHOOK_pre_unit_walktobl_timer) (int *tid, int64 *tick, int *id, intptr_t *data);
+typedef int (*HPMHOOK_post_unit_walktobl_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data);
typedef int (*HPMHOOK_pre_unit_walktobl) (struct block_list **bl, struct block_list **tbl, int *range, int *flag);
typedef int (*HPMHOOK_post_unit_walktobl) (int retVal___, struct block_list *bl, struct block_list *tbl, int range, int flag);
typedef bool (*HPMHOOK_pre_unit_run) (struct block_list **bl, struct map_session_data **sd, enum sc_type *type);
@@ -8314,20 +8322,22 @@ typedef int (*HPMHOOK_pre_unit_escape) (struct block_list **bl, struct block_lis
typedef int (*HPMHOOK_post_unit_escape) (int retVal___, struct block_list *bl, struct block_list *target, short dist);
typedef int (*HPMHOOK_pre_unit_movepos) (struct block_list **bl, short *dst_x, short *dst_y, int *easy, bool *checkpath);
typedef int (*HPMHOOK_post_unit_movepos) (int retVal___, struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath);
-typedef int (*HPMHOOK_pre_unit_setdir) (struct block_list **bl, unsigned char *dir);
-typedef int (*HPMHOOK_post_unit_setdir) (int retVal___, struct block_list *bl, unsigned char dir);
-typedef uint8 (*HPMHOOK_pre_unit_getdir) (struct block_list **bl);
-typedef uint8 (*HPMHOOK_post_unit_getdir) (uint8 retVal___, struct block_list *bl);
+typedef int (*HPMHOOK_pre_unit_set_dir) (struct block_list **bl, enum unit_dir *dir);
+typedef int (*HPMHOOK_post_unit_set_dir) (int retVal___, struct block_list *bl, enum unit_dir dir);
+typedef enum unit_dir (*HPMHOOK_pre_unit_getdir) (const struct block_list **bl);
+typedef enum unit_dir (*HPMHOOK_post_unit_getdir) (enum unit_dir retVal___, const struct block_list *bl);
typedef int (*HPMHOOK_pre_unit_blown) (struct block_list **bl, int *dx, int *dy, int *count, int *flag);
typedef int (*HPMHOOK_post_unit_blown) (int retVal___, struct block_list *bl, int dx, int dy, int count, int flag);
typedef int (*HPMHOOK_pre_unit_warp) (struct block_list **bl, short *m, short *x, short *y, enum clr_type *type);
typedef int (*HPMHOOK_post_unit_warp) (int retVal___, struct block_list *bl, short m, short x, short y, enum clr_type type);
+typedef int (*HPMHOOK_pre_unit_warpto_master) (struct block_list **master_bl, struct block_list **slave_bl);
+typedef int (*HPMHOOK_post_unit_warpto_master) (int retVal___, struct block_list *master_bl, struct block_list *slave_bl);
typedef int (*HPMHOOK_pre_unit_stop_walking) (struct block_list **bl, int *type);
typedef int (*HPMHOOK_post_unit_stop_walking) (int retVal___, struct block_list *bl, int type);
typedef int (*HPMHOOK_pre_unit_skilluse_id) (struct block_list **src, int *target_id, uint16 *skill_id, uint16 *skill_lv);
typedef int (*HPMHOOK_post_unit_skilluse_id) (int retVal___, struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv);
-typedef int (*HPMHOOK_pre_unit_step_timer) (int *tid, int64 *tick, int *id, intptr_t *data);
-typedef int (*HPMHOOK_post_unit_step_timer) (int retVal___, int tid, int64 tick, int id, intptr_t data);
+typedef int (*HPMHOOK_pre_unit_steptimer) (int *tid, int64 *tick, int *id, intptr_t *data);
+typedef int (*HPMHOOK_post_unit_steptimer) (int retVal___, int tid, int64 tick, int id, intptr_t data);
typedef void (*HPMHOOK_pre_unit_stop_stepaction) (struct block_list **bl);
typedef void (*HPMHOOK_post_unit_stop_stepaction) (struct block_list *bl);
typedef int (*HPMHOOK_pre_unit_is_walking) (struct block_list **bl);
@@ -8358,8 +8368,8 @@ typedef bool (*HPMHOOK_pre_unit_can_reach_pos) (struct block_list **bl, int *x,
typedef bool (*HPMHOOK_post_unit_can_reach_pos) (bool retVal___, struct block_list *bl, int x, int y, int easy);
typedef bool (*HPMHOOK_pre_unit_can_reach_bl) (struct block_list **bl, struct block_list **tbl, int *range, int *easy, short **x, short **y);
typedef bool (*HPMHOOK_post_unit_can_reach_bl) (bool retVal___, struct block_list *bl, struct block_list *tbl, int range, int easy, short *x, short *y);
-typedef int (*HPMHOOK_pre_unit_calc_pos) (struct block_list **bl, int *tx, int *ty, uint8 *dir);
-typedef int (*HPMHOOK_post_unit_calc_pos) (int retVal___, struct block_list *bl, int tx, int ty, uint8 dir);
+typedef int (*HPMHOOK_pre_unit_calc_pos) (struct block_list **bl, int *tx, int *ty, enum unit_dir *dir);
+typedef int (*HPMHOOK_post_unit_calc_pos) (int retVal___, struct block_list *bl, int tx, int ty, enum unit_dir dir);
typedef int (*HPMHOOK_pre_unit_attack_timer_sub) (struct block_list **src, int *tid, int64 *tick);
typedef int (*HPMHOOK_post_unit_attack_timer_sub) (int retVal___, struct block_list *src, int tid, int64 tick);
typedef int (*HPMHOOK_pre_unit_skillcastcancel) (struct block_list **bl, int *type);
diff --git a/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc
index 20f57dcb9..ab34a4f18 100644
--- a/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc
@@ -1308,6 +1308,10 @@ struct {
struct HPMHookPoint *HP_mutex_cond_signal_post;
struct HPMHookPoint *HP_mutex_cond_broadcast_pre;
struct HPMHookPoint *HP_mutex_cond_broadcast_post;
+ struct HPMHookPoint *HP_nullpo_init_pre;
+ struct HPMHookPoint *HP_nullpo_init_post;
+ struct HPMHookPoint *HP_nullpo_final_pre;
+ struct HPMHookPoint *HP_nullpo_final_post;
struct HPMHookPoint *HP_nullpo_assert_report_pre;
struct HPMHookPoint *HP_nullpo_assert_report_post;
struct HPMHookPoint *HP_packets_init_pre;
@@ -2933,6 +2937,10 @@ struct {
int HP_mutex_cond_signal_post;
int HP_mutex_cond_broadcast_pre;
int HP_mutex_cond_broadcast_post;
+ int HP_nullpo_init_pre;
+ int HP_nullpo_init_post;
+ int HP_nullpo_final_pre;
+ int HP_nullpo_final_post;
int HP_nullpo_assert_report_pre;
int HP_nullpo_assert_report_post;
int HP_packets_init_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc
index e8e211f8b..238580b83 100644
--- a/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc
@@ -696,6 +696,8 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(mutex->cond_signal, HP_mutex_cond_signal) },
{ HP_POP(mutex->cond_broadcast, HP_mutex_cond_broadcast) },
/* nullpo_interface */
+ { HP_POP(nullpo->init, HP_nullpo_init) },
+ { HP_POP(nullpo->final, HP_nullpo_final) },
{ HP_POP(nullpo->assert_report, HP_nullpo_assert_report) },
/* packets_interface */
{ HP_POP(packets->init, HP_packets_init) },
diff --git a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc
index a022abb54..8c1dec681 100644
--- a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc
@@ -17160,6 +17160,58 @@ void HP_mutex_cond_broadcast(struct cond_data *c) {
return;
}
/* nullpo_interface */
+void HP_nullpo_init(void) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_nullpo_init_pre > 0) {
+ void (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_init_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_nullpo_init_pre[hIndex].func;
+ preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.nullpo.init();
+ }
+ if (HPMHooks.count.HP_nullpo_init_post > 0) {
+ void (*postHookFunc) (void);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_init_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_nullpo_init_post[hIndex].func;
+ postHookFunc();
+ }
+ }
+ return;
+}
+void HP_nullpo_final(void) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_nullpo_final_pre > 0) {
+ void (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_final_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_nullpo_final_pre[hIndex].func;
+ preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.nullpo.final();
+ }
+ if (HPMHooks.count.HP_nullpo_final_post > 0) {
+ void (*postHookFunc) (void);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_final_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_nullpo_final_post[hIndex].func;
+ postHookFunc();
+ }
+ }
+ return;
+}
void HP_nullpo_assert_report(const char *file, int line, const char *func, const char *targetname, const char *title) {
int hIndex = 0;
if (HPMHooks.count.HP_nullpo_assert_report_pre > 0) {
diff --git a/src/plugins/HPMHooking/HPMHooking_login.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_login.HPMHooksCore.inc
index c638a1ef6..2875df334 100644
--- a/src/plugins/HPMHooking/HPMHooking_login.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_login.HPMHooksCore.inc
@@ -520,6 +520,10 @@ struct {
struct HPMHookPoint *HP_mutex_cond_signal_post;
struct HPMHookPoint *HP_mutex_cond_broadcast_pre;
struct HPMHookPoint *HP_mutex_cond_broadcast_post;
+ struct HPMHookPoint *HP_nullpo_init_pre;
+ struct HPMHookPoint *HP_nullpo_init_post;
+ struct HPMHookPoint *HP_nullpo_final_pre;
+ struct HPMHookPoint *HP_nullpo_final_post;
struct HPMHookPoint *HP_nullpo_assert_report_pre;
struct HPMHookPoint *HP_nullpo_assert_report_post;
struct HPMHookPoint *HP_packets_init_pre;
@@ -1325,6 +1329,10 @@ struct {
int HP_mutex_cond_signal_post;
int HP_mutex_cond_broadcast_pre;
int HP_mutex_cond_broadcast_post;
+ int HP_nullpo_init_pre;
+ int HP_nullpo_init_post;
+ int HP_nullpo_final_pre;
+ int HP_nullpo_final_post;
int HP_nullpo_assert_report_pre;
int HP_nullpo_assert_report_post;
int HP_packets_init_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking_login.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_login.HookingPoints.inc
index ef6081f41..61864325b 100644
--- a/src/plugins/HPMHooking/HPMHooking_login.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_login.HookingPoints.inc
@@ -290,6 +290,8 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(mutex->cond_signal, HP_mutex_cond_signal) },
{ HP_POP(mutex->cond_broadcast, HP_mutex_cond_broadcast) },
/* nullpo_interface */
+ { HP_POP(nullpo->init, HP_nullpo_init) },
+ { HP_POP(nullpo->final, HP_nullpo_final) },
{ HP_POP(nullpo->assert_report, HP_nullpo_assert_report) },
/* packets_interface */
{ HP_POP(packets->init, HP_packets_init) },
diff --git a/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc
index 20c709bce..1c1817276 100644
--- a/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc
@@ -6638,6 +6638,58 @@ void HP_mutex_cond_broadcast(struct cond_data *c) {
return;
}
/* nullpo_interface */
+void HP_nullpo_init(void) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_nullpo_init_pre > 0) {
+ void (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_init_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_nullpo_init_pre[hIndex].func;
+ preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.nullpo.init();
+ }
+ if (HPMHooks.count.HP_nullpo_init_post > 0) {
+ void (*postHookFunc) (void);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_init_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_nullpo_init_post[hIndex].func;
+ postHookFunc();
+ }
+ }
+ return;
+}
+void HP_nullpo_final(void) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_nullpo_final_pre > 0) {
+ void (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_final_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_nullpo_final_pre[hIndex].func;
+ preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.nullpo.final();
+ }
+ if (HPMHooks.count.HP_nullpo_final_post > 0) {
+ void (*postHookFunc) (void);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_final_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_nullpo_final_post[hIndex].func;
+ postHookFunc();
+ }
+ }
+ return;
+}
void HP_nullpo_assert_report(const char *file, int line, const char *func, const char *targetname, const char *title) {
int hIndex = 0;
if (HPMHooks.count.HP_nullpo_assert_report_pre > 0) {
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
index 6d8776f18..109c30885 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
@@ -4420,6 +4420,10 @@ struct {
struct HPMHookPoint *HP_npc_questinfo_clear_post;
struct HPMHookPoint *HP_npc_secure_timeout_timer_pre;
struct HPMHookPoint *HP_npc_secure_timeout_timer_post;
+ struct HPMHookPoint *HP_nullpo_init_pre;
+ struct HPMHookPoint *HP_nullpo_init_post;
+ struct HPMHookPoint *HP_nullpo_final_pre;
+ struct HPMHookPoint *HP_nullpo_final_post;
struct HPMHookPoint *HP_nullpo_assert_report_pre;
struct HPMHookPoint *HP_nullpo_assert_report_post;
struct HPMHookPoint *HP_packets_init_pre;
@@ -4764,8 +4768,8 @@ struct {
struct HPMHookPoint *HP_pc_checkitem_post;
struct HPMHookPoint *HP_pc_useitem_pre;
struct HPMHookPoint *HP_pc_useitem_post;
- struct HPMHookPoint *HP_pc_itemskill_clear_pre;
- struct HPMHookPoint *HP_pc_itemskill_clear_post;
+ struct HPMHookPoint *HP_pc_autocast_clear_pre;
+ struct HPMHookPoint *HP_pc_autocast_clear_post;
struct HPMHookPoint *HP_pc_skillatk_bonus_pre;
struct HPMHookPoint *HP_pc_skillatk_bonus_post;
struct HPMHookPoint *HP_pc_skillheal_bonus_pre;
@@ -5072,6 +5076,8 @@ struct {
struct HPMHookPoint *HP_pet_final_post;
struct HPMHookPoint *HP_pet_hungry_val_pre;
struct HPMHookPoint *HP_pet_hungry_val_post;
+ struct HPMHookPoint *HP_pet_set_hunger_pre;
+ struct HPMHookPoint *HP_pet_set_hunger_post;
struct HPMHookPoint *HP_pet_set_intimate_pre;
struct HPMHookPoint *HP_pet_set_intimate_post;
struct HPMHookPoint *HP_pet_create_egg_pre;
@@ -5856,8 +5862,6 @@ struct {
struct HPMHookPoint *HP_skill_vf_cast_fix_post;
struct HPMHookPoint *HP_skill_delay_fix_pre;
struct HPMHookPoint *HP_skill_delay_fix_post;
- struct HPMHookPoint *HP_skill_is_item_skill_pre;
- struct HPMHookPoint *HP_skill_is_item_skill_post;
struct HPMHookPoint *HP_skill_check_condition_castbegin_pre;
struct HPMHookPoint *HP_skill_check_condition_castbegin_post;
struct HPMHookPoint *HP_skill_check_condition_castend_pre;
@@ -5908,6 +5912,8 @@ struct {
struct HPMHookPoint *HP_skill_not_ok_hom_unknown_post;
struct HPMHookPoint *HP_skill_not_ok_mercenary_pre;
struct HPMHookPoint *HP_skill_not_ok_mercenary_post;
+ struct HPMHookPoint *HP_skill_validate_autocast_data_pre;
+ struct HPMHookPoint *HP_skill_validate_autocast_data_post;
struct HPMHookPoint *HP_skill_chastle_mob_changetarget_pre;
struct HPMHookPoint *HP_skill_chastle_mob_changetarget_post;
struct HPMHookPoint *HP_skill_can_produce_mix_pre;
@@ -6786,22 +6792,24 @@ struct {
struct HPMHookPoint *HP_unit_final_post;
struct HPMHookPoint *HP_unit_bl2ud_pre;
struct HPMHookPoint *HP_unit_bl2ud_post;
+ struct HPMHookPoint *HP_unit_cbl2ud_pre;
+ struct HPMHookPoint *HP_unit_cbl2ud_post;
struct HPMHookPoint *HP_unit_bl2ud2_pre;
struct HPMHookPoint *HP_unit_bl2ud2_post;
struct HPMHookPoint *HP_unit_init_ud_pre;
struct HPMHookPoint *HP_unit_init_ud_post;
struct HPMHookPoint *HP_unit_attack_timer_pre;
struct HPMHookPoint *HP_unit_attack_timer_post;
- struct HPMHookPoint *HP_unit_walktoxy_timer_pre;
- struct HPMHookPoint *HP_unit_walktoxy_timer_post;
- struct HPMHookPoint *HP_unit_walktoxy_sub_pre;
- struct HPMHookPoint *HP_unit_walktoxy_sub_post;
- struct HPMHookPoint *HP_unit_delay_walktoxy_timer_pre;
- struct HPMHookPoint *HP_unit_delay_walktoxy_timer_post;
- struct HPMHookPoint *HP_unit_walktoxy_pre;
- struct HPMHookPoint *HP_unit_walktoxy_post;
- struct HPMHookPoint *HP_unit_walktobl_sub_pre;
- struct HPMHookPoint *HP_unit_walktobl_sub_post;
+ struct HPMHookPoint *HP_unit_walk_toxy_timer_pre;
+ struct HPMHookPoint *HP_unit_walk_toxy_timer_post;
+ struct HPMHookPoint *HP_unit_walk_toxy_sub_pre;
+ struct HPMHookPoint *HP_unit_walk_toxy_sub_post;
+ struct HPMHookPoint *HP_unit_delay_walk_toxy_timer_pre;
+ struct HPMHookPoint *HP_unit_delay_walk_toxy_timer_post;
+ struct HPMHookPoint *HP_unit_walk_toxy_pre;
+ struct HPMHookPoint *HP_unit_walk_toxy_post;
+ struct HPMHookPoint *HP_unit_walktobl_timer_pre;
+ struct HPMHookPoint *HP_unit_walktobl_timer_post;
struct HPMHookPoint *HP_unit_walktobl_pre;
struct HPMHookPoint *HP_unit_walktobl_post;
struct HPMHookPoint *HP_unit_run_pre;
@@ -6812,20 +6820,22 @@ struct {
struct HPMHookPoint *HP_unit_escape_post;
struct HPMHookPoint *HP_unit_movepos_pre;
struct HPMHookPoint *HP_unit_movepos_post;
- struct HPMHookPoint *HP_unit_setdir_pre;
- struct HPMHookPoint *HP_unit_setdir_post;
+ struct HPMHookPoint *HP_unit_set_dir_pre;
+ struct HPMHookPoint *HP_unit_set_dir_post;
struct HPMHookPoint *HP_unit_getdir_pre;
struct HPMHookPoint *HP_unit_getdir_post;
struct HPMHookPoint *HP_unit_blown_pre;
struct HPMHookPoint *HP_unit_blown_post;
struct HPMHookPoint *HP_unit_warp_pre;
struct HPMHookPoint *HP_unit_warp_post;
+ struct HPMHookPoint *HP_unit_warpto_master_pre;
+ struct HPMHookPoint *HP_unit_warpto_master_post;
struct HPMHookPoint *HP_unit_stop_walking_pre;
struct HPMHookPoint *HP_unit_stop_walking_post;
struct HPMHookPoint *HP_unit_skilluse_id_pre;
struct HPMHookPoint *HP_unit_skilluse_id_post;
- struct HPMHookPoint *HP_unit_step_timer_pre;
- struct HPMHookPoint *HP_unit_step_timer_post;
+ struct HPMHookPoint *HP_unit_steptimer_pre;
+ struct HPMHookPoint *HP_unit_steptimer_post;
struct HPMHookPoint *HP_unit_stop_stepaction_pre;
struct HPMHookPoint *HP_unit_stop_stepaction_post;
struct HPMHookPoint *HP_unit_is_walking_pre;
@@ -11291,6 +11301,10 @@ struct {
int HP_npc_questinfo_clear_post;
int HP_npc_secure_timeout_timer_pre;
int HP_npc_secure_timeout_timer_post;
+ int HP_nullpo_init_pre;
+ int HP_nullpo_init_post;
+ int HP_nullpo_final_pre;
+ int HP_nullpo_final_post;
int HP_nullpo_assert_report_pre;
int HP_nullpo_assert_report_post;
int HP_packets_init_pre;
@@ -11635,8 +11649,8 @@ struct {
int HP_pc_checkitem_post;
int HP_pc_useitem_pre;
int HP_pc_useitem_post;
- int HP_pc_itemskill_clear_pre;
- int HP_pc_itemskill_clear_post;
+ int HP_pc_autocast_clear_pre;
+ int HP_pc_autocast_clear_post;
int HP_pc_skillatk_bonus_pre;
int HP_pc_skillatk_bonus_post;
int HP_pc_skillheal_bonus_pre;
@@ -11943,6 +11957,8 @@ struct {
int HP_pet_final_post;
int HP_pet_hungry_val_pre;
int HP_pet_hungry_val_post;
+ int HP_pet_set_hunger_pre;
+ int HP_pet_set_hunger_post;
int HP_pet_set_intimate_pre;
int HP_pet_set_intimate_post;
int HP_pet_create_egg_pre;
@@ -12727,8 +12743,6 @@ struct {
int HP_skill_vf_cast_fix_post;
int HP_skill_delay_fix_pre;
int HP_skill_delay_fix_post;
- int HP_skill_is_item_skill_pre;
- int HP_skill_is_item_skill_post;
int HP_skill_check_condition_castbegin_pre;
int HP_skill_check_condition_castbegin_post;
int HP_skill_check_condition_castend_pre;
@@ -12779,6 +12793,8 @@ struct {
int HP_skill_not_ok_hom_unknown_post;
int HP_skill_not_ok_mercenary_pre;
int HP_skill_not_ok_mercenary_post;
+ int HP_skill_validate_autocast_data_pre;
+ int HP_skill_validate_autocast_data_post;
int HP_skill_chastle_mob_changetarget_pre;
int HP_skill_chastle_mob_changetarget_post;
int HP_skill_can_produce_mix_pre;
@@ -13657,22 +13673,24 @@ struct {
int HP_unit_final_post;
int HP_unit_bl2ud_pre;
int HP_unit_bl2ud_post;
+ int HP_unit_cbl2ud_pre;
+ int HP_unit_cbl2ud_post;
int HP_unit_bl2ud2_pre;
int HP_unit_bl2ud2_post;
int HP_unit_init_ud_pre;
int HP_unit_init_ud_post;
int HP_unit_attack_timer_pre;
int HP_unit_attack_timer_post;
- int HP_unit_walktoxy_timer_pre;
- int HP_unit_walktoxy_timer_post;
- int HP_unit_walktoxy_sub_pre;
- int HP_unit_walktoxy_sub_post;
- int HP_unit_delay_walktoxy_timer_pre;
- int HP_unit_delay_walktoxy_timer_post;
- int HP_unit_walktoxy_pre;
- int HP_unit_walktoxy_post;
- int HP_unit_walktobl_sub_pre;
- int HP_unit_walktobl_sub_post;
+ int HP_unit_walk_toxy_timer_pre;
+ int HP_unit_walk_toxy_timer_post;
+ int HP_unit_walk_toxy_sub_pre;
+ int HP_unit_walk_toxy_sub_post;
+ int HP_unit_delay_walk_toxy_timer_pre;
+ int HP_unit_delay_walk_toxy_timer_post;
+ int HP_unit_walk_toxy_pre;
+ int HP_unit_walk_toxy_post;
+ int HP_unit_walktobl_timer_pre;
+ int HP_unit_walktobl_timer_post;
int HP_unit_walktobl_pre;
int HP_unit_walktobl_post;
int HP_unit_run_pre;
@@ -13683,20 +13701,22 @@ struct {
int HP_unit_escape_post;
int HP_unit_movepos_pre;
int HP_unit_movepos_post;
- int HP_unit_setdir_pre;
- int HP_unit_setdir_post;
+ int HP_unit_set_dir_pre;
+ int HP_unit_set_dir_post;
int HP_unit_getdir_pre;
int HP_unit_getdir_post;
int HP_unit_blown_pre;
int HP_unit_blown_post;
int HP_unit_warp_pre;
int HP_unit_warp_post;
+ int HP_unit_warpto_master_pre;
+ int HP_unit_warpto_master_post;
int HP_unit_stop_walking_pre;
int HP_unit_stop_walking_post;
int HP_unit_skilluse_id_pre;
int HP_unit_skilluse_id_post;
- int HP_unit_step_timer_pre;
- int HP_unit_step_timer_post;
+ int HP_unit_steptimer_pre;
+ int HP_unit_steptimer_post;
int HP_unit_stop_stepaction_pre;
int HP_unit_stop_stepaction_post;
int HP_unit_is_walking_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
index 672b94dd8..ac30b97d4 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
@@ -2263,6 +2263,8 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(npc->questinfo_clear, HP_npc_questinfo_clear) },
{ HP_POP(npc->secure_timeout_timer, HP_npc_secure_timeout_timer) },
/* nullpo_interface */
+ { HP_POP(nullpo->init, HP_nullpo_init) },
+ { HP_POP(nullpo->final, HP_nullpo_final) },
{ HP_POP(nullpo->assert_report, HP_nullpo_assert_report) },
/* packets_interface */
{ HP_POP(packets->init, HP_packets_init) },
@@ -2440,7 +2442,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(pc->unequipitem_pos, HP_pc_unequipitem_pos) },
{ HP_POP(pc->checkitem, HP_pc_checkitem) },
{ HP_POP(pc->useitem, HP_pc_useitem) },
- { HP_POP(pc->itemskill_clear, HP_pc_itemskill_clear) },
+ { HP_POP(pc->autocast_clear, HP_pc_autocast_clear) },
{ HP_POP(pc->skillatk_bonus, HP_pc_skillatk_bonus) },
{ HP_POP(pc->skillheal_bonus, HP_pc_skillheal_bonus) },
{ HP_POP(pc->skillheal2_bonus, HP_pc_skillheal2_bonus) },
@@ -2596,6 +2598,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(pet->init, HP_pet_init) },
{ HP_POP(pet->final, HP_pet_final) },
{ HP_POP(pet->hungry_val, HP_pet_hungry_val) },
+ { HP_POP(pet->set_hunger, HP_pet_set_hunger) },
{ HP_POP(pet->set_intimate, HP_pet_set_intimate) },
{ HP_POP(pet->create_egg, HP_pet_create_egg) },
{ HP_POP(pet->unlocktarget, HP_pet_unlocktarget) },
@@ -2997,7 +3000,6 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(skill->cast_fix_sc, HP_skill_cast_fix_sc) },
{ HP_POP(skill->vf_cast_fix, HP_skill_vf_cast_fix) },
{ HP_POP(skill->delay_fix, HP_skill_delay_fix) },
- { HP_POP(skill->is_item_skill, HP_skill_is_item_skill) },
{ HP_POP(skill->check_condition_castbegin, HP_skill_check_condition_castbegin) },
{ HP_POP(skill->check_condition_castend, HP_skill_check_condition_castend) },
{ HP_POP(skill->consume_requirement, HP_skill_consume_requirement) },
@@ -3023,6 +3025,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(skill->not_ok_hom, HP_skill_not_ok_hom) },
{ HP_POP(skill->not_ok_hom_unknown, HP_skill_not_ok_hom_unknown) },
{ HP_POP(skill->not_ok_mercenary, HP_skill_not_ok_mercenary) },
+ { HP_POP(skill->validate_autocast_data, HP_skill_validate_autocast_data) },
{ HP_POP(skill->chastle_mob_changetarget, HP_skill_chastle_mob_changetarget) },
{ HP_POP(skill->can_produce_mix, HP_skill_can_produce_mix) },
{ HP_POP(skill->produce_mix, HP_skill_produce_mix) },
@@ -3475,26 +3478,28 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(unit->init, HP_unit_init) },
{ HP_POP(unit->final, HP_unit_final) },
{ HP_POP(unit->bl2ud, HP_unit_bl2ud) },
+ { HP_POP(unit->cbl2ud, HP_unit_cbl2ud) },
{ HP_POP(unit->bl2ud2, HP_unit_bl2ud2) },
{ HP_POP(unit->init_ud, HP_unit_init_ud) },
{ HP_POP(unit->attack_timer, HP_unit_attack_timer) },
- { HP_POP(unit->walktoxy_timer, HP_unit_walktoxy_timer) },
- { HP_POP(unit->walktoxy_sub, HP_unit_walktoxy_sub) },
- { HP_POP(unit->delay_walktoxy_timer, HP_unit_delay_walktoxy_timer) },
- { HP_POP(unit->walktoxy, HP_unit_walktoxy) },
- { HP_POP(unit->walktobl_sub, HP_unit_walktobl_sub) },
+ { HP_POP(unit->walk_toxy_timer, HP_unit_walk_toxy_timer) },
+ { HP_POP(unit->walk_toxy_sub, HP_unit_walk_toxy_sub) },
+ { HP_POP(unit->delay_walk_toxy_timer, HP_unit_delay_walk_toxy_timer) },
+ { HP_POP(unit->walk_toxy, HP_unit_walk_toxy) },
+ { HP_POP(unit->walktobl_timer, HP_unit_walktobl_timer) },
{ HP_POP(unit->walktobl, HP_unit_walktobl) },
{ HP_POP(unit->run, HP_unit_run) },
{ HP_POP(unit->run_hit, HP_unit_run_hit) },
{ HP_POP(unit->escape, HP_unit_escape) },
{ HP_POP(unit->movepos, HP_unit_movepos) },
- { HP_POP(unit->setdir, HP_unit_setdir) },
+ { HP_POP(unit->set_dir, HP_unit_set_dir) },
{ HP_POP(unit->getdir, HP_unit_getdir) },
{ HP_POP(unit->blown, HP_unit_blown) },
{ HP_POP(unit->warp, HP_unit_warp) },
+ { HP_POP(unit->warpto_master, HP_unit_warpto_master) },
{ HP_POP(unit->stop_walking, HP_unit_stop_walking) },
{ HP_POP(unit->skilluse_id, HP_unit_skilluse_id) },
- { HP_POP(unit->step_timer, HP_unit_step_timer) },
+ { HP_POP(unit->steptimer, HP_unit_steptimer) },
{ HP_POP(unit->stop_stepaction, HP_unit_stop_stepaction) },
{ HP_POP(unit->is_walking, HP_unit_is_walking) },
{ HP_POP(unit->can_move, HP_unit_can_move) },
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index 423490182..940f96ca2 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -48284,11 +48284,11 @@ void HP_map_reloadnpc(bool clear) {
}
return;
}
-int HP_map_check_dir(int s_dir, int t_dir) {
+int HP_map_check_dir(enum unit_dir s_dir, enum unit_dir t_dir) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_map_check_dir_pre > 0) {
- int (*preHookFunc) (int *s_dir, int *t_dir);
+ int (*preHookFunc) (enum unit_dir *s_dir, enum unit_dir *t_dir);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_map_check_dir_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_map_check_dir_pre[hIndex].func;
@@ -48303,7 +48303,7 @@ int HP_map_check_dir(int s_dir, int t_dir) {
retVal___ = HPMHooks.source.map.check_dir(s_dir, t_dir);
}
if (HPMHooks.count.HP_map_check_dir_post > 0) {
- int (*postHookFunc) (int retVal___, int s_dir, int t_dir);
+ int (*postHookFunc) (int retVal___, enum unit_dir s_dir, enum unit_dir t_dir);
for (hIndex = 0; hIndex < HPMHooks.count.HP_map_check_dir_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_map_check_dir_post[hIndex].func;
retVal___ = postHookFunc(retVal___, s_dir, t_dir);
@@ -48311,11 +48311,11 @@ int HP_map_check_dir(int s_dir, int t_dir) {
}
return retVal___;
}
-uint8 HP_map_calc_dir(struct block_list *src, int16 x, int16 y) {
+enum unit_dir HP_map_calc_dir(const struct block_list *src, int16 x, int16 y) {
int hIndex = 0;
- uint8 retVal___ = 0;
+ enum unit_dir retVal___ = UNIT_DIR_UNDEFINED;
if (HPMHooks.count.HP_map_calc_dir_pre > 0) {
- uint8 (*preHookFunc) (struct block_list **src, int16 *x, int16 *y);
+ enum unit_dir (*preHookFunc) (const struct block_list **src, int16 *x, int16 *y);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_map_calc_dir_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_map_calc_dir_pre[hIndex].func;
@@ -48330,7 +48330,7 @@ uint8 HP_map_calc_dir(struct block_list *src, int16 x, int16 y) {
retVal___ = HPMHooks.source.map.calc_dir(src, x, y);
}
if (HPMHooks.count.HP_map_calc_dir_post > 0) {
- uint8 (*postHookFunc) (uint8 retVal___, struct block_list *src, int16 x, int16 y);
+ enum unit_dir (*postHookFunc) (enum unit_dir retVal___, const struct block_list *src, int16 x, int16 y);
for (hIndex = 0; hIndex < HPMHooks.count.HP_map_calc_dir_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_map_calc_dir_post[hIndex].func;
retVal___ = postHookFunc(retVal___, src, x, y);
@@ -57108,11 +57108,11 @@ bool HP_npc_viewisid(const char *viewid) {
}
return retVal___;
}
-struct npc_data* HP_npc_create_npc(enum npc_subtype subtype, int m, int x, int y, uint8 dir, int class_) {
+struct npc_data* HP_npc_create_npc(enum npc_subtype subtype, int m, int x, int y, enum unit_dir dir, int class_) {
int hIndex = 0;
struct npc_data* retVal___ = NULL;
if (HPMHooks.count.HP_npc_create_npc_pre > 0) {
- struct npc_data* (*preHookFunc) (enum npc_subtype *subtype, int *m, int *x, int *y, uint8 *dir, int *class_);
+ struct npc_data* (*preHookFunc) (enum npc_subtype *subtype, int *m, int *x, int *y, enum unit_dir *dir, int *class_);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_npc_create_npc_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_npc_create_npc_pre[hIndex].func;
@@ -57127,7 +57127,7 @@ struct npc_data* HP_npc_create_npc(enum npc_subtype subtype, int m, int x, int y
retVal___ = HPMHooks.source.npc.create_npc(subtype, m, x, y, dir, class_);
}
if (HPMHooks.count.HP_npc_create_npc_post > 0) {
- struct npc_data* (*postHookFunc) (struct npc_data* retVal___, enum npc_subtype subtype, int m, int x, int y, uint8 dir, int class_);
+ struct npc_data* (*postHookFunc) (struct npc_data* retVal___, enum npc_subtype subtype, int m, int x, int y, enum unit_dir dir, int class_);
for (hIndex = 0; hIndex < HPMHooks.count.HP_npc_create_npc_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_npc_create_npc_post[hIndex].func;
retVal___ = postHookFunc(retVal___, subtype, m, x, y, dir, class_);
@@ -58718,6 +58718,58 @@ int HP_npc_secure_timeout_timer(int tid, int64 tick, int id, intptr_t data) {
return retVal___;
}
/* nullpo_interface */
+void HP_nullpo_init(void) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_nullpo_init_pre > 0) {
+ void (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_init_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_nullpo_init_pre[hIndex].func;
+ preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.nullpo.init();
+ }
+ if (HPMHooks.count.HP_nullpo_init_post > 0) {
+ void (*postHookFunc) (void);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_init_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_nullpo_init_post[hIndex].func;
+ postHookFunc();
+ }
+ }
+ return;
+}
+void HP_nullpo_final(void) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_nullpo_final_pre > 0) {
+ void (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_final_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_nullpo_final_pre[hIndex].func;
+ preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.nullpo.final();
+ }
+ if (HPMHooks.count.HP_nullpo_final_post > 0) {
+ void (*postHookFunc) (void);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_nullpo_final_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_nullpo_final_post[hIndex].func;
+ postHookFunc();
+ }
+ }
+ return;
+}
void HP_nullpo_assert_report(const char *file, int line, const char *func, const char *targetname, const char *title) {
int hIndex = 0;
if (HPMHooks.count.HP_nullpo_assert_report_pre > 0) {
@@ -63359,14 +63411,14 @@ int HP_pc_useitem(struct map_session_data *sd, int n) {
}
return retVal___;
}
-int HP_pc_itemskill_clear(struct map_session_data *sd) {
+int HP_pc_autocast_clear(struct map_session_data *sd) {
int hIndex = 0;
int retVal___ = 0;
- if (HPMHooks.count.HP_pc_itemskill_clear_pre > 0) {
+ if (HPMHooks.count.HP_pc_autocast_clear_pre > 0) {
int (*preHookFunc) (struct map_session_data **sd);
*HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_itemskill_clear_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_pc_itemskill_clear_pre[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_autocast_clear_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_pc_autocast_clear_pre[hIndex].func;
retVal___ = preHookFunc(&sd);
}
if (*HPMforce_return) {
@@ -63375,12 +63427,12 @@ int HP_pc_itemskill_clear(struct map_session_data *sd) {
}
}
{
- retVal___ = HPMHooks.source.pc.itemskill_clear(sd);
+ retVal___ = HPMHooks.source.pc.autocast_clear(sd);
}
- if (HPMHooks.count.HP_pc_itemskill_clear_post > 0) {
+ if (HPMHooks.count.HP_pc_autocast_clear_post > 0) {
int (*postHookFunc) (int retVal___, struct map_session_data *sd);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_itemskill_clear_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_pc_itemskill_clear_post[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_autocast_clear_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_pc_autocast_clear_post[hIndex].func;
retVal___ = postHookFunc(retVal___, sd);
}
}
@@ -67509,6 +67561,32 @@ int HP_pet_hungry_val(struct pet_data *pd) {
}
return retVal___;
}
+void HP_pet_set_hunger(struct pet_data *pd, int value) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_pet_set_hunger_pre > 0) {
+ void (*preHookFunc) (struct pet_data **pd, int *value);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_set_hunger_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_pet_set_hunger_pre[hIndex].func;
+ preHookFunc(&pd, &value);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pet.set_hunger(pd, value);
+ }
+ if (HPMHooks.count.HP_pet_set_hunger_post > 0) {
+ void (*postHookFunc) (struct pet_data *pd, int value);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pet_set_hunger_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_pet_set_hunger_post[hIndex].func;
+ postHookFunc(pd, value);
+ }
+ }
+ return;
+}
void HP_pet_set_intimate(struct pet_data *pd, int value) {
int hIndex = 0;
if (HPMHooks.count.HP_pet_set_intimate_pre > 0) {
@@ -77704,11 +77782,11 @@ int HP_skill_counter_additional_effect(struct block_list *src, struct block_list
}
return retVal___;
}
-int HP_skill_blown(struct block_list *src, struct block_list *target, int count, int8 dir, int flag) {
+int HP_skill_blown(struct block_list *src, struct block_list *target, int count, enum unit_dir dir, int flag) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_skill_blown_pre > 0) {
- int (*preHookFunc) (struct block_list **src, struct block_list **target, int *count, int8 *dir, int *flag);
+ int (*preHookFunc) (struct block_list **src, struct block_list **target, int *count, enum unit_dir *dir, int *flag);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_blown_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_skill_blown_pre[hIndex].func;
@@ -77723,7 +77801,7 @@ int HP_skill_blown(struct block_list *src, struct block_list *target, int count,
retVal___ = HPMHooks.source.skill.blown(src, target, count, dir, flag);
}
if (HPMHooks.count.HP_skill_blown_post > 0) {
- int (*postHookFunc) (int retVal___, struct block_list *src, struct block_list *target, int count, int8 dir, int flag);
+ int (*postHookFunc) (int retVal___, struct block_list *src, struct block_list *target, int count, enum unit_dir dir, int flag);
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_blown_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_skill_blown_post[hIndex].func;
retVal___ = postHookFunc(retVal___, src, target, count, dir, flag);
@@ -78163,33 +78241,6 @@ int HP_skill_delay_fix(struct block_list *bl, uint16 skill_id, uint16 skill_lv)
}
return retVal___;
}
-bool HP_skill_is_item_skill(struct map_session_data *sd, int skill_id, int skill_lv) {
- int hIndex = 0;
- bool retVal___ = false;
- if (HPMHooks.count.HP_skill_is_item_skill_pre > 0) {
- bool (*preHookFunc) (struct map_session_data **sd, int *skill_id, int *skill_lv);
- *HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_is_item_skill_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_skill_is_item_skill_pre[hIndex].func;
- retVal___ = preHookFunc(&sd, &skill_id, &skill_lv);
- }
- if (*HPMforce_return) {
- *HPMforce_return = false;
- return retVal___;
- }
- }
- {
- retVal___ = HPMHooks.source.skill.is_item_skill(sd, skill_id, skill_lv);
- }
- if (HPMHooks.count.HP_skill_is_item_skill_post > 0) {
- bool (*postHookFunc) (bool retVal___, struct map_session_data *sd, int skill_id, int skill_lv);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_is_item_skill_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_skill_is_item_skill_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, sd, skill_id, skill_lv);
- }
- }
- return retVal___;
-}
int HP_skill_check_condition_castbegin(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv) {
int hIndex = 0;
int retVal___ = 0;
@@ -78867,6 +78918,32 @@ int HP_skill_not_ok_mercenary(uint16 skill_id, struct mercenary_data *md) {
}
return retVal___;
}
+void HP_skill_validate_autocast_data(struct map_session_data *sd, int skill_id, int skill_lv) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_skill_validate_autocast_data_pre > 0) {
+ void (*preHookFunc) (struct map_session_data **sd, int *skill_id, int *skill_lv);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_validate_autocast_data_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_skill_validate_autocast_data_pre[hIndex].func;
+ preHookFunc(&sd, &skill_id, &skill_lv);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.skill.validate_autocast_data(sd, skill_id, skill_lv);
+ }
+ if (HPMHooks.count.HP_skill_validate_autocast_data_post > 0) {
+ void (*postHookFunc) (struct map_session_data *sd, int skill_id, int skill_lv);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_validate_autocast_data_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_skill_validate_autocast_data_post[hIndex].func;
+ postHookFunc(sd, skill_id, skill_lv);
+ }
+ }
+ return;
+}
int HP_skill_chastle_mob_changetarget(struct block_list *bl, va_list ap) {
int hIndex = 0;
int retVal___ = 0;
@@ -80034,10 +80111,10 @@ int HP_skill_check_condition_mob_master_sub(struct block_list *bl, va_list ap) {
}
return retVal___;
}
-void HP_skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int16 y) {
+void HP_skill_brandishspear_first(struct square *tc, enum unit_dir dir, int16 x, int16 y) {
int hIndex = 0;
if (HPMHooks.count.HP_skill_brandishspear_first_pre > 0) {
- void (*preHookFunc) (struct square **tc, uint8 *dir, int16 *x, int16 *y);
+ void (*preHookFunc) (struct square **tc, enum unit_dir *dir, int16 *x, int16 *y);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_brandishspear_first_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_skill_brandishspear_first_pre[hIndex].func;
@@ -80052,7 +80129,7 @@ void HP_skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int16 y
HPMHooks.source.skill.brandishspear_first(tc, dir, x, y);
}
if (HPMHooks.count.HP_skill_brandishspear_first_post > 0) {
- void (*postHookFunc) (struct square *tc, uint8 dir, int16 x, int16 y);
+ void (*postHookFunc) (struct square *tc, enum unit_dir dir, int16 x, int16 y);
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_brandishspear_first_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_skill_brandishspear_first_post[hIndex].func;
postHookFunc(tc, dir, x, y);
@@ -80060,10 +80137,10 @@ void HP_skill_brandishspear_first(struct square *tc, uint8 dir, int16 x, int16 y
}
return;
}
-void HP_skill_brandishspear_dir(struct square *tc, uint8 dir, int are) {
+void HP_skill_brandishspear_dir(struct square *tc, enum unit_dir dir, int are) {
int hIndex = 0;
if (HPMHooks.count.HP_skill_brandishspear_dir_pre > 0) {
- void (*preHookFunc) (struct square **tc, uint8 *dir, int *are);
+ void (*preHookFunc) (struct square **tc, enum unit_dir *dir, int *are);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_brandishspear_dir_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_skill_brandishspear_dir_pre[hIndex].func;
@@ -80078,7 +80155,7 @@ void HP_skill_brandishspear_dir(struct square *tc, uint8 dir, int are) {
HPMHooks.source.skill.brandishspear_dir(tc, dir, are);
}
if (HPMHooks.count.HP_skill_brandishspear_dir_post > 0) {
- void (*postHookFunc) (struct square *tc, uint8 dir, int are);
+ void (*postHookFunc) (struct square *tc, enum unit_dir dir, int are);
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_brandishspear_dir_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_skill_brandishspear_dir_post[hIndex].func;
postHookFunc(tc, dir, are);
@@ -81995,10 +82072,10 @@ int HP_skill_attack_dir_unknown(int *attack_type, struct block_list *src, struct
}
return retVal___;
}
-void HP_skill_attack_blow_unknown(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 *type, struct Damage *dmg, int64 *damage, int8 *dir) {
+void HP_skill_attack_blow_unknown(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 *type, struct Damage *dmg, int64 *damage, enum unit_dir *dir) {
int hIndex = 0;
if (HPMHooks.count.HP_skill_attack_blow_unknown_pre > 0) {
- void (*preHookFunc) (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 **type, struct Damage **dmg, int64 **damage, int8 **dir);
+ void (*preHookFunc) (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 **type, struct Damage **dmg, int64 **damage, enum unit_dir **dir);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_attack_blow_unknown_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_skill_attack_blow_unknown_pre[hIndex].func;
@@ -82013,7 +82090,7 @@ void HP_skill_attack_blow_unknown(int *attack_type, struct block_list *src, stru
HPMHooks.source.skill.attack_blow_unknown(attack_type, src, dsrc, bl, skill_id, skill_lv, tick, flag, type, dmg, damage, dir);
}
if (HPMHooks.count.HP_skill_attack_blow_unknown_post > 0) {
- void (*postHookFunc) (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 *type, struct Damage *dmg, int64 *damage, int8 *dir);
+ void (*postHookFunc) (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 *type, struct Damage *dmg, int64 *damage, enum unit_dir *dir);
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_attack_blow_unknown_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_skill_attack_blow_unknown_post[hIndex].func;
postHookFunc(attack_type, src, dsrc, bl, skill_id, skill_lv, tick, flag, type, dmg, damage, dir);
@@ -90806,6 +90883,33 @@ struct unit_data* HP_unit_bl2ud(struct block_list *bl) {
}
return retVal___;
}
+const struct unit_data* HP_unit_cbl2ud(const struct block_list *bl) {
+ int hIndex = 0;
+ const struct unit_data* retVal___ = NULL;
+ if (HPMHooks.count.HP_unit_cbl2ud_pre > 0) {
+ const struct unit_data* (*preHookFunc) (const struct block_list **bl);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_cbl2ud_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_unit_cbl2ud_pre[hIndex].func;
+ retVal___ = preHookFunc(&bl);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.unit.cbl2ud(bl);
+ }
+ if (HPMHooks.count.HP_unit_cbl2ud_post > 0) {
+ const struct unit_data* (*postHookFunc) (const struct unit_data* retVal___, const struct block_list *bl);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_cbl2ud_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_unit_cbl2ud_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, bl);
+ }
+ }
+ return retVal___;
+}
struct unit_data* HP_unit_bl2ud2(struct block_list *bl) {
int hIndex = 0;
struct unit_data* retVal___ = NULL;
@@ -90886,14 +90990,14 @@ int HP_unit_attack_timer(int tid, int64 tick, int id, intptr_t data) {
}
return retVal___;
}
-int HP_unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
+int HP_unit_walk_toxy_timer(int tid, int64 tick, int id, intptr_t data) {
int hIndex = 0;
int retVal___ = 0;
- if (HPMHooks.count.HP_unit_walktoxy_timer_pre > 0) {
+ if (HPMHooks.count.HP_unit_walk_toxy_timer_pre > 0) {
int (*preHookFunc) (int *tid, int64 *tick, int *id, intptr_t *data);
*HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walktoxy_timer_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_unit_walktoxy_timer_pre[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walk_toxy_timer_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_unit_walk_toxy_timer_pre[hIndex].func;
retVal___ = preHookFunc(&tid, &tick, &id, &data);
}
if (*HPMforce_return) {
@@ -90902,25 +91006,25 @@ int HP_unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
}
}
{
- retVal___ = HPMHooks.source.unit.walktoxy_timer(tid, tick, id, data);
+ retVal___ = HPMHooks.source.unit.walk_toxy_timer(tid, tick, id, data);
}
- if (HPMHooks.count.HP_unit_walktoxy_timer_post > 0) {
+ if (HPMHooks.count.HP_unit_walk_toxy_timer_post > 0) {
int (*postHookFunc) (int retVal___, int tid, int64 tick, int id, intptr_t data);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walktoxy_timer_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_unit_walktoxy_timer_post[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walk_toxy_timer_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_unit_walk_toxy_timer_post[hIndex].func;
retVal___ = postHookFunc(retVal___, tid, tick, id, data);
}
}
return retVal___;
}
-int HP_unit_walktoxy_sub(struct block_list *bl) {
+int HP_unit_walk_toxy_sub(struct block_list *bl) {
int hIndex = 0;
int retVal___ = 0;
- if (HPMHooks.count.HP_unit_walktoxy_sub_pre > 0) {
+ if (HPMHooks.count.HP_unit_walk_toxy_sub_pre > 0) {
int (*preHookFunc) (struct block_list **bl);
*HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walktoxy_sub_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_unit_walktoxy_sub_pre[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walk_toxy_sub_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_unit_walk_toxy_sub_pre[hIndex].func;
retVal___ = preHookFunc(&bl);
}
if (*HPMforce_return) {
@@ -90929,25 +91033,25 @@ int HP_unit_walktoxy_sub(struct block_list *bl) {
}
}
{
- retVal___ = HPMHooks.source.unit.walktoxy_sub(bl);
+ retVal___ = HPMHooks.source.unit.walk_toxy_sub(bl);
}
- if (HPMHooks.count.HP_unit_walktoxy_sub_post > 0) {
+ if (HPMHooks.count.HP_unit_walk_toxy_sub_post > 0) {
int (*postHookFunc) (int retVal___, struct block_list *bl);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walktoxy_sub_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_unit_walktoxy_sub_post[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walk_toxy_sub_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_unit_walk_toxy_sub_post[hIndex].func;
retVal___ = postHookFunc(retVal___, bl);
}
}
return retVal___;
}
-int HP_unit_delay_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
+int HP_unit_delay_walk_toxy_timer(int tid, int64 tick, int id, intptr_t data) {
int hIndex = 0;
int retVal___ = 0;
- if (HPMHooks.count.HP_unit_delay_walktoxy_timer_pre > 0) {
+ if (HPMHooks.count.HP_unit_delay_walk_toxy_timer_pre > 0) {
int (*preHookFunc) (int *tid, int64 *tick, int *id, intptr_t *data);
*HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_delay_walktoxy_timer_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_unit_delay_walktoxy_timer_pre[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_delay_walk_toxy_timer_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_unit_delay_walk_toxy_timer_pre[hIndex].func;
retVal___ = preHookFunc(&tid, &tick, &id, &data);
}
if (*HPMforce_return) {
@@ -90956,25 +91060,25 @@ int HP_unit_delay_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
}
}
{
- retVal___ = HPMHooks.source.unit.delay_walktoxy_timer(tid, tick, id, data);
+ retVal___ = HPMHooks.source.unit.delay_walk_toxy_timer(tid, tick, id, data);
}
- if (HPMHooks.count.HP_unit_delay_walktoxy_timer_post > 0) {
+ if (HPMHooks.count.HP_unit_delay_walk_toxy_timer_post > 0) {
int (*postHookFunc) (int retVal___, int tid, int64 tick, int id, intptr_t data);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_delay_walktoxy_timer_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_unit_delay_walktoxy_timer_post[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_delay_walk_toxy_timer_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_unit_delay_walk_toxy_timer_post[hIndex].func;
retVal___ = postHookFunc(retVal___, tid, tick, id, data);
}
}
return retVal___;
}
-int HP_unit_walktoxy(struct block_list *bl, short x, short y, int flag) {
+int HP_unit_walk_toxy(struct block_list *bl, short x, short y, int flag) {
int hIndex = 0;
int retVal___ = 0;
- if (HPMHooks.count.HP_unit_walktoxy_pre > 0) {
+ if (HPMHooks.count.HP_unit_walk_toxy_pre > 0) {
int (*preHookFunc) (struct block_list **bl, short *x, short *y, int *flag);
*HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walktoxy_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_unit_walktoxy_pre[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walk_toxy_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_unit_walk_toxy_pre[hIndex].func;
retVal___ = preHookFunc(&bl, &x, &y, &flag);
}
if (*HPMforce_return) {
@@ -90983,25 +91087,25 @@ int HP_unit_walktoxy(struct block_list *bl, short x, short y, int flag) {
}
}
{
- retVal___ = HPMHooks.source.unit.walktoxy(bl, x, y, flag);
+ retVal___ = HPMHooks.source.unit.walk_toxy(bl, x, y, flag);
}
- if (HPMHooks.count.HP_unit_walktoxy_post > 0) {
+ if (HPMHooks.count.HP_unit_walk_toxy_post > 0) {
int (*postHookFunc) (int retVal___, struct block_list *bl, short x, short y, int flag);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walktoxy_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_unit_walktoxy_post[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walk_toxy_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_unit_walk_toxy_post[hIndex].func;
retVal___ = postHookFunc(retVal___, bl, x, y, flag);
}
}
return retVal___;
}
-int HP_unit_walktobl_sub(int tid, int64 tick, int id, intptr_t data) {
+int HP_unit_walktobl_timer(int tid, int64 tick, int id, intptr_t data) {
int hIndex = 0;
int retVal___ = 0;
- if (HPMHooks.count.HP_unit_walktobl_sub_pre > 0) {
+ if (HPMHooks.count.HP_unit_walktobl_timer_pre > 0) {
int (*preHookFunc) (int *tid, int64 *tick, int *id, intptr_t *data);
*HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walktobl_sub_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_unit_walktobl_sub_pre[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walktobl_timer_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_unit_walktobl_timer_pre[hIndex].func;
retVal___ = preHookFunc(&tid, &tick, &id, &data);
}
if (*HPMforce_return) {
@@ -91010,12 +91114,12 @@ int HP_unit_walktobl_sub(int tid, int64 tick, int id, intptr_t data) {
}
}
{
- retVal___ = HPMHooks.source.unit.walktobl_sub(tid, tick, id, data);
+ retVal___ = HPMHooks.source.unit.walktobl_timer(tid, tick, id, data);
}
- if (HPMHooks.count.HP_unit_walktobl_sub_post > 0) {
+ if (HPMHooks.count.HP_unit_walktobl_timer_post > 0) {
int (*postHookFunc) (int retVal___, int tid, int64 tick, int id, intptr_t data);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walktobl_sub_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_unit_walktobl_sub_post[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_walktobl_timer_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_unit_walktobl_timer_post[hIndex].func;
retVal___ = postHookFunc(retVal___, tid, tick, id, data);
}
}
@@ -91155,14 +91259,14 @@ int HP_unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, b
}
return retVal___;
}
-int HP_unit_setdir(struct block_list *bl, unsigned char dir) {
+int HP_unit_set_dir(struct block_list *bl, enum unit_dir dir) {
int hIndex = 0;
int retVal___ = 0;
- if (HPMHooks.count.HP_unit_setdir_pre > 0) {
- int (*preHookFunc) (struct block_list **bl, unsigned char *dir);
+ if (HPMHooks.count.HP_unit_set_dir_pre > 0) {
+ int (*preHookFunc) (struct block_list **bl, enum unit_dir *dir);
*HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_setdir_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_unit_setdir_pre[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_set_dir_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_unit_set_dir_pre[hIndex].func;
retVal___ = preHookFunc(&bl, &dir);
}
if (*HPMforce_return) {
@@ -91171,22 +91275,22 @@ int HP_unit_setdir(struct block_list *bl, unsigned char dir) {
}
}
{
- retVal___ = HPMHooks.source.unit.setdir(bl, dir);
+ retVal___ = HPMHooks.source.unit.set_dir(bl, dir);
}
- if (HPMHooks.count.HP_unit_setdir_post > 0) {
- int (*postHookFunc) (int retVal___, struct block_list *bl, unsigned char dir);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_setdir_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_unit_setdir_post[hIndex].func;
+ if (HPMHooks.count.HP_unit_set_dir_post > 0) {
+ int (*postHookFunc) (int retVal___, struct block_list *bl, enum unit_dir dir);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_set_dir_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_unit_set_dir_post[hIndex].func;
retVal___ = postHookFunc(retVal___, bl, dir);
}
}
return retVal___;
}
-uint8 HP_unit_getdir(struct block_list *bl) {
+enum unit_dir HP_unit_getdir(const struct block_list *bl) {
int hIndex = 0;
- uint8 retVal___ = 0;
+ enum unit_dir retVal___ = UNIT_DIR_UNDEFINED;
if (HPMHooks.count.HP_unit_getdir_pre > 0) {
- uint8 (*preHookFunc) (struct block_list **bl);
+ enum unit_dir (*preHookFunc) (const struct block_list **bl);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_getdir_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_unit_getdir_pre[hIndex].func;
@@ -91201,7 +91305,7 @@ uint8 HP_unit_getdir(struct block_list *bl) {
retVal___ = HPMHooks.source.unit.getdir(bl);
}
if (HPMHooks.count.HP_unit_getdir_post > 0) {
- uint8 (*postHookFunc) (uint8 retVal___, struct block_list *bl);
+ enum unit_dir (*postHookFunc) (enum unit_dir retVal___, const struct block_list *bl);
for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_getdir_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_unit_getdir_post[hIndex].func;
retVal___ = postHookFunc(retVal___, bl);
@@ -91263,6 +91367,33 @@ int HP_unit_warp(struct block_list *bl, short m, short x, short y, enum clr_type
}
return retVal___;
}
+int HP_unit_warpto_master(struct block_list *master_bl, struct block_list *slave_bl) {
+ int hIndex = 0;
+ int retVal___ = 0;
+ if (HPMHooks.count.HP_unit_warpto_master_pre > 0) {
+ int (*preHookFunc) (struct block_list **master_bl, struct block_list **slave_bl);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_warpto_master_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_unit_warpto_master_pre[hIndex].func;
+ retVal___ = preHookFunc(&master_bl, &slave_bl);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.unit.warpto_master(master_bl, slave_bl);
+ }
+ if (HPMHooks.count.HP_unit_warpto_master_post > 0) {
+ int (*postHookFunc) (int retVal___, struct block_list *master_bl, struct block_list *slave_bl);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_warpto_master_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_unit_warpto_master_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, master_bl, slave_bl);
+ }
+ }
+ return retVal___;
+}
int HP_unit_stop_walking(struct block_list *bl, int type) {
int hIndex = 0;
int retVal___ = 0;
@@ -91317,14 +91448,14 @@ int HP_unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id,
}
return retVal___;
}
-int HP_unit_step_timer(int tid, int64 tick, int id, intptr_t data) {
+int HP_unit_steptimer(int tid, int64 tick, int id, intptr_t data) {
int hIndex = 0;
int retVal___ = 0;
- if (HPMHooks.count.HP_unit_step_timer_pre > 0) {
+ if (HPMHooks.count.HP_unit_steptimer_pre > 0) {
int (*preHookFunc) (int *tid, int64 *tick, int *id, intptr_t *data);
*HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_step_timer_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_unit_step_timer_pre[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_steptimer_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_unit_steptimer_pre[hIndex].func;
retVal___ = preHookFunc(&tid, &tick, &id, &data);
}
if (*HPMforce_return) {
@@ -91333,12 +91464,12 @@ int HP_unit_step_timer(int tid, int64 tick, int id, intptr_t data) {
}
}
{
- retVal___ = HPMHooks.source.unit.step_timer(tid, tick, id, data);
+ retVal___ = HPMHooks.source.unit.steptimer(tid, tick, id, data);
}
- if (HPMHooks.count.HP_unit_step_timer_post > 0) {
+ if (HPMHooks.count.HP_unit_steptimer_post > 0) {
int (*postHookFunc) (int retVal___, int tid, int64 tick, int id, intptr_t data);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_step_timer_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_unit_step_timer_post[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_steptimer_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_unit_steptimer_post[hIndex].func;
retVal___ = postHookFunc(retVal___, tid, tick, id, data);
}
}
@@ -91747,11 +91878,11 @@ bool HP_unit_can_reach_bl(struct block_list *bl, struct block_list *tbl, int ran
}
return retVal___;
}
-int HP_unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir) {
+int HP_unit_calc_pos(struct block_list *bl, int tx, int ty, enum unit_dir dir) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_unit_calc_pos_pre > 0) {
- int (*preHookFunc) (struct block_list **bl, int *tx, int *ty, uint8 *dir);
+ int (*preHookFunc) (struct block_list **bl, int *tx, int *ty, enum unit_dir *dir);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_calc_pos_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_unit_calc_pos_pre[hIndex].func;
@@ -91766,7 +91897,7 @@ int HP_unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir) {
retVal___ = HPMHooks.source.unit.calc_pos(bl, tx, ty, dir);
}
if (HPMHooks.count.HP_unit_calc_pos_post > 0) {
- int (*postHookFunc) (int retVal___, struct block_list *bl, int tx, int ty, uint8 dir);
+ int (*postHookFunc) (int retVal___, struct block_list *bl, int tx, int ty, enum unit_dir dir);
for (hIndex = 0; hIndex < HPMHooks.count.HP_unit_calc_pos_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_unit_calc_pos_post[hIndex].func;
retVal___ = postHookFunc(retVal___, bl, tx, ty, dir);
diff --git a/src/plugins/Makefile.in b/src/plugins/Makefile.in
index 5527ceb2f..e44412bfa 100644
--- a/src/plugins/Makefile.in
+++ b/src/plugins/Makefile.in
@@ -103,7 +103,7 @@ Makefile: Makefile.in
../../plugins/%@DLLEXT@: %.c $(ALL_H) $$(shell ls %/* 2>/dev/null)
@echo " CC $<"
- @$(CC) $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @PLUGINSTATIC@ @DEFS@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ @SOFLAGS@ -o $@ $<
+ @$(CC) $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @PLUGINSTATIC@ @DEFS@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ @SOFLAGS@ @LIBS@ @MYSQL_LIBS@ -o $@ $<
../../plugins/HPMHooking_login@DLLEXT@: HPMHOOKINGTYPE = LOGIN
../../plugins/HPMHooking_char@DLLEXT@: HPMHOOKINGTYPE = CHAR
diff --git a/src/test/Makefile.in b/src/test/Makefile.in
index 8399100f1..91263c939 100644
--- a/src/test/Makefile.in
+++ b/src/test/Makefile.in
@@ -36,6 +36,19 @@ LIBCONFIG_OBJ = $(addprefix $(LIBCONFIG_D)/, libconfig.o grammar.o scanctx.o \
LIBCONFIG_H = $(addprefix $(LIBCONFIG_D)/, libconfig.h grammar.h parsectx.h \
scanctx.h scanner.h strbuf.h wincompat.h)
+ifeq (@USE_LIBBACKTRACE@,yes)
+ LIBBACKTRACE_D = $(THIRDPARTY_D)/libbacktrace
+ LIBBACKTRACE_OBJ = $(addprefix $(LIBBACKTRACE_D)/, atomic.o backtrace.o \
+ dwarf.o @LIBBACKTRACE_FORMAT_FILE@ fileline.o mmapio.o mmap.o posix.o print.o \
+ simple.o sort.o state.o)
+ LIBBACKTRACE_H = $(addprefix $(LIBBACKTRACE_D)/, backtrace.h \
+ backtrace-supported.h config.h filenames.h internal.h)
+else
+ LIBBACKTRACE_D =
+ LIBBACKTRACE_OBJ =
+ LIBBACKTRACE_H =
+endif
+
MT19937AR_D = $(THIRDPARTY_D)/mt19937ar
MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
@@ -43,7 +56,7 @@ MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
TEST_C = test_libconfig.c test_spinlock.c
TEST_OBJ = $(addprefix obj/, $(patsubst %c,%o,%(TEST_C)))
TEST_H =
-TEST_DEPENDS = $(COMMON_D)/obj_sql/common_sql.a $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(SYSINFO_INC)
+TEST_DEPENDS = $(COMMON_D)/obj_sql/common_sql.a $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) $(SYSINFO_INC)
TESTS_ALL = test_libconfig test_spinlock
@@ -70,7 +83,7 @@ clean: buildclean
Makefile: Makefile.in
@$(MAKE) -C ../.. src/test/Makefile
-$(SYSINFO_INC): $(TEST_C) $(TEST_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H)
+$(SYSINFO_INC): $(TEST_C) $(TEST_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H)
@echo " MAKE $@"
@$(MAKE) -C ../.. sysinfo
@@ -88,11 +101,11 @@ $(TESTS_ALL): test_%: ../../test_%@EXEEXT@
../../test_%@EXEEXT@: obj/test_%.o $(TEST_DEPENDS) Makefile
@echo " LD $(notdir $@)"
@$(CC) @STATIC@ @LDFLAGS@ -o $@ $< $(COMMON_D)/obj_all/common.a $(COMMON_D)/obj_sql/common_sql.a \
- $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
+ $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) $(LIBBACKTRACE_OBJ) @LIBS@ @MYSQL_LIBS@
# object files
-obj/%.o: %.c $(TEST_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj
+obj/%.o: %.c $(TEST_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(LIBBACKTRACE_H) | obj
@echo " CC $<"
@$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
@@ -112,3 +125,7 @@ $(MT19937AR_OBJ):
$(LIBCONFIG_OBJ):
@echo " MAKE $@"
@$(MAKE) -C $(LIBCONFIG_D)
+
+$(LIBBACKTRACE_OBJ):
+ @echo " MAKE $@"
+ @$(MAKE) -C $(LIBBACKTRACE_D)