summaryrefslogtreecommitdiff
path: root/src/map/npc.c
diff options
context:
space:
mode:
authorKenpachi Developer <Kenpachi.Developer@gmx.de>2019-11-27 02:50:08 +0100
committerHaru <haru@dotalux.com>2020-02-09 20:19:12 +0100
commit30c175a9041a17e0d2ef1d4750163c19ab3a7959 (patch)
tree8d4accec56aa49efaf40e2e4d3b8ac40a03f0259 /src/map/npc.c
parentc76c63d2dddb8c7ec4461dd660b7bb0210f4db96 (diff)
downloadhercules-30c175a9041a17e0d2ef1d4750163c19ab3a7959.tar.gz
hercules-30c175a9041a17e0d2ef1d4750163c19ab3a7959.tar.bz2
hercules-30c175a9041a17e0d2ef1d4750163c19ab3a7959.tar.xz
hercules-30c175a9041a17e0d2ef1d4750163c19ab3a7959.zip
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.
Diffstat (limited to 'src/map/npc.c')
-rw-r--r--src/map/npc.c51
1 files changed, 39 insertions, 12 deletions
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;