diff --git a/db/re/status.yml b/db/re/status.yml index 920bf620ca..55d6ce889d 100644 --- a/db/re/status.yml +++ b/db/re/status.yml @@ -6076,6 +6076,7 @@ Body: NoBanishingBuster: true NoClearance: true NoForcedEnd: true + SendVal1: true EndReturn: All_Riding: true - Status: Teargas_Sob diff --git a/doc/status.txt b/doc/status.txt index 1fffe1df27..b072489e3d 100644 --- a/doc/status.txt +++ b/doc/status.txt @@ -199,9 +199,11 @@ Flags: Various status flags for specific status change events. BlEffect - Flag to send a visual effect to clients around if the affected unit is BL_PC, BL_HOM, BL_MER, BL_MOB, BL_ELEM or BL_NPC when the status is given. The status must have an EFST defined in Icon - other than EFST_BLANK. When not defined (default) the status is displayed to clients around when the affected unit is BL_PC (player) only. - DisplayPc - Whether the status is displayed (again) to client around when the affected unit (player) appears in the client's range. - DisplayNpc - Whether the status is displayed (again) to client around when the affected unit (NPC) appears in the client's range. - DisplayMob - Whether the status is displayed (again) to client around when the affected unit (monster) appears in the client's range. + DisplayPc - Whether the status is displayed (again) to client around when the affected unit (BL_PC) appears in the client's range. + DisplayNpc - Whether the status is displayed (again) to client around when the affected unit (BL_NPC) appears in the client's range. + DisplayMob - Whether the status is displayed (again) to client around when the affected unit (BL_MOB) appears in the client's range. + DisplayAll - Whether the status is displayed (again) to client around when the affected unit (BL_PC, BL_HOM, BL_MER, BL_MOB, BL_ELEM, BL_NPC or BL_PET) appears in the client's range. + When defined, other display flags are ignored. Debuff - Status is considered a debuff. Used in combination with 'battle_config.debuff_on_logout'. SetStand - Sets player to standing state. OverlapIgnoreLevel - The status will successfully activate for any level if the status is already active. diff --git a/src/map/clif.cpp b/src/map/clif.cpp index e5c0211404..e6cc319540 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -1721,7 +1721,7 @@ int clif_spawn( struct block_list *bl, bool walking ){ clif_spiritcharm(sd); if (sd->status.robe) clif_refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); - clif_efst_status_change_sub( *bl, *bl, AREA ); + clif_efst_status_change_sub( *bl, *bl, AREA, !sd->state.connect_new ); clif_hat_effects( *sd, sd->bl, AREA ); } break; @@ -1734,7 +1734,7 @@ int clif_spawn( struct block_list *bl, bool walking ){ clif_specialeffect(&md->bl,EF_BABYBODY2,AREA); if ( md->special_state.ai == AI_ABR || md->special_state.ai == AI_BIONIC ) clif_summon_init(*md); - clif_efst_status_change_sub( *bl, *bl, AREA ); + clif_efst_status_change_sub( *bl, *bl, AREA_WOS ); } break; case BL_NPC: @@ -1744,13 +1744,19 @@ int clif_spawn( struct block_list *bl, bool walking ){ clif_specialeffect(&nd->bl,EF_GIANTBODY2,AREA); else if( nd->size == SZ_MEDIUM ) clif_specialeffect(&nd->bl,EF_BABYBODY2,AREA); - clif_efst_status_change_sub( *bl, *bl, AREA ); + clif_efst_status_change_sub( *bl, *bl, AREA_WOS ); clif_progressbar_npc_area(nd); } break; case BL_PET: if (vd->head_bottom) clif_pet_equip_area((TBL_PET*)bl); // needed to display pet equip properly + clif_efst_status_change_sub( *bl, *bl, AREA_WOS ); + break; + case BL_HOM: + case BL_MER: + case BL_ELEM: + clif_efst_status_change_sub( *bl, *bl, AREA_WOS ); break; } return 0; @@ -5063,7 +5069,7 @@ void clif_getareachar_unit( map_session_data* sd,struct block_list *bl ){ clif_sendbgemblem_single(sd->fd,tsd); if ( tsd->status.robe ) clif_refreshlook(&sd->bl,bl->id,LOOK_ROBE,tsd->status.robe,SELF); - clif_efst_status_change_sub( sd->bl, *bl, SELF ); + clif_efst_status_change_sub( sd->bl, *bl, SELF, !sd->state.connect_new ); clif_hat_effects( *sd, tsd->bl, SELF ); } break; @@ -5099,12 +5105,17 @@ void clif_getareachar_unit( map_session_data* sd,struct block_list *bl ){ clif_monster_hp_bar(md, sd->fd); } #endif - clif_efst_status_change_sub( *bl, *bl, AREA ); + clif_efst_status_change_sub( sd->bl, *bl, SELF ); } break; case BL_PET: if (vd->head_bottom) clif_pet_equip(sd, (TBL_PET*)bl); // needed to display pet equip properly + clif_efst_status_change_sub( sd->bl, *bl, SELF ); + break; + case BL_HOM: + case BL_ELEM: + clif_efst_status_change_sub( sd->bl, *bl, SELF ); break; } } @@ -6555,54 +6566,20 @@ void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick, * @param bl: Objects walking into view * @param target: Client send type */ -void clif_efst_status_change_sub( block_list& tbl, block_list& bl, enum send_target target ){ - bool spheres_sent; - std::unordered_map> sc_display; +void clif_efst_status_change_sub( block_list& tbl, block_list& src, enum send_target target, bool spheres_sent ){ + status_change *sc = status_get_sc( &src ); - switch( bl.type ){ - case BL_PC: { - map_session_data* sd = BL_CAST(BL_PC, &bl); + if (sc == nullptr || sc->sc_display.empty()) + return; - if (sd == nullptr) - return; + for ( const auto &type : sc->sc_display ) { + struct status_change_entry* sce = sc->getSCE(type); + std::shared_ptr scdb = status_db.find(type); - sc_display = sd->sc_display; + if (sce == nullptr || scdb == nullptr) + continue; - spheres_sent = !sd->state.connect_new; - } - break; - case BL_NPC: { - npc_data* nd = BL_CAST(BL_NPC, &bl); - - if (nd == nullptr) - return; - - sc_display = nd->sc_display; - - spheres_sent = true; - } - break; - case BL_MOB: { - mob_data* md = BL_CAST(BL_MOB, &bl); - - if (md == nullptr) - return; - - sc_display = md->sc_display; - - spheres_sent = true; - } - break; - default: - return; - } - - for ( const auto &it : sc_display ) { - std::shared_ptr entry = it.second; - - enum sc_type type = entry->type; - status_change *sc = status_get_sc( &bl ); - const struct TimerData *td = (sc && sc->getSCE(type) ? get_timer(sc->getSCE(type)->timer) : nullptr); + const struct TimerData *td = get_timer(sc->getSCE(type)->timer); t_tick tick = 0; if (td != nullptr) @@ -6616,20 +6593,23 @@ void clif_efst_status_change_sub( block_list& tbl, block_list& bl, enum send_tar case SC_SPHERE_4: case SC_SPHERE_5: if( spheres_sent ){ - target = AREA_WOS; + target = AREA_WOS; // area without self + // check me : target should stay AREA_WOS ? } break; case SC_HELLS_PLANT: - if( sc && sc->getSCE(type) ){ - tick = sc->getSCE(type)->val4; - } + tick = sce->val4; break; } + int dval1 = scdb->flag[SCF_SENDVAL1] ? sce->val1 : 0; + int dval2 = scdb->flag[SCF_SENDVAL2] ? sce->val2 : 0; + int dval3 = scdb->flag[SCF_SENDVAL3] ? sce->val3 : 0; + #if PACKETVER > 20120418 - clif_efst_status_change( &tbl, bl.id, target, status_db.getIcon(type), tick, entry->val1, entry->val2, entry->val3 ); + clif_efst_status_change( &tbl, src.id, target, status_db.getIcon(type), tick, dval1, dval2, dval3 ); #else - clif_status_change_sub( &tbl, bl.id, status_db.getIcon(type), 1, tick, entry->val1, entry->val2, entry->val3, target ); + clif_status_change_sub( &tbl, src.id, status_db.getIcon(type), 1, tick, dval1, dval2, dval3, target ); #endif } } @@ -9899,7 +9879,7 @@ void clif_refresh(map_session_data *sd) clif_clearunit_single( sd->bl.id, CLR_DEAD, *sd ); else clif_changed_dir(&sd->bl, SELF); - clif_efst_status_change_sub( sd->bl, sd->bl, SELF ); + clif_efst_status_change_sub( sd->bl, sd->bl, SELF, !sd->state.connect_new ); //Issue #2143 //Cancel Trading State diff --git a/src/map/clif.hpp b/src/map/clif.hpp index 79041a3a33..21ea0760ca 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -947,7 +947,7 @@ void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_targe #define clif_status_load(bl, type, flag) clif_status_change((bl), (type), (flag), 0, 0, 0, 0) void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick, int val1, int val2, int val3); void clif_efst_status_change(struct block_list *bl, int tid, enum send_target target, int type, t_tick tick, int val1, int val2, int val3); -void clif_efst_status_change_sub( block_list& tbl, block_list& bl, enum send_target target ); +void clif_efst_status_change_sub( block_list& tbl, block_list& src, enum send_target target, bool spheres_sent = true ); void clif_wis_message(map_session_data* sd, const char* nick, const char* mes, size_t mes_len, int gmlvl); void clif_wis_end( map_session_data& sd, e_ack_whisper result ); diff --git a/src/map/mob.hpp b/src/map/mob.hpp index e1151ff876..c0a7e66509 100644 --- a/src/map/mob.hpp +++ b/src/map/mob.hpp @@ -388,8 +388,6 @@ struct mob_data { uint16 damagetaken; e_mob_bosstype get_bosstype(); - - std::unordered_map> sc_display; }; class MobAvailDatabase : public YamlDatabase { diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 223c0d932d..c9b26fa5a2 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -3528,7 +3528,6 @@ int npc_unload(struct npc_data* nd, bool single) { } nd->qi_data.clear(); - nd->sc_display.clear(); script_stop_sleeptimers(nd->bl.id); diff --git a/src/map/npc.hpp b/src/map/npc.hpp index 283e60e669..06e945802a 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -218,8 +218,6 @@ struct npc_data { std::vector> qi_data; - std::unordered_map> sc_display; - struct { t_tick timeout; unsigned long color; diff --git a/src/map/pc.hpp b/src/map/pc.hpp index 6bfb57266c..b5d662c22d 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -863,8 +863,6 @@ public: unsigned char fontcolor; t_tick *channel_tick; - std::unordered_map> sc_display; - unsigned char delayed_damage; //[Ind] /** diff --git a/src/map/script_constants.hpp b/src/map/script_constants.hpp index d49b62c9a8..feb29bca4e 100644 --- a/src/map/script_constants.hpp +++ b/src/map/script_constants.hpp @@ -11231,6 +11231,7 @@ export_constant(SCF_REMOVEONHERMODE); export_constant(SCF_REQUIRENOWEAPON); export_constant(SCF_DISPLAYMOB); + export_constant(SCF_DISPLAYALL); /* enchantgrades */ export_constant(ENCHANTGRADE_NONE); diff --git a/src/map/status.cpp b/src/map/status.cpp index 80b92b2384..4fdcdcc139 100644 --- a/src/map/status.cpp +++ b/src/map/status.cpp @@ -9821,100 +9821,6 @@ t_tick status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_ return i64max(tick, scdb->min_duration); } -/** - * Applies SC effect - * @param bl: Source to apply effect - * @param type: Status change (SC_*) - * @param dval1~3: Depends on type of status change - * Author: Ind - */ -void status_display_add( block_list& bl, enum sc_type type, int val1, int val2, int val3 ){ - std::shared_ptr entry = std::make_shared(); - - entry->type = type; - entry->val1 = val1; - entry->val2 = val2; - entry->val3 = val3; - - switch( bl.type ){ - case BL_PC: { - map_session_data* sd = BL_CAST(BL_PC, &bl); - - if (sd == nullptr) - return; - - sd->sc_display[type] = entry; - } - break; - case BL_NPC: { - npc_data* nd = BL_CAST(BL_NPC, &bl); - - if (nd == nullptr) - return; - - nd->sc_display[type] = entry; - } - break; - case BL_MOB: { - mob_data* md = BL_CAST(BL_MOB, &bl); - - if (md == nullptr) - return; - - md->sc_display[type] = entry; - } - break; - default: - return; - } -} - -/** - * Removes SC effect - * @param bl: Source to remove effect - * @param type: Status change (SC_*) - * Author: Ind - */ -void status_display_remove( block_list& bl, enum sc_type type ){ - switch( bl.type ){ - case BL_PC: { - map_session_data* sd = BL_CAST(BL_PC, &bl); - - if (sd == nullptr) - return; - - if (util::umap_find( sd->sc_display, type ) != nullptr) { - sd->sc_display.erase( type ); - } - } - break; - case BL_NPC: { - npc_data* nd = BL_CAST(BL_NPC, &bl); - - if (nd == nullptr) - return; - - if (util::umap_find( nd->sc_display, type ) != nullptr) { - nd->sc_display.erase( type ); - } - } - break; - case BL_MOB: { - mob_data* md = BL_CAST(BL_MOB, &bl); - - if (md == nullptr) - return; - - if (util::umap_find( md->sc_display, type ) != nullptr) { - md->sc_display.erase( type ); - } - } - break; - default: - return; - } -} - /** * Applies SC defense to a given status change * This function also determines whether or not the status change will be applied @@ -12793,25 +12699,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty } // Save sc to display it again later - if (scdb->flag[SCF_DISPLAYPC] && bl->type == BL_PC || scdb->flag[SCF_DISPLAYNPC] && bl->type == BL_NPC || scdb->flag[SCF_DISPLAYMOB] && bl->type == BL_MOB) { - int dval1 = scdb->flag[SCF_SENDVAL1] ? val1 : 0; - int dval2 = scdb->flag[SCF_SENDVAL2] ? val2 : 0; - int dval3 = scdb->flag[SCF_SENDVAL3] ? val3 : 0; - - switch (type) { - case SC_ALL_RIDING: - dval1 = 1; - break; - case SC_CLAN_INFO: - dval1 = val1; - dval2 = val2; - dval3 = val3; - break; - default: /* All others: just copy val1 */ - dval1 = val1; - break; - } - status_display_add( *bl, type, dval1, dval2, dval3 ); + if (scdb->flag[SCF_DISPLAYALL] || (scdb->flag[SCF_DISPLAYPC] && bl->type == BL_PC || scdb->flag[SCF_DISPLAYNPC] && bl->type == BL_NPC || scdb->flag[SCF_DISPLAYMOB] && bl->type == BL_MOB)) { + if (!util::vector_exists(sc->sc_display, type)) + sc->sc_display.push_back(type); } //SC that force player to stand if is sitting @@ -13215,8 +13105,8 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) sc->clearSCE(type); - if (scdb->flag[SCF_DISPLAYPC] && bl->type == BL_PC || scdb->flag[SCF_DISPLAYNPC] && bl->type == BL_NPC || scdb->flag[SCF_DISPLAYMOB] && bl->type == BL_MOB) - status_display_remove( *bl, type ); + if (scdb->flag[SCF_DISPLAYALL] || (scdb->flag[SCF_DISPLAYPC] && bl->type == BL_PC || scdb->flag[SCF_DISPLAYNPC] && bl->type == BL_NPC || scdb->flag[SCF_DISPLAYMOB] && bl->type == BL_MOB)) + util::vector_erase_if_exists(sc->sc_display, type); vd = status_get_viewdata(bl); std::bitset calc_flag = scdb->calc_flag; diff --git a/src/map/status.hpp b/src/map/status.hpp index faa168dc74..5f98c1baa7 100644 --- a/src/map/status.hpp +++ b/src/map/status.hpp @@ -3058,6 +3058,7 @@ enum e_status_change_flag : uint16 { SCF_REMOVEONHERMODE, SCF_REQUIRENOWEAPON, SCF_DISPLAYMOB, + SCF_DISPLAYALL, SCF_MAX }; @@ -3141,7 +3142,7 @@ enum e_refine_chance_type { ///Define to determine who has regen #define BL_REGEN (BL_PC|BL_HOM|BL_MER|BL_ELEM) ///Define to determine who will receive a clif_status_change packet for effects that require one to display correctly -#define BL_SCEFFECT (BL_PC|BL_HOM|BL_MER|BL_MOB|BL_ELEM|BL_NPC) +#define BL_SCEFFECT (BL_PC|BL_HOM|BL_MER|BL_MOB|BL_ELEM|BL_NPC|BL_PET) /** Basic damage info of a weapon * Required because players have two of these, one in status_data @@ -3242,12 +3243,6 @@ struct regen_data { struct regen_data_sub *sregen, *ssregen; }; -///Status display entry -struct sc_display_entry { - enum sc_type type; - int val1, val2, val3; -}; - ///Status change entry struct status_change_entry { int timer; @@ -3281,6 +3276,7 @@ public: } cant;/* status change state flags */ //int sg_id; //ID of the previous Storm gust that hit you short comet_x, comet_y; // Point where src casted Comet - required to calculate damage from this point + std::vector sc_display; /** * The Storm Gust counter was dropped in renewal **/ diff --git a/src/map/unit.cpp b/src/map/unit.cpp index bc37bf55d9..03b74a9af1 100644 --- a/src/map/unit.cpp +++ b/src/map/unit.cpp @@ -3494,8 +3494,6 @@ int unit_free(struct block_list *bl, clr_type clrtype) sd->combos.clear(); - sd->sc_display.clear(); - if( sd->quest_log != nullptr ) { aFree(sd->quest_log); sd->quest_log = nullptr;