Browse Source

Address spell caster dead ptrs, location enter/leave with discovery based on grid id alone

Emagi 1 month ago
parent
commit
878dd00fb9

+ 15 - 3
EQ2/source/WorldServer/SpellProcess.cpp

@@ -43,6 +43,18 @@ SpellProcess::~SpellProcess(){
 	RemoveAllSpells();
 }
 
+void SpellProcess::RemoveCaster(Spawn* caster){
+	MutexList<LuaSpell*>::iterator active_spells_itr = active_spells.begin();
+	while(active_spells_itr.Next()){
+		LuaSpell* spell = active_spells_itr->value;
+		spell->MSpellTargets.writelock(__FUNCTION__, __LINE__);
+		if(spell->caster == caster) {
+			spell->caster = nullptr;
+		}
+		spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__);
+	}
+}
+
 void SpellProcess::RemoveAllSpells(bool reload_spells){
 	ClearSpellScriptTimerList();
 
@@ -2751,14 +2763,13 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete
 				targets = &spell->targets;
 				remove_targets = remove_itr->second;
 				if (remove_targets && targets){
+					spell->MSpellTargets.writelock(__FUNCTION__, __LINE__);
 					for (remove_target_itr = remove_targets->begin(); remove_target_itr != remove_targets->end(); remove_target_itr++){
 						if(!spell->caster || !spell->caster->GetZone())
 							continue;
 
 						remove_spawn = spell->caster->GetZone()->GetSpawnByID((*remove_target_itr));
 						if (remove_spawn) {
-							spell->MSpellTargets.writelock(__FUNCTION__, __LINE__);
-
 							if(remove_spawn && remove_spawn->IsPlayer())
 							{
 								multimap<int32,int8>::iterator entries;
@@ -2791,13 +2802,14 @@ void SpellProcess::CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete
 									break;
 								}
 							}
-							spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__);
 							if (targets->size() == 0 && spell->char_id_targets.size() == 0 && allow_delete) {
+								spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__);
 								should_delete = true;
 								break;
 							}
 						}
 					}
+					spell->MSpellTargets.releasewritelock(__FUNCTION__, __LINE__);
 				}
 				break;
 			}

+ 4 - 1
EQ2/source/WorldServer/SpellProcess.h

@@ -157,7 +157,10 @@ class SpellProcess{
 public:
 	SpellProcess();
 	~SpellProcess();
-
+	
+	/// Remove dead pointers for casters when the Spawn is deconstructed
+	void RemoveCaster(Spawn* caster);
+	
 	/// <summary>Remove all spells from the SpellProcess </summary>
 	void RemoveAllSpells(bool reload_spells = false);
 

+ 5 - 3
EQ2/source/WorldServer/WorldDatabase.cpp

@@ -6099,10 +6099,12 @@ bool WorldDatabase::LoadLocationGridLocations(LocationGrid* grid) {
 	bool ret = false;
 	if (grid) {
 		Query query;
+		int row_count = 0;
 		MYSQL_ROW row;
 		MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT `id`, `x`, `y`, `z` FROM `location_details` WHERE `location_id`=%u", grid->id);
-		if (result->row_count >= 3) {
+		if (result) {
 			while (result && (row = mysql_fetch_row(result))) {
+				row_count++;
 				Location* location = new Location;
 				location->id = atoul(row[0]);
 				location->x = atof(row[1]);
@@ -6112,8 +6114,8 @@ bool WorldDatabase::LoadLocationGridLocations(LocationGrid* grid) {
 			}
 			ret = true;
 		}
-		else
-			LogWrite(WORLD__ERROR, 0, "World", "Grid '%s' only has %u location(s).  A minimum of 3 is needed.", grid->name.c_str(), result->row_count);
+		if(row_count > 0 && row_count < 3)
+			LogWrite(WORLD__WARNING, 0, "World", "Grid '%s' only has %u location(s).  A minimum of 3 is needed for a proper location based grid.", grid->name.c_str(), row_count);
 	}
 	return ret;
 }

+ 36 - 41
EQ2/source/WorldServer/zoneserver.cpp

@@ -1475,18 +1475,6 @@ void ZoneServer::AddPendingDelete(Spawn* spawn) {
 	MSpawnDeleteList.releasewritelock(__FUNCTION__, __LINE__);
 }
 
-void ZoneServer::RemovePendingDelete(Spawn* spawn) {
-	if (!spawn)
-		return;
-
-	MSpawnDeleteList.writelock(__FUNCTION__, __LINE__);
-	if (spawn_delete_list.count(spawn) > 0)
-	{
-		spawn_delete_list.erase(spawn);
-	}
-	MSpawnDeleteList.releasewritelock(__FUNCTION__, __LINE__);
-}
-
 void ZoneServer::DeleteSpawns(bool delete_all) {
 	MSpawnDeleteList.writelock(__FUNCTION__, __LINE__);
 	MPendingSpawnRemoval.readlock(__FUNCTION__, __LINE__);
@@ -1538,8 +1526,9 @@ void ZoneServer::DeleteSpawns(bool delete_all) {
 					}
 					housing_spawn_map.erase(spawn->GetID());
 				}
-				MSpawnList.releasewritelock(__FUNCTION__, __LINE__);
 				
+				spellProcess->RemoveCaster(spawn);
+				MSpawnList.releasewritelock(__FUNCTION__, __LINE__);
 				safe_delete(spawn);
 			}
 			else
@@ -6403,7 +6392,8 @@ void ZoneServer::CheckLocationGrids() {
 			MutexList<LocationGrid*>::iterator location_grid_itr = location_grids.begin();
 			while (location_grid_itr.Next()) {
 				LocationGrid* grid = location_grid_itr.value;
-				if (grid->locations.size() > 0 || /*(grid->grid_id == grid_id ||*/ grid->players.count(player) > 0) {
+				bool playerInGrid = false;
+				if (grid->locations.size() > 0 || (playerInGrid = (grid->grid_id > 0 && grid->grid_id == grid_id)) || grid->players.count(player) > 0) {
 					float x_small = 0;
 					float x_large = 0;
 					float y_small = 0;
@@ -6412,41 +6402,46 @@ void ZoneServer::CheckLocationGrids() {
 					float z_large = 0;
 					bool first = true;
 					bool in_grid = false;
-					MutexList<Location*>::iterator location_itr = grid->locations.begin();
-					while (location_itr.Next()) {
-						Location* location = location_itr.value;
-						if (first) {
-							x_small = location->x;
-							x_large = location->x;
-							if (grid->include_y) {
-								y_small = location->y;
-								y_large = location->y;
-							}
-							z_small = location->z;
-							z_large = location->z;
-							first = false;
-						}
-						else {
-							if (location->x < x_small)
+					if(grid->locations.size() == 0 && playerInGrid) { // no locations, we presume player is in grid
+						in_grid = true;
+					}
+					else {
+						MutexList<Location*>::iterator location_itr = grid->locations.begin();
+						while (location_itr.Next()) {
+							Location* location = location_itr.value;
+							if (first) {
 								x_small = location->x;
-							else if (location->x > x_large)
 								x_large = location->x;
-							if (grid->include_y) {
-								if (location->y < y_small)
+								if (grid->include_y) {
 									y_small = location->y;
-								else if (location->y > y_large)
 									y_large = location->y;
-							}
-							if (location->z < z_small)
+								}
 								z_small = location->z;
-							else if (location->z > z_large)
 								z_large = location->z;
+								first = false;
+							}
+							else {
+								if (location->x < x_small)
+									x_small = location->x;
+								else if (location->x > x_large)
+									x_large = location->x;
+								if (grid->include_y) {
+									if (location->y < y_small)
+										y_small = location->y;
+									else if (location->y > y_large)
+										y_large = location->y;
+								}
+								if (location->z < z_small)
+									z_small = location->z;
+								else if (location->z > z_large)
+									z_large = location->z;
+							}
 						}
+						if (grid->include_y && (x >= x_small && x <= x_large && y >= y_small && y <= y_large && z >= z_small && z <= z_large))
+							in_grid = true;
+						else if (x >= x_small && x <= x_large && z >= z_small && z <= z_large)
+							in_grid = true;
 					}
-					if (grid->include_y && (x >= x_small && x <= x_large && y >= y_small && y <= y_large && z >= z_small && z <= z_large))
-						in_grid = true;
-					else if (x >= x_small && x <= x_large && z >= z_small && z <= z_large)
-						in_grid = true;
 					if (in_grid && grid->players.count(player) == 0) {
 						grid->players.Put(player, true);
 

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

@@ -783,7 +783,6 @@ private:
 	void	ReloadTransporters();																				// never used outside zone server
 	void	DeleteSpawns(bool delete_all);																		// never used outside zone server
 	void	AddPendingDelete(Spawn* spawn);																		// never used outside zone server
-	void	RemovePendingDelete(Spawn* spawn);																		// never used outside zone server
 	void	ClearDeadSpawns();																					// never used outside zone server
 	void	RemoveChangedSpawn(Spawn* spawn);																	// never used outside zone server
 	void	ProcessDrowning();																					// never used outside zone server