Add EVENT_TICK for NPCs

This event fires at the start of the tick processing so we can
script on the actual tick.
This commit is contained in:
Michael Cook (mackal) 2015-08-13 22:30:49 -04:00
parent 1fc23beb78
commit fe0758c984
5 changed files with 64 additions and 58 deletions

View File

@ -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<EQEmu::Any> *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<QGlobal>::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<EQEmu::Any> *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<EQEmu::Any> *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: {

View File

@ -82,6 +82,7 @@ typedef enum {
EVENT_RESPAWN,
EVENT_DEATH_COMPLETE,
EVENT_UNHANDLED_OPCODE,
EVENT_TICK,
_LargestEventID
} QuestEventID;

View File

@ -1713,7 +1713,8 @@ luabind::scope lua_register_events() {
luabind::value("enter_area", static_cast<int>(EVENT_ENTER_AREA)),
luabind::value("leave_area", static_cast<int>(EVENT_LEAVE_AREA)),
luabind::value("death_complete", static_cast<int>(EVENT_DEATH_COMPLETE)),
luabind::value("unhandled_opcode", static_cast<int>(EVENT_UNHANDLED_OPCODE))
luabind::value("unhandled_opcode", static_cast<int>(EVENT_UNHANDLED_OPCODE)),
luabind::value("tick", static_cast<int>(EVENT_TICK))
];
}

View File

@ -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<int>(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<int>(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<int>(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<EQEmu::Any> *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<int>(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<EQEmu::Any> *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<int>(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) {

View File

@ -37,6 +37,7 @@
#include "string_ids.h"
#include "spawn2.h"
#include "zone.h"
#include "quest_parser_collection.h"
#include <cctype>
#include <stdio.h>
@ -601,6 +602,7 @@ bool NPC::Process()
if(tic_timer.Check())
{
parse->EventNPC(EVENT_TICK, this, nullptr, "", 0);
BuffProcess();
if(curfp)