From 30c175a9041a17e0d2ef1d4750163c19ab3a7959 Mon Sep 17 00:00:00 2001 From: Kenpachi Developer Date: Wed, 27 Nov 2019 02:50:08 +0100 Subject: Change unload NPC behavior to kill mobs that were spawned by unloaded NPC (non-permanent monster spawns) [Issue #2530] Mobs spawned by NPC will be removed on @reloadnpc, @unloadnpc, and @unloadnpcfile. Additionally OnNPCUnload NPC label was added, to revert other changes made by NPC. For example set/removed mapflags or added mob drops. --- src/map/atcommand.c | 42 +++++--- src/map/clif.c | 4 +- src/map/instance.c | 2 +- src/map/map.c | 2 +- src/map/mob.c | 21 ++-- src/map/mob.h | 9 +- src/map/npc.c | 51 ++++++--- src/map/npc.h | 7 +- src/map/script.c | 6 +- src/map/skill.c | 12 +-- .../HPMHooking/HPMHooking_map.HPMHooksCore.inc | 4 + .../HPMHooking/HPMHooking_map.HookingPoints.inc | 1 + src/plugins/HPMHooking/HPMHooking_map.Hooks.inc | 117 +++++++++++++-------- 13 files changed, 177 insertions(+), 101 deletions(-) (limited to 'src') diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 5d95e2c14..7bc10edf0 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -4487,11 +4487,12 @@ ACMD(unloadnpc) { struct npc_data *nd; char NPCname[NAME_LENGTH+1]; + short flag = 1; memset(NPCname, '\0', sizeof(NPCname)); - if (!*message || sscanf(message, "%24[^\n]", NPCname) < 1) { - clif->message(fd, msg_fd(fd,1133)); // Please enter a NPC name (usage: @npcoff ). + if (!*message || sscanf(message, "%24s %5hd", NPCname, &flag) < 1) { + clif->message(fd, msg_fd(fd, 1133)); // Please enter a NPC name (Usage: @unloadnpc {}). return false; } @@ -4500,24 +4501,28 @@ ACMD(unloadnpc) return false; } - npc->unload_duplicates(nd); - npc->unload(nd,true); + npc->unload_duplicates(nd, (flag != 0)); + npc->unload(nd, true, (flag != 0)); npc->read_event_script(); clif->message(fd, msg_fd(fd,112)); // Npc Disabled. return true; } /// Unload existing NPC within the NPC file and reload it. -/// Usage: @reloadnpc npc/sample_npc.txt +/// Usage: @reloadnpc npc/sample_npc.txt {flag} +/// Note: Be aware that some changes made by NPC are not reverted on unload. See doc/atcommands.txt for details. ACMD(reloadnpc) { - if (!*message) { - clif->message(fd, msg_fd(fd, 1385)); // Usage: @unloadnpcfile + char file_path[100]; + short flag = 1; + + if (!*message || (sscanf(message, "%99s %5hd", file_path, &flag) < 1)) { + clif->message(fd, msg_fd(fd, 1516)); // Usage: @reloadnpc {} return false; - } else if (npc->unloadfile(message) == true) { - clif->message(fd, msg_fd(fd, 1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed. + } else if (npc->unloadfile(file_path, (flag != 0)) == true) { + clif->message(fd, msg_fd(fd, 1386)); // File unloaded. Be aware that... - FILE *fp = fopen(message, "r"); + FILE *fp = fopen(file_path, "r"); // check if script file exists if (fp == NULL) { clif->message(fd, msg_fd(fd, 261)); @@ -4526,8 +4531,8 @@ ACMD(reloadnpc) fclose(fp); // add to list of script sources and run it - npc->addsrcfile(message); - npc->parsesrcfile(message, true); + npc->addsrcfile(file_path); + npc->parsesrcfile(file_path, true); npc->read_event_script(); clif->message(fd, msg_fd(fd, 262)); @@ -6603,7 +6608,7 @@ ACMD(summon) return false; } - md = mob->once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, DEFAULT_MOB_JNAME, mob_id, "", SZ_SMALL, AI_NONE); + md = mob->once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, DEFAULT_MOB_JNAME, mob_id, "", SZ_SMALL, AI_NONE, 0); if(!md) return false; @@ -9011,13 +9016,16 @@ ACMD(addperm) ACMD(unloadnpcfile) { - if (!*message) { - clif->message(fd, msg_fd(fd,1385)); // Usage: @unloadnpcfile + char file_path[100]; + short flag = 1; + + if (!*message || (sscanf(message, "%99s %5hd", file_path, &flag) < 1)) { + clif->message(fd, msg_fd(fd, 1385)); // Usage: @unloadnpcfile {} return false; } - if (npc->unloadfile(message)) { - clif->message(fd, msg_fd(fd,1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed. + if (npc->unloadfile(file_path, (flag != 0))) { + clif->message(fd, msg_fd(fd, 1386)); // File unloaded. Be aware that... } else { clif->message(fd, msg_fd(fd,1387)); // File not found. return false; diff --git a/src/map/clif.c b/src/map/clif.c index 942e492c2..1223d2b7e 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -15273,8 +15273,8 @@ static void clif_parse_GMKick(int fd, struct map_session_data *sd) clif->GM_kickack(sd, 0); return; } - npc->unload_duplicates(nd); - npc->unload(nd,true); + npc->unload_duplicates(nd, true); + npc->unload(nd, true, true); npc->read_event_script(); } break; diff --git a/src/map/instance.c b/src/map/instance.c index 90f2217b1..1104b7e88 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -446,7 +446,7 @@ static int instance_cleanup_sub(struct block_list *bl, va_list ap) map->quit(BL_UCAST(BL_PC, bl)); break; case BL_NPC: - npc->unload(BL_UCAST(BL_NPC, bl), true); + npc->unload(BL_UCAST(BL_NPC, bl), true, true); break; case BL_MOB: unit->free(bl,CLR_OUTSIGHT); diff --git a/src/map/map.c b/src/map/map.c index 9a45c4d21..8b52fc761 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -6092,7 +6092,7 @@ static int cleanup_sub(struct block_list *bl, va_list ap) map->quit(BL_UCAST(BL_PC, bl)); break; case BL_NPC: - npc->unload(BL_UCAST(BL_NPC, bl), false); + npc->unload(BL_UCAST(BL_NPC, bl), false, true); break; case BL_MOB: unit->free(bl,CLR_OUTSIGHT); diff --git a/src/map/mob.c b/src/map/mob.c index 4b74abc8f..8495dfa06 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -340,7 +340,7 @@ static int mob_parse_dataset(struct spawn_data *data) /*========================================== * Generates the basic mob data using the spawn_data provided. *------------------------------------------*/ -static struct mob_data *mob_spawn_dataset(struct spawn_data *data) +static struct mob_data *mob_spawn_dataset(struct spawn_data *data, int npc_id) { struct mob_data *md = NULL; nullpo_retr(NULL, data); @@ -364,6 +364,7 @@ static struct mob_data *mob_spawn_dataset(struct spawn_data *data) memcpy(md->npc_event, data->eventname, 50); if(md->db->status.mode&MD_LOOTER) md->lootitem = (struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item)); + md->npc_id = npc_id; md->spawn_timer = INVALID_TIMER; md->deletetimer = INVALID_TIMER; md->skill_idx = -1; @@ -503,7 +504,7 @@ static bool mob_ksprotected(struct block_list *src, struct block_list *target) return false; } -static struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai) +static struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai, int npc_id) { struct spawn_data data; @@ -538,7 +539,7 @@ static struct mob_data *mob_once_spawn_sub(struct block_list *bl, int16 m, int16 if (!mob->parse_dataset(&data)) return NULL; - return mob->spawn_dataset(&data); + return mob->spawn_dataset(&data, npc_id); } /*========================================== @@ -562,7 +563,7 @@ static int mob_once_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y for (count = 0; count < amount; count++) { int c = (class_ >= 0) ? class_ : mob->get_random_id(-class_ - 1, (battle_config.random_monster_checklv) ? 3 : 1, lv); - md = mob->once_spawn_sub((sd) ? &sd->bl : NULL, m, x, y, mobname, c, event, size, ai); + md = mob->once_spawn_sub((sd != NULL) ? &sd->bl : NULL, m, x, y, mobname, c, event, size, ai, (sd != NULL) ? sd->npc_id : 0); if (!md) continue; @@ -698,7 +699,7 @@ static int mob_spawn_guardian_sub(int tid, int64 tick, int id, intptr_t data) /*========================================== * Summoning Guardians [Valaris] *------------------------------------------*/ -static int mob_spawn_guardian(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index) +static int mob_spawn_guardian(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index, int npc_id) { struct mob_data *md=NULL; struct spawn_data data; @@ -767,7 +768,7 @@ static int mob_spawn_guardian(const char *mapname, short x, short y, const char } } - md = mob->spawn_dataset(&data); + md = mob->spawn_dataset(&data, npc_id); md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data)); md->guardian_data->number = guardian; md->guardian_data->castle = gc; @@ -798,7 +799,7 @@ static int mob_spawn_guardian(const char *mapname, short x, short y, const char /*========================================== * Summoning BattleGround [Zephyrus] *------------------------------------------*/ -static int mob_spawn_bg(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id) +static int mob_spawn_bg(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id, int npc_id) { struct mob_data *md = NULL; struct spawn_data data; @@ -835,7 +836,7 @@ static int mob_spawn_bg(const char *mapname, short x, short y, const char *mobna if( !mob->parse_dataset(&data) ) return 0; - md = mob->spawn_dataset(&data); + md = mob->spawn_dataset(&data, npc_id); mob->spawn(md); md->bg_id = bg_id; // BG Team ID @@ -3161,7 +3162,7 @@ static int mob_summonslave(struct mob_data *md2, int *value, int amount, uint16 if (!mob->parse_dataset(&data)) continue; - md= mob->spawn_dataset(&data); + md = mob->spawn_dataset(&data, 0); if(skill_id == NPC_SUMMONSLAVE){ md->master_id=md2->bl.id; md->special_state.ai = md2->special_state.ai; @@ -3773,7 +3774,7 @@ static int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 sd->fd = fd; //Finally, spawn it. - md = mob->once_spawn_sub(&sd->bl, m, x, y, DEFAULT_MOB_NAME, class_, event, SZ_SMALL, AI_NONE); + md = mob->once_spawn_sub(&sd->bl, m, x, y, DEFAULT_MOB_NAME, class_, event, SZ_SMALL, AI_NONE, 0); if (!md) return 0; //Failed? md->special_state.clone = 1; diff --git a/src/map/mob.h b/src/map/mob.h index 8fd16f191..8839809f2 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -255,6 +255,7 @@ struct mob_data { int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs) unsigned int bg_id; // BattleGround System int clan_id; // Clan System + int npc_id; // NPC ID if spawned with monster/areamonster/guardian/bg_monster/atcommand("@monster xy") (Used to kill mob on NPC unload.) int64 next_walktime, last_thinktime, last_linktime, last_pcneartime, dmgtick; short move_fail_count; @@ -507,14 +508,14 @@ struct mob_interface { int (*db_checkid) (const int id); struct view_data* (*get_viewdata) (int class_); int (*parse_dataset) (struct spawn_data *data); - struct mob_data* (*spawn_dataset) (struct spawn_data *data); + struct mob_data* (*spawn_dataset) (struct spawn_data *data, int npc_id); int (*get_random_id) (int type, int flag, int lv); bool (*ksprotected) (struct block_list *src, struct block_list *target); - struct mob_data* (*once_spawn_sub) (struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai); + struct mob_data* (*once_spawn_sub) (struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai, int npc_id); int (*once_spawn) (struct map_session_data *sd, int16 m, int16 x, int16 y, const char *mobname, int class_, int amount, const char *event, unsigned int size, unsigned int ai); int (*once_spawn_area) (struct map_session_data *sd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, const char *mobname, int class_, int amount, const char *event, unsigned int size, unsigned int ai); - int (*spawn_guardian) (const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index); - int (*spawn_bg) (const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id); + int (*spawn_guardian) (const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index, int npc_id); + int (*spawn_bg) (const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id, int npc_id); int (*can_reach) (struct mob_data *md, struct block_list *bl, int range, int state); int (*linksearch) (struct block_list *bl, va_list ap); int (*delayspawn) (int tid, int64 tick, int id, intptr_t data); diff --git a/src/map/npc.c b/src/map/npc.c index 657fb987e..8aed1d2fc 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -2939,25 +2939,42 @@ static int npc_unload_ev_label(union DBKey key, struct DBData *data, va_list ap) //Sub-function used to find duplicates. static int npc_unload_dup_sub(struct npc_data *nd, va_list args) { - int src_id; - nullpo_ret(nd); - src_id = va_arg(args, int); + int src_id = va_arg(args, int); + int unload_mobs = va_arg(args, int); + if (nd->src_id == src_id) - npc->unload(nd, true); + npc->unload(nd, true, (unload_mobs == 1)); + return 0; } //Removes all npcs that are duplicates of the passed one. [Skotlex] -static void npc_unload_duplicates(struct npc_data *nd) +static void npc_unload_duplicates(struct npc_data *nd, bool unload_mobs) { nullpo_retv(nd); - map->foreachnpc(npc->unload_dup_sub,nd->bl.id); + // passing unload_mobs as int, because va_arg() would promote bool to int and cause compiler warnings + map->foreachnpc(npc->unload_dup_sub, nd->bl.id, unload_mobs ? 1 : 0); +} + +//Removes mobs spawned by NPC (monster/areamonster/guardian/bg_monster/atcommand("@monster xy")) +static int npc_unload_mob(struct mob_data *md, va_list args) +{ + nullpo_ret(md); + int npc_id = va_arg(args, int); + + if (md->npc_id == npc_id) { + md->state.npc_killmonster = 1; + status_kill(&md->bl); + return 1; + } + + return 0; } //Removes an npc from map and db. //Single is to free name (for duplicates). -static int npc_unload(struct npc_data *nd, bool single) +static int npc_unload(struct npc_data *nd, bool single, bool unload_mobs) { nullpo_ret(nd); @@ -2991,6 +3008,12 @@ static int npc_unload(struct npc_data *nd, bool single) struct s_mapiterator *iter; struct map_session_data *sd = NULL; + char evname[EVENT_NAME_LENGTH]; + struct event_data *ev; + snprintf(evname, ARRAYLENGTH(evname), "%s::OnNPCUnload", nd->exname); + if ((ev = (struct event_data*)strdb_get(npc->ev_db, evname)) != NULL) + script->run_npc(nd->u.scr.script, ev->pos, 0, nd->bl.id); // Run OnNPCUnload + if( single ) { npc->ev_db->foreach(npc->ev_db,npc->unload_ev,nd->exname); //Clean up all events related npc->ev_label_db->foreach(npc->ev_label_db,npc->unload_ev_label,nd); @@ -3051,6 +3074,9 @@ static int npc_unload(struct npc_data *nd, bool single) nd->ud = NULL; } + if (unload_mobs) + map->foreachmob(npc->unload_mob, nd->bl.id); + HPM->data_store_destroy(&nd->hdata); aFree(nd); @@ -4442,7 +4468,7 @@ static void npc_parse_mob2(struct spawn_data *mobspawn) nullpo_retv(mobspawn); for( i = mobspawn->active; i < mobspawn->num; ++i ) { - struct mob_data* md = mob->spawn_dataset(mobspawn); + struct mob_data *md = mob->spawn_dataset(mobspawn, 0); md->spawn = mobspawn; md->spawn->active++; mob->spawn(md); @@ -5528,7 +5554,7 @@ static int npc_reload(void) switch(bl->type) { case BL_NPC: if( bl->id != npc->fake_nd->bl.id )// don't remove fake_nd - npc->unload(BL_UCAST(BL_NPC, bl), false); + npc->unload(BL_UCAST(BL_NPC, bl), false, false); break; case BL_MOB: unit->free(bl,CLR_OUTSIGHT); @@ -5603,7 +5629,7 @@ static int npc_reload(void) } //Unload all npc in the given file -static bool npc_unloadfile(const char *filepath) +static bool npc_unloadfile(const char *filepath, bool unload_mobs) { struct DBIterator *iter = db_iterator(npc->name_db); struct npc_data* nd = NULL; @@ -5614,8 +5640,8 @@ static bool npc_unloadfile(const char *filepath) for( nd = dbi_first(iter); dbi_exists(iter); nd = dbi_next(iter) ) { if( nd->path && strcasecmp(nd->path,filepath) == 0 ) { // FIXME: This can break in case-sensitive file systems found = true; - npc->unload_duplicates(nd);/* unload any npcs which could duplicate this but be in a different file */ - npc->unload(nd, true); + npc->unload_duplicates(nd, unload_mobs);/* unload any npcs which could duplicate this but be in a different file */ + npc->unload(nd, true, unload_mobs); } } @@ -5854,6 +5880,7 @@ void npc_defaults(void) npc->unload_ev_label = npc_unload_ev_label; npc->unload_dup_sub = npc_unload_dup_sub; npc->unload_duplicates = npc_unload_duplicates; + npc->unload_mob = npc_unload_mob; npc->unload = npc_unload; npc->clearsrcfile = npc_clearsrcfile; npc->addsrcfile = npc_addsrcfile; diff --git a/src/map/npc.h b/src/map/npc.h index 392911046..65c9796d9 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -270,8 +270,9 @@ struct npc_interface { int (*unload_ev) (union DBKey key, struct DBData *data, va_list ap); int (*unload_ev_label) (union DBKey key, struct DBData *data, va_list ap); int (*unload_dup_sub) (struct npc_data *nd, va_list args); - void (*unload_duplicates) (struct npc_data *nd); - int (*unload) (struct npc_data *nd, bool single); + void (*unload_duplicates) (struct npc_data *nd, bool unload_mobs); + int (*unload_mob) (struct mob_data *md, va_list args); + int (*unload) (struct npc_data *nd, bool single, bool unload_mobs); void (*clearsrcfile) (void); void (*addsrcfile) (const char *name); void (*delsrcfile) (const char *name); @@ -313,7 +314,7 @@ struct npc_interface { int (*path_db_clear_sub) (union DBKey key, struct DBData *data, va_list args); int (*ev_label_db_clear_sub) (union DBKey key, struct DBData *data, va_list args); int (*reload) (void); - bool (*unloadfile) (const char *filepath); + bool (*unloadfile) (const char *filepath, bool unload_mobs); void (*do_clear_npc) (void); void (*debug_warps_sub) (struct npc_data *nd); void (*debug_warps) (void); diff --git a/src/map/script.c b/src/map/script.c index 1d5919d3b..fe8052c65 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -14565,7 +14565,7 @@ static BUILDIN(guardian) } script->check_event(st, evt); - script_pushint(st, mob->spawn_guardian(mapname,x,y,str,class_,evt,guardian,has_index)); + script_pushint(st, mob->spawn_guardian(mapname, x, y, str, class_, evt, guardian, has_index, st->oid)); return true; } @@ -16915,7 +16915,7 @@ static BUILDIN(summon) clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick); - md = mob->once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, class_, event, SZ_SMALL, AI_NONE); + md = mob->once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, class_, event, SZ_SMALL, AI_NONE, 0); if (md) { md->master_id=sd->bl.id; md->special_state.ai = AI_ATTACK; @@ -22353,7 +22353,7 @@ static BUILDIN(bg_monster) class_ = script_getnum(st,7); if( script_hasdata(st,8) ) evt = script_getstr(st,8); script->check_event(st, evt); - script_pushint(st, mob->spawn_bg(mapname,x,y,str,class_,evt,bg_id)); + script_pushint(st, mob->spawn_bg(mapname, x, y, str, class_, evt, bg_id, st->oid)); return true; } diff --git a/src/map/skill.c b/src/map/skill.c index 09e216804..a488e3eaf 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -10417,7 +10417,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * if(sd) { struct mob_data *summon_md; - summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, clif->get_bl_name(src), MOBID_KO_KAGE, "", SZ_SMALL, AI_NONE); + summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, clif->get_bl_name(src), MOBID_KO_KAGE, "", SZ_SMALL, AI_NONE, 0); if( summon_md ) { summon_md->master_id = src->id; summon_md->special_state.ai = AI_ZANZOU; @@ -10600,7 +10600,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * for (i = 0; i < summons[skill_lv-1].quantity; i++) { struct mob_data *summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, clif->get_bl_name(src), - summons[skill_lv-1].mob_id, "", SZ_SMALL, AI_ATTACK); + summons[skill_lv-1].mob_id, "", SZ_SMALL, AI_ATTACK, 0); if (summon_md != NULL) { summon_md->master_id = src->id; if (summon_md->deletetimer != INVALID_TIMER) @@ -11383,7 +11383,7 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill } // Correct info, don't change any of this! [Celest] - md = mob->once_spawn_sub(src, src->m, x, y, clif->get_bl_name(src), class_, "", SZ_SMALL, AI_NONE); + md = mob->once_spawn_sub(src, src->m, x, y, clif->get_bl_name(src), class_, "", SZ_SMALL, AI_NONE, 0); if (md) { md->master_id = src->id; md->special_state.ai = (skill_id == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA; @@ -11485,7 +11485,7 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0); } else { int mob_id = skill_lv < 2 ? MOBID_BLACK_MUSHROOM + rnd()%2 : MOBID_RED_PLANT + rnd()%6; - struct mob_data *md = mob->once_spawn_sub(src, src->m, x, y, DEFAULT_MOB_JNAME, mob_id, "", SZ_SMALL, AI_NONE); + struct mob_data *md = mob->once_spawn_sub(src, src->m, x, y, DEFAULT_MOB_JNAME, mob_id, "", SZ_SMALL, AI_NONE, 0); int i; if (md == NULL) break; @@ -11631,7 +11631,7 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill case NC_SILVERSNIPER: { - struct mob_data *md = mob->once_spawn_sub(src, src->m, x, y, clif->get_bl_name(src), MOBID_SILVERSNIPER, "", SZ_SMALL, AI_NONE); + struct mob_data *md = mob->once_spawn_sub(src, src->m, x, y, clif->get_bl_name(src), MOBID_SILVERSNIPER, "", SZ_SMALL, AI_NONE, 0); if (md) { md->master_id = src->id; md->special_state.ai = AI_FLORA; @@ -18793,7 +18793,7 @@ static int skill_magicdecoy(struct map_session_data *sd, int nameid) break; } - md = mob->once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_SMALL, AI_NONE); + md = mob->once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_SMALL, AI_NONE, 0); if( md ) { md->master_id = sd->bl.id; md->special_state.ai = AI_FLORA; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc index f8a25a649..b5f04af50 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc @@ -4278,6 +4278,8 @@ struct { struct HPMHookPoint *HP_npc_unload_dup_sub_post; struct HPMHookPoint *HP_npc_unload_duplicates_pre; struct HPMHookPoint *HP_npc_unload_duplicates_post; + struct HPMHookPoint *HP_npc_unload_mob_pre; + struct HPMHookPoint *HP_npc_unload_mob_post; struct HPMHookPoint *HP_npc_unload_pre; struct HPMHookPoint *HP_npc_unload_post; struct HPMHookPoint *HP_npc_clearsrcfile_pre; @@ -11141,6 +11143,8 @@ struct { int HP_npc_unload_dup_sub_post; int HP_npc_unload_duplicates_pre; int HP_npc_unload_duplicates_post; + int HP_npc_unload_mob_pre; + int HP_npc_unload_mob_post; int HP_npc_unload_pre; int HP_npc_unload_post; int HP_npc_clearsrcfile_pre; diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc index 7af336fdc..1967f8c82 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc @@ -2191,6 +2191,7 @@ struct HookingPointData HookingPoints[] = { { HP_POP(npc->unload_ev_label, HP_npc_unload_ev_label) }, { HP_POP(npc->unload_dup_sub, HP_npc_unload_dup_sub) }, { HP_POP(npc->unload_duplicates, HP_npc_unload_duplicates) }, + { HP_POP(npc->unload_mob, HP_npc_unload_mob) }, { HP_POP(npc->unload, HP_npc_unload) }, { HP_POP(npc->clearsrcfile, HP_npc_clearsrcfile) }, { HP_POP(npc->addsrcfile, HP_npc_addsrcfile) }, diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc index ccc11d52b..d7d183f28 100644 --- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc +++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc @@ -52027,15 +52027,15 @@ int HP_mob_parse_dataset(struct spawn_data *data) { } return retVal___; } -struct mob_data* HP_mob_spawn_dataset(struct spawn_data *data) { +struct mob_data* HP_mob_spawn_dataset(struct spawn_data *data, int npc_id) { int hIndex = 0; struct mob_data* retVal___ = NULL; if (HPMHooks.count.HP_mob_spawn_dataset_pre > 0) { - struct mob_data* (*preHookFunc) (struct spawn_data **data); + struct mob_data* (*preHookFunc) (struct spawn_data **data, int *npc_id); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_spawn_dataset_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_mob_spawn_dataset_pre[hIndex].func; - retVal___ = preHookFunc(&data); + retVal___ = preHookFunc(&data, &npc_id); } if (*HPMforce_return) { *HPMforce_return = false; @@ -52043,13 +52043,13 @@ struct mob_data* HP_mob_spawn_dataset(struct spawn_data *data) { } } { - retVal___ = HPMHooks.source.mob.spawn_dataset(data); + retVal___ = HPMHooks.source.mob.spawn_dataset(data, npc_id); } if (HPMHooks.count.HP_mob_spawn_dataset_post > 0) { - struct mob_data* (*postHookFunc) (struct mob_data* retVal___, struct spawn_data *data); + struct mob_data* (*postHookFunc) (struct mob_data* retVal___, struct spawn_data *data, int npc_id); for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_spawn_dataset_post; hIndex++) { postHookFunc = HPMHooks.list.HP_mob_spawn_dataset_post[hIndex].func; - retVal___ = postHookFunc(retVal___, data); + retVal___ = postHookFunc(retVal___, data, npc_id); } } return retVal___; @@ -52108,15 +52108,15 @@ bool HP_mob_ksprotected(struct block_list *src, struct block_list *target) { } return retVal___; } -struct mob_data* HP_mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai) { +struct mob_data* HP_mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai, int npc_id) { int hIndex = 0; struct mob_data* retVal___ = NULL; if (HPMHooks.count.HP_mob_once_spawn_sub_pre > 0) { - struct mob_data* (*preHookFunc) (struct block_list **bl, int16 *m, int16 *x, int16 *y, const char **mobname, int *class_, const char **event, unsigned int *size, unsigned int *ai); + struct mob_data* (*preHookFunc) (struct block_list **bl, int16 *m, int16 *x, int16 *y, const char **mobname, int *class_, const char **event, unsigned int *size, unsigned int *ai, int *npc_id); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_once_spawn_sub_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_mob_once_spawn_sub_pre[hIndex].func; - retVal___ = preHookFunc(&bl, &m, &x, &y, &mobname, &class_, &event, &size, &ai); + retVal___ = preHookFunc(&bl, &m, &x, &y, &mobname, &class_, &event, &size, &ai, &npc_id); } if (*HPMforce_return) { *HPMforce_return = false; @@ -52124,13 +52124,13 @@ struct mob_data* HP_mob_once_spawn_sub(struct block_list *bl, int16 m, int16 x, } } { - retVal___ = HPMHooks.source.mob.once_spawn_sub(bl, m, x, y, mobname, class_, event, size, ai); + retVal___ = HPMHooks.source.mob.once_spawn_sub(bl, m, x, y, mobname, class_, event, size, ai, npc_id); } if (HPMHooks.count.HP_mob_once_spawn_sub_post > 0) { - struct mob_data* (*postHookFunc) (struct mob_data* retVal___, struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai); + struct mob_data* (*postHookFunc) (struct mob_data* retVal___, struct block_list *bl, int16 m, int16 x, int16 y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai, int npc_id); for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_once_spawn_sub_post; hIndex++) { postHookFunc = HPMHooks.list.HP_mob_once_spawn_sub_post[hIndex].func; - retVal___ = postHookFunc(retVal___, bl, m, x, y, mobname, class_, event, size, ai); + retVal___ = postHookFunc(retVal___, bl, m, x, y, mobname, class_, event, size, ai, npc_id); } } return retVal___; @@ -52189,15 +52189,15 @@ int HP_mob_once_spawn_area(struct map_session_data *sd, int16 m, int16 x0, int16 } return retVal___; } -int HP_mob_spawn_guardian(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index) { +int HP_mob_spawn_guardian(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index, int npc_id) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_mob_spawn_guardian_pre > 0) { - int (*preHookFunc) (const char **mapname, short *x, short *y, const char **mobname, int *class_, const char **event, int *guardian, bool *has_index); + int (*preHookFunc) (const char **mapname, short *x, short *y, const char **mobname, int *class_, const char **event, int *guardian, bool *has_index, int *npc_id); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_spawn_guardian_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_mob_spawn_guardian_pre[hIndex].func; - retVal___ = preHookFunc(&mapname, &x, &y, &mobname, &class_, &event, &guardian, &has_index); + retVal___ = preHookFunc(&mapname, &x, &y, &mobname, &class_, &event, &guardian, &has_index, &npc_id); } if (*HPMforce_return) { *HPMforce_return = false; @@ -52205,26 +52205,26 @@ int HP_mob_spawn_guardian(const char *mapname, short x, short y, const char *mob } } { - retVal___ = HPMHooks.source.mob.spawn_guardian(mapname, x, y, mobname, class_, event, guardian, has_index); + retVal___ = HPMHooks.source.mob.spawn_guardian(mapname, x, y, mobname, class_, event, guardian, has_index, npc_id); } if (HPMHooks.count.HP_mob_spawn_guardian_post > 0) { - int (*postHookFunc) (int retVal___, const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index); + int (*postHookFunc) (int retVal___, const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index, int npc_id); for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_spawn_guardian_post; hIndex++) { postHookFunc = HPMHooks.list.HP_mob_spawn_guardian_post[hIndex].func; - retVal___ = postHookFunc(retVal___, mapname, x, y, mobname, class_, event, guardian, has_index); + retVal___ = postHookFunc(retVal___, mapname, x, y, mobname, class_, event, guardian, has_index, npc_id); } } return retVal___; } -int HP_mob_spawn_bg(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id) { +int HP_mob_spawn_bg(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id, int npc_id) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_mob_spawn_bg_pre > 0) { - int (*preHookFunc) (const char **mapname, short *x, short *y, const char **mobname, int *class_, const char **event, unsigned int *bg_id); + int (*preHookFunc) (const char **mapname, short *x, short *y, const char **mobname, int *class_, const char **event, unsigned int *bg_id, int *npc_id); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_spawn_bg_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_mob_spawn_bg_pre[hIndex].func; - retVal___ = preHookFunc(&mapname, &x, &y, &mobname, &class_, &event, &bg_id); + retVal___ = preHookFunc(&mapname, &x, &y, &mobname, &class_, &event, &bg_id, &npc_id); } if (*HPMforce_return) { *HPMforce_return = false; @@ -52232,13 +52232,13 @@ int HP_mob_spawn_bg(const char *mapname, short x, short y, const char *mobname, } } { - retVal___ = HPMHooks.source.mob.spawn_bg(mapname, x, y, mobname, class_, event, bg_id); + retVal___ = HPMHooks.source.mob.spawn_bg(mapname, x, y, mobname, class_, event, bg_id, npc_id); } if (HPMHooks.count.HP_mob_spawn_bg_post > 0) { - int (*postHookFunc) (int retVal___, const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id); + int (*postHookFunc) (int retVal___, const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id, int npc_id); for (hIndex = 0; hIndex < HPMHooks.count.HP_mob_spawn_bg_post; hIndex++) { postHookFunc = HPMHooks.list.HP_mob_spawn_bg_post[hIndex].func; - retVal___ = postHookFunc(retVal___, mapname, x, y, mobname, class_, event, bg_id); + retVal___ = postHookFunc(retVal___, mapname, x, y, mobname, class_, event, bg_id, npc_id); } } return retVal___; @@ -56785,14 +56785,14 @@ int HP_npc_unload_dup_sub(struct npc_data *nd, va_list args) { } return retVal___; } -void HP_npc_unload_duplicates(struct npc_data *nd) { +void HP_npc_unload_duplicates(struct npc_data *nd, bool unload_mobs) { int hIndex = 0; if (HPMHooks.count.HP_npc_unload_duplicates_pre > 0) { - void (*preHookFunc) (struct npc_data **nd); + void (*preHookFunc) (struct npc_data **nd, bool *unload_mobs); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_npc_unload_duplicates_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_npc_unload_duplicates_pre[hIndex].func; - preHookFunc(&nd); + preHookFunc(&nd, &unload_mobs); } if (*HPMforce_return) { *HPMforce_return = false; @@ -56800,26 +56800,59 @@ void HP_npc_unload_duplicates(struct npc_data *nd) { } } { - HPMHooks.source.npc.unload_duplicates(nd); + HPMHooks.source.npc.unload_duplicates(nd, unload_mobs); } if (HPMHooks.count.HP_npc_unload_duplicates_post > 0) { - void (*postHookFunc) (struct npc_data *nd); + void (*postHookFunc) (struct npc_data *nd, bool unload_mobs); for (hIndex = 0; hIndex < HPMHooks.count.HP_npc_unload_duplicates_post; hIndex++) { postHookFunc = HPMHooks.list.HP_npc_unload_duplicates_post[hIndex].func; - postHookFunc(nd); + postHookFunc(nd, unload_mobs); } } return; } -int HP_npc_unload(struct npc_data *nd, bool single) { +int HP_npc_unload_mob(struct mob_data *md, va_list args) { + int hIndex = 0; + int retVal___ = 0; + if (HPMHooks.count.HP_npc_unload_mob_pre > 0) { + int (*preHookFunc) (struct mob_data **md, va_list args); + *HPMforce_return = false; + for (hIndex = 0; hIndex < HPMHooks.count.HP_npc_unload_mob_pre; hIndex++) { + va_list args___copy; va_copy(args___copy, args); + preHookFunc = HPMHooks.list.HP_npc_unload_mob_pre[hIndex].func; + retVal___ = preHookFunc(&md, args___copy); + va_end(args___copy); + } + if (*HPMforce_return) { + *HPMforce_return = false; + return retVal___; + } + } + { + va_list args___copy; va_copy(args___copy, args); + retVal___ = HPMHooks.source.npc.unload_mob(md, args___copy); + va_end(args___copy); + } + if (HPMHooks.count.HP_npc_unload_mob_post > 0) { + int (*postHookFunc) (int retVal___, struct mob_data *md, va_list args); + for (hIndex = 0; hIndex < HPMHooks.count.HP_npc_unload_mob_post; hIndex++) { + va_list args___copy; va_copy(args___copy, args); + postHookFunc = HPMHooks.list.HP_npc_unload_mob_post[hIndex].func; + retVal___ = postHookFunc(retVal___, md, args___copy); + va_end(args___copy); + } + } + return retVal___; +} +int HP_npc_unload(struct npc_data *nd, bool single, bool unload_mobs) { int hIndex = 0; int retVal___ = 0; if (HPMHooks.count.HP_npc_unload_pre > 0) { - int (*preHookFunc) (struct npc_data **nd, bool *single); + int (*preHookFunc) (struct npc_data **nd, bool *single, bool *unload_mobs); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_npc_unload_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_npc_unload_pre[hIndex].func; - retVal___ = preHookFunc(&nd, &single); + retVal___ = preHookFunc(&nd, &single, &unload_mobs); } if (*HPMforce_return) { *HPMforce_return = false; @@ -56827,13 +56860,13 @@ int HP_npc_unload(struct npc_data *nd, bool single) { } } { - retVal___ = HPMHooks.source.npc.unload(nd, single); + retVal___ = HPMHooks.source.npc.unload(nd, single, unload_mobs); } if (HPMHooks.count.HP_npc_unload_post > 0) { - int (*postHookFunc) (int retVal___, struct npc_data *nd, bool single); + int (*postHookFunc) (int retVal___, struct npc_data *nd, bool single, bool unload_mobs); for (hIndex = 0; hIndex < HPMHooks.count.HP_npc_unload_post; hIndex++) { postHookFunc = HPMHooks.list.HP_npc_unload_post[hIndex].func; - retVal___ = postHookFunc(retVal___, nd, single); + retVal___ = postHookFunc(retVal___, nd, single, unload_mobs); } } return retVal___; @@ -57948,15 +57981,15 @@ int HP_npc_reload(void) { } return retVal___; } -bool HP_npc_unloadfile(const char *filepath) { +bool HP_npc_unloadfile(const char *filepath, bool unload_mobs) { int hIndex = 0; bool retVal___ = false; if (HPMHooks.count.HP_npc_unloadfile_pre > 0) { - bool (*preHookFunc) (const char **filepath); + bool (*preHookFunc) (const char **filepath, bool *unload_mobs); *HPMforce_return = false; for (hIndex = 0; hIndex < HPMHooks.count.HP_npc_unloadfile_pre; hIndex++) { preHookFunc = HPMHooks.list.HP_npc_unloadfile_pre[hIndex].func; - retVal___ = preHookFunc(&filepath); + retVal___ = preHookFunc(&filepath, &unload_mobs); } if (*HPMforce_return) { *HPMforce_return = false; @@ -57964,13 +57997,13 @@ bool HP_npc_unloadfile(const char *filepath) { } } { - retVal___ = HPMHooks.source.npc.unloadfile(filepath); + retVal___ = HPMHooks.source.npc.unloadfile(filepath, unload_mobs); } if (HPMHooks.count.HP_npc_unloadfile_post > 0) { - bool (*postHookFunc) (bool retVal___, const char *filepath); + bool (*postHookFunc) (bool retVal___, const char *filepath, bool unload_mobs); for (hIndex = 0; hIndex < HPMHooks.count.HP_npc_unloadfile_post; hIndex++) { postHookFunc = HPMHooks.list.HP_npc_unloadfile_post[hIndex].func; - retVal___ = postHookFunc(retVal___, filepath); + retVal___ = postHookFunc(retVal___, filepath, unload_mobs); } } return retVal___; -- cgit v1.2.3-70-g09d2