diff options
Diffstat (limited to 'src/map/clif.c')
-rw-r--r-- | src/map/clif.c | 71 |
1 files changed, 47 insertions, 24 deletions
diff --git a/src/map/clif.c b/src/map/clif.c index 477894805..649df3e33 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -936,19 +936,25 @@ static void clif_clearunit_area(struct block_list *bl, enum clr_type type) static int clif_clearunit_delayed_sub(int tid, int64 tick, int id, intptr_t data) { struct block_list *bl = (struct block_list *)data; + nullpo_ret(bl); + Assert_ret(bl->m >= 0 && bl->m < map->count); + if (map->list[bl->m].block == NULL) { + // avoid error report for missing/removed map + ers_free(clif->delay_clearunit_ers, bl); + return 0; + } clif->clearunit_area(bl, (enum clr_type) id); - ers_free(clif->delay_clearunit_ers,bl); + ers_free(clif->delay_clearunit_ers, bl); return 0; } static void clif_clearunit_delayed(struct block_list *bl, enum clr_type type, int64 tick) { - struct block_list *tbl; - nullpo_retv(bl); - tbl = ers_alloc(clif->delay_clearunit_ers, struct block_list); - memcpy (tbl, bl, sizeof (struct block_list)); - timer->add(tick, clif->clearunit_delayed_sub, (int)type, (intptr_t)tbl); + Assert_retv(bl->type == BL_MOB); + struct mob_data *md = ers_alloc(clif->delay_clearunit_ers, struct mob_data); + memcpy (md, bl, sizeof (struct mob_data)); + timer->add(tick, clif->clearunit_delayed_sub, (int)type, (intptr_t)md); } /// Gets weapon view info from sd's inventory_data and points (*rhand,*lhand) @@ -1031,6 +1037,7 @@ static void clif_set_unit_idle2(struct block_list *bl, struct map_session_data * int g_id = status->get_guild_id(bl); nullpo_retv(bl); + nullpo_retv(vd); sd = BL_CAST(BL_PC, bl); p.PacketType = idle_unit2Type; @@ -1087,6 +1094,7 @@ static void clif_set_unit_idle(struct block_list *bl, struct map_session_data *t int g_id = status->get_guild_id(bl); nullpo_retv(bl); + nullpo_retv(vd); #if PACKETVER < 20091103 if (!pc->db_checkid(vd->class)) { @@ -1197,6 +1205,7 @@ static void clif_spawn_unit2(struct block_list *bl, enum send_target target) int g_id = status->get_guild_id(bl); nullpo_retv(bl); + nullpo_retv(vd); sd = BL_CAST(BL_PC, bl); p.PacketType = spawn_unit2Type; @@ -1244,6 +1253,7 @@ static void clif_spawn_unit(struct block_list *bl, enum send_target target) int g_id = status->get_guild_id(bl); nullpo_retv(bl); + nullpo_retv(vd); #if PACKETVER < 20091103 if (!pc->db_checkid(vd->class)) { @@ -1357,6 +1367,7 @@ static void clif_set_unit_walking(struct block_list *bl, struct map_session_data nullpo_retv(bl); nullpo_retv(ud); + nullpo_retv(vd); sd = BL_CAST(BL_PC, bl); @@ -6224,7 +6235,7 @@ static void clif_displaymessage_sprintf(const int fd, const char *mes, ...) /// 009a <packet len>.W <message>.?B static void clif_broadcast(struct block_list *bl, const char *mes, int len, int type, enum send_target target) { - int lp = (type&BC_COLOR_MASK) ? 4 : 0; + int lp = ((type & BC_COLOR_MASK) != 0 || (type & BC_MEGAPHONE) != 0) ? 4 : 0; unsigned char *buf = NULL; nullpo_retv(mes); @@ -6236,6 +6247,8 @@ static void clif_broadcast(struct block_list *bl, const char *mes, int len, int WBUFL(buf,4) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. else if( type&BC_WOE ) WBUFL(buf,4) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. + else if ((type & BC_MEGAPHONE) != 0) + WBUFL(buf, 4) = 0x6363696d; // If there's "micc" at the beginning of the message, the game client will recognize message as 'Megaphone shout'. memcpy(WBUFP(buf, 4 + lp), mes, len); clif->send(buf, WBUFW(buf,2), bl, target); @@ -10850,6 +10863,12 @@ static void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) clif->updatestatus(sd, SP_SKILLPOINT); clif->initialstatus(sd); + // Unequip items which can't be equipped by the character. + for (int i = 0; i < EQI_MAX; i++) { + if (sd->equip_index[i] >= 0 && pc->isequip(sd , sd->equip_index[i]) == 0) + pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_FORCE); + } + if (pc_isfalcon(sd)) { int sc_icn = status->get_sc_icon(SC_FALCON); int sc_typ = status->get_sc_relevant_bl_types(SC_FALCON); @@ -12031,7 +12050,7 @@ static void clif_parse_EquipItem(int fd, struct map_session_data *sd) return; //Out of bounds check. if( sd->npc_id ) { - if ( !sd->npc_item_flag ) + if ((sd->npc_item_flag & ITEMENABLEDNPC_EQUIP) == 0) return; } else if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->sc.opt1) ; //You can equip/unequip stuff while storage is open/under status changes @@ -12076,7 +12095,7 @@ static void clif_parse_UnequipItem(int fd, struct map_session_data *sd) } if( sd->npc_id ) { - if ( !sd->npc_item_flag ) + if ((sd->npc_item_flag & ITEMENABLEDNPC_EQUIP) == 0) return; } else if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->sc.opt1) ; //You can equip/unequip stuff while storage is open/under status changes @@ -12827,7 +12846,11 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill // Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] pc->update_idle_time(sd, BCIDLE_USESKILLTOID); - if (sd->npc_id || sd->state.workinprogress & 1) { + bool allow_self_skill = ((tmp & INF_SELF_SKILL) != 0 && (skill->get_nk(skill_id) & NK_NO_DAMAGE) != 0); + allow_self_skill = (allow_self_skill && battle_config.skill_enabled_npc == SKILLENABLEDNPC_SELF); + + if ((sd->npc_id != 0 && !allow_self_skill && battle_config.skill_enabled_npc != SKILLENABLEDNPC_ALL) + || (sd->state.workinprogress & 1) != 0) { #if PACKETVER >= 20110308 clif->msgtable(sd, MSG_BUSY); #else @@ -12836,7 +12859,7 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill return; } - if (pc_cant_act(sd) + if (pc_cant_act_except_npc(sd) && skill_id != RK_REFRESH && !(skill_id == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN)) && (sd->state.storage_flag != STORAGE_FLAG_CLOSED && !(tmp&INF_SELF_SKILL)) // SELF skills can be used with the storage open, issue: 8027 @@ -12973,7 +12996,8 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin return; } - if (sd->state.workinprogress & 1) { + if ((sd->npc_id != 0 && battle_config.skill_enabled_npc != SKILLENABLEDNPC_ALL) + || (sd->state.workinprogress & 1) != 0) { #if PACKETVER >= 20110308 clif->msgtable(sd, MSG_BUSY); #else @@ -13043,7 +13067,7 @@ static void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) __attr /// There are various variants of this packet, some of them have padding between fields. static void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) { - if (pc_cant_act(sd)) + if (pc_cant_act_except_npc(sd)) return; if (pc_issit(sd)) return; @@ -13064,7 +13088,7 @@ static void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd /// There are various variants of this packet, some of them have padding between fields. static void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd) { - if (pc_cant_act(sd)) + if (pc_cant_act_except_npc(sd)) return; if (pc_issit(sd)) return; @@ -13093,7 +13117,8 @@ static void clif_parse_UseSkillMap(int fd, struct map_session_data *sd) return; // It is possible to use teleport with the storage window open issue:8027 - if (pc_cant_act(sd) && (sd->state.storage_flag == STORAGE_FLAG_CLOSED && skill_id != AL_TELEPORT)) { + if ((pc_cant_act_except_npc(sd) && sd->state.storage_flag == STORAGE_FLAG_CLOSED && skill_id != AL_TELEPORT) + || (sd->npc_id != 0 && battle_config.skill_enabled_npc != SKILLENABLEDNPC_ALL)) { clif_menuskill_clear(sd); return; } @@ -15474,6 +15499,7 @@ static void clif_parse_GMKick(int fd, struct map_session_data *sd) } npc->unload_duplicates(nd, true); npc->unload(nd, true, true); + npc->motd = npc->name2id("HerculesMOTD"); npc->read_event_script(); } break; @@ -19927,9 +19953,9 @@ static int clif_autoshadowspell_list(struct map_session_data *sd) WFIFOHEAD(fd, 2 * 6 + 4); WFIFOW(fd,0) = 0x442; for (i = 0, c = 0; i < MAX_SKILL_DB; i++) - if( sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].id > 0 && - sd->status.skill[i].id < GS_GLITTERING && skill->get_type(sd->status.skill[i].id) == BF_MAGIC ) - { // Can't auto cast both Extended class and 3rd class skills. + if (sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].id > 0 && sd->status.skill[i].id < GS_GLITTERING + && skill->get_type(sd->status.skill[i].id, sd->status.skill[i].lv) == BF_MAGIC) { + // Can't auto cast both Extended class and 3rd class skills. WFIFOW(fd,8+c*2) = sd->status.skill[i].id; c++; } @@ -20435,17 +20461,14 @@ static void clif_maptypeproperty2(struct block_list *bl, enum send_target t) { #if PACKETVER >= 20121010 struct packet_maptypeproperty2 p; - struct map_session_data *sd = NULL; nullpo_retv(bl); - sd = BL_CAST(BL_PC, bl); - p.PacketType = maptypeproperty2Type; p.type = 0x28; p.flag.party = map->list[bl->m].flag.pvp ? 1 : 0; //PARTY p.flag.guild = (map->list[bl->m].flag.battleground || map_flag_gvg(bl->m)) ? 1 : 0; // GUILD p.flag.siege = (map->list[bl->m].flag.battleground || map_flag_gvg2(bl->m)) ? 1: 0; // SIEGE - p.flag.mineffect = map_flag_gvg(bl->m) ? 1 : ( (sd && sd->state.lesseffect) ? 1 : 0); // USE_SIMPLE_EFFECT - Forcing /mineffect in castles during WoE (probably redundant? I'm not sure) + p.flag.mineffect = map_flag_gvg2(bl->m) ? 1 : 0; // USE_SIMPLE_EFFECT - Automatically enable /mineffect in guild arenas and castles. p.flag.nolockon = 0; // DISABLE_LOCKON - TODO p.flag.countpk = map->list[bl->m].flag.pvp ? 1 : 0; // COUNT_PK p.flag.nopartyformation = map->list[bl->m].flag.partylock ? 1 : 0; // NO_PARTY_FORMATION @@ -22299,7 +22322,7 @@ static void clif_rodex_checkname_result(struct map_session_data *sd, int char_id sPacket->Class = class_; sPacket->BaseLevel = base_level; #if PACKETVER >= 20160316 - strncpy(sPacket->Name, name, NAME_LENGTH); + safestrncpy(sPacket->Name, name, NAME_LENGTH); #endif WFIFOSET(fd, sizeof(*sPacket)); #endif @@ -24192,7 +24215,7 @@ static int do_init_clif(bool minimal) timer->add_func_list(clif->clearunit_delayed_sub, "clif_clearunit_delayed_sub"); timer->add_func_list(clif->delayquit, "clif_delayquit"); - clif->delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR); + clif->delay_clearunit_ers = ers_new(sizeof(struct mob_data), "clif.c::delay_clearunit_ers", ERS_OPT_CLEAR); clif->delayed_damage_ers = ers_new(sizeof(struct cdelayed_damage),"clif.c::delayed_damage_ers",ERS_OPT_CLEAR); #if PACKETVER_MAIN_NUM >= 20190403 || PACKETVER_RE_NUM >= 20190320 |