Multiple dynamic npc (#7486)

* Vectorize npc_id_dynamic to support multiple dynamic npc with different ids

Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>

Thanks to @dimasshotta and @eppc0330 !
This commit is contained in:
Atemo
2022-12-16 21:22:31 +01:00
committed by GitHub
parent 20dedc7918
commit ef602d98cb
3 changed files with 28 additions and 15 deletions

View File

@@ -3528,7 +3528,7 @@ int npc_unload(struct npc_data* nd, bool single) {
map_session_data* owner = map_charid2sd( nd->dynamicnpc.owner_char_id );
if( owner != nullptr ){
owner->npc_id_dynamic = 0;
util::vector_erase_if_exists(owner->npc_id_dynamic, nd->bl.id);
}
}
@@ -4515,7 +4515,7 @@ const char* npc_parse_duplicate( char* w1, char* w2, char* w3, char* w4, const c
if( owner != nullptr ){
nd->dynamicnpc.owner_char_id = owner->status.char_id;
owner->npc_id_dynamic = nd->bl.id;
owner->npc_id_dynamic.push_back(nd->bl.id);
}
switch( type ) {
@@ -5796,7 +5796,7 @@ TIMER_FUNC(npc_dynamicnpc_removal_timer){
return 0;
}
sd->npc_id_dynamic = 0;
// npc id from sd->npc_id_dynamic is removed in npc_unload
}
// Delete the NPC
@@ -5808,9 +5808,17 @@ TIMER_FUNC(npc_dynamicnpc_removal_timer){
}
struct npc_data* npc_duplicate_npc_for_player( struct npc_data& nd, map_session_data& sd ){
if( sd.npc_id_dynamic != 0 ){
clif_msg_color( &sd, C_DYNAMICNPC_TWICE, color_table[COLOR_LIGHT_YELLOW] );
return nullptr;
// A duplicate of a duplicate is still a duplicate of the same NPC
int src_id = nd.src_id > 0 ? nd.src_id : nd.bl.id;
for (const auto &it : sd.npc_id_dynamic) {
struct npc_data* src_nd = map_id2nd( it );
// Check if the source NPC id of currently active duplicates already exists.
if( src_nd != nullptr && src_nd->src_id == src_id ){
clif_msg_color( &sd, C_DYNAMICNPC_TWICE, color_table[COLOR_LIGHT_YELLOW] );
return nullptr;
}
}
if( map_getmapflag( sd.bl.m, MF_NODYNAMICNPC ) ){

View File

@@ -492,7 +492,7 @@ public:
unsigned char head_dir; //0: Look forward. 1: Look right, 2: Look left.
t_tick client_tick;
int npc_id,npc_shopid; //for script follow scriptoid; ,npcid
int npc_id_dynamic;
std::vector<int> npc_id_dynamic;
std::vector<int> areanpc, npc_ontouch_; ///< Array of OnTouch and OnTouch_ NPC ID
int npc_item_flag; //Marks the npc_id with which you can use items during interactions with said npc (see script command enable_itemuse)
int npc_menu; // internal variable, used in npc menu handling

View File

@@ -3423,17 +3423,22 @@ int unit_free(struct block_list *bl, clr_type clrtype)
sd->npc_id = 0;
}
if( sd->npc_id_dynamic != 0 ){
struct npc_data* nd = map_id2nd( sd->npc_id_dynamic );
if( !sd->npc_id_dynamic.empty() ){
for (const auto &it : sd->npc_id_dynamic) {
struct npc_data* nd = map_id2nd( it );
if( nd != nullptr ){
// Delete the NPC
npc_unload( nd, true );
// Update NPC event database
npc_read_event_script();
if( nd != nullptr ){
// Erase the owner first to prevent loops from npc_unload
nd->dynamicnpc.owner_char_id = 0;
// Delete the NPC
npc_unload( nd, true );
}
}
// Update NPC event database
npc_read_event_script();
sd->npc_id_dynamic = 0;
sd->npc_id_dynamic.clear();
}
sd->combos.clear();