Browse Source

Change how SpellProcess grabs the spell targets from the grid to an ID

Emagi 1 year ago
parent
commit
baff7ced26

+ 8 - 7
EQ2/source/WorldServer/SpellProcess.cpp

@@ -2522,10 +2522,9 @@ void SpellProcess::GetSpellTargetsTrueAOE(LuaSpell* luaspell) {
 			}
 		}
 		int32 ignore_target = 0;
-		vector<Spawn*> spawns = luaspell->caster->GetZone()->GetAttackableSpawnsByDistance(luaspell->caster, luaspell->spell->GetSpellData()->radius);
+		vector<int32> spawns = luaspell->caster->GetZone()->GetAttackableSpawnsByDistance(luaspell->caster, luaspell->spell->GetSpellData()->radius);
 		luaspell->MSpellTargets.writelock(__FUNCTION__, __LINE__);
 		for (int8 i = 0; i < spawns.size(); i++) {
-			Spawn* spawn = spawns.at(i);
 			if (i == 0){
 				if (luaspell->initial_target && luaspell->caster->GetID() != luaspell->initial_target){
 					//this is the "Direct" target and aoe can't be avoided
@@ -2535,13 +2534,15 @@ void SpellProcess::GetSpellTargetsTrueAOE(LuaSpell* luaspell) {
 				if (luaspell->targets.size() >= luaspell->spell->GetSpellData()->max_aoe_targets)
 					break;
 			}
+			
+			int32 target_id = spawns.at(i);
+			Spawn* spawn = luaspell->caster->GetZone()->GetSpawnByID(target_id);
+			if(!spawn) {
+				LogWrite(SPELL__ERROR, 0, "Spell", "Error: Spell target is NULL!  SpellProcess::ProcessSpell for Spell '%s' target id %u", (luaspell->spell != nullptr) ? luaspell->spell->GetName() : "Unknown", target_id);
+			}
 			//If we have already added this spawn, check the next spawn in the list
 			if (spawn && spawn->GetID() == ignore_target){
-				i++;
-				if (i < spawns.size())
-					spawn = spawns.at(i);
-				else
-					break;
+				continue;
 			}
 			if (spawn){
 				//If this spawn is immune to aoe, continue

+ 16 - 11
EQ2/source/WorldServer/zoneserver.cpp

@@ -7025,19 +7025,24 @@ void ZoneServer::RemovePlayerPassenger(int32 char_id) {
 	MTransportSpawns.releasereadlock(__FUNCTION__, __LINE__);
 }
 
-vector<Spawn*> ZoneServer::GetAttackableSpawnsByDistance(Spawn* caster, float distance) {
-	vector<Spawn*> ret;
+vector<int32> ZoneServer::GetAttackableSpawnsByDistance(Spawn* caster, float distance) {
+	vector<int32> ret;
 	Spawn* spawn = 0;
-	std::vector<Spawn*>* ret_list = GetSpawnsInGrid(caster->GetLocation());
-	std::vector<Spawn*>::iterator itr;
-	for (itr = ret_list->begin(); itr != ret_list->end(); itr++) {
-		spawn = *itr;
-		if (spawn && spawn->IsNPC() && spawn->appearance.attackable > 0 && spawn->GetID() > 0 && spawn->GetID() != caster->GetID() &&
-			spawn->Alive() && spawn->GetDistance(caster, true) <= distance) 
-			ret.push_back(spawn);
-	}
 	
-	safe_delete(ret_list);
+    std::shared_lock lock(MGridMaps);
+	std::map<int32, GridMap*>::iterator grids = grid_maps.find(caster->GetLocation());
+	if(grids != grid_maps.end()) {
+		grids->second->MSpawns.lock();
+		typedef map <int32, Spawn*> SpawnMapType;
+		for( SpawnMapType::iterator it = grids->second->spawns.begin(); it != grids->second->spawns.end(); ++it ) {
+			Spawn* spawn = it->second;
+			if (spawn && spawn->IsNPC() && spawn->appearance.attackable > 0 && spawn->GetID() > 0 && spawn->GetID() != caster->GetID() &&
+				spawn->Alive() && spawn->GetDistance(caster, true) <= distance) {
+				ret.push_back(spawn->GetID());
+			}
+		}
+		grids->second->MSpawns.unlock();
+	}
 	
 	return ret;
 }

+ 1 - 1
EQ2/source/WorldServer/zoneserver.h

@@ -441,7 +441,7 @@ public:
 	Client*	GetClientByCharID(int32 charid);
 
 	/// <summary>Gets spawns for a true AoE spell</summary>
-	vector<Spawn*> GetAttackableSpawnsByDistance(Spawn* spawn, float distance);
+	vector<int32> GetAttackableSpawnsByDistance(Spawn* spawn, float distance);
 
 	void StartZoneSpawnsForLevelThread(Client* client);