Redoing event item api

This commit is contained in:
KimLS 2013-06-07 02:26:17 -07:00
parent 8c3cce822a
commit 56b41c882b
20 changed files with 192 additions and 235 deletions

View File

@ -2,6 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(common_sources
BasePacket.cpp
callback_manager.cpp
classes.cpp
Condition.cpp
crash.cpp
@ -93,6 +94,7 @@ SET(common_headers
BasePacket.h
bodytypes.h
breakdowns.h
callback_manager.h
classes.h
common_profile.h
Condition.h

View File

@ -65,6 +65,7 @@ ItemInst::ItemInst(const Item_Struct* item, int16 charges) {
m_color = 0;
m_merchantcount = 1;
m_SerialNumber = GetNextItemInstSerialNumber();
m_on_destroy = GetEQCallback("OnItemInstDestroy");
}
ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) {
@ -80,6 +81,7 @@ ItemInst::ItemInst(SharedDatabase *db, uint32 item_id, int16 charges) {
m_color = 0;
m_merchantcount = 1;
m_SerialNumber = GetNextItemInstSerialNumber();
m_on_destroy = GetEQCallback("OnItemInstDestroy");
}
ItemInstQueue::~ItemInstQueue() {
@ -170,11 +172,16 @@ ItemInst::ItemInst(const ItemInst& copy)
}
m_SerialNumber = copy.m_SerialNumber;
m_custom_data = copy.m_custom_data;
m_on_destroy = copy.m_on_destroy;
}
// Clean up container contents
ItemInst::~ItemInst()
{
if(m_on_destroy) {
m_on_destroy(this);
}
Clear();
}
@ -1677,6 +1684,8 @@ EvoItemInst::EvoItemInst(const EvoItemInst &copy) {
m_scaledItem = new Item_Struct(*copy.m_scaledItem);
else
m_scaledItem = nullptr;
m_on_destroy = GetEQCallback("OnItemInstDestroy");
}
EvoItemInst::EvoItemInst(const ItemInst &basecopy) {
@ -1716,6 +1725,7 @@ EvoItemInst::EvoItemInst(const ItemInst &basecopy) {
m_activated = false;
m_evolveInfo = nullptr;
m_scaledItem = nullptr;
m_on_destroy = copy->m_on_destroy;
}
EvoItemInst::EvoItemInst(const Item_Struct* item, int16 charges) {
@ -1736,9 +1746,13 @@ EvoItemInst::EvoItemInst(const Item_Struct* item, int16 charges) {
m_activated = false;
m_evolveInfo = nullptr;
m_scaledItem = nullptr;
m_on_destroy = GetEQCallback("OnItemInstDestroy");
}
EvoItemInst::~EvoItemInst() {
if(m_on_destroy) {
m_on_destroy(this);
}
safe_delete(m_scaledItem);
}

View File

@ -37,6 +37,7 @@ class EvolveInfo; // Stores information about an evolving item family
#include "../common/eq_packet_structs.h"
#include "../common/eq_constants.h"
#include "../common/item_struct.h"
#include "callback_manager.h"
// Helper typedefs
typedef std::list<ItemInst*>::const_iterator iter_queue;
@ -265,6 +266,8 @@ public:
m_instnodrop = false;
m_merchantslot = 0;
m_color = 0;
m_on_destroy = GetEQCallback("OnItemInstDestroy");
}
ItemInst(const ItemInst& copy);
@ -404,6 +407,7 @@ protected:
// Items inside of this item (augs or contents);
std::map<uint8, ItemInst*> m_contents; // Zero-based index: min=0, max=9
std::map<std::string, std::string> m_custom_data;
eqemu_callback m_on_destroy;
};
class EvoItemInst: public ItemInst {

View File

@ -0,0 +1,17 @@
#include <map>
#include "callback_manager.h"
std::map<std::string, eqemu_callback> callback_functions;
void RegisterEQCallback(std::string name, eqemu_callback func) {
callback_functions[name] = func;
}
eqemu_callback GetEQCallback(std::string name) {
auto iter = callback_functions.find(name);
if(iter == callback_functions.end()) {
return nullptr;
}
return iter->second;
}

12
common/callback_manager.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef EQEMU_CALLBACK_MANAGER_H
#define EQEMU_CALLBACK_MANAGER_H
#include <string>
#include <functional>
typedef std::function<void(void*)> eqemu_callback;
void RegisterEQCallback(std::string name, eqemu_callback func);
eqemu_callback GetEQCallback(std::string name);
#endif

View File

@ -34,7 +34,7 @@ public:
std::vector<ItemInst*> *items) { return 0; }
virtual int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data) { return 0; }
virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data) { return 0; }
virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data) { return 0; }
virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data) { return 0; }
virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data) { return 0; }
virtual int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data) { return 0; }
@ -49,14 +49,14 @@ public:
virtual void LoadGlobalNPCScript(std::string filename) { }
virtual void LoadPlayerScript(std::string filename) { }
virtual void LoadGlobalPlayerScript(std::string filename) { }
virtual void LoadItemScript(std::string filename, std::string item_script) { }
virtual void LoadItemScript(std::string filename, ItemInst *item) { }
virtual void LoadSpellScript(std::string filename, uint32 spell_id) { }
virtual void LoadEncounterScript(std::string filename, std::string encounter_name) { }
virtual void DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<ItemInst*> *items) { }
virtual void DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data) { }
virtual void DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data) { }
virtual void DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data) { }
virtual void DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data) { }
virtual void AddVar(std::string name, std::string val) { }

View File

@ -194,16 +194,17 @@ bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, const char *subnam
bool QuestParserCollection::ItemHasQuestSub(ItemInst *itm, const char *subname) {
std::string item_script;
if(strcmp("EVENT_SCALE_CALC", subname) == 0 || strcmp("EVENT_ITEM_ENTER_ZONE", subname) == 0) {
item_script = itm->GetItem()->CharmFile;
} else if(strcmp("EVENT_ITEM_CLICK", subname) == 0 || strcmp("EVENT_ITEM_CLICK_CAST", subname) == 0) {
if(itm->GetItem()->ScriptFileID != 0) {
item_script = "script_";
item_script += itoa(itm->GetItem()->ScriptFileID);
item_script += std::to_string(itm->GetItem()->ScriptFileID);
} else if(strlen(itm->GetItem()->CharmFile) > 0) {
item_script = itm->GetItem()->CharmFile;
} else {
item_script += itoa(itm->GetItem()->ID);
item_script = std::to_string(itm->GetID());
}
std::map<std::string, uint32>::iterator iter = _item_quest_status.find(item_script);
uint32 item_id = itm->GetID();
std::map<uint32, uint32>::iterator iter = _item_quest_status.find(item_id);
if(iter != _item_quest_status.end()) {
//loaded or failed to load
if(iter->second != QuestFailedToLoad) {
@ -214,11 +215,11 @@ bool QuestParserCollection::ItemHasQuestSub(ItemInst *itm, const char *subname)
std::string filename;
QuestInterface *qi = GetQIByItemQuest(item_script, filename);
if(qi) {
_item_quest_status[item_script] = qi->GetIdentifier();
qi->LoadItemScript(filename, item_script);
_item_quest_status[item_id] = qi->GetIdentifier();
qi->LoadItemScript(filename, itm);
return qi->ItemHasQuestSub(itm, subname);
} else {
_item_quest_status[item_script] = QuestFailedToLoad;
_item_quest_status[item_id] = QuestFailedToLoad;
}
}
return false;
@ -333,39 +334,40 @@ int QuestParserCollection::EventPlayerGlobal(QuestEventID evt, Client *client, s
return 0;
}
int QuestParserCollection::EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data) {
int QuestParserCollection::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data) {
std::string item_script;
if(evt == EVENT_SCALE_CALC || evt == EVENT_ITEM_ENTER_ZONE) {
item_script = item->GetItem()->CharmFile;
} else if(evt == EVENT_ITEM_CLICK || evt == EVENT_ITEM_CLICK_CAST) {
if(item->GetItem()->ScriptFileID != 0) {
item_script = "script_";
item_script += itoa(item->GetItem()->ScriptFileID);
item_script += std::to_string(item->GetItem()->ScriptFileID);
} else if(strlen(item->GetItem()->CharmFile) > 0) {
item_script = item->GetItem()->CharmFile;
} else {
item_script += itoa(item->GetItem()->ID);
item_script = std::to_string(item->GetID());
}
std::map<std::string, uint32>::iterator iter = _item_quest_status.find(item_script);
uint32 item_id = item->GetID();
std::map<uint32, uint32>::iterator iter = _item_quest_status.find(item_id);
if(iter != _item_quest_status.end()) {
//loaded or failed to load
if(iter->second != QuestFailedToLoad) {
std::map<uint32, QuestInterface*>::iterator qiter = _interfaces.find(iter->second);
auto ret = qiter->second->EventItem(evt, client, item, objid, extra_data);
DispatchEventItem(evt, client, item, objid, extra_data);
auto ret = qiter->second->EventItem(evt, client, item, mob, data, extra_data);
DispatchEventItem(evt, client, item, mob, data, extra_data);
return ret;
}
DispatchEventItem(evt, client, item, objid, extra_data);
DispatchEventItem(evt, client, item, mob, data, extra_data);
} else {
std::string filename;
QuestInterface *qi = GetQIByItemQuest(item_script, filename);
if(qi) {
_item_quest_status[item_script] = qi->GetIdentifier();
qi->LoadItemScript(filename, item_script);
auto ret = qi->EventItem(evt, client, item, objid, extra_data);
DispatchEventItem(evt, client, item, objid, extra_data);
_item_quest_status[item_id] = qi->GetIdentifier();
qi->LoadItemScript(filename, item);
auto ret = qi->EventItem(evt, client, item, mob, data, extra_data);
DispatchEventItem(evt, client, item, mob, data, extra_data);
return ret;
} else {
_item_quest_status[item_script] = QuestFailedToLoad;
DispatchEventItem(evt, client, item, objid, extra_data);
_item_quest_status[item_id] = QuestFailedToLoad;
DispatchEventItem(evt, client, item, mob, data, extra_data);
}
}
return 0;
@ -869,10 +871,11 @@ void QuestParserCollection::DispatchEventPlayer(QuestEventID evt, Client *client
}
}
void QuestParserCollection::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data) {
void QuestParserCollection::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data,
uint32 extra_data) {
auto iter = _load_precedence.begin();
while(iter != _load_precedence.end()) {
(*iter)->DispatchEventItem(evt, client, item, objid, extra_data);
(*iter)->DispatchEventItem(evt, client, item, mob, data, extra_data);
++iter;
}
}

View File

@ -52,7 +52,7 @@ public:
int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<ItemInst*> *items = nullptr);
int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data);
int EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data);
int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data);
int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data);
int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data);
@ -79,7 +79,7 @@ private:
void DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector<ItemInst*> *items);
void DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data);
void DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data);
void DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data);
void DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data);
std::map<uint32, QuestInterface*> _interfaces;
@ -93,7 +93,7 @@ private:
uint32 _player_quest_status;
uint32 _global_player_quest_status;
std::map<uint32, uint32> _spell_quest_status;
std::map<std::string, uint32> _item_quest_status;
std::map<uint32, uint32> _item_quest_status;
std::map<std::string, uint32> _encounter_quest_status;
};

View File

@ -2443,9 +2443,9 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y, bool login)
uint16 oldexp = e_inst->GetExp();
if(login) {
parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, e_inst, e_inst->GetID(), 0);
parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, e_inst, nullptr, "", 0);
}
parse->EventItem(EVENT_SCALE_CALC, this, e_inst, e_inst->GetID(), 0);
parse->EventItem(EVENT_SCALE_CALC, this, e_inst, nullptr, "", 0);
if (e_inst->GetExp() != oldexp) { // if the scaling factor changed, rescale the item and update the client
e_inst->ScaleItem();
@ -2467,9 +2467,9 @@ bool Client::CalcItemScale(uint32 slot_x, uint32 slot_y, bool login)
uint16 oldexp = e_inst->GetExp();
if(login) {
parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, e_inst, e_inst->GetID(), 0);
parse->EventItem(EVENT_ITEM_ENTER_ZONE, this, e_inst, nullptr, "", 0);
}
parse->EventItem(EVENT_SCALE_CALC, this, e_inst, e_inst->GetID(), 0);
parse->EventItem(EVENT_SCALE_CALC, this, e_inst, nullptr, "", 0);
if (e_inst->GetExp() != oldexp)
{

View File

@ -7697,7 +7697,7 @@ void Client::TryItemTick(int slot)
if( GetLevel() >= zone->tick_items[iid].level && MakeRandomInt(0, 100) >= (100 - zone->tick_items[iid].chance) && (zone->tick_items[iid].bagslot || slot < 22) )
{
ItemInst* e_inst = (ItemInst*)inst;
parse->EventItem(EVENT_ITEM_TICK, this, e_inst, e_inst->GetID(), slot);
parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot);
}
}
@ -7716,7 +7716,7 @@ void Client::TryItemTick(int slot)
if( GetLevel() >= zone->tick_items[iid].level && MakeRandomInt(0, 100) >= (100 - zone->tick_items[iid].chance) )
{
ItemInst* e_inst = (ItemInst*)a_inst;
parse->EventItem(EVENT_ITEM_TICK, this, e_inst, e_inst->GetID(), slot);
parse->EventItem(EVENT_ITEM_TICK, this, e_inst, nullptr, "", slot);
}
}
}

View File

@ -2059,7 +2059,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
{
ItemInst* p_inst = (ItemInst*)inst;
int i = parse->EventItem(EVENT_ITEM_CLICK, this, p_inst, p_inst->GetID(), slot_id);
int i = parse->EventItem(EVENT_ITEM_CLICK, this, p_inst, nullptr, "", slot_id);
inst = m_inv[slot_id];
if(!inst)
{
@ -2114,7 +2114,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
}
if(GetLevel() >= item->Click.Level2)
{
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, p_inst->GetID(), slot_id);
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", slot_id);
inst = m_inv[slot_id];
if(!inst)
{
@ -2141,7 +2141,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
}
if(GetLevel() >= augitem->Click.Level2)
{
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, clickaug, clickaug->GetID(), slot_id);
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, clickaug, nullptr, "", slot_id);
inst = m_inv[slot_id];
if(!inst)
{
@ -4595,7 +4595,7 @@ LogFile->write(EQEMuLog::Debug, "OP CastSpell: slot=%d, spell=%d, target=%d, inv
if(GetLevel() >= item->Click.Level2)
{
ItemInst* p_inst = (ItemInst*)inst;
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, p_inst->GetID(), castspell->inventoryslot);
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot);
if(i != 0) {
CastSpell(item->Click.Effect, castspell->target_id, castspell->slot, item->CastTime, 0, 0, castspell->inventoryslot);
@ -4614,7 +4614,7 @@ LogFile->write(EQEMuLog::Debug, "OP CastSpell: slot=%d, spell=%d, target=%d, inv
else
{
ItemInst* p_inst = (ItemInst*)inst;
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, p_inst->GetID(), castspell->inventoryslot);
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot);
if(i != 0) {
CastSpell(item->Click.Effect, castspell->target_id, castspell->slot, item->CastTime, 0, 0, castspell->inventoryslot);

View File

@ -225,8 +225,8 @@ int PerlembParser::EventGlobalPlayer(QuestEventID evt, Client *client, std::stri
return 0;
}
int PerlembParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data) {
EventCommon(evt, objid, nullptr, nullptr, item, client, extra_data, false, nullptr);
int PerlembParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data) {
EventCommon(evt, item->GetID(), nullptr, nullptr, item, client, extra_data, false, nullptr);
return 0;
}
@ -300,30 +300,12 @@ bool PerlembParser::SpellHasQuestSub(uint32 spell_id, const char *subname) {
bool PerlembParser::ItemHasQuestSub(ItemInst *itm, const char *subname) {
std::stringstream package_name;
package_name << "qst_item_";
std::string item_name;
const Item_Struct* item = itm->GetItem();
if(strcmp("EVENT_SCALE_CALC", subname) == 0 || strcmp("EVENT_ITEM_ENTER_ZONE", subname) == 0)
{
item_name = item->CharmFile;
}
else if(strcmp("EVENT_ITEM_CLICK", subname) == 0 || strcmp("EVENT_ITEM_CLICK_CAST", subname) == 0 )
{
item_name = "script_";
item_name += itoa(item->ScriptFileID);
}
else
{
item_name += itoa(item->ID);
}
package_name << item_name;
package_name << "qst_item_" << itm->GetID();
if(!perl)
return false;
auto iter = item_quest_status_.find(item_name);
auto iter = item_quest_status_.find(itm->GetID());
if(iter == item_quest_status_.end() || iter->second == QuestFailedToLoad) {
return false;
}
@ -439,34 +421,34 @@ void PerlembParser::LoadGlobalPlayerScript(std::string filename) {
global_player_quest_status_ = questLoaded;
}
void PerlembParser::LoadItemScript(std::string filename, std::string item_script) {
void PerlembParser::LoadItemScript(std::string filename, ItemInst *item) {
std::stringstream package_name;
package_name << "qst_item_" << item_script;
package_name << "qst_item_" << item->GetID();
if(!perl)
return;
if(perl->InUse())
{
return;
}
auto iter = item_quest_status_.find(item_script);
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());
}
catch(const char *err)
{
LogFile->write(EQEMuLog::Quest, "WARNING: error compiling quest file %s: %s", filename.c_str(), err);
item_quest_status_[item_script] = questFailedToLoad;
item_quest_status_[item->GetID()] = questFailedToLoad;
return;
}
item_quest_status_[item_script] = questLoaded;
item_quest_status_[item->GetID()] = questLoaded;
}
void PerlembParser::LoadSpellScript(std::string filename, uint32 spell_id) {
@ -810,17 +792,7 @@ void PerlembParser::GetQuestPackageName(bool &isPlayerQuest, bool &isGlobalPlaye
else if(isItemQuest) {
const Item_Struct* item = iteminst->GetItem();
package_name = "qst_item_";
if (event == EVENT_SCALE_CALC || event == EVENT_ITEM_ENTER_ZONE) {
package_name += item->CharmFile;
}
else if (event == EVENT_ITEM_CLICK || event == EVENT_ITEM_CLICK_CAST) {
package_name += "script_";
package_name += itoa(item->ScriptFileID);
}
else {
package_name += itoa(objid);
}
package_name += itoa(item->ID);
}
else if(isPlayerQuest) {
package_name = "qst_player";

View File

@ -62,7 +62,7 @@ public:
std::vector<ItemInst*> *items);
virtual int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data);
virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data);
virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data);
virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data);
virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data);
virtual bool HasQuestSub(uint32 npcid, const char *subname);
@ -76,7 +76,7 @@ public:
virtual void LoadGlobalNPCScript(std::string filename);
virtual void LoadPlayerScript(std::string filename);
virtual void LoadGlobalPlayerScript(std::string filename);
virtual void LoadItemScript(std::string filename, std::string item_script);
virtual void LoadItemScript(std::string filename, ItemInst *item);
virtual void LoadSpellScript(std::string filename, uint32 spell_id);
virtual void AddVar(std::string name, std::string val);
@ -121,7 +121,7 @@ private:
PerlQuestStatus global_npc_quest_status_;
PerlQuestStatus player_quest_status_;
PerlQuestStatus global_player_quest_status_;
std::map<std::string, PerlQuestStatus> item_quest_status_;
std::map<uint32, PerlQuestStatus> item_quest_status_;
std::map<uint32, PerlQuestStatus> spell_quest_status_;
bool event_queue_in_use_;

View File

@ -330,7 +330,7 @@ void Client::DropItem(int16 slot_id)
// Take control of item in client inventory
ItemInst *inst = m_inv.PopItem(slot_id);
if(inst) {
int i = parse->EventItem(EVENT_DROP_ITEM, this, inst, 0, 0);
int i = parse->EventItem(EVENT_DROP_ITEM, this, inst, nullptr, "", 0);
if(i != 0) {
safe_delete(inst);
return;
@ -1014,7 +1014,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
ItemInst *inst = m_inv.GetItem(SLOT_CURSOR);
if(inst) {
parse->EventItem(EVENT_DESTROY_ITEM, this, inst, 0, 0);
parse->EventItem(EVENT_DESTROY_ITEM, this, inst, nullptr, "", 0);
}
DeleteItemInInventory(move_in->from_slot);

View File

@ -112,29 +112,11 @@ void register_item_event(std::string name, int evt, Lua_Item item, luabind::obje
return;
}
std::stringstream package_name;
package_name << "item_";
std::string package_name = "item_";
package_name += std::to_string(itm->ID);
std::stringstream item_name;
if(EVENT_SCALE_CALC == evt || EVENT_ITEM_ENTER_ZONE == evt)
{
item_name << itm->CharmFile;
}
else if(EVENT_ITEM_CLICK == evt || EVENT_ITEM_CLICK_CAST == evt)
{
item_name << "script_";
item_name << itm->ScriptFileID;
}
else
{
item_name << "item_";
item_name << itm->ID;
}
package_name << item_name;
if(luabind::type(func) == LUA_TFUNCTION) {
register_event(package_name.str(), name, evt, func);
register_event(package_name, name, evt, func);
}
}
@ -144,27 +126,10 @@ void unregister_item_event(std::string name, int evt, Lua_Item item) {
return;
}
std::stringstream package_name;
package_name << "item_";
std::stringstream item_name;
if(EVENT_SCALE_CALC == evt || EVENT_ITEM_ENTER_ZONE == evt)
{
item_name << itm->CharmFile;
}
else if(EVENT_ITEM_CLICK == evt || EVENT_ITEM_CLICK_CAST == evt)
{
item_name << "script_";
item_name << itm->ScriptFileID;
}
else
{
item_name << "item_";
item_name << itm->ID;
}
package_name << item_name;
unregister_event(package_name.str(), name, evt);
std::string package_name = "item_";
package_name += std::to_string(itm->ID);
unregister_event(package_name, name, evt);
}
void register_spell_event(std::string name, int evt, int spell_id, luabind::object func) {

View File

@ -366,43 +366,26 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client *
return 0;
}
int LuaParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data) {
int LuaParser::EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data) {
if(evt >= _LargestEventID) {
return 0;
}
if(!item) {
return 0;
}
if(!ItemHasQuestSub(item, LuaEvents[evt])) {
return 0;
}
std::string package_name = "item_";
std::stringstream item_name;
const Item_Struct* itm = item->GetItem();
if(evt == EVENT_SCALE_CALC || evt == EVENT_ITEM_ENTER_ZONE)
{
item_name << itm->CharmFile;
}
else if(evt == EVENT_ITEM_CLICK || evt == EVENT_ITEM_CLICK_CAST)
{
item_name << "script_";
item_name << itm->ScriptFileID;
}
else
{
item_name << itm->ID;
}
package_name += item_name.str();
return _EventItem(package_name, evt, client, item, objid, extra_data);
package_name += std::to_string(item->GetID());
return _EventItem(package_name, evt, client, item, mob, data, extra_data);
}
int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data,
luabind::object *l_func) {
int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, Mob *mob,
std::string data, uint32 extra_data, luabind::object *l_func) {
const char *sub_name = LuaEvents[evt];
int start = lua_gettop(L);
@ -428,8 +411,9 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl
l_client_o.push(L);
lua_setfield(L, -2, "owner");
//redo this arg function
auto arg_function = ItemArgumentDispatch[evt];
arg_function(this, L, client, item, objid, extra_data);
arg_function(this, L, client, item, 0, extra_data);
quest_manager.StartQuest(nullptr, client, item);
if(lua_pcall(L, 1, 1, 0)) {
@ -630,24 +614,8 @@ bool LuaParser::SpellHasQuestSub(uint32 spell_id, const char *subname) {
bool LuaParser::ItemHasQuestSub(ItemInst *itm, const char *subname) {
std::string package_name = "item_";
package_name += std::to_string(itm->GetID());
std::stringstream item_name;
const Item_Struct* item = itm->GetItem();
if(strcmp("EVENT_SCALE_CALC", subname) == 0 || strcmp("EVENT_ITEM_ENTER_ZONE", subname) == 0)
{
item_name << item->CharmFile;
}
else if(strcmp("EVENT_ITEM_CLICK", subname) == 0 || strcmp("EVENT_ITEM_CLICK_CAST", subname) == 0 )
{
item_name << "script_";
item_name << item->ScriptFileID;
}
else
{
item_name << item->ID;
}
package_name += item_name.str();
return HasFunction(subname, package_name);
}
@ -676,11 +644,11 @@ void LuaParser::LoadGlobalPlayerScript(std::string filename) {
LoadScript(filename, "global_player");
}
void LuaParser::LoadItemScript(std::string filename, std::string item_script) {
std::stringstream package_name;
package_name << "item_" << item_script;
void LuaParser::LoadItemScript(std::string filename, ItemInst *item) {
std::string package_name = "item_";
package_name += std::to_string(item->GetID());
LoadScript(filename, package_name.str());
LoadScript(filename, package_name);
}
void LuaParser::LoadSpellScript(std::string filename, uint32 spell_id) {
@ -914,40 +882,23 @@ void LuaParser::DispatchEventPlayer(QuestEventID evt, Client *client, std::strin
}
}
void LuaParser::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data) {
void LuaParser::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data) {
if(!item)
return;
std::stringstream package_name;
package_name << "item_";
std::stringstream item_name;
const Item_Struct* itm = item->GetItem();
if(evt == EVENT_SCALE_CALC || evt == EVENT_ITEM_ENTER_ZONE)
{
item_name << itm->CharmFile;
}
else if(evt == EVENT_ITEM_CLICK || evt == EVENT_ITEM_CLICK_CAST)
{
item_name << "script_";
item_name << itm->ScriptFileID;
}
else
{
item_name << itm->ID;
}
package_name << item_name;
auto iter = lua_encounter_events_registered.find(package_name.str());
std::string package_name = "item_";
package_name += std::to_string(item->GetID());
auto iter = lua_encounter_events_registered.find(package_name);
if(iter == lua_encounter_events_registered.end()) {
return;
}
auto riter = iter->second.begin();
while(riter != iter->second.end()) {
if(riter->event_id == evt) {
std::string package_name = "encounter_" + riter->encounter_name;
_EventItem(package_name, evt, client, item, objid, extra_data, &riter->lua_reference);
_EventItem(package_name, evt, client, item, mob, data, extra_data, &riter->lua_reference);
}
++riter;
}

View File

@ -31,7 +31,7 @@ public:
std::vector<ItemInst*> *items);
virtual int EventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data);
virtual int EventGlobalPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data);
virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data);
virtual int EventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data);
virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data);
virtual int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data);
@ -47,7 +47,7 @@ public:
virtual void LoadGlobalNPCScript(std::string filename);
virtual void LoadPlayerScript(std::string filename);
virtual void LoadGlobalPlayerScript(std::string filename);
virtual void LoadItemScript(std::string filename, std::string item_script);
virtual void LoadItemScript(std::string filename, ItemInst *item);
virtual void LoadSpellScript(std::string filename, uint32 spell_id);
virtual void LoadEncounterScript(std::string filename, std::string encounter_name);
@ -60,7 +60,7 @@ public:
virtual void DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
std::vector<ItemInst*> *items);
virtual void DispatchEventPlayer(QuestEventID evt, Client *client, std::string data, uint32 extra_data);
virtual void DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data);
virtual void DispatchEventItem(QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data, uint32 extra_data);
virtual void DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data);
private:
@ -68,8 +68,8 @@ private:
std::vector<ItemInst*> *items, luabind::object *l_func = nullptr);
int _EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data,
luabind::object *l_func = nullptr);
int _EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, uint32 objid, uint32 extra_data,
luabind::object *l_func = nullptr);
int _EventItem(std::string package_name, QuestEventID evt, Client *client, ItemInst *item, Mob *mob, std::string data,
uint32 extra_data, luabind::object *l_func = nullptr);
int _EventSpell(std::string package_name, QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
luabind::object *l_func = nullptr);
int _EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, uint32 extra_data);

View File

@ -42,6 +42,7 @@
#include "../common/memory_mapped_file.h"
#include "../common/eqemu_exception.h"
#include "../common/spdat.h"
#include "../common/callback_manager.h"
#include "ZoneConfig.h"
#include "masterentity.h"
@ -85,8 +86,6 @@
volatile bool RunLoops = true;
extern volatile bool ZoneLoaded;
TimeoutManager timeout_manager;
NetConnection net;
EntityList entity_list;
@ -290,6 +289,10 @@ int main(int argc, char** argv) {
parse->RegisterQuestInterface(perl_parser, "pl");
#endif
RegisterEQCallback("OnItemInstDestroy", [](void* item) {
quest_manager.stop_item_timers(reinterpret_cast<ItemInst*>(item));
});
//now we have our parser, load the quests
_log(ZONE__INIT, "Loading quests");
parse->ReloadQuests();

View File

@ -107,6 +107,7 @@ QuestManager quest_manager;
QuestManager::QuestManager() {
HaveProximitySays = false;
item_timers = 0;
}
QuestManager::~QuestManager() {
@ -118,8 +119,13 @@ void QuestManager::Process() {
end = QTimerList.end();
while (cur != end) {
if (cur->Timer_.Enabled() && cur->Timer_.Check()) {
//make sure the mob is still in zone.
if(entity_list.IsMobInZone(cur->mob)){
if(cur->item) {
parse->EventItem(EVENT_TIMER, cur->mob->CastToClient(), cur->item, nullptr, cur->name, 0);
cur = QTimerList.begin();
end = QTimerList.end();
} else if(entity_list.IsMobInZone(cur->mob)) {
if(cur->mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER, cur->mob->CastToNPC(), nullptr, cur->name, 0);
}
@ -188,17 +194,7 @@ void QuestManager::EndQuest() {
}
void QuestManager::ClearAllTimers() {
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end, tmp;
end = QTimerList.end();
while (cur != end)
{
tmp = cur;
tmp++;
QTimerList.erase(cur);
cur = tmp;
}
QTimerList.clear();
}
//quest perl functions
@ -461,17 +457,16 @@ void QuestManager::settimer(const char *timer_name, int seconds) {
end = QTimerList.end();
while (cur != end) {
if (cur->mob == owner && cur->name == timer_name) {
if (cur->mob == owner && cur->item == questitem && cur->name == timer_name) {
cur->mob = owner;
cur->Timer_.Enable();
cur->Timer_.Start(seconds * 1000, false);
printf("Resetting: %s for %d seconds\n", cur->name.c_str(), seconds);
return;
}
cur++;
}
QTimerList.push_back(QuestTimer(seconds * 1000, owner, timer_name));
QTimerList.push_back(QuestTimer(seconds * 1000, owner, questitem, timer_name));
}
void QuestManager::settimerMS(const char *timer_name, int milliseconds) {
@ -481,17 +476,16 @@ void QuestManager::settimerMS(const char *timer_name, int milliseconds) {
end = QTimerList.end();
while (cur != end) {
if (cur->mob == owner && cur->name == timer_name) {
if (cur->mob == owner && cur->item == questitem && cur->name == timer_name) {
cur->mob = owner;
cur->Timer_.Enable();
cur->Timer_.Start(milliseconds, false);
printf("Resetting: %s for %d seconds\n", cur->name.c_str(), milliseconds);
return;
}
cur++;
}
QTimerList.push_back(QuestTimer(milliseconds, owner, timer_name));
QTimerList.push_back(QuestTimer(milliseconds, owner, questitem, timer_name));
}
void QuestManager::stoptimer(const char *timer_name) {
@ -502,7 +496,7 @@ void QuestManager::stoptimer(const char *timer_name) {
end = QTimerList.end();
while (cur != end)
{
if(cur->mob == owner && cur->name == timer_name)
if(cur->mob == owner && cur->item == questitem && cur->name == timer_name)
{
QTimerList.erase(cur);
return;
@ -519,7 +513,7 @@ void QuestManager::stopalltimers() {
end = QTimerList.end();
while (cur != end)
{
if(cur->mob == owner)
if(cur->mob == owner && cur->item == questitem)
{
tmp = cur;
tmp++;
@ -2905,3 +2899,19 @@ ItemInst *QuestManager::GetQuestItem() const {
return nullptr;
}
void QuestManager::stop_item_timers(ItemInst *item) {
if(item_timers == 0)
return;
auto iter = QTimerList.begin();
while(iter != QTimerList.end()) {
if(iter->item == item) {
iter = QTimerList.erase(iter);
--item_timers;
continue;
}
++iter;
}
}

View File

@ -237,6 +237,7 @@ public:
Mob *GetOwner() const;
ItemInst *GetQuestItem() const;
inline bool ProximitySayInUse() { return HaveProximitySays; }
void stop_item_timers(ItemInst *item);
#ifdef BOTS
int createbotcount();
@ -257,8 +258,10 @@ private:
class QuestTimer {
public:
inline QuestTimer(int duration, Mob *_mob, std::string _name) : mob(_mob), name(_name), Timer_(duration) { Timer_.Start(duration, false); }
inline QuestTimer(int duration, Mob *_mob, ItemInst *_item, std::string _name)
: mob(_mob), item(_item), name(_name), Timer_(duration) { Timer_.Start(duration, false); }
Mob* mob;
ItemInst *item;
std::string name;
Timer Timer_;
};
@ -271,6 +274,7 @@ private:
};
std::list<QuestTimer> QTimerList;
std::list<SignalTimer> STimerList;
size_t item_timers;
};