Implemented encounter timers - no spawn required

This commit is contained in:
Russell Kinasz 2015-06-02 12:25:09 -07:00
parent 66d37cabe4
commit 2c6fd44811
14 changed files with 237 additions and 19 deletions

53
zone/encounter.cpp Normal file
View File

@ -0,0 +1,53 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef _WINDOWS
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#endif
#include "../common/races.h"
#include "encounter.h"
#include "entity.h"
#include "mob.h"
class Zone;
Encounter::Encounter(const char* enc_name)
:Mob
(
nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, glm::vec4(0,0,0,0), 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
)
{
encounter_name[0] = 0;
strn0cpy(encounter_name, enc_name, 64);
remove_me = false;
}
Encounter::~Encounter()
{
}
bool Encounter::Process() {
if (remove_me) return false;
return true;
}

62
zone/encounter.h Normal file
View File

@ -0,0 +1,62 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2003 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef ENCOUNTER_H
#define ENCOUNTER_H
#include "mob.h"
#include "../common/types.h"
#include "../common/timer.h"
class Group;
class Raid;
struct ExtraAttackOptions;
class Encounter : public Mob
{
public:
Encounter(const char* enc_name);
~Encounter();
//abstract virtual function implementations required by base abstract class
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) { return true; }
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false) { return; }
virtual bool Attack(Mob* other, int Hand = MainPrimary, bool FromRiposte = false, bool IsStrikethrough = false, bool IsFromSpell = false,
ExtraAttackOptions *opts = nullptr) {
return false;
}
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
bool IsEncounter() const { return true; }
const char* GetEncounterName() const { return encounter_name; }
bool Process();
virtual void Depop(bool not_used = true) { remove_me = true; }
protected:
bool remove_me;
char encounter_name[64];
private:
};
#endif

View File

@ -173,6 +173,11 @@ Beacon *Entity::CastToBeacon()
return static_cast<Beacon *>(this);
}
Encounter *Entity::CastToEncounter()
{
return static_cast<Encounter *>(this);
}
const Client *Entity::CastToClient() const
{
if (this == 0x00) {
@ -263,6 +268,11 @@ const Beacon* Entity::CastToBeacon() const
return static_cast<const Beacon *>(this);
}
const Encounter* Entity::CastToEncounter() const
{
return static_cast<const Encounter *>(this);
}
#ifdef BOTS
Bot *Entity::CastToBot()
{
@ -533,6 +543,21 @@ void EntityList::BeaconProcess()
}
}
void EntityList::EncounterProcess()
{
auto it = encounter_list.begin();
while (it != encounter_list.end()) {
if (!it->second->Process()) {
safe_delete(it->second);
free_ids.push(it->first);
it = encounter_list.erase(it);
}
else {
++it;
}
}
}
void EntityList::AddGroup(Group *group)
{
if (group == nullptr) //this seems to be happening somehow...
@ -708,6 +733,12 @@ void EntityList::AddBeacon(Beacon *beacon)
beacon_list.insert(std::pair<uint16, Beacon *>(beacon->GetID(), beacon));
}
void EntityList::AddEncounter(Encounter *encounter)
{
encounter->SetID(GetFreeID());
encounter_list.insert(std::pair<uint16, Encounter *>(encounter->GetID(), encounter));
}
void EntityList::AddToSpawnQueue(uint16 entityid, NewSpawn_Struct **ns)
{
uint32 count;
@ -935,6 +966,11 @@ Entity *EntityList::GetEntityBeacon(uint16 id)
return beacon_list.count(id) ? beacon_list.at(id) : nullptr;
}
Entity *EntityList::GetEntityEncounter(uint16 id)
{
return encounter_list.count(id) ? encounter_list.at(id) : nullptr;
}
Entity *EntityList::GetID(uint16 get_id)
{
Entity *ent = 0;
@ -950,6 +986,8 @@ Entity *EntityList::GetID(uint16 get_id)
return ent;
else if ((ent=entity_list.GetEntityBeacon(get_id)) != 0)
return ent;
else if ((ent = entity_list.GetEntityEncounter(get_id)) != 0)
return ent;
else
return 0;
}
@ -3424,6 +3462,15 @@ bool EntityList::IsMobInZone(Mob *who)
}
++it;
}
auto enc_it = encounter_list.begin();
while (enc_it != encounter_list.end()) {
if (enc_it->second == who) {
return true;
}
++enc_it;
}
return false;
}

View File

@ -30,6 +30,7 @@
#include "position.h"
#include "zonedump.h"
class Encounter;
class Beacon;
class Client;
class Corpse;
@ -77,6 +78,7 @@ public:
virtual bool IsDoor() const { return false; }
virtual bool IsTrap() const { return false; }
virtual bool IsBeacon() const { return false; }
virtual bool IsEncounter() const { return false; }
virtual bool Process() { return false; }
virtual bool Save() { return true; }
@ -91,6 +93,7 @@ public:
Doors *CastToDoors();
Trap *CastToTrap();
Beacon *CastToBeacon();
Encounter *CastToEncounter();
const Client *CastToClient() const;
const NPC *CastToNPC() const;
@ -101,6 +104,7 @@ public:
const Doors *CastToDoors() const;
const Trap *CastToTrap() const;
const Beacon *CastToBeacon() const;
const Encounter *CastToEncounter() const;
inline const uint16& GetID() const { return id; }
inline const time_t& GetSpawnTimeStamp() const { return spawn_timestamp; }
@ -203,6 +207,7 @@ public:
void MobProcess();
void TrapProcess();
void BeaconProcess();
void EncounterProcess();
void ProcessMove(Client *c, const glm::vec3& location);
void ProcessMove(NPC *n, float x, float y, float z);
void AddArea(int id, int type, float min_x, float max_x, float min_y, float max_y, float min_z, float max_z);
@ -228,6 +233,7 @@ public:
void AddDoor(Doors* door);
void AddTrap(Trap* trap);
void AddBeacon(Beacon *beacon);
void AddEncounter(Encounter *encounter);
void AddProximity(NPC *proximity_for);
void Clear();
bool RemoveMob(uint16 delete_id);
@ -266,6 +272,7 @@ public:
Entity *GetEntityCorpse(uint16 id);
Entity *GetEntityTrap(uint16 id);
Entity *GetEntityBeacon(uint16 id);
Entity *GetEntityEncounter(uint16 id);
Entity *GetEntityMob(const char *name);
Entity *GetEntityCorpse(const char *name);
@ -448,6 +455,7 @@ private:
std::unordered_map<uint16, Doors *> door_list;
std::unordered_map<uint16, Trap *> trap_list;
std::unordered_map<uint16, Beacon *> beacon_list;
std::unordered_map<uint16, Encounter *> encounter_list;
std::list<NPC *> proximity_list;
std::list<Group *> group_list;
std::list<Raid *> raid_list;

View File

@ -34,6 +34,8 @@ struct lua_registered_event {
extern std::map<std::string, std::list<lua_registered_event>> lua_encounter_events_registered;
extern std::map<std::string, bool> lua_encounters_loaded;
extern std::map<std::string, Encounter *> lua_encounters;
extern void MapOpcodes();
extern void ClearMappedOpcode(EmuOpcode op);
@ -42,19 +44,23 @@ void unregister_event(std::string package_name, std::string name, int evt);
void load_encounter(std::string name) {
if(lua_encounters_loaded.count(name) > 0)
return;
Encounter *enc = new Encounter(name.c_str());
entity_list.AddEncounter(enc);
lua_encounters[name] = enc;
lua_encounters_loaded[name] = true;
parse->EventEncounter(EVENT_ENCOUNTER_LOAD, name, 0);
parse->EventEncounter(EVENT_ENCOUNTER_LOAD, name, "", 0);
}
void load_encounter_with_data(std::string name, std::string info_str) {
if(lua_encounters_loaded.count(name) > 0)
return;
Encounter *enc = new Encounter(name.c_str());
entity_list.AddEncounter(enc);
lua_encounters[name] = enc;
lua_encounters_loaded[name] = true;
std::vector<EQEmu::Any> info_ptrs;
info_ptrs.push_back(&info_str);
parse->EventEncounter(EVENT_ENCOUNTER_LOAD, name, 0, &info_ptrs);
parse->EventEncounter(EVENT_ENCOUNTER_LOAD, name, "", 0, &info_ptrs);
}
void unload_encounter(std::string name) {
@ -80,8 +86,10 @@ void unload_encounter(std::string name) {
}
}
lua_encounters[name]->Depop();
lua_encounters.erase(name);
lua_encounters_loaded.erase(name);
parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, 0);
parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, "", 0);
}
void unload_encounter_with_data(std::string name, std::string info_str) {
@ -109,10 +117,12 @@ void unload_encounter_with_data(std::string name, std::string info_str) {
}
}
lua_encounters[name]->Depop();
lua_encounters.erase(name);
lua_encounters_loaded.erase(name);
std::vector<EQEmu::Any> info_ptrs;
info_ptrs.push_back(&info_str);
parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, 0, &info_ptrs);
parse->EventEncounter(EVENT_ENCOUNTER_UNLOAD, name, "", 0, &info_ptrs);
}
void register_event(std::string package_name, std::string name, int evt, luabind::adl::object func) {

View File

@ -128,6 +128,7 @@ struct lua_registered_event {
std::map<std::string, std::list<lua_registered_event>> lua_encounter_events_registered;
std::map<std::string, bool> lua_encounters_loaded;
std::map<std::string, Encounter *> lua_encounters;
LuaParser::LuaParser() {
for(int i = 0; i < _LargestEventID; ++i) {
@ -135,6 +136,7 @@ LuaParser::LuaParser() {
PlayerArgumentDispatch[i] = handle_player_null;
ItemArgumentDispatch[i] = handle_item_null;
SpellArgumentDispatch[i] = handle_spell_null;
EncounterArgumentDispatch[i] = handle_encounter_null;
}
NPCArgumentDispatch[EVENT_SAY] = handle_npc_event_say;
@ -213,6 +215,8 @@ LuaParser::LuaParser() {
SpellArgumentDispatch[EVENT_SPELL_FADE] = handle_spell_fade;
SpellArgumentDispatch[EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE] = handle_translocate_finish;
EncounterArgumentDispatch[EVENT_TIMER] = handle_encounter_timer;
L = nullptr;
}
@ -575,7 +579,7 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, NPC* npc,
return 0;
}
int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data, std::vector<EQEmu::Any> *extra_pointers) {
int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data, std::vector<EQEmu::Any> *extra_pointers) {
evt = ConvertLuaEvent(evt);
if(evt >= _LargestEventID) {
return 0;
@ -587,10 +591,10 @@ int LuaParser::EventEncounter(QuestEventID evt, std::string encounter_name, uint
return 0;
}
return _EventEncounter(package_name, evt, encounter_name, extra_data, extra_pointers);
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, uint32 extra_data,
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];
@ -604,13 +608,17 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::
lua_pushstring(L, encounter_name.c_str());
lua_setfield(L, -2, "name");
if(extra_pointers) {
/*if(extra_pointers) {
std::string *str = EQEmu::any_cast<std::string*>(extra_pointers->at(0));
lua_pushstring(L, str->c_str());
lua_setfield(L, -2, "data");
}
}*/
quest_manager.StartQuest(nullptr, nullptr, nullptr, encounter_name);
auto arg_function = EncounterArgumentDispatch[evt];
arg_function(this, L, data, extra_data, extra_pointers);
Encounter *enc = lua_encounters[encounter_name];
quest_manager.StartQuest(enc, nullptr, nullptr, encounter_name);
if(lua_pcall(L, 1, 1, 0)) {
std::string error = lua_tostring(L, -1);
AddError(error);
@ -786,6 +794,11 @@ void LuaParser::ReloadQuests() {
lua_encounter_events_registered.clear();
lua_encounters_loaded.clear();
for (auto encounter : lua_encounters) {
encounter.second->Depop();
}
lua_encounters.clear();
if(L) {
lua_close(L);
}

View File

@ -39,7 +39,7 @@ public:
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
virtual int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data,
virtual int EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
virtual bool HasQuestSub(uint32 npc_id, QuestEventID evt);
@ -82,7 +82,7 @@ private:
uint32 extra_data, std::vector<EQEmu::Any> *extra_pointers, luabind::adl::object *l_func = nullptr);
int _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 = nullptr);
int _EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, uint32 extra_data,
int _EventEncounter(std::string package_name, QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
void LoadScript(std::string filename, std::string package_name);
@ -99,6 +99,8 @@ private:
PlayerArgumentHandler PlayerArgumentDispatch[_LargestEventID];
ItemArgumentHandler ItemArgumentDispatch[_LargestEventID];
SpellArgumentHandler SpellArgumentDispatch[_LargestEventID];
EncounterArgumentHandler EncounterArgumentDispatch[_LargestEventID];
};
#endif

View File

@ -704,4 +704,15 @@ void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* cl
std::vector<EQEmu::Any> *extra_pointers) {
}
void handle_encounter_timer(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "timer");
}
void handle_encounter_null(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) {
}
#endif

View File

@ -6,6 +6,7 @@ typedef void(*NPCArgumentHandler)(QuestInterface*, lua_State*, NPC*, Mob*, std::
typedef void(*PlayerArgumentHandler)(QuestInterface*, lua_State*, Client*, std::string, uint32, std::vector<EQEmu::Any>*);
typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, ItemInst*, Mob*, std::string, uint32, std::vector<EQEmu::Any>*);
typedef void(*SpellArgumentHandler)(QuestInterface*, lua_State*, NPC*, Client*, uint32, uint32, std::vector<EQEmu::Any>*);
typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, std::string, uint32, std::vector<EQEmu::Any>*);
//NPC
void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
@ -127,5 +128,12 @@ void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Cl
void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
//Encounter
void handle_encounter_timer(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
void handle_encounter_null(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
#endif
#endif

View File

@ -423,6 +423,7 @@ int main(int argc, char** argv) {
entity_list.Process();
entity_list.MobProcess();
entity_list.BeaconProcess();
entity_list.EncounterProcess();
if (zone) {
if(!zone->Process()) {

View File

@ -41,7 +41,7 @@ public:
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data,
virtual int EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) { return 0; }
virtual bool HasQuestSub(uint32 npcid, QuestEventID evt) { return false; }

View File

@ -434,14 +434,14 @@ int QuestParserCollection::EventSpell(QuestEventID evt, NPC* npc, Client *client
return 0;
}
int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data,
int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) {
auto iter = _encounter_quest_status.find(encounter_name);
if(iter != _encounter_quest_status.end()) {
//loaded or failed to load
if(iter->second != QuestFailedToLoad) {
std::map<uint32, QuestInterface*>::iterator qiter = _interfaces.find(iter->second);
return qiter->second->EventEncounter(evt, encounter_name, extra_data, extra_pointers);
return qiter->second->EventEncounter(evt, encounter_name, data, extra_data, extra_pointers);
}
} else {
std::string filename;
@ -449,7 +449,7 @@ int QuestParserCollection::EventEncounter(QuestEventID evt, std::string encounte
if(qi) {
_encounter_quest_status[encounter_name] = qi->GetIdentifier();
qi->LoadEncounterScript(filename, encounter_name);
return qi->EventEncounter(evt, encounter_name, extra_data, extra_pointers);
return qi->EventEncounter(evt, encounter_name, data, extra_data, extra_pointers);
} else {
_encounter_quest_status[encounter_name] = QuestFailedToLoad;
}

View File

@ -21,6 +21,7 @@
#include "../common/types.h"
#include "encounter.h"
#include "beacon.h"
#include "client.h"
#include "corpse.h"
@ -71,7 +72,7 @@ public:
std::vector<EQEmu::Any> *extra_pointers = nullptr);
int EventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers = nullptr);
int EventEncounter(QuestEventID evt, std::string encounter_name, uint32 extra_data,
int EventEncounter(QuestEventID evt, std::string encounter_name, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers = nullptr);
void GetErrors(std::list<std::string> &err);

View File

@ -84,6 +84,8 @@ void QuestManager::Process() {
if(entity_list.IsMobInZone(cur->mob)) {
if(cur->mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER, cur->mob->CastToNPC(), nullptr, cur->name, 0);
} else if (cur->mob->IsEncounter()) {
parse->EventEncounter(EVENT_TIMER, cur->mob->CastToEncounter()->GetEncounterName(), cur->name, 0, nullptr);
} else {
//this is inheriently unsafe if we ever make it so more than npc/client start timers
parse->EventPlayer(EVENT_TIMER, cur->mob->CastToClient(), cur->name, 0);