mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +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 [{}]",
|
||||
((killer_mob) ? (killer_mob->GetName()) : ("[nullptr]")), damage, spell, attack_skill);
|
||||
|
||||
Mob *oos = 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;
|
||||
}
|
||||
Mob* oos = killer_mob ? killer_mob->GetOwnerOrSelf() : nullptr;
|
||||
|
||||
if ((killer_mob->IsClient() || killer_mob->IsBot()) && (spell != SPELL_UNKNOWN) && damage > 0) {
|
||||
char val1[20] = { 0 };
|
||||
std::string export_string = fmt::format(
|
||||
"{} {} {} {}",
|
||||
killer_mob ? killer_mob->GetID() : 0,
|
||||
damage,
|
||||
spell,
|
||||
static_cast<int>(attack_skill)
|
||||
);
|
||||
|
||||
entity_list.MessageCloseString(
|
||||
this, /* Sender */
|
||||
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 */
|
||||
);
|
||||
// todo: multiple attacks causes this to fire multiple times (DoAttackRounds, DoMain/OffHandAttackRounds, DoRiposte, spells?)
|
||||
if (parse->EventNPC(EVENT_DEATH, this, oos, export_string, 0) != 0) {
|
||||
if (GetHP() < 0) {
|
||||
SetHP(0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
std::string export_string = fmt::format(
|
||||
"{} {} {} {}",
|
||||
0,
|
||||
damage,
|
||||
spell,
|
||||
static_cast<int>(attack_skill)
|
||||
|
||||
if (killer_mob && (killer_mob->IsClient() || killer_mob->IsBot()) && (spell != SPELL_UNKNOWN) && damage > 0) {
|
||||
char val1[20] = { 0 };
|
||||
|
||||
entity_list.MessageCloseString(
|
||||
this, /* Sender */
|
||||
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()) {
|
||||
@ -2752,35 +2737,12 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
|
||||
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);
|
||||
combat_record.Stop();
|
||||
|
||||
/* Zone controller process EVENT_DEATH_ZONE (Death events) */
|
||||
if (RuleB(Zone, UseZoneController)) {
|
||||
auto controller = entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID);
|
||||
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);
|
||||
}
|
||||
}
|
||||
std::vector<std::any> args = { this };
|
||||
DispatchZoneControllerEvent(EVENT_DEATH_ZONE, oos, export_string, 0, &args);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1599,6 +1599,7 @@ void PerlembParser::ExportEventVariables(
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_DEATH_ZONE:
|
||||
case EVENT_DEATH:
|
||||
case EVENT_DEATH_COMPLETE: {
|
||||
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_spell", sep.arg[2]);
|
||||
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;
|
||||
}
|
||||
case EVENT_DROP_ITEM: {
|
||||
@ -1617,22 +1630,8 @@ void PerlembParser::ExportEventVariables(
|
||||
break;
|
||||
}
|
||||
case EVENT_SPAWN_ZONE: {
|
||||
Seperator sep(data);
|
||||
ExportVar(package_name.c_str(), "spawned_entity_id", sep.arg[0]);
|
||||
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]);
|
||||
ExportVar(package_name.c_str(), "spawned_entity_id", mob->GetID());
|
||||
ExportVar(package_name.c_str(), "spawned_npc_id", mob->GetNPCTypeID());
|
||||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
/* Zone controller process EVENT_SPAWN_ZONE */
|
||||
if (RuleB(Zone, UseZoneController)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
npc->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, npc, "", 0, nullptr);
|
||||
|
||||
/**
|
||||
* Set whether NPC was spawned in or out of water
|
||||
|
||||
@ -194,12 +194,14 @@ LuaParser::LuaParser() {
|
||||
NPCArgumentDispatch[EVENT_TIMER] = handle_npc_timer;
|
||||
NPCArgumentDispatch[EVENT_DEATH] = 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_BEGIN] = handle_npc_cast;
|
||||
NPCArgumentDispatch[EVENT_FEIGN_DEATH] = handle_npc_single_client;
|
||||
NPCArgumentDispatch[EVENT_ENTER_AREA] = handle_npc_area;
|
||||
NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area;
|
||||
NPCArgumentDispatch[EVENT_LOOT_ZONE] = handle_npc_loot_zone;
|
||||
NPCArgumentDispatch[EVENT_SPAWN_ZONE] = handle_npc_spawn_zone;
|
||||
|
||||
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
|
||||
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());
|
||||
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");
|
||||
|
||||
int spell_id = std::stoi(sep.arg[1]);
|
||||
int spell_id = std::stoi(sep.arg[2]);
|
||||
if(IsValidSpell(spell_id)) {
|
||||
Lua_Spell l_spell(&spells[spell_id]);
|
||||
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_pushinteger(L, std::stoi(sep.arg[2]));
|
||||
lua_pushinteger(L, std::stoi(sep.arg[3]));
|
||||
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,
|
||||
@ -255,6 +266,14 @@ void handle_npc_loot_zone(QuestInterface *parse, lua_State* L, NPC* npc, Mob *in
|
||||
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
|
||||
void handle_player_say(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
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_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");
|
||||
|
||||
int spell_id = std::stoi(sep.arg[2]);
|
||||
int spell_id = std::stoi(sep.arg[3]);
|
||||
if(IsValidSpell(spell_id)) {
|
||||
Lua_Spell l_spell(&spells[spell_id]);
|
||||
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_pushinteger(L, std::stoi(sep.arg[3]));
|
||||
lua_pushinteger(L, std::stoi(sep.arg[4]));
|
||||
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);
|
||||
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);
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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 "../common/loottable.h"
|
||||
|
||||
#include <any>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
|
||||
@ -549,6 +550,9 @@ public:
|
||||
void ReloadSpells();
|
||||
|
||||
static LootDropEntries_Struct NewLootDropEntry();
|
||||
|
||||
int DispatchZoneControllerEvent(QuestEventID evt, Mob* init, const std::string& data, uint32 extra, std::vector<std::any>* pointers);
|
||||
|
||||
protected:
|
||||
|
||||
const NPCType* NPCTypedata;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user