diff --git a/zone/command.cpp b/zone/command.cpp index 93698fca0..18496b9d6 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -3388,11 +3388,13 @@ void command_reloadqst(Client *c, const Seperator *sep) if (sep->arg[1][0] == 0) { c->Message(0, "Clearing quest memory cache."); + entity_list.ClearAreas(); parse->ReloadQuests(); } else { c->Message(0, "Clearing quest memory cache and stopping timers."); + entity_list.ClearAreas(); parse->ReloadQuests(true); } diff --git a/zone/entity.cpp b/zone/entity.cpp index 8deeba20d..b5aa20c66 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1334,8 +1334,6 @@ void EntityList::SendZoneSpawnsBulk(Client* client) Mob *spawn; uint32 maxspawns=100; - //rate = rate > 1.0 ? (rate < 10.0 ? rate : 10.0) : 1.0; - //maxspawns = (uint32)rate * SPAWNS_PER_POINT_DATARATE; // FYI > 10240 entities will cause BulkZoneSpawnPacket to throw exception if(maxspawns > mob_list.Count()) maxspawns = mob_list.Count(); BulkZoneSpawnPacket* bzsp = new BulkZoneSpawnPacket(client, maxspawns); @@ -1389,8 +1387,6 @@ void EntityList::SendZoneCorpsesBulk(Client* client) { Corpse *spawn; uint32 maxspawns=100; - //rate = rate > 1.0 ? (rate < 10.0 ? rate : 10.0) : 1.0; - //maxspawns = (uint32)rate * SPAWNS_PER_POINT_DATARATE; // FYI > 10240 entities will cause BulkZoneSpawnPacket to throw exception BulkZoneSpawnPacket* bzsp = new BulkZoneSpawnPacket(client, maxspawns); for(iterator.Reset(); iterator.MoreElements(); iterator.Advance()) @@ -3527,31 +3523,26 @@ void EntityList::SendAlarm(Trap* trap, Mob* currenttarget, uint8 kos) void EntityList::AddProximity(NPC *proximity_for) { RemoveProximity(proximity_for->GetID()); - proximity_list.Insert(proximity_for); + proximity_list.push_back(proximity_for); proximity_for->proximity = new NPCProximity; } bool EntityList::RemoveProximity(uint16 delete_npc_id) { - LinkedListIterator iterator(proximity_list); - iterator.Reset(); - while(iterator.MoreElements()) { - NPC *d = iterator.GetData(); - if(d->GetID() == delete_npc_id) { - //safe_delete(d->proximity); - iterator.RemoveCurrent(false); + auto iter = proximity_list.begin(); + + while(iter != proximity_list.end()) { + if((*iter)->GetID() == delete_npc_id) { + proximity_list.erase(iter); return true; } - iterator.Advance(); + ++iter; } return false; } void EntityList::RemoveAllLocalities() { - LinkedListIterator iterator(proximity_list); - iterator.Reset(); - while(iterator.MoreElements()) - iterator.RemoveCurrent(false); + proximity_list.clear(); } void EntityList::ProcessMove(Client *c, float x, float y, float z) { @@ -3559,15 +3550,15 @@ void EntityList::ProcessMove(Client *c, float x, float y, float z) { We look through each proximity, looking to see if last_* was in(out) the proximity, and the new supplied coords are out(in)... */ - LinkedListIterator iterator(proximity_list); std::list skip_ids; float last_x = c->ProximityX(); float last_y = c->ProximityY(); float last_z = c->ProximityZ(); - for(iterator.Reset(); iterator.MoreElements(); iterator.Advance()) { - NPC *d = iterator.GetData(); + auto iter = proximity_list.begin(); + for(; iter != proximity_list.end(); ++iter) { + NPC *d = (*iter); NPCProximity *l = d->proximity; if(l == nullptr) continue; @@ -3577,16 +3568,16 @@ void EntityList::ProcessMove(Client *c, float x, float y, float z) { //This causes our list to become invalid but we don't know it. On GCC it's basic heap //corruption and it doesn't appear to catch it at all. //MSVC it's a crash with 0xfeeefeee debug address (freed memory off the heap) - std::list::iterator iter = skip_ids.begin(); + std::list::iterator skip_iter = skip_ids.begin(); bool skip = false; - while(iter != skip_ids.end()) + while(skip_iter != skip_ids.end()) { - if(d->GetID() == (*iter)) + if(d->GetID() == (*skip_iter)) { skip = true; break; } - iter++; + ++skip_iter; } if(skip) @@ -3614,18 +3605,120 @@ void EntityList::ProcessMove(Client *c, float x, float y, float z) { parse->EventNPC(EVENT_EXIT, d, c, "", 0); //Reentrant fix - iterator.Reset(); + iter = proximity_list.begin(); skip_ids.push_back(d->GetID()); } else if(new_in && !old_in) { //we were not in the proximity, we are now, send enter event parse->EventNPC(EVENT_ENTER, d, c, "", 0); //Reentrant fix - iterator.Reset(); + iter = proximity_list.begin(); skip_ids.push_back(d->GetID()); } } + for(auto area_iter = area_list.begin(); area_iter != area_list.end(); ++area_iter) { + Area& a = (*area_iter); + bool old_in = true; + bool new_in = true; + if(last_x < a.min_x || last_x > a.max_x || + last_y < a.min_y || last_y > a.max_y || + last_z < a.min_z || last_z > a.max_z ) + { + old_in = false; + } + + if(x < a.min_x || x > a.max_x || + y < a.min_y || y > a.max_y || + z < a.min_z || z > a.max_z ) + { + new_in = false; + } + + if(old_in && !new_in) { + //were in but are no longer. + } else if (!old_in && new_in) { + //were not in but now are + } + } +} + +void EntityList::ProcessMove(NPC *n, float x, float y, float z) { + float last_x = n->GetX(); + float last_y = n->GetY(); + float last_z = n->GetZ(); + + for(auto area_iter = area_list.begin(); area_iter != area_list.end(); ++area_iter) { + Area& a = (*area_iter); + bool old_in = true; + bool new_in = true; + if(last_x < a.min_x || last_x > a.max_x || + last_y < a.min_y || last_y > a.max_y || + last_z < a.min_z || last_z > a.max_z ) + { + old_in = false; + } + + if(x < a.min_x || x > a.max_x || + y < a.min_y || y > a.max_y || + z < a.min_z || z > a.max_z ) + { + new_in = false; + } + + if(old_in && !new_in) { + //were in but are no longer. + } else if (!old_in && new_in) { + //were not in but now are + } + } +} + +void EntityList::AddArea(int id, int type, float min_x, float max_x, float min_y, float max_y, float min_z, float max_z) { + RemoveArea(id); + Area a; + a.id = id; + a.type = type; + if(min_x > max_x) { + a.min_x = max_x; + a.max_x = min_x; + } else { + a.min_x = min_x; + a.max_x = max_x; + } + + if(min_y > max_y) { + a.min_y = max_y; + a.max_y = min_y; + } else { + a.min_y = min_y; + a.max_y = max_y; + } + + if(min_z > max_z) { + a.min_z = max_z; + a.max_z = min_z; + } else { + a.min_z = min_z; + a.max_z = max_z; + } + + area_list.push_back(a); +} + +void EntityList::RemoveArea(int id) { + auto iter = area_list.begin(); + while(iter != area_list.end()) { + if((*iter).id == id) { + area_list.erase(iter); + return; + } + ++iter; + } +} + +void EntityList::ClearAreas() { + area_list.clear(); } void EntityList::ProcessProximitySay(const char *Message, Client *c, uint8 language) { @@ -3633,10 +3726,9 @@ void EntityList::ProcessProximitySay(const char *Message, Client *c, uint8 langu if(!Message || !c) return; - LinkedListIterator iterator(proximity_list); - - for(iterator.Reset(); iterator.MoreElements(); iterator.Advance()) { - NPC *d = iterator.GetData(); + auto iter = proximity_list.begin(); + for(; iter != proximity_list.end(); ++iter) { + NPC *d = (*iter); NPCProximity *l = d->proximity; if(l == nullptr || !l->say) continue; diff --git a/zone/entity.h b/zone/entity.h index 492501bb0..32878876f 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -29,15 +29,7 @@ #include "zonedbasync.h" #include "QGlobals.h" -// max number of newspawns to send per bulk packet -#define SPAWNS_PER_POINT_DATARATE 10 -#define MAX_SPAWNS_PER_PACKET 100 - -//#ifdef _WINDOWS - class EQApplicationPacket; -//#else -// struct EQApplicationPacket; -//#endif +class EQApplicationPacket; class Client; class Mob; @@ -61,8 +53,6 @@ class BotRaids; extern EntityList entity_list; -void ProcessClientThreadSpawn(void *tmp); - class Entity { public: @@ -77,7 +67,6 @@ public: virtual bool IsPlayerCorpse() const { return false; } virtual bool IsNPCCorpse() const { return false; } virtual bool IsObject() const { return false; } -// virtual bool IsGroup() const { return false; } virtual bool IsDoor() const { return false; } virtual bool IsTrap() const { return false; } virtual bool IsBeacon() const { return false; } @@ -102,7 +91,6 @@ public: const Merc* CastToMerc() const; const Corpse* CastToCorpse() const; const Object* CastToObject() const; -// const Group* CastToGroup() const; const Doors* CastToDoors() const; const Trap* CastToTrap() const; const Beacon* CastToBeacon() const; @@ -129,6 +117,14 @@ private: class EntityList { public: + struct Area { + int id; + int type; + float min_x, max_x; + float min_y, max_y; + float min_z, max_z; + }; + EntityList(); ~EntityList(); @@ -181,8 +177,6 @@ public: void SendGuildMembers(uint32 guild_id); void RefreshAllGuildInfo(uint32 guild_id); void SendGuildList(); -// void SendGuildJoin(GuildJoin_Struct* gj); - // Check group list for nullptr entries void CheckGroupList (const char *fname, const int fline); void GroupProcess(); void RaidProcess(); @@ -193,6 +187,10 @@ public: void TrapProcess(); void BeaconProcess(); void ProcessMove(Client *c, float x, float y, float z); + void ProcessMove(NPC *n, float x, float y, float z); + void AddArea(int id, int type, float x1, float x2, float y1, float y2, float z1, float z2); + void RemoveArea(int id); + void ClearAreas(); void ProcessProximitySay(const char *Message, Client *c, uint8 language = 0); void SendAATimer(uint32 charid,UseAA_Struct* uaa); Doors* FindDoor(uint8 door_id); @@ -249,7 +247,6 @@ public: Entity* GetEntityObject(uint16 id); Entity* GetEntityCorpse(uint16 id); Entity* GetEntityCorpse(const char *name); -// Entity* GetEntityGroup(uint32 id); Entity* GetEntityTrap(uint16 id); Entity* GetEntityBeacon(uint16 id); @@ -430,8 +427,9 @@ private: LinkedList door_list; LinkedList trap_list; LinkedList beacon_list; - LinkedList proximity_list; + std::list proximity_list; std::list raid_list; + std::list area_list; uint16 last_insert_id; // Please Do Not Declare Any EntityList Class Members After This Comment diff --git a/zone/lua_iteminst.cpp b/zone/lua_iteminst.cpp index 32224d6a3..0427614d1 100644 --- a/zone/lua_iteminst.cpp +++ b/zone/lua_iteminst.cpp @@ -18,6 +18,27 @@ Lua_ItemInst::Lua_ItemInst(int item_id, int charges) { cloned_ = true; } +Lua_ItemInst& Lua_ItemInst::operator=(const Lua_ItemInst& o) { + if(o.cloned_) { + cloned_ = true; + d_ = new ItemInst(*o.d_); + } else { + cloned_ = false; + d_ = o.d_; + } + return *this; +} + +Lua_ItemInst::Lua_ItemInst(const Lua_ItemInst& o) { + if(o.cloned_) { + cloned_ = true; + d_ = new ItemInst(*o.d_); + } else { + cloned_ = false; + d_ = o.d_; + } +} + bool Lua_ItemInst::IsType(int item_class) { Lua_Safe_Call_Bool(); return self->IsType(static_cast(item_class)); diff --git a/zone/lua_iteminst.h b/zone/lua_iteminst.h index 4e3461b68..f12d16983 100644 --- a/zone/lua_iteminst.h +++ b/zone/lua_iteminst.h @@ -22,6 +22,8 @@ public: Lua_ItemInst() : Lua_Ptr(nullptr), cloned_(false) { } Lua_ItemInst(ItemInst *d) : Lua_Ptr(d), cloned_(false) { } Lua_ItemInst(ItemInst *d, bool cloned) : Lua_Ptr(d), cloned_(cloned) { } + Lua_ItemInst& operator=(const Lua_ItemInst& o); + Lua_ItemInst(const Lua_ItemInst& o); virtual ~Lua_ItemInst() { if(cloned_) { ItemInst *ptr = GetLuaPtrData(); if(ptr) { delete ptr; } } } operator ItemInst*() { diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index b19fe8aeb..87f00c645 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -924,6 +924,18 @@ void LuaParser::DispatchEventNPC(QuestEventID evt, NPC* npc, Mob *init, std::str std::string package_name = "npc_" + std::to_string(npc->GetNPCTypeID()); auto iter = lua_encounter_events_registered.find(package_name); + if(iter != lua_encounter_events_registered.end()) { + auto riter = iter->second.begin(); + while(riter != iter->second.end()) { + if(riter->event_id == evt) { + std::string package_name = "encounter_" + riter->encounter_name; + _EventNPC(package_name, evt, npc, init, data, extra_data, extra_pointers, &riter->lua_reference); + } + ++riter; + } + } + + iter = lua_encounter_events_registered.find("npc_-1"); if(iter == lua_encounter_events_registered.end()) { return; } @@ -976,6 +988,18 @@ void LuaParser::DispatchEventItem(QuestEventID evt, Client *client, ItemInst *it package_name += std::to_string(item->GetID()); auto iter = lua_encounter_events_registered.find(package_name); + if(iter != lua_encounter_events_registered.end()) { + 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, mob, data, extra_data, extra_pointers, &riter->lua_reference); + } + ++riter; + } + } + + iter = lua_encounter_events_registered.find("item_-1"); if(iter == lua_encounter_events_registered.end()) { return; } @@ -1000,6 +1024,18 @@ void LuaParser::DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, u std::string package_name = "spell_" + std::to_string(spell_id); auto iter = lua_encounter_events_registered.find(package_name); + if(iter != lua_encounter_events_registered.end()) { + auto riter = iter->second.begin(); + while(riter != iter->second.end()) { + if(riter->event_id == evt) { + std::string package_name = "encounter_" + riter->encounter_name; + _EventSpell(package_name, evt, npc, client, spell_id, extra_data, extra_pointers, &riter->lua_reference); + } + ++riter; + } + } + + iter = lua_encounter_events_registered.find("spell_-1"); if(iter == lua_encounter_events_registered.end()) { return; } diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 202be6b93..bc347b9ba 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -3261,10 +3261,9 @@ void ClientTaskState::ProcessTaskProximities(Client *c, float X, float Y, float float LastY = c->ProximityY(); float LastZ = c->ProximityZ(); - //_log(TASKS__PROXIMITY, "Checing proximities for Position %8.3f, %8.3f, %8.3f Last: %8.3f, %8.3f, %8.3f\n", X, Y, Z, LastX, LastY, LastZ); if((LastX==X) && (LastY==Y) && (LastZ==Z)) return; - _log(TASKS__PROXIMITY, "Checing proximities for Position %8.3f, %8.3f, %8.3f\n", X, Y, Z); + _log(TASKS__PROXIMITY, "Checking proximities for Position %8.3f, %8.3f, %8.3f\n", X, Y, Z); int ExploreID = taskmanager->ProximityManager.CheckProximities(X, Y, Z); if(ExploreID>0) { @@ -3273,9 +3272,6 @@ void ClientTaskState::ProcessTaskProximities(Client *c, float X, float Y, float } } - - - TaskGoalListManager::TaskGoalListManager() { TaskGoalLists = nullptr; diff --git a/zone/zone.cpp b/zone/zone.cpp index ca075de7c..1c61ee357 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -112,9 +112,6 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) { zone->pathing = PathManager::LoadPathFile(zone->map_name); char tmp[10]; - //PlayerProfile_Struct* pp; - //int char_num = 0; - //unsigned long* lengths; if (database.GetVariable("loglevel",tmp, 9)) { int log_levels[4]; if (atoi(tmp)>9){ //Server is using the new code @@ -457,36 +454,6 @@ void Zone::LoadTempMerchantData(){ LogFile->write(EQEMuLog::Error, "dbasync->AddWork() failed adding merchant list query"); return; } -/* char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - std::list merlist; - if (database.RunQuery(query, MakeAnyLenString(&query, "select ml.npcid,ml.slot,ml.itemid,ml.charges from merchantlist_temp ml, npc_types nt, spawnentry se, spawn2 s2 where nt.id=ml.npcid and nt.id=se.npcid and se.spawngroupid=s2.spawngroupid and s2.zone='%s' group by ml.npcid,slot order by npcid,slot asc", GetShortName()), errbuf, &result)) { - uint32 npcid = 0; - while((row = mysql_fetch_row(result))) { - if(npcid != atoul(row[0])){ - if(npcid > 0) - tmpmerchanttable[npcid] = merlist; - npcid = atoul(row[0]); - merlist.clear(); - } - TempMerchantList ml; - ml.npcid = npcid; - ml.slot = atoul(row[1]); - ml.item = atoul(row[2]); - ml.charges = atoul(row[3]); - ml.origslot = ml.slot; - merlist.push_back(ml); - } - if(npcid > 0) - tmpmerchanttable[npcid] = merlist; - mysql_free_result(result); - } - else - cerr << "Error in LoadTempMerchantData query '" << query << "' " << errbuf << endl; - safe_delete_array(query); -*/ } void Zone::LoadTempMerchantData_result(MYSQL_RES* result) { @@ -511,8 +478,6 @@ void Zone::LoadTempMerchantData_result(MYSQL_RES* result) { ml.origslot = ml.slot; cur->second.push_back(ml); } - //mysql_free_result(result); - //LogFile->write(EQEMuLog::Status, "Finished Loading Temporary Merchant Lists..."); } //there should prolly be a temp counterpart of this... @@ -601,34 +566,6 @@ void Zone::GetMerchantDataForZoneLoad(){ LogFile->write(EQEMuLog::Error,"dbasync->AddWork() failed adding merchant list query"); return; } -/* char errbuf[MYSQL_ERRMSG_SIZE]; - char *query = 0; - MYSQL_RES *result; - MYSQL_ROW row; - std::list merlist; - if (database.RunQuery(query, MakeAnyLenString(&query, "select ml.merchantid,ml.slot,ml.item from merchantlist ml, npc_types nt, spawnentry se, spawn2 s2 where nt.merchant_id=ml.merchantid and nt.id=se.npcid and se.spawngroupid=s2.spawngroupid and s2.zone='%s' group by ml.merchantid,slot order by merchantid,slot asc", GetShortName()), errbuf, &result)) { - uint32 npcid = 0; - while((row = mysql_fetch_row(result))) { - if(npcid != atoul(row[0])){ - if(npcid > 0) - merchanttable[npcid] = merlist; - npcid = atoul(row[0]); - merlist.clear(); - } - MerchantList ml; - ml.id = npcid; - ml.slot = atoul(row[1]); - ml.item = atoul(row[2]); - merlist.push_back(ml); - } - if(npcid > 0) - merchanttable[npcid] = merlist; - mysql_free_result(result); - } - else - cerr << "Error in GetMerchantDataForZoneLoad query '" << query << "' " << errbuf << endl; - safe_delete_array(query); -*/ } void Zone::LoadMercTemplates(){ @@ -879,6 +816,7 @@ void Zone::Shutdown(bool quite) zone->ResetAuth(); safe_delete(zone); dbasync->CommitWrites(); + entity_list.ClearAreas(); parse->ReloadQuests(true); UpdateWindowTitle(); } @@ -2665,6 +2603,7 @@ void Zone::LoadNPCEmotes(LinkedList* NPCEmoteList) void Zone::ReloadWorld(uint32 Option){ if(Option == 1){ zone->Repop(0); + entity_list.ClearAreas(); parse->ReloadQuests(); } } diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 3b5112c78..b424e077a 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -616,7 +616,7 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z safe_delete(outapp); } else { - if(zoneID == this->GetZoneID()) { + if(zoneID == GetZoneID()) { //properly handle proximities entity_list.ProcessMove(this, x_pos, y_pos, z_pos); proximity_x = x_pos;