mirror of
https://github.com/EQEmu/Server.git
synced 2026-03-12 12:12:25 +00:00
[Quest API] Add Lua handlers for zone controller events (#2514)
This cleans up some of the NPC::Death event dispatch code. Adds handlers for EVENT_SPAWN_ZONE and EVENT_DEATH_ZONE used by zone controller and fixes the death handler exports which were incorrect.
This commit is contained in:
parent
070bf64d6a
commit
9c7dd70b5f
@ -2318,52 +2318,37 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
LogCombat("Fatal blow dealt by [{}] with [{}] damage, spell [{}], skill [{}]",
|
LogCombat("Fatal blow dealt by [{}] with [{}] damage, spell [{}], skill [{}]",
|
||||||
((killer_mob) ? (killer_mob->GetName()) : ("[nullptr]")), damage, spell, attack_skill);
|
((killer_mob) ? (killer_mob->GetName()) : ("[nullptr]")), damage, spell, attack_skill);
|
||||||
|
|
||||||
Mob *oos = nullptr;
|
Mob* oos = killer_mob ? killer_mob->GetOwnerOrSelf() : nullptr;
|
||||||
if (killer_mob) {
|
|
||||||
oos = killer_mob->GetOwnerOrSelf();
|
|
||||||
std::string export_string = fmt::format(
|
|
||||||
"{} {} {} {}",
|
|
||||||
killer_mob->GetID(),
|
|
||||||
damage,
|
|
||||||
spell,
|
|
||||||
static_cast<int>(attack_skill)
|
|
||||||
);
|
|
||||||
if (parse->EventNPC(EVENT_DEATH, this, oos, export_string, 0) != 0) {
|
|
||||||
if (GetHP() < 0) {
|
|
||||||
SetHP(0);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((killer_mob->IsClient() || killer_mob->IsBot()) && (spell != SPELL_UNKNOWN) && damage > 0) {
|
std::string export_string = fmt::format(
|
||||||
char val1[20] = { 0 };
|
"{} {} {} {}",
|
||||||
|
killer_mob ? killer_mob->GetID() : 0,
|
||||||
|
damage,
|
||||||
|
spell,
|
||||||
|
static_cast<int>(attack_skill)
|
||||||
|
);
|
||||||
|
|
||||||
entity_list.MessageCloseString(
|
// todo: multiple attacks causes this to fire multiple times (DoAttackRounds, DoMain/OffHandAttackRounds, DoRiposte, spells?)
|
||||||
this, /* Sender */
|
if (parse->EventNPC(EVENT_DEATH, this, oos, export_string, 0) != 0) {
|
||||||
false, /* Skip Sender */
|
if (GetHP() < 0) {
|
||||||
RuleI(Range, DamageMessages),
|
SetHP(0);
|
||||||
Chat::NonMelee, /* 283 */
|
|
||||||
HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */
|
|
||||||
killer_mob->GetCleanName(), /* Message1 */
|
|
||||||
GetCleanName(), /* Message2 */
|
|
||||||
ConvertArray(damage, val1) /* Message3 */
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
std::string export_string = fmt::format(
|
if (killer_mob && (killer_mob->IsClient() || killer_mob->IsBot()) && (spell != SPELL_UNKNOWN) && damage > 0) {
|
||||||
"{} {} {} {}",
|
char val1[20] = { 0 };
|
||||||
0,
|
|
||||||
damage,
|
entity_list.MessageCloseString(
|
||||||
spell,
|
this, /* Sender */
|
||||||
static_cast<int>(attack_skill)
|
false, /* Skip Sender */
|
||||||
|
RuleI(Range, DamageMessages),
|
||||||
|
Chat::NonMelee, /* 283 */
|
||||||
|
HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */
|
||||||
|
killer_mob->GetCleanName(), /* Message1 */
|
||||||
|
GetCleanName(), /* Message2 */
|
||||||
|
ConvertArray(damage, val1) /* Message3 */
|
||||||
);
|
);
|
||||||
if (parse->EventNPC(EVENT_DEATH, this, nullptr, export_string, 0) != 0) {
|
|
||||||
if (GetHP() < 0) {
|
|
||||||
SetHP(0);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsEngaged()) {
|
if (IsEngaged()) {
|
||||||
@ -2752,35 +2737,12 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
|||||||
|
|
||||||
entity_list.UpdateFindableNPCState(this, true);
|
entity_list.UpdateFindableNPCState(this, true);
|
||||||
|
|
||||||
std::string export_string = fmt::format(
|
|
||||||
"{} {} {} {}",
|
|
||||||
killer_mob ? killer_mob->GetID() : 0,
|
|
||||||
damage,
|
|
||||||
spell,
|
|
||||||
static_cast<int>(attack_skill)
|
|
||||||
);
|
|
||||||
parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0);
|
parse->EventNPC(EVENT_DEATH_COMPLETE, this, oos, export_string, 0);
|
||||||
combat_record.Stop();
|
combat_record.Stop();
|
||||||
|
|
||||||
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
|
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
|
||||||
if (RuleB(Zone, UseZoneController)) {
|
std::vector<std::any> args = { this };
|
||||||
auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID);
|
DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args);
|
||||||
if (controller && GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID) {
|
|
||||||
export_string = fmt::format(
|
|
||||||
"{} {} {} {} {} {:.2f} {:.2f} {:.2f} {:.2f}",
|
|
||||||
killer_mob ? killer_mob->GetID() : 0,
|
|
||||||
damage,
|
|
||||||
spell,
|
|
||||||
static_cast<int>(attack_skill),
|
|
||||||
GetNPCTypeID(),
|
|
||||||
GetX(),
|
|
||||||
GetY(),
|
|
||||||
GetZ(),
|
|
||||||
GetHeading()
|
|
||||||
);
|
|
||||||
parse->EventNPC(EVENT_DEATH_ZONE, controller, nullptr, export_string, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1599,6 +1599,7 @@ void PerlembParser::ExportEventVariables(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EVENT_DEATH_ZONE:
|
||||||
case EVENT_DEATH:
|
case EVENT_DEATH:
|
||||||
case EVENT_DEATH_COMPLETE: {
|
case EVENT_DEATH_COMPLETE: {
|
||||||
Seperator sep(data);
|
Seperator sep(data);
|
||||||
@ -1606,6 +1607,18 @@ void PerlembParser::ExportEventVariables(
|
|||||||
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]);
|
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]);
|
||||||
ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]);
|
ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]);
|
||||||
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
|
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
|
||||||
|
if (extra_pointers && !extra_pointers->empty())
|
||||||
|
{
|
||||||
|
NPC* killed = std::any_cast<NPC*>(extra_pointers->at(0));
|
||||||
|
if (killed)
|
||||||
|
{
|
||||||
|
ExportVar(package_name.c_str(), "killed_npc_id", killed->GetNPCTypeID());
|
||||||
|
ExportVar(package_name.c_str(), "killed_x", killed->GetX());
|
||||||
|
ExportVar(package_name.c_str(), "killed_y", killed->GetY());
|
||||||
|
ExportVar(package_name.c_str(), "killed_z", killed->GetZ());
|
||||||
|
ExportVar(package_name.c_str(), "killed_h", killed->GetHeading());
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EVENT_DROP_ITEM: {
|
case EVENT_DROP_ITEM: {
|
||||||
@ -1617,22 +1630,8 @@ void PerlembParser::ExportEventVariables(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EVENT_SPAWN_ZONE: {
|
case EVENT_SPAWN_ZONE: {
|
||||||
Seperator sep(data);
|
ExportVar(package_name.c_str(), "spawned_entity_id", mob->GetID());
|
||||||
ExportVar(package_name.c_str(), "spawned_entity_id", sep.arg[0]);
|
ExportVar(package_name.c_str(), "spawned_npc_id", mob->GetNPCTypeID());
|
||||||
ExportVar(package_name.c_str(), "spawned_npc_id", sep.arg[1]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EVENT_DEATH_ZONE: {
|
|
||||||
Seperator sep(data);
|
|
||||||
ExportVar(package_name.c_str(), "killer_id", sep.arg[0]);
|
|
||||||
ExportVar(package_name.c_str(), "killer_damage", sep.arg[1]);
|
|
||||||
ExportVar(package_name.c_str(), "killer_spell", sep.arg[2]);
|
|
||||||
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
|
|
||||||
ExportVar(package_name.c_str(), "killed_npc_id", sep.arg[4]);
|
|
||||||
ExportVar(package_name.c_str(), "killed_x", sep.arg[5]);
|
|
||||||
ExportVar(package_name.c_str(), "killed_y", sep.arg[6]);
|
|
||||||
ExportVar(package_name.c_str(), "killed_z", sep.arg[7]);
|
|
||||||
ExportVar(package_name.c_str(), "killed_h", sep.arg[8]);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EVENT_USE_SKILL: {
|
case EVENT_USE_SKILL: {
|
||||||
|
|||||||
@ -729,17 +729,7 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
|
|||||||
entity_list.ScanCloseMobs(npc->close_mobs, npc, true);
|
entity_list.ScanCloseMobs(npc->close_mobs, npc, true);
|
||||||
|
|
||||||
/* Zone controller process EVENT_SPAWN_ZONE */
|
/* Zone controller process EVENT_SPAWN_ZONE */
|
||||||
if (RuleB(Zone, UseZoneController)) {
|
npc->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, npc, "", 0, nullptr);
|
||||||
auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID);
|
|
||||||
if (controller && npc->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){
|
|
||||||
std::string export_string = fmt::format(
|
|
||||||
"{} {}",
|
|
||||||
npc->GetID(),
|
|
||||||
npc->GetNPCTypeID()
|
|
||||||
);
|
|
||||||
parse->EventNPC(EVENT_SPAWN_ZONE, controller, nullptr, export_string, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether NPC was spawned in or out of water
|
* Set whether NPC was spawned in or out of water
|
||||||
|
|||||||
@ -194,12 +194,14 @@ LuaParser::LuaParser() {
|
|||||||
NPCArgumentDispatch[EVENT_TIMER] = handle_npc_timer;
|
NPCArgumentDispatch[EVENT_TIMER] = handle_npc_timer;
|
||||||
NPCArgumentDispatch[EVENT_DEATH] = handle_npc_death;
|
NPCArgumentDispatch[EVENT_DEATH] = handle_npc_death;
|
||||||
NPCArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_npc_death;
|
NPCArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_npc_death;
|
||||||
|
NPCArgumentDispatch[EVENT_DEATH_ZONE] = handle_npc_death;
|
||||||
NPCArgumentDispatch[EVENT_CAST] = handle_npc_cast;
|
NPCArgumentDispatch[EVENT_CAST] = handle_npc_cast;
|
||||||
NPCArgumentDispatch[EVENT_CAST_BEGIN] = handle_npc_cast;
|
NPCArgumentDispatch[EVENT_CAST_BEGIN] = handle_npc_cast;
|
||||||
NPCArgumentDispatch[EVENT_FEIGN_DEATH] = handle_npc_single_client;
|
NPCArgumentDispatch[EVENT_FEIGN_DEATH] = handle_npc_single_client;
|
||||||
NPCArgumentDispatch[EVENT_ENTER_AREA] = handle_npc_area;
|
NPCArgumentDispatch[EVENT_ENTER_AREA] = handle_npc_area;
|
||||||
NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area;
|
NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area;
|
||||||
NPCArgumentDispatch[EVENT_LOOT_ZONE] = handle_npc_loot_zone;
|
NPCArgumentDispatch[EVENT_LOOT_ZONE] = handle_npc_loot_zone;
|
||||||
|
NPCArgumentDispatch[EVENT_SPAWN_ZONE] = handle_npc_spawn_zone;
|
||||||
|
|
||||||
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
|
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
|
||||||
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;
|
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;
|
||||||
|
|||||||
@ -189,9 +189,12 @@ void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init,
|
|||||||
|
|
||||||
Seperator sep(data.c_str());
|
Seperator sep(data.c_str());
|
||||||
lua_pushinteger(L, std::stoi(sep.arg[0]));
|
lua_pushinteger(L, std::stoi(sep.arg[0]));
|
||||||
|
lua_setfield(L, -2, "killer_id");
|
||||||
|
|
||||||
|
lua_pushinteger(L, std::stoi(sep.arg[1]));
|
||||||
lua_setfield(L, -2, "damage");
|
lua_setfield(L, -2, "damage");
|
||||||
|
|
||||||
int spell_id = std::stoi(sep.arg[1]);
|
int spell_id = std::stoi(sep.arg[2]);
|
||||||
if(IsValidSpell(spell_id)) {
|
if(IsValidSpell(spell_id)) {
|
||||||
Lua_Spell l_spell(&spells[spell_id]);
|
Lua_Spell l_spell(&spells[spell_id]);
|
||||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||||
@ -204,8 +207,16 @@ void handle_npc_death(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init,
|
|||||||
lua_setfield(L, -2, "spell");
|
lua_setfield(L, -2, "spell");
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pushinteger(L, std::stoi(sep.arg[2]));
|
lua_pushinteger(L, std::stoi(sep.arg[3]));
|
||||||
lua_setfield(L, -2, "skill_id");
|
lua_setfield(L, -2, "skill_id");
|
||||||
|
|
||||||
|
if (extra_pointers && !extra_pointers->empty())
|
||||||
|
{
|
||||||
|
Lua_NPC l_npc(std::any_cast<NPC*>(extra_pointers->at(0)));
|
||||||
|
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
|
||||||
|
l_npc_o.push(L);
|
||||||
|
lua_setfield(L, -2, "killed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_npc_cast(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
void handle_npc_cast(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||||
@ -255,6 +266,14 @@ void handle_npc_loot_zone(QuestInterface *parse, lua_State* L, NPC* npc, Mob *in
|
|||||||
lua_setfield(L, -2, "corpse");
|
lua_setfield(L, -2, "corpse");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_npc_spawn_zone(QuestInterface* parse, lua_State* L, NPC* npc, Mob* init, std::string data, uint32 extra_data,
|
||||||
|
std::vector<std::any> *extra_pointers) {
|
||||||
|
Lua_NPC l_npc(std::any_cast<NPC*>(init->CastToNPC()));
|
||||||
|
luabind::adl::object l_npc_o = luabind::adl::object(L, l_npc);
|
||||||
|
l_npc_o.push(L);
|
||||||
|
lua_setfield(L, -2, "other");
|
||||||
|
}
|
||||||
|
|
||||||
//Player
|
//Player
|
||||||
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||||
std::vector<std::any> *extra_pointers) {
|
std::vector<std::any> *extra_pointers) {
|
||||||
@ -289,9 +308,12 @@ void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, st
|
|||||||
lua_setfield(L, -2, "other");
|
lua_setfield(L, -2, "other");
|
||||||
|
|
||||||
lua_pushinteger(L, std::stoi(sep.arg[1]));
|
lua_pushinteger(L, std::stoi(sep.arg[1]));
|
||||||
|
lua_setfield(L, -2, "killer_id");
|
||||||
|
|
||||||
|
lua_pushinteger(L, std::stoi(sep.arg[2]));
|
||||||
lua_setfield(L, -2, "damage");
|
lua_setfield(L, -2, "damage");
|
||||||
|
|
||||||
int spell_id = std::stoi(sep.arg[2]);
|
int spell_id = std::stoi(sep.arg[3]);
|
||||||
if(IsValidSpell(spell_id)) {
|
if(IsValidSpell(spell_id)) {
|
||||||
Lua_Spell l_spell(&spells[spell_id]);
|
Lua_Spell l_spell(&spells[spell_id]);
|
||||||
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
|
||||||
@ -304,7 +326,7 @@ void handle_player_death(QuestInterface *parse, lua_State* L, Client* client, st
|
|||||||
lua_setfield(L, -2, "spell");
|
lua_setfield(L, -2, "spell");
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pushinteger(L, std::stoi(sep.arg[3]));
|
lua_pushinteger(L, std::stoi(sep.arg[4]));
|
||||||
lua_setfield(L, -2, "skill");
|
lua_setfield(L, -2, "skill");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,6 +43,8 @@ void handle_npc_null(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, s
|
|||||||
std::vector<std::any> *extra_pointers);
|
std::vector<std::any> *extra_pointers);
|
||||||
void handle_npc_loot_zone(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
void handle_npc_loot_zone(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||||
std::vector<std::any> *extra_pointers);
|
std::vector<std::any> *extra_pointers);
|
||||||
|
void handle_npc_spawn_zone(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
|
||||||
|
std::vector<std::any> *extra_pointers);
|
||||||
|
|
||||||
//Player
|
//Player
|
||||||
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||||
|
|||||||
15
zone/npc.cpp
15
zone/npc.cpp
@ -3764,3 +3764,18 @@ 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;
|
||||||
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
#include "zonedump.h"
|
#include "zonedump.h"
|
||||||
#include "../common/loottable.h"
|
#include "../common/loottable.h"
|
||||||
|
|
||||||
|
#include <any>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
@ -549,6 +550,9 @@ public:
|
|||||||
void ReloadSpells();
|
void ReloadSpells();
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user