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
NoClearance: true
NoForcedEnd: true
SendVal1: true
EndReturn:
All_Riding: true
- 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.
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.

View File

@ -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_type, std::shared_ptr<sc_display_entry>> 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 (sd == nullptr)
if (sc == nullptr || sc->sc_display.empty())
return;
sc_display = sd->sc_display;
for ( const auto &type : sc->sc_display ) {
struct status_change_entry* sce = sc->getSCE(type);
std::shared_ptr<s_status_change_db> scdb = status_db.find(type);
spheres_sent = !sd->state.connect_new;
}
break;
case BL_NPC: {
npc_data* nd = BL_CAST(BL_NPC, &bl);
if (sce == nullptr || scdb == nullptr)
continue;
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);
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

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)
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 );

View File

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

View File

@ -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);

View File

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

View File

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

View File

@ -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);

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);
}
/**
* 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
* 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<SCB_MAX> calc_flag = scdb->calc_flag;

View File

@ -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_type> sc_display;
/**
* 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->sc_display.clear();
if( sd->quest_log != nullptr ) {
aFree(sd->quest_log);
sd->quest_log = nullptr;