summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c64
-rw-r--r--src/char/inter.c8
-rw-r--r--src/char/mapif.c7
-rw-r--r--src/common/cbasetypes.h2
-rw-r--r--src/common/mmo.h5
-rw-r--r--src/login/account.c15
-rw-r--r--src/login/login.c8
-rw-r--r--src/map/atcommand.c49
-rw-r--r--src/map/battle.c15
-rw-r--r--src/map/clif.c79
-rw-r--r--src/map/clif.h11
-rw-r--r--src/map/intif.c14
-rw-r--r--src/map/map.c11
-rw-r--r--src/map/map.h5
-rw-r--r--src/map/mapreg_sql.c10
-rw-r--r--src/map/mob.c683
-rw-r--r--src/map/mob.h9
-rw-r--r--src/map/npc_chat.c3
-rw-r--r--src/map/packets.h5
-rw-r--r--src/map/packets_keys_main.h5
-rw-r--r--src/map/packets_keys_zero.h5
-rw-r--r--src/map/packets_shuffle_main.h5
-rw-r--r--src/map/packets_shuffle_zero.h5
-rw-r--r--src/map/packets_struct.h36
-rw-r--r--src/map/pc.c164
-rw-r--r--src/map/pc.h11
-rw-r--r--src/map/pet.c20
-rw-r--r--src/map/script.c52
-rw-r--r--src/map/script.h1
-rw-r--r--src/map/skill.c119
-rw-r--r--src/map/skill.h1
-rw-r--r--src/map/status.c5
-rw-r--r--src/map/unit.c4
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Defs.inc32
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc40
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc10
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc284
37 files changed, 1273 insertions, 529 deletions
diff --git a/src/char/char.c b/src/char/char.c
index aac9ad20c..c61b6107a 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -425,8 +425,6 @@ static struct DBData char_create_charstatus(union DBKey key, va_list args)
static int char_mmo_char_tosql(int char_id, struct mmo_charstatus *p)
{
- int i = 0;
- int count = 0;
int diff = 0;
char save_status[128]; //For displaying save information. [Skotlex]
struct mmo_charstatus *cp;
@@ -591,8 +589,9 @@ static int char_mmo_char_tosql(int char_id, struct mmo_charstatus *p)
//insert here.
StrBuf->Clear(&buf);
StrBuf->Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", memo_db);
- for( i = 0, count = 0; i < MAX_MEMOPOINTS; ++i )
- {
+
+ int count = 0;
+ for (int i = 0; i < MAX_MEMOPOINTS; ++i) {
if( p->memo_point[i].map )
{
if( count )
@@ -624,24 +623,29 @@ static int char_mmo_char_tosql(int char_id, struct mmo_charstatus *p)
StrBuf->Clear(&buf);
StrBuf->Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`,`flag`) VALUES ", skill_db);
//insert here.
- for (i = 0, count = 0; i < MAX_SKILL_DB; ++i) {
- if( p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY ) {
- if( p->skill[i].lv == 0 && ( p->skill[i].flag == SKILL_FLAG_PERM_GRANTED || p->skill[i].flag == SKILL_FLAG_PERMANENT ) )
- continue;
- if( p->skill[i].flag != SKILL_FLAG_PERMANENT && p->skill[i].flag != SKILL_FLAG_PERM_GRANTED && (p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0) == 0 )
- continue;
- if( count )
- StrBuf->AppendStr(&buf, ",");
- StrBuf->Printf(&buf, "('%d','%d','%d','%d')", char_id, p->skill[i].id,
- ( (p->skill[i].flag == SKILL_FLAG_PERMANENT || p->skill[i].flag == SKILL_FLAG_PERM_GRANTED) ? p->skill[i].lv : p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0),
- p->skill[i].flag == SKILL_FLAG_PERM_GRANTED ? p->skill[i].flag : 0);/* other flags do not need to be saved */
- ++count;
- }
+ int count = 0;
+ for (int i = 0; i < MAX_SKILL_DB; ++i) {
+ if (p->skill[i].id == 0)
+ continue;
+ if (p->skill[i].flag == SKILL_FLAG_TEMPORARY)
+ continue;
+ if (p->skill[i].lv == 0 && (p->skill[i].flag == SKILL_FLAG_PERM_GRANTED || p->skill[i].flag == SKILL_FLAG_PERMANENT))
+ continue;
+ if (p->skill[i].flag == SKILL_FLAG_REPLACED_LV_0)
+ continue;
+
+ if (Assert_chk(p->skill[i].flag == SKILL_FLAG_PERMANENT || p->skill[i].flag == SKILL_FLAG_PERM_GRANTED || p->skill[i].flag > SKILL_FLAG_REPLACED_LV_0))
+ continue;
+ if (count != 0)
+ StrBuf->AppendStr(&buf, ",");
+ int saved_lv = (p->skill[i].flag > SKILL_FLAG_REPLACED_LV_0) ? p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0 : p->skill[i].lv;
+ int saved_flag = p->skill[i].flag == SKILL_FLAG_PERM_GRANTED ? p->skill[i].flag : 0; // other flags do not need to be saved
+ StrBuf->Printf(&buf, "('%d','%d','%d','%d')", char_id, p->skill[i].id, saved_lv, saved_flag);
+
+ ++count;
}
- if( count )
- {
- if( SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)) )
- {
+ if (count != 0) {
+ if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
Sql_ShowDebug(inter->sql_handle);
errors++;
}
@@ -651,7 +655,7 @@ static int char_mmo_char_tosql(int char_id, struct mmo_charstatus *p)
}
diff = 0;
- for(i = 0; i < MAX_FRIENDS; i++){
+ for (int i = 0; i < MAX_FRIENDS; i++) {
if(p->friends[i].char_id != cp->friends[i].char_id ||
p->friends[i].account_id != cp->friends[i].account_id){
diff = 1;
@@ -669,8 +673,8 @@ static int char_mmo_char_tosql(int char_id, struct mmo_charstatus *p)
StrBuf->Clear(&buf);
StrBuf->Printf(&buf, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", friend_db);
- for( i = 0, count = 0; i < MAX_FRIENDS; ++i )
- {
+ int count = 0;
+ for (int i = 0; i < MAX_FRIENDS; ++i) {
if( p->friends[i].char_id > 0 )
{
if( count )
@@ -695,7 +699,7 @@ static int char_mmo_char_tosql(int char_id, struct mmo_charstatus *p)
StrBuf->Clear(&buf);
StrBuf->Printf(&buf, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", hotkey_db);
diff = 0;
- for(i = 0; i < ARRAYLENGTH(p->hotkeys); i++){
+ for (int i = 0; i < ARRAYLENGTH(p->hotkeys); i++) {
if(memcmp(&p->hotkeys[i], &cp->hotkeys[i], sizeof(struct hotkey)))
{
if( diff )
@@ -1369,7 +1373,7 @@ static int char_mmo_char_fromsql(int char_id, struct mmo_charstatus *p, bool loa
SqlStmt_ShowDebug(stmt);
}
- if( tmp_skill.flag != SKILL_FLAG_PERM_GRANTED )
+ if (tmp_skill.flag != SKILL_FLAG_PERM_GRANTED)
tmp_skill.flag = SKILL_FLAG_PERMANENT;
for (i = 0; i < MAX_SKILL_DB && SQL_SUCCESS == SQL->StmtNextRow(stmt); ++i) {
@@ -2898,13 +2902,13 @@ static void char_global_accreg_to_login_add(const char *key, unsigned int index,
if( val ) {
char *sval = (char*)val;
- len = strlen(sval)+1;
+ len = strlen(sval);
- WFIFOB(chr->login_fd, nlen) = (unsigned char)len;/* won't be higher; the column size is 254 */
+ WFIFOB(chr->login_fd, nlen) = (unsigned char)len; // Won't be higher; the column size is 255.
nlen += 1;
- safestrncpy(WFIFOP(chr->login_fd,nlen), sval, len);
- nlen += len;
+ safestrncpy(WFIFOP(chr->login_fd, nlen), sval, len + 1);
+ nlen += len + 1;
}
} else {
WFIFOB(chr->login_fd, nlen) = val ? 0 : 1;
diff --git a/src/char/inter.c b/src/char/inter.c
index 2d8d06a9c..5252b3315 100644
--- a/src/char/inter.c
+++ b/src/char/inter.c
@@ -676,13 +676,13 @@ static int inter_accreg_fromsql(int account_id, int char_id, int fd, int type)
plen += 4;
SQL->GetData(inter->sql_handle, 2, &data, NULL);
- len = strlen(data)+1;
+ len = strlen(data);
- WFIFOB(fd, plen) = (unsigned char)len;/* won't be higher; the column size is 254 */
+ WFIFOB(fd, plen) = (unsigned char)len; // Won't be higher; the column size is 255.
plen += 1;
- safestrncpy(WFIFOP(fd,plen), data, len);
- plen += len;
+ safestrncpy(WFIFOP(fd, plen), data, len + 1);
+ plen += len + 1;
WFIFOW(fd, 14) += 1;
diff --git a/src/char/mapif.c b/src/char/mapif.c
index 9077afae4..f0c886586 100644
--- a/src/char/mapif.c
+++ b/src/char/mapif.c
@@ -2030,7 +2030,8 @@ static int mapif_parse_Registry(int fd)
if (count != 0) {
int cursor = 14, i;
- char key[SCRIPT_VARNAME_LENGTH+1], sval[254];
+ char key[SCRIPT_VARNAME_LENGTH + 1];
+ char sval[SCRIPT_STRING_VAR_LENGTH + 1];
bool isLoginActive = sockt->session_is_active(chr->login_fd);
if (isLoginActive)
@@ -2057,8 +2058,8 @@ static int mapif_parse_Registry(int fd)
/* str */
case 2:
len = RFIFOB(fd, cursor);
- safestrncpy(sval, RFIFOP(fd, cursor + 1), min((int)sizeof(sval), len));
- cursor += len + 1;
+ safestrncpy(sval, RFIFOP(fd, cursor + 1), min((int)sizeof(sval), len + 1));
+ cursor += len + 2;
inter->savereg(account_id, char_id, key, index, (intptr_t)sval, true);
break;
case 3:
diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h
index 0b5613316..6053d86d9 100644
--- a/src/common/cbasetypes.h
+++ b/src/common/cbasetypes.h
@@ -95,7 +95,7 @@
// debug function name
#ifndef __NETBSD__
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
-# if __GNUC__ >= 2
+# if __GNUC__ >= 2 || defined(WIN32)
# define __func__ __FUNCTION__
# else
# define __func__ ""
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 9421f6e35..d2f3aa8f1 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -380,7 +380,10 @@ STATIC_ASSERT(MAX_ITEM_OPTIONS <= 5, "This value is limited by the client and da
#define JOBL_BABY 0x2000
#define JOBL_THIRD 0x4000
-#define SCRIPT_VARNAME_LENGTH 32 ///< Maximum length of a script variable
+#define SCRIPT_VARNAME_LENGTH 32 ///< Maximum length of a script variable's name including affixes and excluding NULL-terminator.
+STATIC_ASSERT(SCRIPT_VARNAME_LENGTH <= 32, "This value is limited by the inter-server communication and database layout and should only be increased if you know the consequences.");
+#define SCRIPT_STRING_VAR_LENGTH 255 ///< Maximum length of strings stored in script variables excluding NULL-terminator.
+STATIC_ASSERT(SCRIPT_STRING_VAR_LENGTH <= 255, "This value is limited by the inter-server communication and database layout and should only be increased if you know the consequences.");
#define INFINITE_DURATION (-1) // Infinite duration for status changes
diff --git a/src/login/account.c b/src/login/account.c
index 3632c257a..ec0bc81e8 100644
--- a/src/login/account.c
+++ b/src/login/account.c
@@ -632,7 +632,8 @@ static void account_mmo_save_accreg2(AccountDB *self, int fd, int account_id, in
sql_handle = db->accounts;
if (count) {
int cursor = 14, i;
- char key[SCRIPT_VARNAME_LENGTH+1], sval[254];
+ char key[SCRIPT_VARNAME_LENGTH + 1];
+ char sval[SCRIPT_STRING_VAR_LENGTH + 1];
for (i = 0; i < count; i++) {
unsigned int index;
@@ -657,8 +658,8 @@ static void account_mmo_save_accreg2(AccountDB *self, int fd, int account_id, in
/* str */
case 2:
len = RFIFOB(fd, cursor);
- safestrncpy(sval, RFIFOP(fd, cursor + 1), min((int)sizeof(sval), len));
- cursor += len + 1;
+ safestrncpy(sval, RFIFOP(fd, cursor + 1), min((int)sizeof(sval), len + 1));
+ cursor += len + 2;
if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%s')", db->global_acc_reg_str_db, account_id, key, index, sval) )
Sql_ShowDebug(sql_handle);
break;
@@ -719,13 +720,13 @@ static void account_mmo_send_accreg2(AccountDB *self, int fd, int account_id, in
plen += 4;
SQL->GetData(sql_handle, 2, &data, NULL);
- len = strlen(data)+1;
+ len = strlen(data);
- WFIFOB(fd, plen) = (unsigned char)len;/* won't be higher; the column size is 254 */
+ WFIFOB(fd, plen) = (unsigned char)len; // Won't be higher; the column size is 255.
plen += 1;
- safestrncpy(WFIFOP(fd,plen), data, len);
- plen += len;
+ safestrncpy(WFIFOP(fd, plen), data, len + 1);
+ plen += len + 1;
WFIFOW(fd, 14) += 1;
diff --git a/src/login/login.c b/src/login/login.c
index 4201a8b4e..623457b8a 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -1406,10 +1406,10 @@ static void login_client_login_mobile_otp_request(int fd, struct login_session_d
static void login_char_server_connection_status(int fd, struct login_session_data* sd, uint8 status) __attribute__((nonnull (2)));
static void login_char_server_connection_status(int fd, struct login_session_data* sd, uint8 status)
{
- WFIFOHEAD(fd,3);
- WFIFOW(fd,0) = 0x2711;
- WFIFOB(fd,2) = status;
- WFIFOSET(fd,3);
+ WFIFOHEAD(fd, 3);
+ WFIFOW(fd, 0) = 0x2711;
+ WFIFOB(fd, 2) = status;
+ WFIFOSET2(fd, 3);
}
// CA_CHARSERVERCONNECT
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 91ddc3ef9..54cc9e2c9 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -962,39 +962,10 @@ ACMD(option)
*------------------------------------------*/
ACMD(hide)
{
- if (pc_isinvisible(sd)) {
- sd->sc.option &= ~OPTION_INVISIBLE;
- if (sd->disguise != -1 )
- status->set_viewdata(&sd->bl, sd->disguise);
- else
- status->set_viewdata(&sd->bl, sd->status.class);
- clif->message(fd, msg_fd(fd,10)); // Invisible: Off
-
- // increment the number of pvp players on the map
- map->list[sd->bl.m].users_pvp++;
-
- if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank ) {
- // register the player for ranking calculations
- sd->pvp_timer = timer->add( timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0 );
- }
- //bugreport:2266
- map->foreachinmovearea(clif->insight, &sd->bl, AREA_SIZE, sd->bl.x, sd->bl.y, BL_ALL, &sd->bl);
- } else {
- clif->clearunit_area(&sd->bl, CLR_OUTSIGHT);
- sd->sc.option |= OPTION_INVISIBLE;
- sd->vd.class = INVISIBLE_CLASS;
- clif->message(fd, msg_fd(fd,11)); // Invisible: On
-
- // decrement the number of pvp players on the map
- map->list[sd->bl.m].users_pvp--;
-
- if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ) {
- // unregister the player for ranking
- timer->delete( sd->pvp_timer, pc->calc_pvprank_timer );
- sd->pvp_timer = INVALID_TIMER;
- }
- }
- clif->changeoption(&sd->bl);
+ if (pc_isinvisible(sd))
+ pc->unhide(sd, true);
+ else
+ pc->hide(sd, true);
return true;
}
@@ -8945,13 +8916,17 @@ ACMD(accinfo)
/* [Ind] */
ACMD(set)
{
- char reg[SCRIPT_VARNAME_LENGTH+1], val[254];
+ char reg[SCRIPT_VARNAME_LENGTH + 1];
+ char val[SCRIPT_STRING_VAR_LENGTH + 1];
struct script_data* data;
int toset = 0;
bool is_str = false;
size_t len;
- if (!*message || (toset = sscanf(message, "%32s %253[^\n]", reg, val)) < 1) {
+ char format[20];
+ safesnprintf(format, sizeof(format), "%%%ds %%%d[^\\n]", SCRIPT_VARNAME_LENGTH, SCRIPT_STRING_VAR_LENGTH);
+
+ if (*message == '\0' || (toset = sscanf(message, format, reg, val)) < 1) {
clif->message(fd, msg_fd(fd,1367)); // Usage: @set <variable name> <value>
clif->message(fd, msg_fd(fd,1368)); // Usage: ex. "@set PoringCharVar 50"
clif->message(fd, msg_fd(fd,1369)); // Usage: ex. "@set PoringCharVarSTR$ Super Duper String"
@@ -10594,9 +10569,9 @@ static bool atcommand_exec(const int fd, struct map_session_data *sd, const char
clif->message(fd, msg_fd(fd,143));
return false;
}
+ if (sd->block_action.commands) // *pcblock script command
+ return false;
}
- if (sd->block_action.commands) // *pcblock script command
- return false;
if (*message == atcommand->char_symbol)
is_atcommand = false;
diff --git a/src/map/battle.c b/src/map/battle.c
index 40c645cf7..c8cd71b94 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -3750,7 +3750,7 @@ static struct Damage battle_calc_magic_attack(struct block_list *src, struct blo
if (sc){
if( sc->data[SC_TELEKINESIS_INTENSE] && s_ele == ELE_GHOST )
- ad.damage += sc->data[SC_TELEKINESIS_INTENSE]->val3;
+ ad.damage += ad.damage * sc->data[SC_TELEKINESIS_INTENSE]->val3 / 100;
}
switch(skill_id){
case MG_FIREBOLT:
@@ -4124,13 +4124,6 @@ static struct Damage battle_calc_misc_attack(struct block_list *src, struct bloc
case NPC_EVILLAND:
md.damage = skill->calc_heal(src,target,skill_id,skill_lv,false);
break;
- case RK_DRAGONBREATH:
- case RK_DRAGONBREATH_WATER:
- md.damage = ((status_get_hp(src) / 50) + (status_get_max_sp(src) / 4)) * skill_lv;
- RE_LVL_MDMOD(150);
- if (sd) md.damage = md.damage * (95 + 5 * pc->checkskill(sd,RK_DRAGONTRAINING)) / 100;
- md.flag |= BF_LONG|BF_WEAPON;
- break;
/**
* Ranger
**/
@@ -4958,6 +4951,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
break;
}
break;
+ case RK_DRAGONBREATH:
+ case RK_DRAGONBREATH_WATER:
+ wd.damage = ((status_get_hp(src) / 50) + (status_get_max_sp(src) / 4)) * skill_lv;
+ wd.damage = wd.damage * status->get_lv(src) / 150;
+ if (sd) wd.damage = wd.damage * (95 + 5 * pc->checkskill(sd, RK_DRAGONTRAINING)) / 100;
+ break;
default:
{
i = (flag.cri
diff --git a/src/map/clif.c b/src/map/clif.c
index 496a8beda..ab13ffe1f 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9722,6 +9722,17 @@ static void clif_elemname_ack(int fd, struct block_list *bl)
clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAME_TITLE));
}
+static void clif_skillname_ack(int fd, struct block_list *bl)
+{
+}
+
+static void clif_itemname_ack(int fd, struct block_list *bl)
+{
+ nullpo_retv(bl);
+ ShowError("clif_itemname_ack: bad type %u(%d)\n", bl->type, bl->id);
+ Assert_retv(0);
+}
+
static void clif_unknownname_ack(int fd, struct block_list *bl)
{
nullpo_retv(bl);
@@ -9758,6 +9769,12 @@ static void clif_blname_ack(int fd, struct block_list *bl)
case BL_ELEM:
clif->elemname_ack(fd, bl);
break;
+ case BL_ITEM:
+ clif->itemname_ack(fd, bl);
+ break;
+ case BL_SKILL:
+ clif->skillname_ack(fd, bl);
+ break;
default:
clif->unknownname_ack(fd, bl);
break;
@@ -11777,7 +11794,7 @@ static void clif_parse_WisMessage(int fd, struct map_session_data *sd)
char *str = target + 4; // Skip the NPC: string part.
struct npc_data *nd;
if ((nd = npc->name2id(str))) {
- char split_data[NUM_WHISPER_VAR][CHAT_SIZE_MAX];
+ char split_data[NUM_WHISPER_VAR][SCRIPT_STRING_VAR_LENGTH + 1];
char *split;
char output[256];
@@ -23780,12 +23797,15 @@ static void clif_parse_lapineDdukDdak_ack(int fd, struct map_session_data *sd) _
static void clif_parse_lapineDdukDdak_ack(int fd, struct map_session_data *sd)
{
#if PACKETVER >= 20160302
+ if (sd->state.lapine_ui == 0)
+ return;
+
const struct PACKET_CZ_LAPINEDDUKDDAK_ACK *p = RP2PTR(fd);
struct item_data *it = itemdb->exists(p->itemId);
if (it == NULL || it->lapineddukddak == NULL)
return;
- if (pc_cant_act(sd))
+ if (pc_cant_act_except_lapine(sd))
return;
if (pc->search_inventory(sd, it->nameid) == INDEX_NOT_FOUND)
return;
@@ -23846,6 +23866,55 @@ static void clif_parse_lapineDdukDdak_close(int fd, struct map_session_data *sd)
#endif // PACKETVER >= 20160504
}
+static bool clif_lapineUpgrade_open(struct map_session_data *sd, int item_id)
+{
+#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+ nullpo_retr(false, sd);
+ nullpo_retr(false, itemdb->exists(item_id));
+ struct PACKET_ZC_LAPINEUPGRADE_OPEN p;
+
+ p.packetType = HEADER_ZC_LAPINEUPGRADE_OPEN;
+ p.itemId = item_id;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+
+ return true;
+#else
+ return false;
+#endif // PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+}
+
+static void clif_parse_lapineUpgrade_close(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_lapineUpgrade_close(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+#endif // PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+}
+
+static void clif_parse_lapineUpgrade_makeItem(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+static void clif_parse_lapineUpgrade_makeItem(int fd, struct map_session_data *sd)
+{
+#if PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+ ShowError("Lapin upgrade not implimented yet");
+ clif->lapineUpgrade_result(sd, LAPINE_UPGRADE_FAILED);
+#endif // PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+}
+
+static bool clif_lapineUpgrade_result(struct map_session_data *sd, enum lapineUpgrade_result result)
+{
+#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+ nullpo_retr(false, sd);
+ struct PACKET_ZC_LAPINEUPGRADE_RESULT p;
+
+ p.packetType = HEADER_ZC_LAPINEUPGRADE_RESULT;
+ p.result = result;
+ clif->send(&p, sizeof(p), &sd->bl, SELF);
+
+ return true;
+#else
+ return false;
+#endif // PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+}
+
/*==========================================
* Main client packet processing function
*------------------------------------------*/
@@ -24346,6 +24415,8 @@ void clif_defaults(void)
clif->mobname_normal_ack = clif_mobname_normal_ack;
clif->chatname_ack = clif_chatname_ack;
clif->elemname_ack = clif_elemname_ack;
+ clif->skillname_ack = clif_skillname_ack;
+ clif->itemname_ack = clif_itemname_ack;
clif->unknownname_ack = clif_unknownname_ack;
clif->monster_hp_bar = clif_monster_hp_bar;
clif->hpmeter = clif_hpmeter;
@@ -25089,5 +25160,9 @@ void clif_defaults(void)
clif->lapineDdukDdak_result = clif_lapineDdukDdak_result;
clif->plapineDdukDdak_ack = clif_parse_lapineDdukDdak_ack;
clif->plapineDdukDdak_close = clif_parse_lapineDdukDdak_close;
+ clif->lapineUpgrade_open = clif_lapineUpgrade_open;
+ clif->lapineUpgrade_result = clif_lapineUpgrade_result;
+ clif->pLapineUpgrade_close = clif_parse_lapineUpgrade_close;
+ clif->pLapineUpgrade_makeItem = clif_parse_lapineUpgrade_makeItem;
clif->pReqGearOff = clif_parse_reqGearOff;
}
diff --git a/src/map/clif.h b/src/map/clif.h
index 25ac65af5..fdaaf85e3 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -733,6 +733,11 @@ enum lapineddukddak_result {
LAPINEDDKUKDDAK_INVALID_ITEM = 7,
};
+enum lapineUpgrade_result {
+ LAPINE_UPGRADE_SUCCESS = 0,
+ LAPINE_UPGRADE_FAILED = 1
+};
+
enum removeGear_flag {
REMOVE_MOUNT_0 = 0, // unused
REMOVE_MOUNT_DRAGON = 1,
@@ -952,6 +957,8 @@ struct clif_interface {
void (*mobname_normal_ack) (int fd, struct block_list *bl);
void (*chatname_ack) (int fd, struct block_list *bl);
void (*elemname_ack) (int fd, struct block_list *bl);
+ void (*skillname_ack) (int fd, struct block_list *bl);
+ void (*itemname_ack) (int fd, struct block_list *bl);
void (*unknownname_ack) (int fd, struct block_list *bl);
void (*monster_hp_bar) ( struct mob_data* md, struct map_session_data *sd );
int (*hpmeter) (struct map_session_data *sd);
@@ -1688,6 +1695,10 @@ struct clif_interface {
bool (*lapineDdukDdak_result) (struct map_session_data *sd, enum lapineddukddak_result result);
void (*plapineDdukDdak_ack) (int fd, struct map_session_data *sd);
void (*plapineDdukDdak_close) (int fd, struct map_session_data *sd);
+ bool (*lapineUpgrade_open) (struct map_session_data *sd, int item_id);
+ bool (*lapineUpgrade_result) (struct map_session_data *sd, enum lapineUpgrade_result result);
+ void (*pLapineUpgrade_close) (int fd, struct map_session_data *sd);
+ void (*pLapineUpgrade_makeItem) (int fd, struct map_session_data *sd);
void (*pReqGearOff) (int fd, struct map_session_data *sd);
};
diff --git a/src/map/intif.c b/src/map/intif.c
index a420b7204..276b40780 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -218,13 +218,13 @@ static int intif_saveregistry(struct map_session_data *sd)
plen += 1;
if( p->value ) {
- len = strlen(p->value)+1;
+ len = strlen(p->value);
- WFIFOB(inter_fd, plen) = (unsigned char)len;/* won't be higher; the column size is 254 */
+ WFIFOB(inter_fd, plen) = (unsigned char)len; // Won't be higher; the column size is 255.
plen += 1;
- safestrncpy(WFIFOP(inter_fd,plen), p->value, len);
- plen += len;
+ safestrncpy(WFIFOP(inter_fd, plen), p->value, len + 1);
+ plen += len + 1;
} else {
script->reg_destroy_single(sd,key.i64,&p->flag);
}
@@ -1025,7 +1025,7 @@ static void intif_parse_Registers(int fd)
* { keyLength(B), key(<keyLength>), index(L), valLength(B), val(<valLength>) }
**/
if (type) {
- char sval[254];
+ char sval[SCRIPT_STRING_VAR_LENGTH + 1];
for (i = 0; i < max; i++) {
int len = RFIFOB(fd, cursor);
safestrncpy(key, RFIFOP(fd, cursor + 1), min((int)sizeof(key), len));
@@ -1035,8 +1035,8 @@ static void intif_parse_Registers(int fd)
cursor += 4;
len = RFIFOB(fd, cursor);
- safestrncpy(sval, RFIFOP(fd, cursor + 1), min((int)sizeof(sval), len));
- cursor += len + 1;
+ safestrncpy(sval, RFIFOP(fd, cursor + 1), min((int)sizeof(sval), len + 1));
+ cursor += len + 2;
script->set_reg(NULL,sd,reference_uid(script->add_variable(key), index), key, sval, NULL);
}
diff --git a/src/map/map.c b/src/map/map.c
index b2c9c77c3..f66f40dfc 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -1713,9 +1713,9 @@ static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x,
tx = *x + dx;
ty = *y + dy;
if (unit_is_dir_or_opposite(dir, UNIT_DIR_SOUTHWEST))
- tx *= costrange / MOVE_COST;
+ tx = tx * costrange / MOVE_COST;
if (unit_is_dir_or_opposite(dir, UNIT_DIR_NORTHWEST))
- ty *= costrange / MOVE_COST;
+ ty = 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;
@@ -1724,9 +1724,9 @@ static bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x,
tx = *x + dx;
ty = *y + dy;
if (unit_is_dir_or_opposite(dir, UNIT_DIR_NORTHWEST))
- tx *= costrange / MOVE_COST;
+ tx = tx * costrange / MOVE_COST;
if (unit_is_dir_or_opposite(dir, UNIT_DIR_SOUTHWEST))
- ty *= costrange / MOVE_COST;
+ ty = 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;
@@ -3077,6 +3077,8 @@ static int map_getcellp(struct map_data *m, const struct block_list *bl, int16 x
return (cell.icewall);
case CELL_CHKNOICEWALL:
return (cell.noicewall);
+ case CELL_CHKNOSKILL:
+ return (cell.noskill);
// special checks
case CELL_CHKPASS:
@@ -3141,6 +3143,7 @@ static void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag)
case CELL_NOCHAT: map->list[m].cell[j].nochat = flag; break;
case CELL_ICEWALL: map->list[m].cell[j].icewall = flag; break;
case CELL_NOICEWALL: map->list[m].cell[j].noicewall = flag; break;
+ case CELL_NOSKILL: map->list[m].cell[j].noskill = flag; break;
default:
ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell);
diff --git a/src/map/map.h b/src/map/map.h
index 2de6df2f7..64736a6f5 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -588,6 +588,7 @@ typedef enum {
CELL_NOCHAT,
CELL_ICEWALL,
CELL_NOICEWALL,
+ CELL_NOSKILL,
} cell_t;
@@ -612,6 +613,7 @@ typedef enum {
CELL_CHKNOCHAT,
CELL_CHKICEWALL,
CELL_CHKNOICEWALL,
+ CELL_CHKNOSKILL,
} cell_chk;
@@ -630,7 +632,8 @@ struct mapcell {
novending : 1,
nochat : 1,
icewall : 1,
- noicewall : 1;
+ noicewall : 1,
+ noskill : 1;
#ifdef CELL_NOSTACK
int cell_bl; //Holds amount of bls in this cell.
diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c
index 741505e17..2963637da 100644
--- a/src/map/mapreg_sql.c
+++ b/src/map/mapreg_sql.c
@@ -176,9 +176,9 @@ static bool mapreg_setregstr(int64 uid, const char *str)
if(name[1] != '@' && !mapreg->skip_insert) { //put returned null, so we must insert.
char tmp_str[(SCRIPT_VARNAME_LENGTH+1)*2+1];
- char tmp_str2[255*2+1];
+ char tmp_str2[SCRIPT_STRING_VAR_LENGTH * 2 + 1];
SQL->EscapeStringLen(map->mysql_handle, tmp_str, name, strnlen(name, SCRIPT_VARNAME_LENGTH+1));
- SQL->EscapeStringLen(map->mysql_handle, tmp_str2, str, strnlen(str, 255));
+ SQL->EscapeStringLen(map->mysql_handle, tmp_str2, str, strnlen(str, SCRIPT_STRING_VAR_LENGTH));
if( SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%u','%s')", mapreg->table, tmp_str, i, tmp_str2) )
Sql_ShowDebug(map->mysql_handle);
}
@@ -203,7 +203,7 @@ static void script_load_mapreg(void)
struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
char varname[SCRIPT_VARNAME_LENGTH+1];
int index;
- char value[255+1];
+ char value[SCRIPT_STRING_VAR_LENGTH + 1];
uint32 length;
if ( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `varname`, `index`, `value` FROM `%s`", mapreg->table)
@@ -261,8 +261,8 @@ static void script_save_mapreg(void)
if( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg->table, m->u.i, name, i) )
Sql_ShowDebug(map->mysql_handle);
} else {
- char tmp_str2[2*255+1];
- SQL->EscapeStringLen(map->mysql_handle, tmp_str2, m->u.str, safestrnlen(m->u.str, 255));
+ char tmp_str2[SCRIPT_STRING_VAR_LENGTH * 2 + 1];
+ SQL->EscapeStringLen(map->mysql_handle, tmp_str2, m->u.str, safestrnlen(m->u.str, SCRIPT_STRING_VAR_LENGTH));
if( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE `%s` SET `value`='%s' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg->table, tmp_str2, name, i) )
Sql_ShowDebug(map->mysql_handle);
}
diff --git a/src/map/mob.c b/src/map/mob.c
index 51a32abd9..dcbdccedd 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -78,6 +78,7 @@ struct mob_interface *mob;
// Move probability for mobs away from players (rate of 1000 minute)
// in Aegis, this is 100% for mobs that have been activated by players and none otherwise.
#define MOB_LAZYMOVEPERC(md) ((md)->state.spotted?1000:0)
+#define MOB_MAX_CASTTIME (10 * 60 * 1000) // Maximum cast time for monster skills. (10 minutes)
#define MOB_MAX_DELAY (24*3600*1000)
#define MAX_MINCHASE 30 //Max minimum chase value to use for mobs.
#define RUDE_ATTACKED_COUNT 2 //After how many rude-attacks should the skill be used?
@@ -446,6 +447,9 @@ static bool mob_ksprotected(struct block_list *src, struct block_list *target)
if( !battle_config.ksprotection )
return false; // KS Protection Disabled
+ if (status->isdead(target) != 0)
+ return false; // Target is dead.
+
if( !(md = BL_CAST(BL_MOB,target)) )
return false; // Target is not MOB
@@ -1519,7 +1523,7 @@ static int mob_unlocktarget(struct mob_data *md, int64 tick)
FALLTHROUGH
case MSS_IDLE:
// Idle skill.
- if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL) && mob->skill_use(md, tick, -1))
+ if ((++md->ud.walk_count % IDLE_SKILL_INTERVAL) == 0 && mob->skill_use(md, tick, -1) == 0)
break;
//Random walk.
if (!md->master_id &&
@@ -1699,7 +1703,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, int64 tick)
|| !mob->can_reach(md, tbl, md->min_chase, MSS_RUSH)
)
&& md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
- && !mob->skill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack
+ && mob->skill_use(md, tick, MSC_RUDEATTACKED) == 0 // If can't rude Attack
&& can_move && unit->escape(&md->bl, tbl, rnd()%10 +1) // Attempt escape
) {
//Escaped
@@ -1727,7 +1731,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, int64 tick)
) {
// Rude attacked
if (md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
- && !mob->skill_use(md, tick, MSC_RUDEATTACKED) && can_move
+ && mob->skill_use(md, tick, MSC_RUDEATTACKED) == 0 && can_move != 0
&& !tbl && unit->escape(&md->bl, abl, rnd()%10 +1)
) {
//Escaped.
@@ -3387,272 +3391,344 @@ static struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md, int rate
return NULL;
}
-/*==========================================
- * What a status state suits by nearby MOB is looked for.
- *------------------------------------------*/
+
+/**
+ * Checks if the passed monster/character meets the passed status change requirements
+ * and returns it by reference parameter on success.
+ *
+ * @param bl The monster/character to check.
+ * @param ap List of arguments. (Source monster, MSC_* flag, SC_* flag, reference bl.)
+ * @return Always 0.
+ *
+ **/
static int mob_getfriendstatus_sub(struct block_list *bl, va_list ap)
{
- int cond1,cond2;
- struct mob_data **fr = NULL, *md = NULL, *mmd = NULL;
- int flag=0;
-
nullpo_ret(bl);
- Assert_ret(bl->type == BL_MOB);
- md = BL_UCAST(BL_MOB, bl);
- nullpo_ret(mmd=va_arg(ap,struct mob_data *));
- if( mmd->bl.id == bl->id && !(battle_config.mob_ai&0x10) )
+ struct mob_data *md = va_arg(ap, struct mob_data *);
+
+ nullpo_ret(md);
+
+ if (md->bl.id == bl->id && (battle_config.mob_ai & 0x10) == 0)
+ return 0;
+
+ if (battle->check_target(&md->bl, bl, BCT_ENEMY) > 0)
return 0;
- if (battle->check_target(&mmd->bl,bl,BCT_ENEMY)>0)
+ int cond1 = va_arg(ap, int);
+ int cond2 = va_arg(ap, int);
+ struct block_list **fr = va_arg(ap, struct block_list **);
+
+ if ((*fr) != NULL) // A friend was already found.
return 0;
- cond1=va_arg(ap,int);
- cond2=va_arg(ap,int);
- fr=va_arg(ap,struct mob_data **);
- if( cond2==-1 ){
- int j;
- for(j=SC_COMMON_MIN;j<=SC_COMMON_MAX && !flag;j++){
- if ((flag=(md->sc.data[j] != NULL))) //Once an effect was found, break out. [Skotlex]
+
+ int flag = 0;
+ struct status_change *sc = status->get_sc(bl);
+
+ if (cond2 == -1) { // Check for any of the common status alignments.
+ for (int i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) {
+ if ((flag = (sc->data[i] != NULL)) != 0) // Once an effect was found, break out. [Skotlex]
break;
}
- }else
- flag=( md->sc.data[cond2] != NULL );
- if( flag^( cond1==MSC_FRIENDSTATUSOFF ) )
- (*fr)=md;
+ } else {
+ flag = (sc->data[cond2] != NULL);
+ }
+
+ if ((flag ^ (cond1 == MSC_FRIENDSTATUSOFF)) != 0)
+ (*fr) = bl;
return 0;
}
-static struct mob_data *mob_getfriendstatus(struct mob_data *md, int cond1, int cond2)
+/**
+ * Gets a random monster/character within a range of 8 cells around md.
+ * If md is summoned (no monster slave!) a character is picker, otherwise a monster.
+ *
+ * @param md The monster which tries to cast a skill.
+ * @param cond1 Whether to check for active or inactive status change. (MSC_FRIENDSTATUSON/MSC_FRIENDSTATUSOFF)
+ * @param cond2 The status change (SC_* flag) to check.
+ * @return A randomly picked monster/character within range.
+ *
+ **/
+static struct block_list *mob_getfriendstatus(struct mob_data *md, int cond1, int cond2)
{
- struct mob_data* fr = NULL;
nullpo_ret(md);
- map->foreachinrange(mob->getfriendstatus_sub, &md->bl, 8,BL_MOB, md,cond1,cond2,&fr);
+ int type = (md->special_state.ai != AI_NONE) ? BL_PC : BL_MOB;
+ struct block_list *fr = NULL;
+
+ map->foreachinrange(mob->getfriendstatus_sub, &md->bl, 8, type, md, cond1, cond2, &fr);
+
return fr;
}
-/*==========================================
- * Skill use judging
- *------------------------------------------*/
-static int mobskill_use(struct mob_data *md, int64 tick, int event)
+/**
+ * Checks if skill cast condition in fulfilled and executes the skill in case of success.
+ *
+ * @param md The monster which tries to cast a skill.
+ * @param tick The timestamp of skill execution.
+ * @param event The MSC_* flag which triggered the skill execution. (-1 for non-event skill conditions.)
+ * @return 0 on success, 1 on failure.
+ *
+ **/
+static int mob_skill_use(struct mob_data *md, int64 tick, int event)
{
- struct mob_skill *ms;
- struct block_list *fbl = NULL; //Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex]
- struct block_list *bl;
- struct mob_data *fmd = NULL;
- int i,j,n;
-
nullpo_ret(md);
- nullpo_ret(ms = md->db->skill);
- if (!battle_config.mob_skill_rate || md->ud.skilltimer != INVALID_TIMER || !md->db->maxskill)
- return 0;
+ struct mob_skill *ms = md->db->skill;
+
+ nullpo_ret(ms);
+
+ if (battle_config.mob_skill_rate == 0 || md->ud.skilltimer != INVALID_TIMER || md->db->maxskill == 0)
+ return 1;
if (event == -1 && DIFF_TICK(md->ud.canact_tick, tick) > 0)
- return 0; //Skill act delay only affects non-event skills.
+ return 1; // Skill act delay only affects non-event skill conditions.
- //Pick a starting position and loop from that.
- i = (battle_config.mob_ai&0x100) ? rnd()%md->db->maxskill : 0;
- for (n = 0; n < md->db->maxskill; i++, n++) {
- int c2, flag = 0;
+ // Pick a starting position and loop from that.
+ int skill_idx = ((battle_config.mob_ai & 0x100) != 0) ? rnd() % md->db->maxskill : 0;
- if (i == md->db->maxskill)
- i = 0;
+ for (int i = 0; i < md->db->maxskill; skill_idx++, i++) {
+ if (skill_idx == md->db->maxskill)
+ skill_idx = 0;
- if (DIFF_TICK(tick, md->skilldelay[i]) < ms[i].delay)
+ if (DIFF_TICK(tick, md->skilldelay[skill_idx]) < ms[skill_idx].delay)
continue;
- c2 = ms[i].cond2;
+ enum MobSkillState state = ms[skill_idx].state;
- if (ms[i].state != md->state.skillstate) {
- if (md->state.skillstate != MSS_DEAD && (ms[i].state == MSS_ANY ||
- (ms[i].state == MSS_ANYTARGET && md->target_id && md->state.skillstate != MSS_LOOT)
- )) //ANYTARGET works with any state as long as there's a target. [Skotlex]
- ;
- else
+ if (state != md->state.skillstate) {
+ bool state_dead = (md->state.skillstate == MSS_DEAD);
+ bool any_target = (state == MSS_ANYTARGET && md->target_id != 0 && md->state.skillstate != MSS_LOOT);
+
+ // MSS_ANYTARGET works with any state as long as there's a target. [Skotlex]
+ if (state_dead || (state != MSS_ANY && !any_target))
continue;
}
- if (rnd() % 10000 > ms[i].permillage) //Lupus (max value = 10000)
+
+ if (rnd() % 10000 > ms[skill_idx].permillage)
continue;
- if (ms[i].cond1 == event)
- flag = 1; //Trigger skill.
- else if (ms[i].cond1 == MSC_SKILLUSED)
- flag = ((event & 0xffff) == MSC_SKILLUSED && ((event >> 16) == c2 || c2 == 0));
- else if(event == -1){
- //Avoid entering on defined events to avoid "hyper-active skill use" due to the overflow of calls to this function in battle.
- switch (ms[i].cond1)
- {
- case MSC_ALWAYS:
- flag = 1; break;
- case MSC_MYHPLTMAXRATE: // HP< maxhp%
- flag = get_percentage(md->status.hp, md->status.max_hp);
- flag = (flag <= c2);
- break;
- case MSC_MYHPINRATE:
- flag = get_percentage(md->status.hp, md->status.max_hp);
- flag = (flag >= c2 && flag <= ms[i].val[0]);
- break;
- case MSC_MYSTATUSON: // status[num] on
- case MSC_MYSTATUSOFF: // status[num] off
- if (!md->sc.count) {
- flag = 0;
- } else if (ms[i].cond2 == -1) {
- for (j = SC_COMMON_MIN; j <= SC_COMMON_MAX; j++)
- if ((flag = (md->sc.data[j]!=NULL)) != 0)
- break;
- } else {
- flag = (md->sc.data[ms[i].cond2]!=NULL);
+ int cast_cond = ms[skill_idx].cond1;
+ int cond_data = ms[skill_idx].cond2;
+ int flag = 0;
+ struct block_list *fbl = NULL; // Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex]
+
+ if (cast_cond == event) {
+ flag = 1; // Trigger skill.
+ } else if (cast_cond == MSC_SKILLUSED) {
+ flag = ((event & 0xFFFF) == MSC_SKILLUSED && ((event >> 16) == cond_data || cond_data == 0));
+ } else if (event == -1) {
+ // Avoid entering on defined events to avoid "hyper-active skill use" due to the overflow of calls to this function in battle.
+ switch (cast_cond) {
+ case MSC_ALWAYS:
+ flag = 1;
+ break;
+ case MSC_MYHPLTMAXRATE: // HP <= x%
+ flag = get_percentage(md->status.hp, md->status.max_hp);
+ flag = (flag <= cond_data);
+ break;
+ case MSC_MYHPINRATE: // HP >= x% && HP <= y%
+ flag = get_percentage(md->status.hp, md->status.max_hp);
+ flag = (flag >= cond_data && flag <= ms[skill_idx].val[0]);
+ break;
+ case MSC_MYSTATUSON: // Status change x is active.
+ case MSC_MYSTATUSOFF: // Status change x is inactive.
+ if (cond_data == -1) { // Check for any of the common status alignments.
+ for (int j = SC_COMMON_MIN; j <= SC_COMMON_MAX; j++) {
+ if ((flag = (md->sc.data[j] != NULL)) != 0)
+ break;
}
- flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF); break;
- case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp%
- flag = ((fbl = mob->getfriendhprate(md, 0, ms[i].cond2)) != NULL); break;
- case MSC_FRIENDHPINRATE:
- flag = ((fbl = mob->getfriendhprate(md, ms[i].cond2, ms[i].val[0])) != NULL); break;
- case MSC_FRIENDSTATUSON: // friend status[num] on
- case MSC_FRIENDSTATUSOFF: // friend status[num] off
- flag = ((fmd = mob->getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); break;
- case MSC_SLAVELT: // slave < num
- flag = (mob->countslave(&md->bl) < c2 ); break;
- case MSC_ATTACKPCGT: // attack pc > num
- flag = (unit->counttargeted(&md->bl) > c2); break;
- case MSC_SLAVELE: // slave <= num
- flag = (mob->countslave(&md->bl) <= c2 ); break;
- case MSC_ATTACKPCGE: // attack pc >= num
- flag = (unit->counttargeted(&md->bl) >= c2); break;
- case MSC_AFTERSKILL:
- flag = (md->ud.skill_id == c2); break;
- case MSC_RUDEATTACKED:
- flag = (md->state.attacked_count >= RUDE_ATTACKED_COUNT);
- if (flag) md->state.attacked_count = 0; //Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex]
- break;
- case MSC_MASTERHPLTMAXRATE:
- flag = ((fbl = mob->getmasterhpltmaxrate(md, ms[i].cond2)) != NULL); break;
- case MSC_MASTERATTACKED:
- flag = (md->master_id > 0 && (fbl=map->id2bl(md->master_id)) != NULL && unit->counttargeted(fbl) > 0);
- break;
- case MSC_ALCHEMIST:
- flag = (md->state.alchemist);
- break;
+ } else {
+ flag = (md->sc.data[cond_data] != NULL);
+ }
+
+ flag ^= (cast_cond == MSC_MYSTATUSOFF);
+ break;
+ case MSC_FRIENDHPLTMAXRATE: // FriendHP <= x%
+ flag = ((fbl = mob->getfriendhprate(md, 0, cond_data)) != NULL);
+ break;
+ case MSC_FRIENDHPINRATE: // FriendHP >= x% && FriendHP <= y%
+ flag = ((fbl = mob->getfriendhprate(md, cond_data, ms[skill_idx].val[0])) != NULL);
+ break;
+ case MSC_FRIENDSTATUSON: // Friend's status change x is active.
+ case MSC_FRIENDSTATUSOFF: // Friend's status change x is inactive.
+ flag = ((fbl = mob->getfriendstatus(md, cast_cond, cond_data)) != NULL);
+ break;
+ case MSC_SLAVELT: // Monster has less than x active slaves.
+ flag = (mob->countslave(&md->bl) < cond_data);
+ break;
+ case MSC_ATTACKPCGT: // Monster is attacked by more than x units.
+ flag = (unit->counttargeted(&md->bl) > cond_data);
+ break;
+ case MSC_SLAVELE: // Monster has x or less active slaves.
+ flag = (mob->countslave(&md->bl) <= cond_data);
+ break;
+ case MSC_ATTACKPCGE: // Monster is attacked by x or more units.
+ flag = (unit->counttargeted(&md->bl) >= cond_data);
+ break;
+ case MSC_AFTERSKILL: // Monster used skill x, or any skill if x is 0.
+ flag = (md->ud.skill_id == cond_data || cond_data == 0);
+ break;
+ case MSC_RUDEATTACKED: // Monster was rude attacked RUDE_ATTACKED_COUNT or more times.
+ flag = (md->state.attacked_count >= RUDE_ATTACKED_COUNT);
+
+ // Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex]
+ if (flag)
+ md->state.attacked_count = 0;
+
+ break;
+ case MSC_MASTERHPLTMAXRATE: // MasterHP < x%
+ flag = ((fbl = mob->getmasterhpltmaxrate(md, cond_data)) != NULL);
+ break;
+ case MSC_MASTERATTACKED: // Monster's master is under attack.
+ flag = (md->master_id > 0 && (fbl = map->id2bl(md->master_id)) != NULL);
+ flag = (fbl != NULL && unit->counttargeted(fbl) > 0);
+ break;
+ case MSC_ALCHEMIST: // Monster was summoned by an Alchemist.
+ flag = (md->state.alchemist != 0);
+ break;
}
}
- if (!flag)
- continue; //Skill requisite failed to be fulfilled.
+ if (flag == 0) // Skill cast condition not fulfilled.
+ continue;
+
+ // Execute skill.
+ if (skill->get_casttype(ms[skill_idx].skill_id) == CAST_GROUND) { // Ground skill.
+ int target_type = ms[skill_idx].target;
+ int skill_range = skill->get_range2(&md->bl, ms[skill_idx].skill_id, ms[skill_idx].skill_lv);
+ struct block_list *bl;
- //Execute skill
- if (skill->get_casttype(ms[i].skill_id) == CAST_GROUND) {//Ground skill.
- short x, y;
- switch (ms[i].target) {
- case MST_RANDOM: //Pick a random enemy within skill range.
- bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md),
- skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv));
- break;
- case MST_TARGET:
- case MST_AROUND5:
- case MST_AROUND6:
- case MST_AROUND7:
- case MST_AROUND8:
- bl = map->id2bl(md->target_id);
- break;
- case MST_MASTER:
- bl = &md->bl;
- if (md->master_id)
- bl = map->id2bl(md->master_id);
- if (bl) //Otherwise, fall through.
- break;
- FALLTHROUGH
- case MST_FRIEND:
- bl = fbl?fbl:(fmd?&fmd->bl:&md->bl);
- break;
- default:
- bl = &md->bl;
+ switch (target_type) {
+ case MST_RANDOM: // Pick a random enemy within skill range. Skill center is monster position.
+ bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), skill_range);
+ break;
+ case MST_TARGET: // Monster's current target is within skill range. Skill center is monster position.
+ case MST_AROUND5: // Monster's current target is within skill range. Skill center is a random cell within a range of 1.
+ case MST_AROUND6: // Monster's current target is within skill range. Skill center is a random cell within a range of 2.
+ case MST_AROUND7: // Monster's current target is within skill range. Skill center is a random cell within a range of 3.
+ case MST_AROUND8: // Monster's current target is within skill range. Skill center is a random cell within a range of 4.
+ bl = map->id2bl(md->target_id);
+ break;
+ case MST_MASTER: // Monster's master is within skill range. Skill center is monster position.
+ // If monster has no master, use the monster as target,
+ bl = (md->master_id != 0) ? map->id2bl(md->master_id) : &md->bl;
+
+ if (bl != NULL)
break;
+
+ // If monster has a master but master wasn't found, try a friend.
+ FALLTHROUGH
+ case MST_FRIEND: // Monster's friend is within skill range. Skill center is monster position.
+ bl = (fbl != NULL) ? fbl : &md->bl;
+ break;
+ default: // Monster is within skill range. Skill center is monster position.
+ bl = &md->bl;
+ break;
}
- if (!bl) continue;
-
- x = bl->x;
- y = bl->y;
- // Look for an area to cast the spell around...
- if (ms[i].target >= MST_AROUND1 || ms[i].target >= MST_AROUND5) {
- j = ms[i].target >= MST_AROUND1?
- (ms[i].target-MST_AROUND1) +1:
- (ms[i].target-MST_AROUND5) +1;
- map->search_freecell(&md->bl, md->bl.m, &x, &y, j, j, 3);
+
+ if (bl == NULL) // No target found.
+ continue;
+
+ short x = bl->x;
+ short y = bl->y;
+
+ // Find a target cell.
+ if (target_type >= MST_AROUND5 && target_type <= MST_AROUND) {
+ int range = target_type - ((target_type >= MST_AROUND1) ? MST_AROUND1 : MST_AROUND5) + 1;
+ map->search_freecell(&md->bl, md->bl.m, &x, &y, range, range, 3);
}
- md->skill_idx = i;
+
+ md->skill_idx = skill_idx;
map->freeblock_lock();
- if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv))
- || !unit->skilluse_pos2(&md->bl, x, y,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel)
- ) {
+
+ uint16 sk_id = ms[skill_idx].skill_id;
+ uint16 sk_lv = ms[skill_idx].skill_lv;
+ int casttime = ms[skill_idx].casttime;
+ short cancel = ms[skill_idx].cancel;
+
+ if (!battle->check_range(&md->bl, bl, skill_range)
+ || unit->skilluse_pos2(&md->bl, x, y, sk_id, sk_lv, casttime, cancel) == 0) {
map->freeblock_unlock();
continue;
}
- } else {
- //Targeted skill
- switch (ms[i].target) {
- case MST_RANDOM: //Pick a random enemy within skill range.
- bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md),
- skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv));
- break;
- case MST_TARGET:
- bl = map->id2bl(md->target_id);
- break;
- case MST_MASTER:
- bl = &md->bl;
- if (md->master_id)
- bl = map->id2bl(md->master_id);
- if (bl) //Otherwise, fall through.
- break;
- FALLTHROUGH
- case MST_FRIEND:
- if (fbl) {
- bl = fbl;
- break;
- } else if (fmd) {
- bl = &fmd->bl;
- break;
- } // else fall through
- FALLTHROUGH
- default:
- bl = &md->bl;
+ } else { // Targeted skill.
+ int skill_range = skill->get_range2(&md->bl, ms[skill_idx].skill_id, ms[skill_idx].skill_lv);
+ struct block_list *bl;
+
+ switch (ms[skill_idx].target) {
+ case MST_RANDOM: // Pick a random enemy within skill range.
+ bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), skill_range);
+ break;
+ case MST_TARGET: // Monster's current target is within skill range.
+ bl = map->id2bl(md->target_id);
+ break;
+ case MST_MASTER: // Monster's master is within skill range.
+ // If monster has no master, use the monster as target,
+ bl = (md->master_id != 0) ? map->id2bl(md->master_id) : &md->bl;
+
+ if (bl != NULL)
break;
+
+ // If monster has a master but master wasn't found, try a friend.
+ FALLTHROUGH
+ case MST_FRIEND: // Monster's friend is within skill range.
+ bl = (fbl != NULL) ? fbl : &md->bl;
+ break;
+ default: // Monster is within skill range.
+ bl = &md->bl;
+ break;
}
- if (!bl) continue;
- md->skill_idx = i;
+ if (bl == NULL) // No target found.
+ continue;
+
+ md->skill_idx = skill_idx;
map->freeblock_lock();
- if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv))
- || !unit->skilluse_id2(&md->bl, bl->id,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel)
- ) {
+
+ uint16 sk_id = ms[skill_idx].skill_id;
+ uint16 sk_lv = ms[skill_idx].skill_lv;
+ int casttime = ms[skill_idx].casttime;
+ short cancel = ms[skill_idx].cancel;
+
+ if (!battle->check_range(&md->bl, bl, skill_range)
+ || unit->skilluse_id2(&md->bl, bl->id, sk_id, sk_lv, casttime, cancel) == 0) {
map->freeblock_unlock();
continue;
}
}
- //Skill used. Post-setups...
- if ( ms[ i ].msg_id ){ //Display color message [SnakeDrak]
- struct mob_chat *mc = mob->chat(ms[i].msg_id);
+
+ // Skill used.
+ if (ms[skill_idx].msg_id != 0) { // Display color message. [SnakeDrak]
char temp[CHAT_SIZE_MAX];
char name[NAME_LENGTH];
- snprintf(name, sizeof name,"%s", md->name);
- strtok(name, "#"); // discard extra name identifier if present [Daegaladh]
- safesnprintf(temp, sizeof temp,"%s : %s", name, mc->msg);
+ struct mob_chat *mc = mob->chat(ms[skill_idx].msg_id);
+
+ snprintf(name, sizeof(name), "%s", md->name);
+ strtok(name, "#"); // Discard extra name identifier if present. [Daegaladh]
+ safesnprintf(temp, sizeof(temp), "%s : %s", name, mc->msg);
clif->messagecolor(&md->bl, mc->color, temp);
}
- if(!(battle_config.mob_ai&0x200)) { //pass on delay to same skill.
- for (j = 0; j < md->db->maxskill; j++)
- if (md->db->skill[j].skill_id == ms[i].skill_id)
- md->skilldelay[j]=tick;
- } else
- md->skilldelay[i]=tick;
+
+ if ((battle_config.mob_ai & 0x200) == 0) { // Pass on delay to same skill.
+ for (int j = 0; j < md->db->maxskill; j++) {
+ if (md->db->skill[j].skill_id == ms[skill_idx].skill_id)
+ md->skilldelay[j] = tick;
+ }
+ } else {
+ md->skilldelay[skill_idx] = tick;
+ }
+
map->freeblock_unlock();
- return 1;
+ return 0;
}
- //No skill was used.
+
+ // No skill was used.
md->skill_idx = -1;
- return 0;
+ return 1;
}
+
/*==========================================
* Skill use event processing
*------------------------------------------*/
@@ -3663,7 +3739,7 @@ static int mobskill_event(struct mob_data *md, struct block_list *src, int64 tic
nullpo_ret(md);
nullpo_ret(src);
if(md->bl.prev == NULL || md->status.hp <= 0)
- return 0;
+ return 1;
if (md->special_state.ai == AI_SPHERE) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex]
md->state.alchemist = 1;
@@ -3683,7 +3759,7 @@ static int mobskill_event(struct mob_data *md, struct block_list *src, int64 tic
else if (flag&BF_LONG && !(flag&BF_MAGIC)) //Long-attacked should not include magic.
res = mob->skill_use(md, tick, MSC_LONGRANGEATTACKED);
- if (!res)
+ if (res != 0)
//Restore previous target only if skill condition failed to trigger. [Skotlex]
md->target_id = target_id;
//Otherwise check if the target is an enemy, and unlock if needed.
@@ -3907,8 +3983,8 @@ static int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16
}
}
- mob_skills[i].permillage *= battle_config.mob_skill_rate / 100;
- mob_skills[i].delay *= battle_config.mob_skill_delay / 100;
+ mob_skills[i].permillage = mob_skills[i].permillage * battle_config.mob_skill_rate / 100;
+ mob_skills[i].delay = mob_skills[i].delay * battle_config.mob_skill_delay / 100;
db->maxskill = ++i;
}
@@ -5012,12 +5088,10 @@ static int mob_read_db_sub(struct config_setting_t *mobt, int n, const char *sou
md.status.def_ele = i32;
md.status.ele_lv = value;
} else if (!inherit) {
- ShowWarning("mob_read_db_sub: Missing element for monster ID %d.\n", md.mob_id);
md.status.def_ele = ELE_NEUTRAL;
md.status.ele_lv = 1;
}
} else if (!inherit) {
- ShowWarning("mob_read_db_sub: Missing element for monster ID %d.\n", md.mob_id);
md.status.def_ele = ELE_NEUTRAL;
md.status.ele_lv = 1;
}
@@ -5491,115 +5565,134 @@ static bool mob_skill_db_libconfig_sub(struct config_setting_t *it, int n)
return true;
}
+/**
+ * Reads a single monster skill from DB.
+ *
+ * @param it The libconfig settings block, which contains the skill data.
+ * @param n The skill data block's index within the parent monster block.
+ * @param mob_id The monster's ID.
+ * @return true on success, false on failure.
+ *
+ **/
static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n, int mob_id)
{
- int i, j, idx = 0;
- int i32;
- int skill_id = 0;
- int skill_idx = 0;
- bool clearskills = false;
- const char *name = config_setting_name(it);
- struct mob_skill *ms, gms;
-
nullpo_retr(false, it);
Assert_retr(false, mob_id <= 0 || mob->db(mob_id) != mob->dummy);
- if (!(skill_id = skill->name2id(name))) {
- ShowWarning("mob_skill_db_libconfig_sub_skill: Non existant skill id %d in monster %d, skipping.\n", skill_id, mob_id);
+ int skill_id = 0;
+ const char *name = config_setting_name(it);
+ const char *mob_str = (mob_id < 0) ? "global ID" : "monster";
+
+ if ((skill_id = skill->name2id(name)) == 0) {
+ ShowWarning("%s: Non existant skill %d in %s %d, skipping.\n", __func__, skill_id, mob_str, mob_id);
return false;
}
+ const char *skill_name = skill->get_name(skill_id);
+ bool clearskills = false;
+
// If ClearSkills flag is enabled clear all the previous skills.
- if (libconfig->setting_lookup_bool_real(it, "ClearSkills", &clearskills) && clearskills) {
- if (mob_id < 0) // Clearing skills globaly is not supported
+ if (libconfig->setting_lookup_bool_real(it, "ClearSkills", &clearskills) == CONFIG_TRUE && clearskills) {
+ if (mob_id < 0) {
+ ShowError("%s: Global skill clearing is not supported, skipping. (Global ID %d, skill %d (%s).)\n",
+ __func__, mob_id, skill_id, skill_name);
return false;
+ }
+
memset(mob->db_data[mob_id]->skill, 0, sizeof(struct mob_skill) * MAX_MOBSKILL);
mob->db_data[mob_id]->maxskill = 0;
return true;
}
- if (mob_id < 0) {
- // Prepare global skill. [Skotlex]
+ struct mob_skill *ms;
+
+ if (mob_id < 0) { // Prepare global skill. [Skotlex]
+ struct mob_skill gms;
memset(&gms, 0, sizeof (struct mob_skill));
ms = &gms;
} else {
+ int idx = 0;
+
ARR_FIND(0, MAX_MOBSKILL, idx, (ms = &mob->db_data[mob_id]->skill[idx])->skill_id == 0);
+
if (idx == MAX_MOBSKILL) {
- ShowError("mob_skill_db_libconfig_sub_skill: Too many skills for monster %d\n", mob_id);
+ ShowError("%s: Too many skills for monster %d, skipping.\n", __func__, mob_id);
return false;
}
+
+ mob->db_data[mob_id]->maxskill = idx + 1;
}
+
ms->skill_id = skill_id;
+ int i32 = MSS_ANY;
if (mob->lookup_const(it, "SkillState", &i32) && (i32 < MSS_ANY || i32 > MSS_ANYTARGET)) {
- ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid skill state %d for skill id %d in monster %d, defaulting to MSS_ANY.\n", i32, skill_id, mob_id);
+ ShowWarning("%s: Invalid skill state %d for skill %d (%s) in %s %d, defaulting to MSS_ANY.\n",
+ __func__, i32, skill_id, skill_name, mob_str, mob_id);
i32 = MSS_ANY;
}
ms->state = i32;
- if (!libconfig->setting_lookup_int(it, "SkillLevel", &i32) || i32 <= 0)
- i32 = 1;
- ms->skill_lv = i32 > battle_config.mob_max_skilllvl ? battle_config.mob_max_skilllvl : i32; //we strip max skill level
+ int res = libconfig->setting_lookup_int(it, "SkillLevel", &i32);
+ ms->skill_lv = (res == CONFIG_FALSE) ? 1 : cap_value(i32, 1, battle_config.mob_max_skilllvl);
- //Apply battle_config modifiers to rate (permillage) and delay [Skotlex]
- if (libconfig->setting_lookup_int(it, "Rate", &i32))
- ms->permillage = i32;
+ res = libconfig->setting_lookup_int(it, "Rate", &i32);
+ ms->permillage = (res == CONFIG_FALSE) ? 1 : cap_value(i32, 1, 10000);
+ // Apply battle_config modifier to rate (permillage).
if (battle_config.mob_skill_rate != 100)
ms->permillage = ms->permillage * battle_config.mob_skill_rate / 100;
+
if (ms->permillage > 10000)
ms->permillage = 10000;
- else if (ms->permillage == 0 && battle_config.mob_skill_rate)
+ else if (ms->permillage == 0 && battle_config.mob_skill_rate != 0)
ms->permillage = 1;
- if (libconfig->setting_lookup_int(it, "CastTime", &i32) && i32 > 0)
- ms->casttime = i32;
+ res = libconfig->setting_lookup_int(it, "CastTime", &i32);
+ ms->casttime = (res == CONFIG_FALSE) ? 0 : cap_value(i32, 0, MOB_MAX_CASTTIME);
+
+ res = libconfig->setting_lookup_int(it, "Delay", &i32);
+ ms->delay = (res == CONFIG_FALSE) ? 0 : cap_value(i32, 0, MOB_MAX_DELAY);
- if (libconfig->setting_lookup_int(it, "Delay", &i32))
- ms->delay = i32;
+ // Apply battle_config modifier to delay.
if (battle_config.mob_skill_delay != 100)
ms->delay = ms->delay * battle_config.mob_skill_delay / 100;
- if (ms->delay < 0 || ms->delay > MOB_MAX_DELAY) //time overflow?
- ms->delay = MOB_MAX_DELAY;
- if (libconfig->setting_lookup_bool(it, "Cancelable", &i32))
- ms->cancel = (i32 == 0) ? 0 : 1;
+ ms->delay = min(ms->delay, MOB_MAX_DELAY);
+
+ res = libconfig->setting_lookup_bool(it, "Cancelable", &i32);
+ ms->cancel = (res == CONFIG_FALSE) ? 0 : cap_value(i32, 0, 1);
+ i32 = MST_TARGET;
if (mob->lookup_const(it, "SkillTarget", &i32) && (i32 < MST_TARGET || i32 > MST_AROUND)) {
- ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid skill target %d for skill id %d in monster %d, defaulting to MST_TARGET.\n", i32, skill_id, mob_id);
- ms->target = MST_TARGET;
+ ShowWarning("%s: Invalid skill target %d for skill %d (%s) in %s %d, defaulting to MST_TARGET.\n",
+ __func__, i32, skill_id, skill_name, mob_str, mob_id);
+ i32 = MST_TARGET;
}
ms->target = i32;
- //Check that the target condition is right for the skill type. [Skotlex]
- skill_idx = skill->get_index(skill_id);
- if (skill->get_casttype2(skill_idx) == CAST_GROUND) {//Ground skill.
- if (ms->target > MST_AROUND) {
- ShowWarning("mob_skill_db_libconfig_sub_skill: Wrong mob skill target for ground skill %d (%s) for %s.\n",
- ms->skill_id, skill->dbs->db[skill_idx].name,
- mob_id < 0 ? "all mobs" : mob->db_data[mob_id]->sprite);
- ms->target = MST_TARGET;
- }
- } else if (ms->target > MST_MASTER) {
- ShowWarning("mob_skill_db_libconfig_sub_skill: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s.\n",
- ms->skill_id, skill->dbs->db[skill_idx].name,
- mob_id < 0 ? "all mobs" : mob->db_data[mob_id]->sprite);
+ // Check the target condition for non-ground skills. (Ground skills can use every target.)
+ if (skill->get_casttype2(skill->get_index(skill_id)) != CAST_GROUND && ms->target > MST_MASTER) {
+ ShowWarning("%s: Wrong skill target %d for non-ground skill %d (%s) in %s %d, defaulting to MST_TARGET.\n",
+ __func__, ms->target, skill_id, skill_name, mob_str, mob_id);
ms->target = MST_TARGET;
}
+ i32 = MSC_ALWAYS;
if (mob->lookup_const(it, "CastCondition", &i32) && (i32 < MSC_ALWAYS || i32 > MSC_SPAWN)) {
- ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid skill condition %d for skill id %d in monster %d, defaulting to MSC_ALWAYS.\n", i32, skill_id, mob_id);
- ms->cond1 = MSC_ALWAYS;
+ ShowWarning("%s: Invalid skill condition %d for skill id %d (%s) in %s %d, defaulting to MSC_ALWAYS.\n",
+ __func__, i32, skill_id, skill_name, mob_str, mob_id);
+ i32 = MSC_ALWAYS;
}
ms->cond1 = i32;
- if (mob->lookup_const(it, "ConditionData", &i32))
- ms->cond2 = i32;
+ ms->cond2 = !mob->lookup_const(it, "ConditionData", &i32) ? 0 : cap_value(i32, SHRT_MIN, SHRT_MAX);
- for (i = 0; i < 5; i++) {
+ for (int i = 0; i < 5; i++) {
char valname[16];
sprintf(valname, "val%1d", i);
- if (libconfig->setting_lookup_int(it, valname, &i32))
+
+ if (libconfig->setting_lookup_int(it, valname, &i32) == CONFIG_TRUE)
ms->val[i] = i32;
}
@@ -5610,60 +5703,64 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n,
if (mob_id > 0 && (uint32)ms->val[1] == mob->db(mob_id)->status.mode) {
ms->val[1] = MD_NONE;
- ms->val[4] = 1; //request to return mode to normal.
+ ms->val[4] = 1; // Request to return mode to normal.
}
}
if (ms->skill_id == NPC_EMOTION_ON && mob_id > 0 && ms->val[1] != MD_NONE) {
- //Adds a mode to the mob.
- //Remove aggressive mode when the new mob type is passive.
- if (!(ms->val[1] & MD_AGGRESSIVE))
+ // Add a mode to the mob and remove aggressive mode if the new mode is passive.
+ if ((ms->val[1] & MD_AGGRESSIVE) == 0)
ms->val[3] |= MD_AGGRESSIVE;
- ms->val[2] |= (uint32)ms->val[1]; //Add the new mode.
- ms->val[1] = MD_NONE; //Do not "set" it.
+
+ ms->val[2] |= (uint32)ms->val[1]; // Add the new mode.
+ ms->val[1] = MD_NONE; // Do not "set" it.
}
- if (libconfig->setting_lookup_int(it, "Emotion", &i32))
- ms->emotion = i32;
- else
- ms->emotion = -1;
+ res = libconfig->setting_lookup_int(it, "Emotion", &i32);
+ ms->emotion = (res == CONFIG_FALSE) ? -1 : cap_value(i32, -1, SHRT_MAX);
- if (libconfig->setting_lookup_int(it, "ChatMsgID", &i32) && i32 > 0 && i32 <= MAX_MOB_CHAT) {
- if (mob->chat_db[i32] == NULL) {
- ShowWarning("mob_skill_db_libconfig_sub_skill: Invalid msg id %d for skill id %d in monster %d, ignoring.\n", i32, skill_id, mob_id);
+ if (libconfig->setting_lookup_int(it, "ChatMsgID", &i32) == CONFIG_TRUE) {
+ if (i32 <= 0 || i32 > MAX_MOB_CHAT || mob->chat_db[i32] == NULL) {
+ ShowWarning("%s: Invalid message ID %d for skill %d (%s) in %s %d, ignoring.\n",
+ __func__, i32, skill_id, skill_name, mob_str, mob_id);
} else {
ms->msg_id = i32;
}
}
- if (mob_id < 0) {
- // Set this skill to ALL mobs. [Skotlex]
- mob_id *= -1;
- for (i = 1; i < MAX_MOB_DB; i++) {
+ if (mob_id < 0) { // Global skill assignment.
+ mob_id = -mob_id;
+
+ for (int i = 1; i < MAX_MOB_DB; i++) {
if (mob->db_data[i] == NULL)
continue;
- if (mob->db_data[i]->status.mode & MD_BOSS) {
- if (!(mob_id & 2)) //Skill not for bosses
+
+ if ((mob->db_data[i]->status.mode & MD_BOSS) != 0) {
+ if ((mob_id & 2) == 0) // Skill not for boss monsters.
continue;
} else {
- if (!(mob_id & 1)) //Skill not for normal enemies.
+ if ((mob_id & 1) == 0) // Skill not for normal monsters.
continue;
}
- ARR_FIND(0, MAX_MOBSKILL, j, mob->db_data[i]->skill[j].skill_id == 0);
- if (j == MAX_MOBSKILL)
+
+ int idx;
+
+ ARR_FIND(0, MAX_MOBSKILL, idx, mob->db_data[i]->skill[idx].skill_id == 0);
+
+ if (idx == MAX_MOBSKILL) {
+ ShowError("%s: Too many skills for monster %d in global ID %d, skipping.\n",
+ __func__, i, -mob_id);
continue;
+ }
- memcpy(&mob->db_data[i]->skill[j], ms, sizeof(struct mob_skill));
- mob->db_data[i]->maxskill = j + 1;
+ memcpy(&mob->db_data[i]->skill[idx], ms, sizeof(struct mob_skill));
+ mob->db_data[i]->maxskill = idx + 1;
}
- } else { //Skill set on a single mob.
- mob->db_data[mob_id]->maxskill = idx + 1;
}
return true;
}
-
/*==========================================
* mob_skill_db.txt reading
*------------------------------------------*/
@@ -6059,7 +6156,7 @@ void mob_defaults(void)
mob->getmasterhpltmaxrate = mob_getmasterhpltmaxrate;
mob->getfriendstatus_sub = mob_getfriendstatus_sub;
mob->getfriendstatus = mob_getfriendstatus;
- mob->skill_use = mobskill_use;
+ mob->skill_use = mob_skill_use;
mob->skill_event = mobskill_event;
mob->is_clone = mob_is_clone;
mob->clone_spawn = mob_clone_spawn;
diff --git a/src/map/mob.h b/src/map/mob.h
index 4cfddc2cd..6ad1ce705 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -323,6 +323,13 @@ enum {
MSC_SPAWN,
};
+/** Special monster(-name) constants used to assign skills to a group of monsters. **/
+enum mob_group {
+ ALL_MOBS_NONBOSS = -1,
+ ALL_MOBS_BOSS = -2,
+ ALL_MOBS = -3,
+};
+
/**
* Mob IDs
*/
@@ -566,7 +573,7 @@ struct mob_interface {
struct block_list* (*getfriendhprate) (struct mob_data *md, int min_rate, int max_rate);
struct block_list* (*getmasterhpltmaxrate) (struct mob_data *md, int rate);
int (*getfriendstatus_sub) (struct block_list *bl, va_list ap);
- struct mob_data* (*getfriendstatus) (struct mob_data *md, int cond1, int cond2);
+ struct block_list *(*getfriendstatus) (struct mob_data *md, int cond1, int cond2);
int (*skill_use) (struct mob_data *md, int64 tick, int event);
int (*skill_event) (struct mob_data *md, struct block_list *src, int64 tick, int flag);
int (*is_clone) (int class_);
diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c
index 0ca84cff4..0df323e96 100644
--- a/src/map/npc_chat.c
+++ b/src/map/npc_chat.c
@@ -394,7 +394,8 @@ static int npc_chat_sub(struct block_list *bl, va_list ap)
// save out the matched strings
for (i = 0; i < r; i++)
{
- char var[15], val[255];
+ char var[SCRIPT_VARNAME_LENGTH + 1];
+ char val[SCRIPT_STRING_VAR_LENGTH + 1];
snprintf(var, sizeof(var), "$@p%i$", i);
libpcre->copy_substring(msg, offsets, r, i, val, sizeof(val));
script->set_var(sd, var, val);
diff --git a/src/map/packets.h b/src/map/packets.h
index 1e6dc71bc..e30acbdf7 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -1824,6 +1824,11 @@ packet(0x96e,clif->ackmergeitems);
packet(0x0aa4, clif->pRefineryUIClose);
#endif
+#if PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+ packet(0x0ab5, clif->pLapineUpgrade_close);
+ packet(0x0ab6, clif->pLapineUpgrade_makeItem);
+#endif
+
// 2017-02-28aRagexeRE
#if PACKETVER >= 20170228
// new packets
diff --git a/src/map/packets_keys_main.h b/src/map/packets_keys_main.h
index e3a89827c..8ebbb39be 100644
--- a/src/map/packets_keys_main.h
+++ b/src/map/packets_keys_main.h
@@ -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, 2020-02-12aRagexe, 2020-02-12aRagexeRE, 2020-02-19dRagexe, 2020-02-19eRagexeRE, 2020-03-04aRagexe, 2020-03-04aRagexeRE, 2020-03-18bRagexe, 2020-04-01bRagexe
+// 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, 2020-04-14_6aRagexe, 2020-04-14eRagexe
#if PACKETVER == 20101123 || \
PACKETVER == 20101124 || \
PACKETVER == 20101125 || \
@@ -191,7 +191,8 @@
PACKETVER == 20200219 || \
PACKETVER == 20200304 || \
PACKETVER == 20200318 || \
- PACKETVER >= 20200401
+ PACKETVER == 20200401 || \
+ PACKETVER >= 20200414
packetKeys(0x00000000,0x00000000,0x00000000);
#endif
diff --git a/src/map/packets_keys_zero.h b/src/map/packets_keys_zero.h
index f189032d3..904159d37 100644
--- a/src/map/packets_keys_zero.h
+++ b/src/map/packets_keys_zero.h
@@ -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, 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
+// 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, 2020-04-14bRagexe_zero
#if PACKETVER == 20171018 || \
PACKETVER == 20171019 || \
PACKETVER == 20171023 || \
@@ -110,7 +110,8 @@
PACKETVER == 20200226 || \
PACKETVER == 20200304 || \
PACKETVER == 20200318 || \
- PACKETVER >= 20200401
+ PACKETVER == 20200401 || \
+ PACKETVER >= 20200414
packetKeys(0x00000000,0x00000000,0x00000000);
#endif
diff --git a/src/map/packets_shuffle_main.h b/src/map/packets_shuffle_main.h
index beedc950f..d643f3b0e 100644
--- a/src/map/packets_shuffle_main.h
+++ b/src/map/packets_shuffle_main.h
@@ -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, 2020-02-12aRagexe, 2020-02-19dRagexe, 2020-03-04aRagexe, 2020-03-18bRagexe, 2020-04-01bRagexe
+// 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, 2020-04-14_6aRagexe, 2020-04-14eRagexe
#if PACKETVER == 20190904 || \
PACKETVER == 20190918 || \
PACKETVER == 20190925 || \
@@ -9822,7 +9822,8 @@
PACKETVER == 20200219 || \
PACKETVER == 20200304 || \
PACKETVER == 20200318 || \
- PACKETVER == 20200401
+ PACKETVER == 20200401 || \
+ PACKETVER == 20200414
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 15936f854..fb12688c0 100644
--- a/src/map/packets_shuffle_zero.h
+++ b/src/map/packets_shuffle_zero.h
@@ -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, 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
+// 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, 2020-04-14bRagexe_zero
#if PACKETVER == 20190828 || \
PACKETVER == 20190911 || \
PACKETVER == 20190918 || \
@@ -822,7 +822,8 @@
PACKETVER == 20200226 || \
PACKETVER == 20200304 || \
PACKETVER == 20200318 || \
- PACKETVER == 20200401
+ PACKETVER == 20200401 || \
+ PACKETVER == 20200414
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 ca2fb8aef..3129a05d9 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -3891,6 +3891,42 @@ struct PACKET_ZC_AUTORUN_SKILL {
} __attribute__((packed));
DEFINE_PACKET_HEADER(ZC_AUTORUN_SKILL, 0x0147);
+#if PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+struct PACKET_ZC_LAPINEUPGRADE_OPEN {
+ int16 packetType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_LAPINEUPGRADE_OPEN, 0x0ab4);
+
+struct PACKET_ZC_LAPINEUPGRADE_RESULT {
+ int16 packetType;
+ uint16 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_LAPINEUPGRADE_RESULT, 0x0ab7);
+#endif // PACKETVER_MAIN_NUM >= 20170726 || PACKETVER_RE_NUM >= 20170621 || defined(PACKETVER_ZERO)
+
+#if PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+struct PACKET_CZ_LAPINEUPGRADE_CLOSE {
+ int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_LAPINEUPGRADE_CLOSE, 0x0ab5);
+
+struct PACKET_CZ_LAPINEUPGRADE_MAKE_ITEM {
+ int16 packetType;
+#if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
+ uint32 itemId;
+#else
+ uint16 itemId;
+#endif
+ uint16 index;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_LAPINEUPGRADE_MAKE_ITEM, 0x0ab6);
+#endif // PACKETVER_MAIN_NUM >= 20170111 || PACKETVER_RE_NUM >= 20170111 || defined(PACKETVER_ZERO)
+
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(pop)
#endif // not NetBSD < 6 / Solaris
diff --git a/src/map/pc.c b/src/map/pc.c
index 90282209b..5faadf76a 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1605,58 +1605,56 @@ static void pc_calc_skilltree_clear(struct map_session_data *sd)
*------------------------------------------*/
static int pc_calc_skilltree(struct map_session_data *sd)
{
- int i,id=0,flag;
- int class = 0, classidx = 0;
-
nullpo_ret(sd);
- i = pc->calc_skilltree_normalize_job(sd);
- class = pc->mapid2jobid(i, sd->status.sex);
+ uint32 job = pc->calc_skilltree_normalize_job(sd);
+ int class = pc->mapid2jobid(job, sd->status.sex);
if (class == -1) {
//Unable to normalize job??
- ShowError("pc_calc_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id);
+ ShowError("pc_calc_skilltree: Unable to normalize job %u for character %s (%d:%d)\n", job, sd->status.name, sd->status.account_id, sd->status.char_id);
return 1;
}
- classidx = pc->class2idx(class);
+ int classidx = pc->class2idx(class);
pc->calc_skilltree_clear(sd);
- for (i = 0; i < MAX_SKILL_DB; i++) {
- if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED )
- { // Restore original level of skills after deleting earned skills.
+ for (int i = 0; i < MAX_SKILL_DB; i++) {
+ if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) {
+ // Restore original level of skills after deleting earned skills.
sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
}
- if( sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER && skill->dbs->db[i].nameid >= DC_HUMMING && skill->dbs->db[i].nameid <= DC_SERVICEFORYOU )
- { //Enable Bard/Dancer spirit linked skills.
- if (sd->status.sex) {
- // Link dancer skills to bard.
- if (i < 8) {
- Assert_report(i >= 8);
- continue;
- }
- if (sd->status.skill[i-8].lv < 10)
- continue;
- sd->status.skill[i].id = skill->dbs->db[i].nameid;
- sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill
- sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
+ if (sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER
+ && ((skill->dbs->db[i].nameid >= BA_WHISTLE && skill->dbs->db[i].nameid <= BA_APPLEIDUN)
+ || (skill->dbs->db[i].nameid >= DC_HUMMING && skill->dbs->db[i].nameid <= DC_SERVICEFORYOU))
+ ) {
+ //Enable Bard/Dancer spirit linked skills.
+ int linked_nameid = skill->get_linked_song_dance_id(skill->dbs->db[i].nameid);
+ if (linked_nameid == 0) {
+ Assert_report("Linked bard/dance skill not found");
+ continue;
+ }
+ int copy_from_index;
+ int copy_to_index;
+ if (sd->status.sex == SEX_MALE && skill->dbs->db[i].nameid >= BA_WHISTLE && skill->dbs->db[i].nameid <= BA_APPLEIDUN) {
+ copy_from_index = i;
+ copy_to_index = skill->get_index(linked_nameid);
} else {
- // Link bard skills to dancer.
- if (i < 8) {
- Assert_report(i >= 8);
- continue;
- }
- if (sd->status.skill[i].lv < 10)
- continue;
- sd->status.skill[i-8].id = skill->dbs->db[i-8].nameid;
- sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill
- sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
+ copy_from_index = skill->get_index(linked_nameid);
+ copy_to_index = i;
}
+ if (copy_from_index < copy_to_index)
+ continue; // Copy only after the source skill has been filled into the tree
+ if (sd->status.skill[copy_from_index].lv < 10)
+ continue; // Copy only if the linked skill has been mastered
+ sd->status.skill[copy_to_index].id = skill->dbs->db[copy_to_index].nameid;
+ sd->status.skill[copy_to_index].lv = sd->status.skill[copy_from_index].lv; // Set the level to the same as the linking skill
+ sd->status.skill[copy_to_index].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
}
}
if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) {
- for (i = 0; i < MAX_SKILL_DB; i++) {
+ for (int i = 0; i < MAX_SKILL_DB; i++) {
switch(skill->dbs->db[i].nameid) {
/**
* Dummy skills must be added here otherwise they'll be displayed in the,
@@ -1688,9 +1686,11 @@ static int pc_calc_skilltree(struct map_session_data *sd)
return 0;
}
+ bool changed = false;
do {
- flag = 0;
- for (i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[classidx][i].id) > 0; i++) {
+ changed = false;
+ int id;
+ for (int i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[classidx][i].id) > 0; i++) {
int idx = pc->skill_tree[classidx][i].idx;
bool satisfied = true;
if (sd->status.skill[idx].id > 0)
@@ -1740,10 +1740,10 @@ static int pc_calc_skilltree(struct map_session_data *sd)
sd->status.skill[idx].lv = 1; // need to manually specify a skill level
sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill.
}
- flag = 1; // skill list has changed, perform another pass
+ changed = true; // skill list has changed, perform another pass
}
}
- } while(flag);
+ } while (changed);
pc->calc_skilltree_bonus(sd, classidx);
@@ -4206,7 +4206,7 @@ static int pc_skill(struct map_session_data *sd, int id, int level, int flag)
if( sd->status.skill[index].id == id ) {
if( sd->status.skill[index].lv >= level )
return 0;
- if( sd->status.skill[index].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level.
+ if (sd->status.skill[index].flag == SKILL_FLAG_PERMANENT) // Non-granted skill, store its level.
sd->status.skill[index].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[index].lv;
} else {
sd->status.skill[index].id = id;
@@ -7568,7 +7568,7 @@ static int pc_allskillup(struct map_session_data *sd)
nullpo_ret(sd);
for (i = 0; i < MAX_SKILL_DB; i++) {
- if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) {
+ if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) {
sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
if (sd->status.skill[i].lv == 0)
@@ -8325,7 +8325,7 @@ static int pc_dead(struct map_session_data *sd, struct block_list *src)
base_penalty *= 2;
if (sd->status.mod_death != 100)
- base_penalty *= sd->status.mod_death / 100;
+ base_penalty = base_penalty * sd->status.mod_death / 100;
sd->status.base_exp -= min(sd->status.base_exp, base_penalty);
clif->updatestatus(sd, SP_BASEEXP);
@@ -8350,7 +8350,7 @@ static int pc_dead(struct map_session_data *sd, struct block_list *src)
job_penalty *= 2;
if (sd->status.mod_death != 100)
- job_penalty *= sd->status.mod_death / 100;
+ job_penalty = job_penalty * sd->status.mod_death / 100;
sd->status.job_exp -= min(sd->status.job_exp, job_penalty);
clif->updatestatus(sd, SP_JOBEXP);
@@ -9288,6 +9288,72 @@ static int pc_changelook(struct map_session_data *sd, int type, int val)
return 0;
}
+/**
+ * Hides a character.
+ *
+ * @param sd The character to hide.
+ * @param show_msg Whether to show message to the character or not.
+ *
+ **/
+static void pc_hide(struct map_session_data *sd, bool show_msg)
+{
+ nullpo_retv(sd);
+
+ clif->clearunit_area(&sd->bl, CLR_OUTSIGHT);
+ sd->sc.option |= OPTION_INVISIBLE;
+ sd->vd.class = INVISIBLE_CLASS;
+
+ if (show_msg)
+ clif->message(sd->fd, atcommand->msgsd(sd, 11)); // Invisible: On
+
+ // Decrement the number of pvp players on the map.
+ map->list[sd->bl.m].users_pvp--;
+
+ if (map->list[sd->bl.m].flag.pvp != 0 && map->list[sd->bl.m].flag.pvp_nocalcrank == 0
+ && sd->pvp_timer != INVALID_TIMER) { // Unregister the player for ranking.
+ timer->delete(sd->pvp_timer, pc->calc_pvprank_timer);
+ sd->pvp_timer = INVALID_TIMER;
+ }
+
+ clif->changeoption(&sd->bl);
+}
+
+/**
+ * Unhides a character.
+ *
+ * @param sd The character to unhide.
+ * @param show_msg Whether to show message to the character or not.
+ *
+ **/
+static void pc_unhide(struct map_session_data *sd, bool show_msg)
+{
+ nullpo_retv(sd);
+
+ sd->sc.option &= ~OPTION_INVISIBLE;
+
+ if (sd->disguise != -1)
+ status->set_viewdata(&sd->bl, sd->disguise);
+ else
+ status->set_viewdata(&sd->bl, sd->status.class);
+
+ if (show_msg)
+ clif->message(sd->fd, atcommand->msgsd(sd, 10)); // Invisible: Off
+
+ // Increment the number of pvp players on the map.
+ map->list[sd->bl.m].users_pvp++;
+
+ if (map->list[sd->bl.m].flag.pvp != 0 && map->list[sd->bl.m].flag.pvp_nocalcrank == 0) // Register the player for ranking.
+ sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
+
+ // bugreport:2266
+ map->foreachinmovearea(clif->insight, &sd->bl, AREA_SIZE, sd->bl.x, sd->bl.y, BL_ALL, &sd->bl);
+
+ if (sd->disguise != -1)
+ clif->spawn_unit(&sd->bl, AREA_WOS);
+
+ clif->changeoption(&sd->bl);
+}
+
/*==========================================
* Give an option (type) to player (sd) and display it to client
*------------------------------------------*/
@@ -9299,7 +9365,13 @@ static int pc_setoption(struct map_session_data *sd, int type)
//Option has to be changed client-side before the class sprite or it won't always work (eg: Wedding sprite) [Skotlex]
sd->sc.option=type;
- clif->changeoption(&sd->bl);
+
+ if ((p_type & OPTION_INVISIBLE) != 0 && (type & OPTION_INVISIBLE) == 0) // Unhide character.
+ pc->unhide(sd, false);
+ else if ((p_type & OPTION_INVISIBLE) == 0 && (type & OPTION_INVISIBLE) != 0) // Hide character.
+ pc->hide(sd, false);
+ else
+ clif->changeoption(&sd->bl);
if( (type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc->checkskill(sd,RK_DRAGONTRAINING) > 0) ) {
// Mounting
@@ -11256,7 +11328,7 @@ static int pc_charm_timer(int tid, int64 tick, int id, intptr_t data)
* @param max Maximum amount of charms to add.
* @param type Charm type (@see spirit_charm_types)
*/
-static void pc_add_charm(struct map_session_data *sd, int interval, int max, int type)
+static void pc_add_charm(struct map_session_data *sd, int interval, int max, enum spirit_charm_types type)
{
int tid, i;
@@ -11298,7 +11370,7 @@ static void pc_add_charm(struct map_session_data *sd, int interval, int max, int
* @param count Amount of charms to remove.
* @param type Type of charm to remove.
*/
-static void pc_del_charm(struct map_session_data *sd, int count, int type)
+static void pc_del_charm(struct map_session_data *sd, int count, enum spirit_charm_types type)
{
int i;
@@ -12824,6 +12896,8 @@ void pc_defaults(void)
pc->itemheal = pc_itemheal;
pc->percentheal = pc_percentheal;
pc->jobchange = pc_jobchange;
+ pc->hide = pc_hide;
+ pc->unhide = pc_unhide;
pc->setoption = pc_setoption;
pc->setcart = pc_setcart;
pc->setfalcon = pc_setfalcon;
diff --git a/src/map/pc.h b/src/map/pc.h
index 2699b7882..e560df549 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -439,7 +439,7 @@ END_ZEROED_BLOCK;
int spiritball, spiritball_old;
int spirit_timer[MAX_SPIRITBALL];
int charm_count;
- int charm_type;
+ enum spirit_charm_types charm_type;
int charm_timer[MAX_SPIRITCHARM];
unsigned char potion_success_counter; //Potion successes in row counter
unsigned char mission_count; //Stores the bounty kill count for TK_MISSION
@@ -678,6 +678,7 @@ END_ZEROED_BLOCK;
#define pc_isidle(sd) ( (sd)->chat_id != 0 || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(sockt->last_tick, (sd)->idletime) >= battle->bc->idle_no_share )
#define pc_istrading(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading )
#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chat_id != 0 || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend || (sd)->state.refine_ui == 1 || (sd)->state.lapine_ui == 1)
+#define pc_cant_act_except_lapine(sd) ((sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chat_id != 0 || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend || (sd)->state.refine_ui == 1)
/* equals pc_cant_act except it doesn't check for chat rooms */
#define pc_cant_act2(sd) ( (sd)->npc_id || (sd)->state.buyingstore || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend || (sd)->state.refine_ui == 1 || (sd)->state.lapine_ui == 1)
@@ -687,7 +688,7 @@ END_ZEROED_BLOCK;
#define pc_ishiding(sd) ( (sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) )
#define pc_iscloaking(sd) ( !((sd)->sc.option&OPTION_CHASEWALK) && ((sd)->sc.option&OPTION_CLOAK) )
#define pc_ischasewalk(sd) ( (sd)->sc.option&OPTION_CHASEWALK )
-#define pc_ismuted(sc,type) ( (sc)->data[SC_NOCHAT] && (sc)->data[SC_NOCHAT]->val1&(type) )
+#define pc_ismuted(sc, type) ( (sc)->data[SC_NOCHAT] != NULL && (battle_config.manner_system & (type)) != 0 )
#define pc_isvending(sd) ((sd)->state.vending || (sd)->state.prevend || (sd)->state.buyingstore)
#ifdef NEW_CARTS
@@ -1044,6 +1045,8 @@ END_ZEROED_BLOCK; /* End */
int (*itemheal) (struct map_session_data *sd,int itemid, int hp,int sp);
int (*percentheal) (struct map_session_data *sd,int hp,int sp);
int (*jobchange) (struct map_session_data *sd, int class, int upper);
+ void (*hide) (struct map_session_data *sd, bool show_msg);
+ void (*unhide) (struct map_session_data *sd, bool show_msg);
int (*setoption) (struct map_session_data *sd,int type);
int (*setcart) (struct map_session_data* sd, int type);
void (*setfalcon) (struct map_session_data *sd, bool flag);
@@ -1127,8 +1130,8 @@ END_ZEROED_BLOCK; /* End */
int (*load_combo) (struct map_session_data *sd);
- void (*add_charm) (struct map_session_data *sd, int interval, int max, int type);
- void (*del_charm) (struct map_session_data *sd, int count, int type);
+ void (*add_charm) (struct map_session_data *sd, int interval, int max, enum spirit_charm_types type);
+ void (*del_charm) (struct map_session_data *sd, int count, enum spirit_charm_types type);
void (*baselevelchanged) (struct map_session_data *sd);
int (*level_penalty_mod) (int diff, unsigned char race, uint32 mode, int type);
diff --git a/src/map/pet.c b/src/map/pet.c
index 620779765..299de42c7 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -323,7 +323,7 @@ static int pet_hungry(int tid, int64 tick, int id, intptr_t data)
}
clif->send_petdata(sd, pd, 2, pd->pet.hungry);
- interval *= battle_config.pet_hungry_delay_rate / 100;
+ interval = 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;
@@ -944,7 +944,7 @@ static int pet_food(struct map_session_data *sd, struct pet_data *pd)
else
intimacy += pd->petDB->r_hungry / 2; // Increase intimacy by 50% of FeedIncrement.
- intimacy *= battle_config.pet_friendly_rate / 100;
+ intimacy = intimacy * battle_config.pet_friendly_rate / 100;
pet->set_intimate(pd, pd->pet.intimate + intimacy);
if (pd->pet.intimate == PET_INTIMACY_NONE) {
@@ -1128,12 +1128,22 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int
return 0;
}
+/**
+ * Calls pet_ai_sub_hard() for a character's pet if conditions are fulfilled.
+ *
+ * @param sd The character.
+ * @param ap Additional arguments. In this case only the time stamp of pet AI timer execution.
+ * @return Always 0.
+ *
+ **/
static int pet_ai_sub_foreachclient(struct map_session_data *sd, va_list ap)
{
- int64 tick = va_arg(ap,int64);
nullpo_ret(sd);
- if(sd->status.pet_id && sd->pd)
- pet->ai_sub_hard(sd->pd,sd,tick);
+
+ int64 tick = va_arg(ap, int64);
+
+ if (sd->bl.prev != NULL && sd->status.pet_id != 0 && sd->pd != NULL && sd->pd->bl.prev != NULL)
+ pet->ai_sub_hard(sd->pd, sd, tick);
return 0;
}
diff --git a/src/map/script.c b/src/map/script.c
index c08f5e829..347ef3d2a 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -3395,6 +3395,32 @@ static void set_reg_instance_num(struct script_state *st, int64 num, const char
}
/**
+ * Validates if a variable is permanent (stored in database) by passed variable name.
+ *
+ * @param name The variable name to validate.
+ * @return True if variable is permanent, otherwise false.
+ *
+ **/
+static bool script_is_permanent_variable(const char *name)
+{
+ nullpo_retr(false, name);
+
+ if (strlen(name) == 0)
+ return false;
+
+ if (ISALNUM(name[0]) != 0)
+ return true; // Permanent characater variable.
+
+ if (name[0] == '#')
+ return true; // Permanent (global) account variable.
+
+ if (strlen(name) > 1 && name[0] == '$' && ISALNUM(name[1]) != 0)
+ return true; // Permanent server variable.
+
+ return false;
+}
+
+/**
* Stores the value of a script variable
*
* @param st current script state.
@@ -3439,6 +3465,18 @@ static int set_reg(struct script_state *st, struct map_session_data *sd, int64 n
if (is_string_variable(name)) {// string variable
const char *str = (const char*)value;
+ if (script->is_permanent_variable(name) && strlen(str) > SCRIPT_STRING_VAR_LENGTH) {
+ ShowError("script:set_reg: Value of variable %s is too long: %lu! Maximum is %d. Skipping...\n",
+ name, strlen(str), SCRIPT_STRING_VAR_LENGTH);
+
+ if (st != NULL) {
+ script->reportsrc(st);
+ st->state = END;
+ }
+
+ return 0;
+ }
+
switch (prefix) {
case '@':
if (ref) {
@@ -16111,7 +16149,6 @@ static BUILDIN(atcommand)
struct map_session_data *sd, *dummy_sd = NULL;
int fd;
const char* cmd;
- bool ret = true;
cmd = script_getstr(st,2);
@@ -16134,11 +16171,12 @@ static BUILDIN(atcommand)
if (!atcommand->exec(fd, sd, cmd, false)) {
ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd);
- script->reportsrc(st);
- ret = false;
+ if (dummy_sd != NULL)
+ aFree(dummy_sd);
+ return false;
}
if (dummy_sd) aFree(dummy_sd);
- return ret;
+ return true;
}
/**
@@ -27847,6 +27885,11 @@ static void script_hardcoded_constants(void)
script->set_constant("MST_AROUND4", MST_AROUND4, false, false);
script->set_constant("MST_AROUND", MST_AROUND , false, false);
+ script->constdb_comment("Monster group constants");
+ script->set_constant("ALL_MOBS_NONBOSS", ALL_MOBS_NONBOSS, false, false);
+ script->set_constant("ALL_MOBS_BOSS", ALL_MOBS_BOSS, false, false);
+ script->set_constant("ALL_MOBS", ALL_MOBS, false, false);
+
script->constdb_comment("pc block constants, use with *setpcblock* and *checkpcblock*");
script->set_constant("PCBLOCK_NONE", PCBLOCK_NONE, false, false);
script->set_constant("PCBLOCK_MOVE", PCBLOCK_MOVE, false, false);
@@ -28250,6 +28293,7 @@ void script_defaults(void)
script->load_parameters = script_load_parameters;
script->print_line = script_print_line;
script->errorwarning_sub = script_errorwarning_sub;
+ script->is_permanent_variable = script_is_permanent_variable;
script->set_reg = set_reg;
script->set_reg_ref_str = set_reg_npcscope_str;
script->set_reg_pc_ref_str = set_reg_pc_ref_str;
diff --git a/src/map/script.h b/src/map/script.h
index 511497a66..5fa81dc0e 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -984,6 +984,7 @@ struct script_interface {
void (*load_parameters) (void);
const char* (*print_line) (StringBuf *buf, const char *p, const char *mark, int line);
void (*errorwarning_sub) (StringBuf *buf, const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos);
+ bool (*is_permanent_variable) (const char *name);
int (*set_reg) (struct script_state *st, struct map_session_data *sd, int64 num, const char *name, const void *value, struct reg_db *ref);
void (*set_reg_ref_str) (struct script_state* st, struct reg_db *n, int64 num, const char* name, const char *str);
void (*set_reg_pc_ref_str) (struct script_state* st, struct reg_db *n, int64 num, const char* name, const char *str);
diff --git a/src/map/skill.c b/src/map/skill.c
index 3dccf7a9e..caa1a0f29 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -72,6 +72,34 @@ static struct s_skill_dbs skilldbs;
struct skill_interface *skill;
+static const struct {
+ int start;
+ int end;
+} skill_idx_ranges[] = {
+ { NV_BASIC, NPC_LEX_AETERNA },
+ { KN_CHARGEATK, SA_ELEMENTWIND },
+ { RK_ENCHANTBLADE, AB_SILENTIUM },
+ { WL_WHITEIMPRISON, SC_FEINTBOMB },
+ { LG_CANNONSPEAR, SR_GENTLETOUCH_REVITALIZE },
+ { WA_SWING_DANCE, WA_MOONLIT_SERENADE },
+ { MI_RUSH_WINDMILL, MI_HARMONIZE },
+ { WM_LESSON, WM_UNLIMITED_HUMMING_VOICE },
+ { SO_FIREWALK, SO_EARTH_INSIGNIA },
+ { GN_TRAINING_SWORD, GN_SLINGITEM_RANGEMELEEATK },
+ { AB_SECRAMENT, LG_OVERBRAND_PLUSATK },
+ { ALL_ODINS_RECALL, ALL_LIGHTGUARD },
+ { RL_GLITTERING_GREED, RL_GLITTERING_GREED_ATK },
+ { KO_YAMIKUMO, OB_AKAITSUKI },
+ { ECL_SNOWFLIP, ALL_THANATOS_RECALL },
+ { GC_DARKCROW, NC_MAGMA_ERUPTION_DOTDAMAGE },
+ { SU_BASIC_SKILL, SU_SPIRITOFSEA },
+ { HLIF_HEAL, MH_VOLCANIC_ASH },
+ { MS_BASH, MER_INVINCIBLEOFF2 },
+ { EL_CIRCLE_OF_FIRE, EL_STONE_RAIN },
+ { GD_APPROVAL, GD_DEVELOPMENT },
+ CUSTOM_SKILL_RANGES
+};
+
//Since only mob-casted splash skills can hit ice-walls
static int skill_splash_target(struct block_list *bl)
{
@@ -96,51 +124,37 @@ static int skill_name2id(const char *name)
/// Returns the skill's array index, or 0 (Unknown Skill).
static int skill_get_index(int skill_id)
{
- int skillRange[] = { NV_BASIC, NPC_LEX_AETERNA,
- KN_CHARGEATK, SA_ELEMENTWIND,
- RK_ENCHANTBLADE, AB_SILENTIUM,
- WL_WHITEIMPRISON, SC_FEINTBOMB,
- LG_CANNONSPEAR, SR_GENTLETOUCH_REVITALIZE,
- WA_SWING_DANCE, WA_MOONLIT_SERENADE,
- MI_RUSH_WINDMILL, MI_HARMONIZE,
- WM_LESSON, WM_UNLIMITED_HUMMING_VOICE,
- SO_FIREWALK, SO_EARTH_INSIGNIA,
- GN_TRAINING_SWORD, GN_SLINGITEM_RANGEMELEEATK,
- AB_SECRAMENT, LG_OVERBRAND_PLUSATK,
- ALL_ODINS_RECALL, ALL_LIGHTGUARD,
- RL_GLITTERING_GREED, RL_GLITTERING_GREED_ATK,
- KO_YAMIKUMO, OB_AKAITSUKI,
- ECL_SNOWFLIP, ALL_THANATOS_RECALL,
- GC_DARKCROW, NC_MAGMA_ERUPTION_DOTDAMAGE,
- SU_BASIC_SKILL, SU_SPIRITOFSEA,
- HLIF_HEAL, MH_VOLCANIC_ASH,
- MS_BASH, MER_INVINCIBLEOFF2,
- EL_CIRCLE_OF_FIRE, EL_STONE_RAIN,
- GD_APPROVAL, GD_DEVELOPMENT
- CUSTOM_SKILL_RANGES};
- int length = sizeof(skillRange) / sizeof(int);
- STATIC_ASSERT(sizeof(skillRange) / sizeof(int) % 2 == 0, "skill_get_index: skillRange should be multiple of 2");
-
-
- if (skill_id < skillRange[0] || skill_id > skillRange[length - 1]) {
+ int length = ARRAYLENGTH(skill_idx_ranges);
+
+
+ if (skill_id < skill_idx_ranges[0].start || skill_id > skill_idx_ranges[length - 1].end) {
ShowWarning("skill_get_index: skill id '%d' is not being handled!\n", skill_id);
+ Assert_report(0);
return 0;
}
int skill_idx = 0;
+ bool found = false;
// Map Skill ID to Skill Indexes (in reverse order)
- for (int i = 0; i < length; i += 2) {
+ for (int i = 0; i < length; i++) {
// Check if SkillID belongs to this range.
- if (skill_id <= skillRange[i + 1] && skill_id >= skillRange[i]) {
- skill_idx += (skillRange[i + 1] - skill_id);
+ if (skill_id <= skill_idx_ranges[i].end && skill_id >= skill_idx_ranges[i].start) {
+ skill_idx += (skill_idx_ranges[i].end - skill_id);
+ found = true;
break;
}
// Add the difference of current range
- skill_idx += (skillRange[i + 1] - skillRange[i] + 1);
+ skill_idx += (skill_idx_ranges[i].end - skill_idx_ranges[i].start + 1);
}
+ if (!found) {
+ ShowWarning("skill_get_index: skill id '%d' (idx: %d) is not handled as it lies outside the defined ranges!\n", skill_id, skill_idx);
+ Assert_report(0);
+ return 0;
+ }
if (skill_idx >= MAX_SKILL_DB) {
ShowWarning("skill_get_index: skill id '%d'(idx: %d) is not being handled as it exceeds MAX_SKILL_DB!\n", skill_id, skill_idx);
+ Assert_report(0);
return 0;
}
@@ -1012,6 +1026,9 @@ 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 (map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y, CELL_CHKNOSKILL))
+ return 1; // block usage on 'noskill' cells [Wolfie]
+
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.
@@ -5005,7 +5022,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl
if( (tsc = status->get_sc(bl)) && (tsc->data[SC_HIDING] )) {
clif->skill_nodamage(src,src,skill_id,skill_lv,1);
} else
- skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag);
+ skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
}
break;
case NPC_SELFDESTRUCTION: {
@@ -7383,7 +7400,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
int rate = 100 * (100 - (tstatus->int_ / 2 + tstatus->vit / 3 + tstatus->luk / 10));
int duration = skill->get_time2(skill_id, skill_lv);
- duration *= (100 - (tstatus->int_ + tstatus->vit) / 2) / 100;
+ duration = duration * (100 - (tstatus->int_ + tstatus->vit) / 2) / 100;
status->change_start(src, bl, SC_BLIND, rate, 1, 0, 0, 0, duration, SCFLAG_NONE);
}
@@ -10470,7 +10487,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list *
case KO_KAZEHU_SEIRAN:
case KO_DOHU_KOUKAI:
if(sd) {
- int ttype = skill->get_ele(skill_id, skill_lv);
+ enum spirit_charm_types ttype = skill->get_ele(skill_id, skill_lv);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
pc->add_charm(sd, skill->get_time(skill_id, skill_lv), MAX_SPIRITCHARM, ttype); // replace existing charms of other type
}
@@ -10927,6 +10944,37 @@ static int skill_count_wos(struct block_list *bl, va_list ap)
return 0;
}
+/**
+ * Returns the linked song/dance skill ID, if any (for the Bard/Dancer Soul Link).
+ *
+ * @param skill_id The skill ID to look up
+ *
+ * @return The linked song or dance's skill ID if any
+ * @retval 0 if the given skill_id doesn't have a linked skill ID
+ */
+static int skill_get_linked_song_dance_id(int skill_id)
+{
+ switch (skill_id) {
+ case BA_WHISTLE:
+ return DC_HUMMING;
+ case BA_ASSASSINCROSS:
+ return DC_DONTFORGETME;
+ case BA_POEMBRAGI:
+ return DC_FORTUNEKISS;
+ case BA_APPLEIDUN:
+ return DC_SERVICEFORYOU;
+ case DC_HUMMING:
+ return BA_WHISTLE;
+ case DC_DONTFORGETME:
+ return BA_ASSASSINCROSS;
+ case DC_FORTUNEKISS:
+ return BA_POEMBRAGI;
+ case DC_SERVICEFORYOU:
+ return BA_APPLEIDUN;
+ }
+ return 0;
+}
+
/*==========================================
*
*------------------------------------------*/
@@ -11296,7 +11344,7 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill
FALLTHROUGH
case GS_GROUNDDRIFT: //Ammo should be deleted right away.
if ( skill_id == WM_SEVERE_RAINSTORM )
- sc_start(src,src,SC_NO_SWITCH_EQUIP,100,0,skill->get_time(skill_id,skill_lv));
+ sc_start(src, src, type, 100, 0, skill->get_time(skill_id, skill_lv));
skill->unitsetting(src,skill_id,skill_lv,x,y,0);
break;
case WZ_ICEWALL:
@@ -21801,4 +21849,5 @@ void skill_defaults(void)
skill->splash_target = skill_splash_target;
skill->check_npc_chaospanic = skill_check_npc_chaospanic;
skill->count_wos = skill_count_wos;
+ skill->get_linked_song_dance_id = skill_get_linked_song_dance_id;
}
diff --git a/src/map/skill.h b/src/map/skill.h
index 65195dc75..4dbbaf147 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -2200,6 +2200,7 @@ struct skill_interface {
int (*splash_target) (struct block_list* bl);
int (*check_npc_chaospanic) (struct block_list *bl, va_list args);
int (*count_wos) (struct block_list *bl, va_list ap);
+ int (*get_linked_song_dance_id) (int skill_id);
};
#ifdef HERCULES_CORE
diff --git a/src/map/status.c b/src/map/status.c
index 5ea4d880d..dc49f7e4e 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -696,6 +696,7 @@ static void initChangeTables(void)
status->set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SCB_STR|SCB_CRI|SCB_MAXHP );
status->set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITED_HUMMING_VOICE, SCB_NONE );
status->set_sc( WM_FRIGG_SONG , SC_FRIGG_SONG , SCB_MAXHP );
+ status->set_sc( WM_SEVERE_RAINSTORM , SC_NO_SWITCH_EQUIP , SCB_NONE );
/**
* Sorcerer
@@ -7832,6 +7833,9 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl
calc_flag = status->dbs->ChangeFlagTable[type];
if(!(flag&SCFLAG_LOADED)) { // Do not parse val settings when loading SCs
switch(type) {
+ case SC_AUTOTRADE:
+ case SC_KSPROTECTED:
+ break; // Prevent calling status_change_start_unknown_sc().
case SC_ADORAMUS:
sc_start(src,bl,SC_BLIND,100,val1,skill->get_time(status->sc2skill(type),val1));
// Fall through to SC_INC_AGI
@@ -8076,7 +8080,6 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl
// This is done this way because the message that the client displays is hardcoded, and only
// shows how many minutes are remaining. [Panikon]
total_tick = 60000;
- val1 = battle_config.manner_system; //Mute filters.
if (sd)
{
clif->changestatus(sd,SP_MANNER,sd->status.manner);
diff --git a/src/map/unit.c b/src/map/unit.c
index d484056f9..19f09f83c 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -436,7 +436,7 @@ static int unit_walk_toxy_timer(int tid, int64 tick, int id, intptr_t data)
// 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) {
+ && map->list[bl->m].users > 0 && mob->skill_use(md, tick, -1) == 0) {
// Walk skills are supposed to be used while walking
if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)
&& md->state.skillstate != MSS_WALK) {
@@ -2345,7 +2345,7 @@ static int unit_attack_timer_sub(struct block_list *src, int tid, int64 tick)
if(md) {
//First attack is always a normal attack
if(md->state.skillstate == MSS_ANGRY || md->state.skillstate == MSS_BERSERK) {
- if (mob->skill_use(md,tick,-1)) {
+ if (mob->skill_use(md, tick, -1) == 0) {
map->freeblock_unlock();
return 1;
}
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc
index b8aa5ae61..ef71f1967 100644
--- a/src/plugins/HPMHooking/HPMHooking.Defs.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc
@@ -1410,6 +1410,10 @@ typedef void (*HPMHOOK_pre_clif_chatname_ack) (int *fd, struct block_list **bl);
typedef void (*HPMHOOK_post_clif_chatname_ack) (int fd, struct block_list *bl);
typedef void (*HPMHOOK_pre_clif_elemname_ack) (int *fd, struct block_list **bl);
typedef void (*HPMHOOK_post_clif_elemname_ack) (int fd, struct block_list *bl);
+typedef void (*HPMHOOK_pre_clif_skillname_ack) (int *fd, struct block_list **bl);
+typedef void (*HPMHOOK_post_clif_skillname_ack) (int fd, struct block_list *bl);
+typedef void (*HPMHOOK_pre_clif_itemname_ack) (int *fd, struct block_list **bl);
+typedef void (*HPMHOOK_post_clif_itemname_ack) (int fd, struct block_list *bl);
typedef void (*HPMHOOK_pre_clif_unknownname_ack) (int *fd, struct block_list **bl);
typedef void (*HPMHOOK_post_clif_unknownname_ack) (int fd, struct block_list *bl);
typedef void (*HPMHOOK_pre_clif_monster_hp_bar) (struct mob_data **md, struct map_session_data **sd);
@@ -2762,6 +2766,14 @@ typedef void (*HPMHOOK_pre_clif_plapineDdukDdak_ack) (int *fd, struct map_sessio
typedef void (*HPMHOOK_post_clif_plapineDdukDdak_ack) (int fd, struct map_session_data *sd);
typedef void (*HPMHOOK_pre_clif_plapineDdukDdak_close) (int *fd, struct map_session_data **sd);
typedef void (*HPMHOOK_post_clif_plapineDdukDdak_close) (int fd, struct map_session_data *sd);
+typedef bool (*HPMHOOK_pre_clif_lapineUpgrade_open) (struct map_session_data **sd, int *item_id);
+typedef bool (*HPMHOOK_post_clif_lapineUpgrade_open) (bool retVal___, struct map_session_data *sd, int item_id);
+typedef bool (*HPMHOOK_pre_clif_lapineUpgrade_result) (struct map_session_data **sd, enum lapineUpgrade_result *result);
+typedef bool (*HPMHOOK_post_clif_lapineUpgrade_result) (bool retVal___, struct map_session_data *sd, enum lapineUpgrade_result result);
+typedef void (*HPMHOOK_pre_clif_pLapineUpgrade_close) (int *fd, struct map_session_data **sd);
+typedef void (*HPMHOOK_post_clif_pLapineUpgrade_close) (int fd, struct map_session_data *sd);
+typedef void (*HPMHOOK_pre_clif_pLapineUpgrade_makeItem) (int *fd, struct map_session_data **sd);
+typedef void (*HPMHOOK_post_clif_pLapineUpgrade_makeItem) (int fd, struct map_session_data *sd);
typedef void (*HPMHOOK_pre_clif_pReqGearOff) (int *fd, struct map_session_data **sd);
typedef void (*HPMHOOK_post_clif_pReqGearOff) (int fd, struct map_session_data *sd);
#endif // MAP_CLIF_H
@@ -5452,8 +5464,8 @@ typedef struct block_list* (*HPMHOOK_pre_mob_getmasterhpltmaxrate) (struct mob_d
typedef struct block_list* (*HPMHOOK_post_mob_getmasterhpltmaxrate) (struct block_list* retVal___, struct mob_data *md, int rate);
typedef int (*HPMHOOK_pre_mob_getfriendstatus_sub) (struct block_list **bl, va_list ap);
typedef int (*HPMHOOK_post_mob_getfriendstatus_sub) (int retVal___, struct block_list *bl, va_list ap);
-typedef struct mob_data* (*HPMHOOK_pre_mob_getfriendstatus) (struct mob_data **md, int *cond1, int *cond2);
-typedef struct mob_data* (*HPMHOOK_post_mob_getfriendstatus) (struct mob_data* retVal___, struct mob_data *md, int cond1, int cond2);
+typedef struct block_list* (*HPMHOOK_pre_mob_getfriendstatus) (struct mob_data **md, int *cond1, int *cond2);
+typedef struct block_list* (*HPMHOOK_post_mob_getfriendstatus) (struct block_list* retVal___, struct mob_data *md, int cond1, int cond2);
typedef int (*HPMHOOK_pre_mob_skill_use) (struct mob_data **md, int64 *tick, int *event);
typedef int (*HPMHOOK_post_mob_skill_use) (int retVal___, struct mob_data *md, int64 tick, int event);
typedef int (*HPMHOOK_pre_mob_skill_event) (struct mob_data **md, struct block_list **src, int64 *tick, int *flag);
@@ -6210,6 +6222,10 @@ typedef int (*HPMHOOK_pre_pc_percentheal) (struct map_session_data **sd, int *hp
typedef int (*HPMHOOK_post_pc_percentheal) (int retVal___, struct map_session_data *sd, int hp, int sp);
typedef int (*HPMHOOK_pre_pc_jobchange) (struct map_session_data **sd, int *class, int *upper);
typedef int (*HPMHOOK_post_pc_jobchange) (int retVal___, struct map_session_data *sd, int class, int upper);
+typedef void (*HPMHOOK_pre_pc_hide) (struct map_session_data **sd, bool *show_msg);
+typedef void (*HPMHOOK_post_pc_hide) (struct map_session_data *sd, bool show_msg);
+typedef void (*HPMHOOK_pre_pc_unhide) (struct map_session_data **sd, bool *show_msg);
+typedef void (*HPMHOOK_post_pc_unhide) (struct map_session_data *sd, bool show_msg);
typedef int (*HPMHOOK_pre_pc_setoption) (struct map_session_data **sd, int *type);
typedef int (*HPMHOOK_post_pc_setoption) (int retVal___, struct map_session_data *sd, int type);
typedef int (*HPMHOOK_pre_pc_setcart) (struct map_session_data **sd, int *type);
@@ -6340,10 +6356,10 @@ typedef void (*HPMHOOK_pre_pc_itemcd_do) (struct map_session_data **sd, bool *lo
typedef void (*HPMHOOK_post_pc_itemcd_do) (struct map_session_data *sd, bool load);
typedef int (*HPMHOOK_pre_pc_load_combo) (struct map_session_data **sd);
typedef int (*HPMHOOK_post_pc_load_combo) (int retVal___, struct map_session_data *sd);
-typedef void (*HPMHOOK_pre_pc_add_charm) (struct map_session_data **sd, int *interval, int *max, int *type);
-typedef void (*HPMHOOK_post_pc_add_charm) (struct map_session_data *sd, int interval, int max, int type);
-typedef void (*HPMHOOK_pre_pc_del_charm) (struct map_session_data **sd, int *count, int *type);
-typedef void (*HPMHOOK_post_pc_del_charm) (struct map_session_data *sd, int count, int type);
+typedef void (*HPMHOOK_pre_pc_add_charm) (struct map_session_data **sd, int *interval, int *max, enum spirit_charm_types *type);
+typedef void (*HPMHOOK_post_pc_add_charm) (struct map_session_data *sd, int interval, int max, enum spirit_charm_types type);
+typedef void (*HPMHOOK_pre_pc_del_charm) (struct map_session_data **sd, int *count, enum spirit_charm_types *type);
+typedef void (*HPMHOOK_post_pc_del_charm) (struct map_session_data *sd, int count, enum spirit_charm_types type);
typedef void (*HPMHOOK_pre_pc_baselevelchanged) (struct map_session_data **sd);
typedef void (*HPMHOOK_post_pc_baselevelchanged) (struct map_session_data *sd);
typedef int (*HPMHOOK_pre_pc_level_penalty_mod) (int *diff, unsigned char *race, uint32 *mode, int *type);
@@ -6972,6 +6988,8 @@ typedef const char* (*HPMHOOK_pre_script_print_line) (StringBuf **buf, const cha
typedef const char* (*HPMHOOK_post_script_print_line) (const char* retVal___, StringBuf *buf, const char *p, const char *mark, int line);
typedef void (*HPMHOOK_pre_script_errorwarning_sub) (StringBuf **buf, const char **src, const char **file, int *start_line, const char **error_msg, const char **error_pos);
typedef void (*HPMHOOK_post_script_errorwarning_sub) (StringBuf *buf, const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos);
+typedef bool (*HPMHOOK_pre_script_is_permanent_variable) (const char **name);
+typedef bool (*HPMHOOK_post_script_is_permanent_variable) (bool retVal___, const char *name);
typedef int (*HPMHOOK_pre_script_set_reg) (struct script_state **st, struct map_session_data **sd, int64 *num, const char **name, const void **value, struct reg_db **ref);
typedef int (*HPMHOOK_post_script_set_reg) (int retVal___, struct script_state *st, struct map_session_data *sd, int64 num, const char *name, const void *value, struct reg_db *ref);
typedef void (*HPMHOOK_pre_script_set_reg_ref_str) (struct script_state **st, struct reg_db **n, int64 *num, const char **name, const char **str);
@@ -7668,6 +7686,8 @@ typedef int (*HPMHOOK_pre_skill_check_npc_chaospanic) (struct block_list **bl, v
typedef int (*HPMHOOK_post_skill_check_npc_chaospanic) (int retVal___, struct block_list *bl, va_list args);
typedef int (*HPMHOOK_pre_skill_count_wos) (struct block_list **bl, va_list ap);
typedef int (*HPMHOOK_post_skill_count_wos) (int retVal___, struct block_list *bl, va_list ap);
+typedef int (*HPMHOOK_pre_skill_get_linked_song_dance_id) (int *skill_id);
+typedef int (*HPMHOOK_post_skill_get_linked_song_dance_id) (int retVal___, int skill_id);
#endif // MAP_SKILL_H
#ifdef COMMON_SOCKET_H /* sockt */
typedef void (*HPMHOOK_pre_sockt_init) (void);
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
index 109c30885..e8cb41240 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
@@ -1000,6 +1000,10 @@ struct {
struct HPMHookPoint *HP_clif_chatname_ack_post;
struct HPMHookPoint *HP_clif_elemname_ack_pre;
struct HPMHookPoint *HP_clif_elemname_ack_post;
+ struct HPMHookPoint *HP_clif_skillname_ack_pre;
+ struct HPMHookPoint *HP_clif_skillname_ack_post;
+ struct HPMHookPoint *HP_clif_itemname_ack_pre;
+ struct HPMHookPoint *HP_clif_itemname_ack_post;
struct HPMHookPoint *HP_clif_unknownname_ack_pre;
struct HPMHookPoint *HP_clif_unknownname_ack_post;
struct HPMHookPoint *HP_clif_monster_hp_bar_pre;
@@ -2352,6 +2356,14 @@ struct {
struct HPMHookPoint *HP_clif_plapineDdukDdak_ack_post;
struct HPMHookPoint *HP_clif_plapineDdukDdak_close_pre;
struct HPMHookPoint *HP_clif_plapineDdukDdak_close_post;
+ struct HPMHookPoint *HP_clif_lapineUpgrade_open_pre;
+ struct HPMHookPoint *HP_clif_lapineUpgrade_open_post;
+ struct HPMHookPoint *HP_clif_lapineUpgrade_result_pre;
+ struct HPMHookPoint *HP_clif_lapineUpgrade_result_post;
+ struct HPMHookPoint *HP_clif_pLapineUpgrade_close_pre;
+ struct HPMHookPoint *HP_clif_pLapineUpgrade_close_post;
+ struct HPMHookPoint *HP_clif_pLapineUpgrade_makeItem_pre;
+ struct HPMHookPoint *HP_clif_pLapineUpgrade_makeItem_post;
struct HPMHookPoint *HP_clif_pReqGearOff_pre;
struct HPMHookPoint *HP_clif_pReqGearOff_post;
struct HPMHookPoint *HP_cmdline_init_pre;
@@ -4790,6 +4802,10 @@ struct {
struct HPMHookPoint *HP_pc_percentheal_post;
struct HPMHookPoint *HP_pc_jobchange_pre;
struct HPMHookPoint *HP_pc_jobchange_post;
+ struct HPMHookPoint *HP_pc_hide_pre;
+ struct HPMHookPoint *HP_pc_hide_post;
+ struct HPMHookPoint *HP_pc_unhide_pre;
+ struct HPMHookPoint *HP_pc_unhide_post;
struct HPMHookPoint *HP_pc_setoption_pre;
struct HPMHookPoint *HP_pc_setoption_post;
struct HPMHookPoint *HP_pc_setcart_pre;
@@ -5502,6 +5518,8 @@ struct {
struct HPMHookPoint *HP_script_print_line_post;
struct HPMHookPoint *HP_script_errorwarning_sub_pre;
struct HPMHookPoint *HP_script_errorwarning_sub_post;
+ struct HPMHookPoint *HP_script_is_permanent_variable_pre;
+ struct HPMHookPoint *HP_script_is_permanent_variable_post;
struct HPMHookPoint *HP_script_set_reg_pre;
struct HPMHookPoint *HP_script_set_reg_post;
struct HPMHookPoint *HP_script_set_reg_ref_str_pre;
@@ -6192,6 +6210,8 @@ struct {
struct HPMHookPoint *HP_skill_check_npc_chaospanic_post;
struct HPMHookPoint *HP_skill_count_wos_pre;
struct HPMHookPoint *HP_skill_count_wos_post;
+ struct HPMHookPoint *HP_skill_get_linked_song_dance_id_pre;
+ struct HPMHookPoint *HP_skill_get_linked_song_dance_id_post;
struct HPMHookPoint *HP_sockt_init_pre;
struct HPMHookPoint *HP_sockt_init_post;
struct HPMHookPoint *HP_sockt_final_pre;
@@ -7881,6 +7901,10 @@ struct {
int HP_clif_chatname_ack_post;
int HP_clif_elemname_ack_pre;
int HP_clif_elemname_ack_post;
+ int HP_clif_skillname_ack_pre;
+ int HP_clif_skillname_ack_post;
+ int HP_clif_itemname_ack_pre;
+ int HP_clif_itemname_ack_post;
int HP_clif_unknownname_ack_pre;
int HP_clif_unknownname_ack_post;
int HP_clif_monster_hp_bar_pre;
@@ -9233,6 +9257,14 @@ struct {
int HP_clif_plapineDdukDdak_ack_post;
int HP_clif_plapineDdukDdak_close_pre;
int HP_clif_plapineDdukDdak_close_post;
+ int HP_clif_lapineUpgrade_open_pre;
+ int HP_clif_lapineUpgrade_open_post;
+ int HP_clif_lapineUpgrade_result_pre;
+ int HP_clif_lapineUpgrade_result_post;
+ int HP_clif_pLapineUpgrade_close_pre;
+ int HP_clif_pLapineUpgrade_close_post;
+ int HP_clif_pLapineUpgrade_makeItem_pre;
+ int HP_clif_pLapineUpgrade_makeItem_post;
int HP_clif_pReqGearOff_pre;
int HP_clif_pReqGearOff_post;
int HP_cmdline_init_pre;
@@ -11671,6 +11703,10 @@ struct {
int HP_pc_percentheal_post;
int HP_pc_jobchange_pre;
int HP_pc_jobchange_post;
+ int HP_pc_hide_pre;
+ int HP_pc_hide_post;
+ int HP_pc_unhide_pre;
+ int HP_pc_unhide_post;
int HP_pc_setoption_pre;
int HP_pc_setoption_post;
int HP_pc_setcart_pre;
@@ -12383,6 +12419,8 @@ struct {
int HP_script_print_line_post;
int HP_script_errorwarning_sub_pre;
int HP_script_errorwarning_sub_post;
+ int HP_script_is_permanent_variable_pre;
+ int HP_script_is_permanent_variable_post;
int HP_script_set_reg_pre;
int HP_script_set_reg_post;
int HP_script_set_reg_ref_str_pre;
@@ -13073,6 +13111,8 @@ struct {
int HP_skill_check_npc_chaospanic_post;
int HP_skill_count_wos_pre;
int HP_skill_count_wos_post;
+ int HP_skill_get_linked_song_dance_id_pre;
+ int HP_skill_get_linked_song_dance_id_post;
int HP_sockt_init_pre;
int HP_sockt_init_post;
int HP_sockt_final_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
index ac30b97d4..6b89841ad 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
@@ -524,6 +524,8 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(clif->mobname_normal_ack, HP_clif_mobname_normal_ack) },
{ HP_POP(clif->chatname_ack, HP_clif_chatname_ack) },
{ HP_POP(clif->elemname_ack, HP_clif_elemname_ack) },
+ { HP_POP(clif->skillname_ack, HP_clif_skillname_ack) },
+ { HP_POP(clif->itemname_ack, HP_clif_itemname_ack) },
{ HP_POP(clif->unknownname_ack, HP_clif_unknownname_ack) },
{ HP_POP(clif->monster_hp_bar, HP_clif_monster_hp_bar) },
{ HP_POP(clif->hpmeter, HP_clif_hpmeter) },
@@ -1200,6 +1202,10 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(clif->lapineDdukDdak_result, HP_clif_lapineDdukDdak_result) },
{ HP_POP(clif->plapineDdukDdak_ack, HP_clif_plapineDdukDdak_ack) },
{ HP_POP(clif->plapineDdukDdak_close, HP_clif_plapineDdukDdak_close) },
+ { HP_POP(clif->lapineUpgrade_open, HP_clif_lapineUpgrade_open) },
+ { HP_POP(clif->lapineUpgrade_result, HP_clif_lapineUpgrade_result) },
+ { HP_POP(clif->pLapineUpgrade_close, HP_clif_pLapineUpgrade_close) },
+ { HP_POP(clif->pLapineUpgrade_makeItem, HP_clif_pLapineUpgrade_makeItem) },
{ HP_POP(clif->pReqGearOff, HP_clif_pReqGearOff) },
/* cmdline_interface */
{ HP_POP(cmdline->init, HP_cmdline_init) },
@@ -2453,6 +2459,8 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(pc->itemheal, HP_pc_itemheal) },
{ HP_POP(pc->percentheal, HP_pc_percentheal) },
{ HP_POP(pc->jobchange, HP_pc_jobchange) },
+ { HP_POP(pc->hide, HP_pc_hide) },
+ { HP_POP(pc->unhide, HP_pc_unhide) },
{ HP_POP(pc->setoption, HP_pc_setoption) },
{ HP_POP(pc->setcart, HP_pc_setcart) },
{ HP_POP(pc->setfalcon, HP_pc_setfalcon) },
@@ -2817,6 +2825,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(script->load_parameters, HP_script_load_parameters) },
{ HP_POP(script->print_line, HP_script_print_line) },
{ HP_POP(script->errorwarning_sub, HP_script_errorwarning_sub) },
+ { HP_POP(script->is_permanent_variable, HP_script_is_permanent_variable) },
{ HP_POP(script->set_reg, HP_script_set_reg) },
{ HP_POP(script->set_reg_ref_str, HP_script_set_reg_ref_str) },
{ HP_POP(script->set_reg_pc_ref_str, HP_script_set_reg_pc_ref_str) },
@@ -3165,6 +3174,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(skill->splash_target, HP_skill_splash_target) },
{ HP_POP(skill->check_npc_chaospanic, HP_skill_check_npc_chaospanic) },
{ HP_POP(skill->count_wos, HP_skill_count_wos) },
+ { HP_POP(skill->get_linked_song_dance_id, HP_skill_get_linked_song_dance_id) },
/* socket_interface */
{ HP_POP(sockt->init, HP_sockt_init) },
{ HP_POP(sockt->final, HP_sockt_final) },
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index 940f96ca2..02d55228e 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -13035,6 +13035,58 @@ void HP_clif_elemname_ack(int fd, struct block_list *bl) {
}
return;
}
+void HP_clif_skillname_ack(int fd, struct block_list *bl) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_skillname_ack_pre > 0) {
+ void (*preHookFunc) (int *fd, struct block_list **bl);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_skillname_ack_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_skillname_ack_pre[hIndex].func;
+ preHookFunc(&fd, &bl);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.skillname_ack(fd, bl);
+ }
+ if (HPMHooks.count.HP_clif_skillname_ack_post > 0) {
+ void (*postHookFunc) (int fd, struct block_list *bl);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_skillname_ack_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_skillname_ack_post[hIndex].func;
+ postHookFunc(fd, bl);
+ }
+ }
+ return;
+}
+void HP_clif_itemname_ack(int fd, struct block_list *bl) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_itemname_ack_pre > 0) {
+ void (*preHookFunc) (int *fd, struct block_list **bl);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_itemname_ack_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_itemname_ack_pre[hIndex].func;
+ preHookFunc(&fd, &bl);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.itemname_ack(fd, bl);
+ }
+ if (HPMHooks.count.HP_clif_itemname_ack_post > 0) {
+ void (*postHookFunc) (int fd, struct block_list *bl);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_itemname_ack_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_itemname_ack_post[hIndex].func;
+ postHookFunc(fd, bl);
+ }
+ }
+ return;
+}
void HP_clif_unknownname_ack(int fd, struct block_list *bl) {
int hIndex = 0;
if (HPMHooks.count.HP_clif_unknownname_ack_pre > 0) {
@@ -30663,6 +30715,112 @@ void HP_clif_plapineDdukDdak_close(int fd, struct map_session_data *sd) {
}
return;
}
+bool HP_clif_lapineUpgrade_open(struct map_session_data *sd, int item_id) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if (HPMHooks.count.HP_clif_lapineUpgrade_open_pre > 0) {
+ bool (*preHookFunc) (struct map_session_data **sd, int *item_id);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_lapineUpgrade_open_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_lapineUpgrade_open_pre[hIndex].func;
+ retVal___ = preHookFunc(&sd, &item_id);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.clif.lapineUpgrade_open(sd, item_id);
+ }
+ if (HPMHooks.count.HP_clif_lapineUpgrade_open_post > 0) {
+ bool (*postHookFunc) (bool retVal___, struct map_session_data *sd, int item_id);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_lapineUpgrade_open_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_lapineUpgrade_open_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, sd, item_id);
+ }
+ }
+ return retVal___;
+}
+bool HP_clif_lapineUpgrade_result(struct map_session_data *sd, enum lapineUpgrade_result result) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if (HPMHooks.count.HP_clif_lapineUpgrade_result_pre > 0) {
+ bool (*preHookFunc) (struct map_session_data **sd, enum lapineUpgrade_result *result);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_lapineUpgrade_result_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_lapineUpgrade_result_pre[hIndex].func;
+ retVal___ = preHookFunc(&sd, &result);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.clif.lapineUpgrade_result(sd, result);
+ }
+ if (HPMHooks.count.HP_clif_lapineUpgrade_result_post > 0) {
+ bool (*postHookFunc) (bool retVal___, struct map_session_data *sd, enum lapineUpgrade_result result);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_lapineUpgrade_result_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_lapineUpgrade_result_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, sd, result);
+ }
+ }
+ return retVal___;
+}
+void HP_clif_pLapineUpgrade_close(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_pLapineUpgrade_close_pre > 0) {
+ void (*preHookFunc) (int *fd, struct map_session_data **sd);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pLapineUpgrade_close_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_pLapineUpgrade_close_pre[hIndex].func;
+ preHookFunc(&fd, &sd);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.pLapineUpgrade_close(fd, sd);
+ }
+ if (HPMHooks.count.HP_clif_pLapineUpgrade_close_post > 0) {
+ void (*postHookFunc) (int fd, struct map_session_data *sd);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pLapineUpgrade_close_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_pLapineUpgrade_close_post[hIndex].func;
+ postHookFunc(fd, sd);
+ }
+ }
+ return;
+}
+void HP_clif_pLapineUpgrade_makeItem(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_clif_pLapineUpgrade_makeItem_pre > 0) {
+ void (*preHookFunc) (int *fd, struct map_session_data **sd);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pLapineUpgrade_makeItem_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_clif_pLapineUpgrade_makeItem_pre[hIndex].func;
+ preHookFunc(&fd, &sd);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.pLapineUpgrade_makeItem(fd, sd);
+ }
+ if (HPMHooks.count.HP_clif_pLapineUpgrade_makeItem_post > 0) {
+ void (*postHookFunc) (int fd, struct map_session_data *sd);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_clif_pLapineUpgrade_makeItem_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_clif_pLapineUpgrade_makeItem_post[hIndex].func;
+ postHookFunc(fd, sd);
+ }
+ }
+ return;
+}
void HP_clif_pReqGearOff(int fd, struct map_session_data *sd) {
int hIndex = 0;
if (HPMHooks.count.HP_clif_pReqGearOff_pre > 0) {
@@ -53703,11 +53861,11 @@ int HP_mob_getfriendstatus_sub(struct block_list *bl, va_list ap) {
}
return retVal___;
}
-struct mob_data* HP_mob_getfriendstatus(struct mob_data *md, int cond1, int cond2) {
+struct block_list* HP_mob_getfriendstatus(struct mob_data *md, int cond1, int cond2) {
int hIndex = 0;
- struct mob_data* retVal___ = NULL;
+ struct block_list* retVal___ = NULL;
if (HPMHooks.count.HP_mob_getfriendstatus_pre > 0) {
- struct mob_data* (*preHookFunc) (struct mob_data **md, int *cond1, int *cond2);
+ struct block_list* (*preHookFunc) (struct mob_data **md, int *cond1, int *cond2);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_getfriendstatus_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_mob_getfriendstatus_pre[hIndex].func;
@@ -53722,7 +53880,7 @@ struct mob_data* HP_mob_getfriendstatus(struct mob_data *md, int cond1, int cond
retVal___ = HPMHooks.source.mob.getfriendstatus(md, cond1, cond2);
}
if (HPMHooks.count.HP_mob_getfriendstatus_post > 0) {
- struct mob_data* (*postHookFunc) (struct mob_data* retVal___, struct mob_data *md, int cond1, int cond2);
+ struct block_list* (*postHookFunc) (struct block_list* retVal___, struct mob_data *md, int cond1, int cond2);
for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_getfriendstatus_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_mob_getfriendstatus_post[hIndex].func;
retVal___ = postHookFunc(retVal___, md, cond1, cond2);
@@ -63705,6 +63863,58 @@ int HP_pc_jobchange(struct map_session_data *sd, int class, int upper) {
}
return retVal___;
}
+void HP_pc_hide(struct map_session_data *sd, bool show_msg) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_pc_hide_pre > 0) {
+ void (*preHookFunc) (struct map_session_data **sd, bool *show_msg);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_hide_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_pc_hide_pre[hIndex].func;
+ preHookFunc(&sd, &show_msg);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pc.hide(sd, show_msg);
+ }
+ if (HPMHooks.count.HP_pc_hide_post > 0) {
+ void (*postHookFunc) (struct map_session_data *sd, bool show_msg);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_hide_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_pc_hide_post[hIndex].func;
+ postHookFunc(sd, show_msg);
+ }
+ }
+ return;
+}
+void HP_pc_unhide(struct map_session_data *sd, bool show_msg) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_pc_unhide_pre > 0) {
+ void (*preHookFunc) (struct map_session_data **sd, bool *show_msg);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_unhide_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_pc_unhide_pre[hIndex].func;
+ preHookFunc(&sd, &show_msg);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pc.unhide(sd, show_msg);
+ }
+ if (HPMHooks.count.HP_pc_unhide_post > 0) {
+ void (*postHookFunc) (struct map_session_data *sd, bool show_msg);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_unhide_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_pc_unhide_post[hIndex].func;
+ postHookFunc(sd, show_msg);
+ }
+ }
+ return;
+}
int HP_pc_setoption(struct map_session_data *sd, int type) {
int hIndex = 0;
int retVal___ = 0;
@@ -65443,10 +65653,10 @@ int HP_pc_load_combo(struct map_session_data *sd) {
}
return retVal___;
}
-void HP_pc_add_charm(struct map_session_data *sd, int interval, int max, int type) {
+void HP_pc_add_charm(struct map_session_data *sd, int interval, int max, enum spirit_charm_types type) {
int hIndex = 0;
if (HPMHooks.count.HP_pc_add_charm_pre > 0) {
- void (*preHookFunc) (struct map_session_data **sd, int *interval, int *max, int *type);
+ void (*preHookFunc) (struct map_session_data **sd, int *interval, int *max, enum spirit_charm_types *type);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_add_charm_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_pc_add_charm_pre[hIndex].func;
@@ -65461,7 +65671,7 @@ void HP_pc_add_charm(struct map_session_data *sd, int interval, int max, int typ
HPMHooks.source.pc.add_charm(sd, interval, max, type);
}
if (HPMHooks.count.HP_pc_add_charm_post > 0) {
- void (*postHookFunc) (struct map_session_data *sd, int interval, int max, int type);
+ void (*postHookFunc) (struct map_session_data *sd, int interval, int max, enum spirit_charm_types type);
for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_add_charm_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_pc_add_charm_post[hIndex].func;
postHookFunc(sd, interval, max, type);
@@ -65469,10 +65679,10 @@ void HP_pc_add_charm(struct map_session_data *sd, int interval, int max, int typ
}
return;
}
-void HP_pc_del_charm(struct map_session_data *sd, int count, int type) {
+void HP_pc_del_charm(struct map_session_data *sd, int count, enum spirit_charm_types type) {
int hIndex = 0;
if (HPMHooks.count.HP_pc_del_charm_pre > 0) {
- void (*preHookFunc) (struct map_session_data **sd, int *count, int *type);
+ void (*preHookFunc) (struct map_session_data **sd, int *count, enum spirit_charm_types *type);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_del_charm_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_pc_del_charm_pre[hIndex].func;
@@ -65487,7 +65697,7 @@ void HP_pc_del_charm(struct map_session_data *sd, int count, int type) {
HPMHooks.source.pc.del_charm(sd, count, type);
}
if (HPMHooks.count.HP_pc_del_charm_post > 0) {
- void (*postHookFunc) (struct map_session_data *sd, int count, int type);
+ void (*postHookFunc) (struct map_session_data *sd, int count, enum spirit_charm_types type);
for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_del_charm_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_pc_del_charm_post[hIndex].func;
postHookFunc(sd, count, type);
@@ -73263,6 +73473,33 @@ void HP_script_errorwarning_sub(StringBuf *buf, const char *src, const char *fil
}
return;
}
+bool HP_script_is_permanent_variable(const char *name) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if (HPMHooks.count.HP_script_is_permanent_variable_pre > 0) {
+ bool (*preHookFunc) (const char **name);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_script_is_permanent_variable_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_script_is_permanent_variable_pre[hIndex].func;
+ retVal___ = preHookFunc(&name);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.script.is_permanent_variable(name);
+ }
+ if (HPMHooks.count.HP_script_is_permanent_variable_post > 0) {
+ bool (*postHookFunc) (bool retVal___, const char *name);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_script_is_permanent_variable_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_script_is_permanent_variable_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, name);
+ }
+ }
+ return retVal___;
+}
int HP_script_set_reg(struct script_state *st, struct map_session_data *sd, int64 num, const char *name, const void *value, struct reg_db *ref) {
int hIndex = 0;
int retVal___ = 0;
@@ -82804,6 +83041,33 @@ int HP_skill_count_wos(struct block_list *bl, va_list ap) {
}
return retVal___;
}
+int HP_skill_get_linked_song_dance_id(int skill_id) {
+ int hIndex = 0;
+ int retVal___ = 0;
+ if (HPMHooks.count.HP_skill_get_linked_song_dance_id_pre > 0) {
+ int (*preHookFunc) (int *skill_id);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_linked_song_dance_id_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_skill_get_linked_song_dance_id_pre[hIndex].func;
+ retVal___ = preHookFunc(&skill_id);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.skill.get_linked_song_dance_id(skill_id);
+ }
+ if (HPMHooks.count.HP_skill_get_linked_song_dance_id_post > 0) {
+ int (*postHookFunc) (int retVal___, int skill_id);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_get_linked_song_dance_id_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_skill_get_linked_song_dance_id_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, skill_id);
+ }
+ }
+ return retVal___;
+}
/* socket_interface */
void HP_sockt_init(void) {
int hIndex = 0;