diff options
Diffstat (limited to 'src/map/npc.cpp')
-rw-r--r-- | src/map/npc.cpp | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/src/map/npc.cpp b/src/map/npc.cpp index ee2f30c..7d3e62b 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -357,7 +357,7 @@ void npc_eventtimer(TimerData *, tick_t, BlockId, NpcEvent data) data); return; }); - if ((nd = ev->nd) == nullptr || nd->deletion_pending == true) + if ((nd = ev->nd) == nullptr || nd->deletion_pending != npc_data::NOT_DELETING) { if (battle_config.error_log) PRINTF("npc_event: event not found [%s]\n"_fmt, @@ -591,7 +591,7 @@ int npc_event(dumb_ptr<map_session_data> sd, NpcEvent eventname, ev.pos = ev2->pos; } - if ((nd = ev.nd) == nullptr || nd->deletion_pending == true) + if ((nd = ev.nd) == nullptr || nd->deletion_pending != npc_data::NOT_DELETING) { if (!mob_kill && battle_config.error_log) PRINTF("npc_event: event not found [%s]\n"_fmt, @@ -767,13 +767,22 @@ int npc_click(dumb_ptr<map_session_data> sd, BlockId id) } } - if (npc_checknear(sd, id)) { + if (npc_checknear(sd, id)) + { clif_scriptclose(sd, id); return 1; } nd = map_id_is_npc(id); + // If someone clicked on an NPC that is about to no longer exist, then + // release them + if (nd->deletion_pending != npc_data::NOT_DELETING) + { + clif_scriptclose(sd, id); + return 1; + } + if (nd->flag & 1) // 無効化されている return 1; @@ -818,18 +827,19 @@ int npc_scriptcont(dumb_ptr<map_session_data> sd, BlockId id) nd = map_id_is_npc(id); - if (!nd /* NPC was disposed? */) + // If the NPC is about to be deleted, release the PC + if (nd->deletion_pending != npc_data::NOT_DELETING) { clif_scriptclose(sd, id); npc_event_dequeue(sd); - return 0; + return 1; } if (nd->is_script()->scr.parent && map_id2bl(nd->is_script()->scr.parent) == nullptr) { npc_free(nd); - return 0; + return 1; } sd->npc_pos = run_script(ScriptPointer(script_or_parent(nd->is_script()), sd->npc_pos), sd->bl_id, id); @@ -1050,6 +1060,23 @@ void npc_free_internal(dumb_ptr<npc_data> nd_) nd_->bl_m->npc[nd_->n] = nullptr; } + // Also clean up any events we registered to the global ev_db + if (auto nd = nd_->is_script()) + { + std::vector<NpcEvent> to_erase; + for (auto& pair : ev_db) + { + if (pair.second.nd == nd) + { + to_erase.push_back(pair.first); + } + } + for (auto& key : to_erase) + { + ev_db.erase(key); + } + } + nd_.delete_(); } @@ -1074,10 +1101,10 @@ void npc_propagate_update(dumb_ptr<npc_data> nd) void npc_free(dumb_ptr<npc_data> nd) { - if (nd == nullptr || nd->deletion_pending == true) + if (nd == nullptr || nd->deletion_pending == npc_data::DELETION_ACTIVE) return; - nd->deletion_pending = true; + nd->deletion_pending = npc_data::DELETION_ACTIVE; nd->flag |= 1; clif_clearchar(nd, BeingRemoveWhy::GONE); npc_propagate_update(nd); |