From fe0758c9843d48c98a86cd7318bd3dff53969bb6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 13 Aug 2015 22:30:49 -0400 Subject: [PATCH] Add EVENT_TICK for NPCs This event fires at the start of the tick processing so we can script on the actual tick. --- zone/embparser.cpp | 47 +++++++++++++++--------------- zone/event_codes.h | 1 + zone/lua_general.cpp | 3 +- zone/lua_parser.cpp | 69 ++++++++++++++++++++++---------------------- zone/npc.cpp | 2 ++ 5 files changed, 64 insertions(+), 58 deletions(-) diff --git a/zone/embparser.cpp b/zone/embparser.cpp index d571dce24..389f93d1f 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -113,7 +113,8 @@ const char *QuestEventSubroutines[_LargestEventID] = { "EVENT_LEAVE_AREA", "EVENT_RESPAWN", "EVENT_DEATH_COMPLETE", - "EVENT_UNHANDLED_OPCODE" + "EVENT_UNHANDLED_OPCODE", + "EVENT_TICK" }; PerlembParser::PerlembParser() : perl(nullptr) { @@ -154,7 +155,7 @@ void PerlembParser::ReloadQuests() { spell_quest_status_.clear(); } -int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob, +int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, bool global, std::vector *extra_pointers) { if(!perl) @@ -186,7 +187,7 @@ int PerlembParser::EventCommon(QuestEventID event, uint32 objid, const char * da package_name, npcmob, mob, char_id); //ExportGenericVariables(); - ExportMobVariables(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, + ExportMobVariables(isPlayerQuest, isGlobalPlayerQuest, isGlobalNPC, isItemQuest, isSpellQuest, package_name, mob, npcmob); ExportZoneVariables(package_name); ExportItemVariables(package_name, mob); @@ -459,15 +460,15 @@ void PerlembParser::LoadItemScript(std::string filename, ItemInst *item) { std::stringstream package_name; package_name << "qst_item_" << item->GetID(); - + if(!perl) return; - + auto iter = item_quest_status_.find(item->GetID()); if(iter != item_quest_status_.end()) { return; } - + try { perl->eval_file(package_name.str().c_str(), filename.c_str()); } @@ -480,7 +481,7 @@ void PerlembParser::LoadItemScript(std::string filename, ItemInst *item) { item_quest_status_[item->GetID()] = questFailedToLoad; return; } - + item_quest_status_[item->GetID()] = questLoaded; } @@ -821,10 +822,10 @@ void PerlembParser::MapFunctions() { ); } -void PerlembParser::GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, +void PerlembParser::GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, bool &isSpellQuest, QuestEventID event, NPC* npcmob, ItemInst* iteminst, Mob* mob, bool global) { - if(event == EVENT_SPELL_EFFECT_CLIENT || + if(event == EVENT_SPELL_EFFECT_CLIENT || event == EVENT_SPELL_EFFECT_NPC || event == EVENT_SPELL_BUFF_TIC_CLIENT || event == EVENT_SPELL_BUFF_TIC_NPC || @@ -843,14 +844,14 @@ void PerlembParser::GetQuestTypes(bool &isPlayerQuest, bool &isGlobalPlayerQuest isPlayerQuest = true; } } - else + else isItemQuest = true; } } } -void PerlembParser::GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, - bool &isSpellQuest, std::string &package_name, QuestEventID event, uint32 objid, const char * data, +void PerlembParser::GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlayerQuest, bool &isGlobalNPC, bool &isItemQuest, + bool &isSpellQuest, std::string &package_name, QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, bool global) { if(!isPlayerQuest && !isGlobalPlayerQuest && !isItemQuest && !isSpellQuest) { @@ -897,7 +898,7 @@ void PerlembParser::ExportCharID(const std::string &package_name, int &char_id, ExportVar(package_name.c_str(), "charid", char_id); } -void PerlembParser::ExportQGlobals(bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, +void PerlembParser::ExportQGlobals(bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, bool isSpellQuest, std::string &package_name, NPC *npcmob, Mob *mob, int char_id) { //NPC quest if(!isPlayerQuest && !isGlobalPlayerQuest && !isItemQuest && !isSpellQuest) @@ -953,7 +954,7 @@ void PerlembParser::ExportQGlobals(bool isPlayerQuest, bool isGlobalPlayerQuest, { QGlobalCache::Combine(globalMap, zone_c->GetBucket(), npcmob->GetNPCTypeID(), char_id, zone->GetZoneID()); } - + std::list::iterator iter = globalMap.begin(); while(iter != globalMap.end()) { @@ -1013,8 +1014,8 @@ void PerlembParser::ExportQGlobals(bool isPlayerQuest, bool isGlobalPlayerQuest, } } -void PerlembParser::ExportMobVariables(bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, - bool isSpellQuest, std::string &package_name, Mob *mob, NPC *npcmob) +void PerlembParser::ExportMobVariables(bool isPlayerQuest, bool isGlobalPlayerQuest, bool isGlobalNPC, bool isItemQuest, + bool isSpellQuest, std::string &package_name, Mob *mob, NPC *npcmob) { uint8 fac = 0; if (mob && mob->IsClient()) { @@ -1027,7 +1028,7 @@ void PerlembParser::ExportMobVariables(bool isPlayerQuest, bool isGlobalPlayerQu if (mob && npcmob && mob->IsClient()) { Client* client = mob->CastToClient(); - fac = client->GetFactionLevel(client->CharacterID(), npcmob->GetID(), client->GetRace(), + fac = client->GetFactionLevel(client->CharacterID(), npcmob->GetID(), client->GetRace(), client->GetClass(), client->GetDeity(), npcmob->GetPrimaryFaction(), npcmob); } } @@ -1122,8 +1123,8 @@ void PerlembParser::ExportItemVariables(std::string &package_name, Mob *mob) { #undef HASITEM_LAST #undef HASITEM_ISNULLITEM -void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID event, uint32 objid, const char * data, - NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, std::vector *extra_pointers) +void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID event, uint32 objid, const char * data, + NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, std::vector *extra_pointers) { switch (event) { case EVENT_SAY: { @@ -1240,7 +1241,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID ExportVar(package_name.c_str(), "target_zone_id", data); break; } - + case EVENT_CAST_ON: case EVENT_CAST: case EVENT_CAST_BEGIN: { @@ -1278,7 +1279,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID case EVENT_PLAYER_PICKUP:{ ExportVar(package_name.c_str(), "picked_up_id", data); ExportVar(package_name.c_str(), "picked_up_entity_id", extradata); - break; + break; } case EVENT_AGGRO_SAY: { @@ -1359,12 +1360,12 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID case EVENT_FORAGE_SUCCESS: { ExportVar(package_name.c_str(), "foraged_item", extradata); - break; + break; } case EVENT_FISH_SUCCESS: { ExportVar(package_name.c_str(), "fished_item", extradata); - break; + break; } case EVENT_CLICK_OBJECT: { diff --git a/zone/event_codes.h b/zone/event_codes.h index f793efaf6..7850b0eb3 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -82,6 +82,7 @@ typedef enum { EVENT_RESPAWN, EVENT_DEATH_COMPLETE, EVENT_UNHANDLED_OPCODE, + EVENT_TICK, _LargestEventID } QuestEventID; diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 483426b2e..15a11604b 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1713,7 +1713,8 @@ luabind::scope lua_register_events() { luabind::value("enter_area", static_cast(EVENT_ENTER_AREA)), luabind::value("leave_area", static_cast(EVENT_LEAVE_AREA)), luabind::value("death_complete", static_cast(EVENT_DEATH_COMPLETE)), - luabind::value("unhandled_opcode", static_cast(EVENT_UNHANDLED_OPCODE)) + luabind::value("unhandled_opcode", static_cast(EVENT_UNHANDLED_OPCODE)), + luabind::value("tick", static_cast(EVENT_TICK)) ]; } diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 24f25948e..462752705 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -116,7 +116,8 @@ const char *LuaEvents[_LargestEventID] = { "event_leave_area", "event_respawn", "event_death_complete", - "event_unhandled_opcode" + "event_unhandled_opcode", + "event_tick" }; extern Zone *zone; @@ -281,7 +282,7 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M lua_getfield(L, -1, sub_name); npop = 2; } - + lua_createtable(L, 0, 0); //always push self Lua_NPC l_npc(npc); @@ -292,7 +293,7 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M auto arg_function = NPCArgumentDispatch[evt]; arg_function(this, L, npc, init, data, extra_data, extra_pointers); Client *c = (init && init->IsClient()) ? init->CastToClient() : nullptr; - + quest_manager.StartQuest(npc, c, nullptr); if(lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); @@ -301,13 +302,13 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M return 0; } quest_manager.EndQuest(); - + if(lua_isnumber(L, -1)) { int ret = static_cast(lua_tointeger(L, -1)); lua_pop(L, npop); return ret; } - + lua_pop(L, npop); } catch(std::exception &ex) { std::string error = "Lua Exception: "; @@ -375,17 +376,17 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client * lua_getfield(L, -1, sub_name); npop = 2; } - + lua_createtable(L, 0, 0); //push self Lua_Client l_client(client); luabind::adl::object l_client_o = luabind::adl::object(L, l_client); l_client_o.push(L); lua_setfield(L, -2, "self"); - + auto arg_function = PlayerArgumentDispatch[evt]; arg_function(this, L, client, data, extra_data, extra_pointers); - + quest_manager.StartQuest(client, client, nullptr); if(lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); @@ -394,13 +395,13 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client * return 0; } quest_manager.EndQuest(); - + if(lua_isnumber(L, -1)) { int ret = static_cast(lua_tointeger(L, -1)); lua_pop(L, npop); return ret; } - + lua_pop(L, npop); } catch(std::exception &ex) { std::string error = "Lua Exception: "; @@ -424,15 +425,15 @@ int LuaParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob * if(evt >= _LargestEventID) { return 0; } - + if(!item) { return 0; } - + if(!ItemHasQuestSub(item, evt)) { return 0; } - + std::string package_name = "item_"; package_name += std::to_string(item->GetID()); return _EventItem(package_name, evt, client, item, mob, data, extra_data, extra_pointers); @@ -452,7 +453,7 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str()); lua_getfield(L, -1, sub_name); } - + lua_createtable(L, 0, 0); //always push self Lua_ItemInst l_item(item); @@ -468,7 +469,7 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl //redo this arg function auto arg_function = ItemArgumentDispatch[evt]; arg_function(this, L, client, item, mob, data, extra_data, extra_pointers); - + quest_manager.StartQuest(client, client, item); if(lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); @@ -477,13 +478,13 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl return 0; } quest_manager.EndQuest(); - + if(lua_isnumber(L, -1)) { int ret = static_cast(lua_tointeger(L, -1)); lua_pop(L, npop); return ret; } - + lua_pop(L, npop); } catch(std::exception &ex) { std::string error = "Lua Exception: "; @@ -520,7 +521,7 @@ int LuaParser::EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spe int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func) { const char *sub_name = LuaEvents[evt]; - + int start = lua_gettop(L); try { @@ -532,7 +533,7 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, lua_getfield(L, -1, sub_name); npop = 2; } - + lua_createtable(L, 0, 0); //always push self even if invalid @@ -546,10 +547,10 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, l_spell_o.push(L); } lua_setfield(L, -2, "self"); - + auto arg_function = SpellArgumentDispatch[evt]; arg_function(this, L, npc, client, spell_id, extra_data, extra_pointers); - + quest_manager.StartQuest(npc, client, nullptr); if(lua_pcall(L, 1, 1, 0)) { std::string error = lua_tostring(L, -1); @@ -558,13 +559,13 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc, return 0; } quest_manager.EndQuest(); - + if(lua_isnumber(L, -1)) { int ret = static_cast(lua_tointeger(L, -1)); lua_pop(L, npop); return ret; } - + lua_pop(L, npop); } catch(std::exception &ex) { std::string error = "Lua Exception: "; @@ -593,20 +594,20 @@ int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, std: if(!EncounterHasQuestSub(encounter_name, evt)) { return 0; } - + return _EventEncounter(package_name, evt, encounter_name, data, extra_data, extra_pointers); } int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector *extra_pointers) { const char *sub_name = LuaEvents[evt]; - + int start = lua_gettop(L); try { lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str()); lua_getfield(L, -1, sub_name); - + lua_createtable(L, 0, 0); lua_pushstring(L, encounter_name.c_str()); lua_setfield(L, -2, "name"); @@ -624,13 +625,13 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std:: return 0; } quest_manager.EndQuest(); - + if(lua_isnumber(L, -1)) { int ret = static_cast(lua_tointeger(L, -1)); lua_pop(L, 2); return ret; } - + lua_pop(L, 2); } catch(std::exception &ex) { std::string error = "Lua Exception: "; @@ -864,13 +865,13 @@ void LuaParser::ReloadQuests() { FILE *f = fopen(path.c_str(), "r"); if(f) { fclose(f); - + if(luaL_dofile(L, path.c_str())) { std::string error = lua_tostring(L, -1); AddError(error); } } - + //zone init - always loads after global if(zone) { std::string zone_script = "quests/"; @@ -881,7 +882,7 @@ void LuaParser::ReloadQuests() { f = fopen(zone_script.c_str(), "r"); if(f) { fclose(f); - + if(luaL_dofile(L, zone_script.c_str())) { std::string error = lua_tostring(L, -1); AddError(error); @@ -910,7 +911,7 @@ void LuaParser::LoadScript(std::string filename, std::string package_name) { if(iter != loaded_.end()) { return; } - + if(luaL_loadfile(L, filename.c_str())) { std::string error = lua_tostring(L, -1); AddError(error); @@ -1008,7 +1009,7 @@ void LuaParser::MapFunctions(lua_State *L) { lua_register_packet(), lua_register_packet_opcodes() ]; - + } catch(std::exception &ex) { std::string error = ex.what(); AddError(error); @@ -1122,7 +1123,7 @@ int LuaParser::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *ite if(iter == lua_encounter_events_registered.end()) { return ret; } - + auto riter = iter->second.begin(); while(riter != iter->second.end()) { if(riter->event_id == evt) { diff --git a/zone/npc.cpp b/zone/npc.cpp index 214161a3b..effd04a4a 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -37,6 +37,7 @@ #include "string_ids.h" #include "spawn2.h" #include "zone.h" +#include "quest_parser_collection.h" #include #include @@ -601,6 +602,7 @@ bool NPC::Process() if(tic_timer.Check()) { + parse->EventNPC(EVENT_TICK, this, nullptr, "", 0); BuffProcess(); if(curfp)