Added support for sc_display on BL_HOM, BL_MER, BL_ELEM, BL_PET

This commit is contained in:
Atemo 2024-06-13 16:15:07 +02:00
parent da034f11d9
commit aceeb97126
12 changed files with 52 additions and 191 deletions

View File

@ -6076,6 +6076,7 @@ Body:
NoBanishingBuster: true NoBanishingBuster: true
NoClearance: true NoClearance: true
NoForcedEnd: true NoForcedEnd: true
SendVal1: true
EndReturn: EndReturn:
All_Riding: true All_Riding: true
- Status: Teargas_Sob - Status: Teargas_Sob

View File

@ -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. 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. 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. 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. 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 (NPC) 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 (monster) 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'. Debuff - Status is considered a debuff. Used in combination with 'battle_config.debuff_on_logout'.
SetStand - Sets player to standing state. SetStand - Sets player to standing state.
OverlapIgnoreLevel - The status will successfully activate for any level if the status is already active. OverlapIgnoreLevel - The status will successfully activate for any level if the status is already active.

View File

@ -1721,7 +1721,7 @@ int clif_spawn( struct block_list *bl, bool walking ){
clif_spiritcharm(sd); clif_spiritcharm(sd);
if (sd->status.robe) if (sd->status.robe)
clif_refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); 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 ); clif_hat_effects( *sd, sd->bl, AREA );
} }
break; break;
@ -1734,7 +1734,7 @@ int clif_spawn( struct block_list *bl, bool walking ){
clif_specialeffect(&md->bl,EF_BABYBODY2,AREA); clif_specialeffect(&md->bl,EF_BABYBODY2,AREA);
if ( md->special_state.ai == AI_ABR || md->special_state.ai == AI_BIONIC ) if ( md->special_state.ai == AI_ABR || md->special_state.ai == AI_BIONIC )
clif_summon_init(*md); clif_summon_init(*md);
clif_efst_status_change_sub( *bl, *bl, AREA ); clif_efst_status_change_sub( *bl, *bl, AREA_WOS );
} }
break; break;
case BL_NPC: case BL_NPC:
@ -1744,13 +1744,19 @@ int clif_spawn( struct block_list *bl, bool walking ){
clif_specialeffect(&nd->bl,EF_GIANTBODY2,AREA); clif_specialeffect(&nd->bl,EF_GIANTBODY2,AREA);
else if( nd->size == SZ_MEDIUM ) else if( nd->size == SZ_MEDIUM )
clif_specialeffect(&nd->bl,EF_BABYBODY2,AREA); 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); clif_progressbar_npc_area(nd);
} }
break; break;
case BL_PET: case BL_PET:
if (vd->head_bottom) if (vd->head_bottom)
clif_pet_equip_area((TBL_PET*)bl); // needed to display pet equip properly 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; break;
} }
return 0; return 0;
@ -5063,7 +5069,7 @@ void clif_getareachar_unit( map_session_data* sd,struct block_list *bl ){
clif_sendbgemblem_single(sd->fd,tsd); clif_sendbgemblem_single(sd->fd,tsd);
if ( tsd->status.robe ) if ( tsd->status.robe )
clif_refreshlook(&sd->bl,bl->id,LOOK_ROBE,tsd->status.robe,SELF); 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 ); clif_hat_effects( *sd, tsd->bl, SELF );
} }
break; break;
@ -5099,12 +5105,17 @@ void clif_getareachar_unit( map_session_data* sd,struct block_list *bl ){
clif_monster_hp_bar(md, sd->fd); clif_monster_hp_bar(md, sd->fd);
} }
#endif #endif
clif_efst_status_change_sub( *bl, *bl, AREA ); clif_efst_status_change_sub( sd->bl, *bl, SELF );
} }
break; break;
case BL_PET: case BL_PET:
if (vd->head_bottom) if (vd->head_bottom)
clif_pet_equip(sd, (TBL_PET*)bl); // needed to display pet equip properly 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; 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 bl: Objects walking into view
* @param target: Client send type * @param target: Client send type
*/ */
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 ){
bool spheres_sent; status_change *sc = status_get_sc( &src );
std::unordered_map<sc_type, std::shared_ptr<sc_display_entry>> sc_display;
switch( bl.type ){ if (sc == nullptr || sc->sc_display.empty())
case BL_PC: { return;
map_session_data* sd = BL_CAST(BL_PC, &bl);
if (sd == nullptr) for ( const auto &type : sc->sc_display ) {
return; struct status_change_entry* sce = sc->getSCE(type);
std::shared_ptr<s_status_change_db> scdb = status_db.find(type);
sc_display = sd->sc_display; if (sce == nullptr || scdb == nullptr)
continue;
spheres_sent = !sd->state.connect_new; const struct TimerData *td = get_timer(sc->getSCE(type)->timer);
}
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<sc_display_entry> 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);
t_tick tick = 0; t_tick tick = 0;
if (td != nullptr) 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_4:
case SC_SPHERE_5: case SC_SPHERE_5:
if( spheres_sent ){ if( spheres_sent ){
target = AREA_WOS; target = AREA_WOS; // area without self
// check me : target should stay AREA_WOS ?
} }
break; break;
case SC_HELLS_PLANT: case SC_HELLS_PLANT:
if( sc && sc->getSCE(type) ){ tick = sce->val4;
tick = sc->getSCE(type)->val4;
}
break; 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 #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 #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 #endif
} }
} }
@ -9899,7 +9879,7 @@ void clif_refresh(map_session_data *sd)
clif_clearunit_single( sd->bl.id, CLR_DEAD, *sd ); clif_clearunit_single( sd->bl.id, CLR_DEAD, *sd );
else else
clif_changed_dir(&sd->bl, SELF); 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 //Issue #2143
//Cancel Trading State //Cancel Trading State

View File

@ -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) #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_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(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_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 ); void clif_wis_end( map_session_data& sd, e_ack_whisper result );

View File

@ -388,8 +388,6 @@ struct mob_data {
uint16 damagetaken; uint16 damagetaken;
e_mob_bosstype get_bosstype(); e_mob_bosstype get_bosstype();
std::unordered_map<sc_type, std::shared_ptr<sc_display_entry>> sc_display;
}; };
class MobAvailDatabase : public YamlDatabase { class MobAvailDatabase : public YamlDatabase {

View File

@ -3528,7 +3528,6 @@ int npc_unload(struct npc_data* nd, bool single) {
} }
nd->qi_data.clear(); nd->qi_data.clear();
nd->sc_display.clear();
script_stop_sleeptimers(nd->bl.id); script_stop_sleeptimers(nd->bl.id);

View File

@ -218,8 +218,6 @@ struct npc_data {
std::vector<std::shared_ptr<s_questinfo>> qi_data; std::vector<std::shared_ptr<s_questinfo>> qi_data;
std::unordered_map<sc_type, std::shared_ptr<sc_display_entry>> sc_display;
struct { struct {
t_tick timeout; t_tick timeout;
unsigned long color; unsigned long color;

View File

@ -863,8 +863,6 @@ public:
unsigned char fontcolor; unsigned char fontcolor;
t_tick *channel_tick; t_tick *channel_tick;
std::unordered_map<enum sc_type, std::shared_ptr<sc_display_entry>> sc_display;
unsigned char delayed_damage; //[Ind] unsigned char delayed_damage; //[Ind]
/** /**

View File

@ -11231,6 +11231,7 @@
export_constant(SCF_REMOVEONHERMODE); export_constant(SCF_REMOVEONHERMODE);
export_constant(SCF_REQUIRENOWEAPON); export_constant(SCF_REQUIRENOWEAPON);
export_constant(SCF_DISPLAYMOB); export_constant(SCF_DISPLAYMOB);
export_constant(SCF_DISPLAYALL);
/* enchantgrades */ /* enchantgrades */
export_constant(ENCHANTGRADE_NONE); export_constant(ENCHANTGRADE_NONE);

View File

@ -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); 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<sc_display_entry> entry = std::make_shared<sc_display_entry>();
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 * Applies SC defense to a given status change
* This function also determines whether or not the status change will be applied * 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 // 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) { 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)) {
int dval1 = scdb->flag[SCF_SENDVAL1] ? val1 : 0; if (!util::vector_exists(sc->sc_display, type))
int dval2 = scdb->flag[SCF_SENDVAL2] ? val2 : 0; sc->sc_display.push_back(type);
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 );
} }
//SC that force player to stand if is sitting //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); 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) 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))
status_display_remove( *bl, type ); util::vector_erase_if_exists(sc->sc_display, type);
vd = status_get_viewdata(bl); vd = status_get_viewdata(bl);
std::bitset<SCB_MAX> calc_flag = scdb->calc_flag; std::bitset<SCB_MAX> calc_flag = scdb->calc_flag;

View File

@ -3058,6 +3058,7 @@ enum e_status_change_flag : uint16 {
SCF_REMOVEONHERMODE, SCF_REMOVEONHERMODE,
SCF_REQUIRENOWEAPON, SCF_REQUIRENOWEAPON,
SCF_DISPLAYMOB, SCF_DISPLAYMOB,
SCF_DISPLAYALL,
SCF_MAX SCF_MAX
}; };
@ -3141,7 +3142,7 @@ enum e_refine_chance_type {
///Define to determine who has regen ///Define to determine who has regen
#define BL_REGEN (BL_PC|BL_HOM|BL_MER|BL_ELEM) #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 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 /** Basic damage info of a weapon
* Required because players have two of these, one in status_data * Required because players have two of these, one in status_data
@ -3242,12 +3243,6 @@ struct regen_data {
struct regen_data_sub *sregen, *ssregen; struct regen_data_sub *sregen, *ssregen;
}; };
///Status display entry
struct sc_display_entry {
enum sc_type type;
int val1, val2, val3;
};
///Status change entry ///Status change entry
struct status_change_entry { struct status_change_entry {
int timer; int timer;
@ -3281,6 +3276,7 @@ public:
} cant;/* status change state flags */ } cant;/* status change state flags */
//int sg_id; //ID of the previous Storm gust that hit you //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 short comet_x, comet_y; // Point where src casted Comet - required to calculate damage from this point
std::vector<sc_type> sc_display;
/** /**
* The Storm Gust counter was dropped in renewal * The Storm Gust counter was dropped in renewal
**/ **/

View File

@ -3494,8 +3494,6 @@ int unit_free(struct block_list *bl, clr_type clrtype)
sd->combos.clear(); sd->combos.clear();
sd->sc_display.clear();
if( sd->quest_log != nullptr ) { if( sd->quest_log != nullptr ) {
aFree(sd->quest_log); aFree(sd->quest_log);
sd->quest_log = nullptr; sd->quest_log = nullptr;