[Quest API] Add Despawn Events to Perl/Lua. (#2707)

# Perl
- Add `$bot->GetBotID()`.
- Add `EVENT_DESPAWN`.
- Add `EVENT_DESPAWN_ZONE`.

# Lua
- Add `bot:GetBotID()`.
- Add `event_despawn`.
- Add `event_despawn_zone`.

# Notes
- Allows operators to determine when a Bot or an NPC has been despawned via Depop.
- Bots call NPC::Depop on ^camp so we just put the code there.
- Adds the ability to get a bot's ID using their reference in case you're looping a list and need that value.
- Moves `DispatchZoneControllerEvent` from NPC to Mob so it can be used by any type.
This commit is contained in:
Alex King 2023-01-07 12:04:33 -05:00 committed by GitHub
parent 143c4fe6aa
commit c1ad086eaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 120 additions and 37 deletions

View File

@ -8762,6 +8762,8 @@ void EntityList::AddBot(Bot *new_bot, bool send_spawn_packet, bool dont_queue) {
} }
parse->EventBot(EVENT_SPAWN, new_bot, nullptr, "", 0); parse->EventBot(EVENT_SPAWN, new_bot, nullptr, "", 0);
new_bot->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, new_bot, "", 0, nullptr);
} }
bot_list.push_back(new_bot); bot_list.push_back(new_bot);

View File

@ -166,6 +166,8 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_PAYLOAD", "EVENT_PAYLOAD",
"EVENT_LEVEL_DOWN", "EVENT_LEVEL_DOWN",
"EVENT_GM_COMMAND", "EVENT_GM_COMMAND",
"EVENT_DESPAWN",
"EVENT_DESPAWN_ZONE",
#ifdef BOTS #ifdef BOTS
"EVENT_SPELL_EFFECT_BOT", "EVENT_SPELL_EFFECT_BOT",
"EVENT_SPELL_EFFECT_BUFF_TIC_BOT", "EVENT_SPELL_EFFECT_BUFF_TIC_BOT",
@ -1838,7 +1840,18 @@ void PerlembParser::ExportEventVariables(
NPC* killed = std::any_cast<NPC*>(extra_pointers->at(1)); NPC* killed = std::any_cast<NPC*>(extra_pointers->at(1));
if (killed) if (killed)
{ {
ExportVar(package_name.c_str(), "killed_npc_id", killed->GetNPCTypeID()); ExportVar(package_name.c_str(), "killed_entity_id", killed->GetID());
if (killed->IsNPC()) {
ExportVar(package_name.c_str(), "killed_bot_id", 0);
ExportVar(package_name.c_str(), "killed_npc_id", killed->GetNPCTypeID());
#ifdef BOTS
} else if (killed->IsBot()) {
ExportVar(package_name.c_str(), "killed_bot_id", killed->CastToBot()->GetBotID());
ExportVar(package_name.c_str(), "killed_npc_id", 0);
#endif
}
ExportVar(package_name.c_str(), "killed_x", killed->GetX()); ExportVar(package_name.c_str(), "killed_x", killed->GetX());
ExportVar(package_name.c_str(), "killed_y", killed->GetY()); ExportVar(package_name.c_str(), "killed_y", killed->GetY());
ExportVar(package_name.c_str(), "killed_z", killed->GetZ()); ExportVar(package_name.c_str(), "killed_z", killed->GetZ());
@ -1859,7 +1872,17 @@ void PerlembParser::ExportEventVariables(
case EVENT_SPAWN_ZONE: { case EVENT_SPAWN_ZONE: {
ExportVar(package_name.c_str(), "spawned_entity_id", mob->GetID()); ExportVar(package_name.c_str(), "spawned_entity_id", mob->GetID());
ExportVar(package_name.c_str(), "spawned_npc_id", mob->GetNPCTypeID());
if (mob->IsNPC()) {
ExportVar(package_name.c_str(), "spawned_bot_id", 0);
ExportVar(package_name.c_str(), "spawned_npc_id", mob->GetNPCTypeID());
#ifdef BOTS
} else if (mob->IsBot()) {
ExportVar(package_name.c_str(), "spawned_bot_id", mob->CastToBot()->GetBotID());
ExportVar(package_name.c_str(), "spawned_npc_id", 0);
#endif
}
break; break;
} }
@ -2013,6 +2036,22 @@ void PerlembParser::ExportEventVariables(
break; break;
} }
case EVENT_DESPAWN_ZONE: {
ExportVar(package_name.c_str(), "despawned_entity_id", mob->GetID());
if (mob->IsNPC()) {
ExportVar(package_name.c_str(), "despawned_bot_id", 0);
ExportVar(package_name.c_str(), "despawned_npc_id", mob->GetNPCTypeID());
#ifdef BOTS
} else if (mob->IsBot()) {
ExportVar(package_name.c_str(), "despawned_bot_id", mob->CastToBot()->GetBotID());
ExportVar(package_name.c_str(), "despawned_npc_id", 0);
#endif
}
break;
}
default: { default: {
break; break;
} }

View File

@ -109,6 +109,8 @@ typedef enum {
EVENT_PAYLOAD, EVENT_PAYLOAD,
EVENT_LEVEL_DOWN, EVENT_LEVEL_DOWN,
EVENT_GM_COMMAND, EVENT_GM_COMMAND,
EVENT_DESPAWN,
EVENT_DESPAWN_ZONE,
#ifdef BOTS #ifdef BOTS
EVENT_SPELL_EFFECT_BOT, EVENT_SPELL_EFFECT_BOT,
EVENT_SPELL_EFFECT_BUFF_TIC_BOT, EVENT_SPELL_EFFECT_BUFF_TIC_BOT,

View File

@ -355,6 +355,11 @@ void Lua_Bot::Stand() {
self->Stand(); self->Stand();
} }
uint32 Lua_Bot::GetBotID() {
Lua_Safe_Call_Int();
return self->GetBotID();
}
luabind::scope lua_register_bot() { luabind::scope lua_register_bot() {
return luabind::class_<Lua_Bot, Lua_Mob>("Bot") return luabind::class_<Lua_Bot, Lua_Mob>("Bot")
.def(luabind::constructor<>()) .def(luabind::constructor<>())
@ -390,6 +395,7 @@ luabind::scope lua_register_bot() {
.def("GetBaseSTA", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseSTA) .def("GetBaseSTA", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseSTA)
.def("GetBaseSTR", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseSTR) .def("GetBaseSTR", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseSTR)
.def("GetBaseWIS", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseWIS) .def("GetBaseWIS", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseWIS)
.def("GetBotID", (uint32(Lua_Bot::*)(void))&Lua_Bot::GetBotID)
.def("GetBotItem", (Lua_ItemInst(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItem) .def("GetBotItem", (Lua_ItemInst(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItem)
.def("GetBotItemIDBySlot", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItemIDBySlot) .def("GetBotItemIDBySlot", (uint32(Lua_Bot::*)(uint16))&Lua_Bot::GetBotItemIDBySlot)
.def("GetExpansionBitmask", (int(Lua_Bot::*)(void))&Lua_Bot::GetExpansionBitmask) .def("GetExpansionBitmask", (int(Lua_Bot::*)(void))&Lua_Bot::GetExpansionBitmask)

View File

@ -55,6 +55,7 @@ public:
bool HasBotSpellEntry(uint16 spellid); bool HasBotSpellEntry(uint16 spellid);
void SendPayload(int payload_id); void SendPayload(int payload_id);
void SendPayload(int payload_id, std::string payload_value); void SendPayload(int payload_id, std::string payload_value);
uint32 GetBotID();
void ApplySpell(int spell_id); void ApplySpell(int spell_id);
void ApplySpell(int spell_id, int duration); void ApplySpell(int spell_id, int duration);

View File

@ -4615,7 +4615,9 @@ luabind::scope lua_register_events() {
luabind::value("aa_gain", static_cast<int>(EVENT_AA_GAIN)), luabind::value("aa_gain", static_cast<int>(EVENT_AA_GAIN)),
luabind::value("payload", static_cast<int>(EVENT_PAYLOAD)), luabind::value("payload", static_cast<int>(EVENT_PAYLOAD)),
luabind::value("level_down", static_cast<int>(EVENT_LEVEL_DOWN)), luabind::value("level_down", static_cast<int>(EVENT_LEVEL_DOWN)),
luabind::value("gm_command", static_cast<int>(EVENT_GM_COMMAND)) luabind::value("gm_command", static_cast<int>(EVENT_GM_COMMAND)),
luabind::value("despawn", static_cast<int>(EVENT_DESPAWN)),
luabind::value("despawn_zone", static_cast<int>(EVENT_DESPAWN_ZONE))
)]; )];
} }

View File

@ -152,7 +152,9 @@ const char *LuaEvents[_LargestEventID] = {
"event_aa_gain", "event_aa_gain",
"event_payload", "event_payload",
"event_level_down", "event_level_down",
"event_gm_command" "event_gm_command",
"event_despawn",
"event_despawn_zone",
}; };
extern Zone *zone; extern Zone *zone;

View File

@ -7041,3 +7041,28 @@ void Mob::CopyHateList(Mob* to) {
} }
} }
} }
int Mob::DispatchZoneControllerEvent(
QuestEventID evt,
Mob* init,
const std::string& data,
uint32 extra,
std::vector<std::any>* pointers
) {
auto ret = 0;
if (
RuleB(Zone, UseZoneController) &&
(
!IsNPC() ||
(IsNPC() && GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID)
)
) {
auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID);
if (controller) {
ret = parse->EventNPC(evt, controller, init, data, extra, pointers);
}
}
return ret;
}

View File

@ -29,6 +29,9 @@
#include "../common/light_source.h" #include "../common/light_source.h"
#include "../common/emu_constants.h" #include "../common/emu_constants.h"
#include "combat_record.h" #include "combat_record.h"
#include "event_codes.h"
#include <any>
#include <set> #include <set>
#include <vector> #include <vector>
#include <memory> #include <memory>
@ -1432,6 +1435,8 @@ public:
std::string GetBucketRemaining(std::string bucket_name); std::string GetBucketRemaining(std::string bucket_name);
void SetBucket(std::string bucket_name, std::string bucket_value, std::string expiration = ""); void SetBucket(std::string bucket_name, std::string bucket_value, std::string expiration = "");
int DispatchZoneControllerEvent(QuestEventID evt, Mob* init, const std::string& data, uint32 extra, std::vector<std::any>* pointers);
#ifdef BOTS #ifdef BOTS
// Bots HealRotation methods // Bots HealRotation methods
bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); } bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); }

View File

@ -1111,14 +1111,25 @@ void NPC::UpdateEquipmentLight()
m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]); m_Light.Level[EQ::lightsource::LightEquipment] = EQ::lightsource::TypeToLevel(m_Light.Type[EQ::lightsource::LightEquipment]);
} }
void NPC::Depop(bool StartSpawnTimer) { void NPC::Depop(bool start_spawn_timer) {
uint32 emoteid = GetEmoteID(); const auto emote_id = GetEmoteID();
if(emoteid != 0) if (emote_id) {
DoNPCEmote(EQ::constants::EmoteEventTypes::OnDespawn,emoteid); DoNPCEmote(EQ::constants::EmoteEventTypes::OnDespawn, emoteid);
}
if (IsNPC()) {
parse->EventNPC(EVENT_DESPAWN, this, nullptr, "", 0);
DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr);
#ifdef BOTS
} else if (IsBot()) {
parse->EventBot(EVENT_DESPAWN, CastToBot(), nullptr, "", 0);
DispatchZoneControllerEvent(EVENT_DESPAWN_ZONE, this, "", 0, nullptr);
#endif
}
p_depop = true; p_depop = true;
if (respawn2) if (respawn2) {
{ if (start_spawn_timer) {
if (StartSpawnTimer) {
respawn2->DeathReset(); respawn2->DeathReset();
} else { } else {
respawn2->Depop(); respawn2->Depop();
@ -3779,18 +3790,3 @@ int NPC::GetRolledItemCount(uint32 item_id)
return rolled_count; return rolled_count;
} }
int NPC::DispatchZoneControllerEvent(QuestEventID evt, Mob* init,
const std::string& data, uint32 extra, std::vector<std::any>* pointers)
{
int ret = 0;
if (RuleB(Zone, UseZoneController) && GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID)
{
auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID);
if (controller)
{
ret = parse->EventNPC(evt, controller, init, data, extra, pointers);
}
}
return ret;
}

View File

@ -27,7 +27,6 @@
#include "zonedump.h" #include "zonedump.h"
#include "../common/loottable.h" #include "../common/loottable.h"
#include <any>
#include <deque> #include <deque>
#include <list> #include <list>
@ -251,7 +250,7 @@ public:
inline void MerchantOpenShop() { merchant_open = true; } inline void MerchantOpenShop() { merchant_open = true; }
inline void MerchantCloseShop() { merchant_open = false; } inline void MerchantCloseShop() { merchant_open = false; }
inline bool IsMerchantOpen() { return merchant_open; } inline bool IsMerchantOpen() { return merchant_open; }
void Depop(bool StartSpawnTimer = false); void Depop(bool start_spawn_timer = false);
void Stun(int duration); void Stun(int duration);
void UnStun(); void UnStun();
uint32 GetSwarmOwner(); uint32 GetSwarmOwner();
@ -539,8 +538,6 @@ public:
static LootDropEntries_Struct NewLootDropEntry(); static LootDropEntries_Struct NewLootDropEntry();
int DispatchZoneControllerEvent(QuestEventID evt, Mob* init, const std::string& data, uint32 extra, std::vector<std::any>* pointers);
protected: protected:
const NPCType* NPCTypedata; const NPCType* NPCTypedata;

View File

@ -371,6 +371,11 @@ void Perl_Bot_SendPayload(Bot* self, int payload_id, std::string payload_value)
self->SendPayload(payload_id, payload_value); self->SendPayload(payload_id, payload_value);
} }
uint32 Perl_Bot_GetBotID(Bot* self) // @categories Script Utility
{
return self->GetBotID();
}
void perl_register_bot() void perl_register_bot()
{ {
perl::interpreter state(PERL_GET_THX); perl::interpreter state(PERL_GET_THX);
@ -411,6 +416,7 @@ void perl_register_bot()
package.add("GetBaseSTA", &Perl_Bot_GetBaseSTA); package.add("GetBaseSTA", &Perl_Bot_GetBaseSTA);
package.add("GetBaseSTR", &Perl_Bot_GetBaseSTR); package.add("GetBaseSTR", &Perl_Bot_GetBaseSTR);
package.add("GetBaseWIS", &Perl_Bot_GetBaseWIS); package.add("GetBaseWIS", &Perl_Bot_GetBaseWIS);
package.add("GetBotID", &Perl_Bot_GetBotID);
package.add("GetBotItem", &Perl_Bot_GetBotItem); package.add("GetBotItem", &Perl_Bot_GetBotItem);
package.add("GetBotItemIDBySlot", &Perl_Bot_GetBotItemIDBySlot); package.add("GetBotItemIDBySlot", &Perl_Bot_GetBotItemIDBySlot);
package.add("GetExpansionBitmask", &Perl_Bot_GetExpansionBitmask); package.add("GetExpansionBitmask", &Perl_Bot_GetExpansionBitmask);