Browse Source

SpellProcess stability/protection and LUA SetSpeed against a non Entity fix

Image 2 years ago
parent
commit
42134c800c

+ 6 - 6
EQ2/source/WorldServer/Commands/Commands.cpp

@@ -2645,7 +2645,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 				if(dead && dead->IsPlayer() == false){
 					dead->SetHP(0);
 					if(sep && sep->arg[0] && sep->IsNumber(0) && atoi(sep->arg[0]) == 1)
-						client->GetCurrentZone()->RemoveSpawn(dead, true);
+						client->GetCurrentZone()->RemoveSpawn(dead, true, true, true, true, true);
 					else
 						client->GetPlayer()->KillSpawn(dead);
 				}else{
@@ -3444,7 +3444,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 						{
 							client->Message(CHANNEL_COLOR_YELLOW,"Zoning to %s...", zonestr);
 							if(isInstance)
-								client->Zone(instanceID,true,true);
+								client->Zone(instanceID,true,true,false);
 							else
 								client->Zone(zonestr);
 						}
@@ -3612,7 +3612,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 			query.RunQuery2(Q_INSERT, "delete from spawn_instance_data where spawn_id = %u and spawn_location_id = %u and pickup_item_id = %u", spawn->GetDatabaseID(), spawn->GetSpawnLocationID(), spawn->GetPickupItemID());
 
 			if (database.RemoveSpawnFromSpawnLocation(spawn)) {
-				client->GetCurrentZone()->RemoveSpawn(spawn, true, true);
+				client->GetCurrentZone()->RemoveSpawn(spawn, true, true, true, true, true);
 			}
 
 			// we had a UI Window displayed, update the house items
@@ -3741,7 +3741,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 					if (client->GetTempPlacementSpawn())
 					{
 						Spawn* tmp = client->GetTempPlacementSpawn();
-						client->GetCurrentZone()->RemoveSpawn(tmp);
+						client->GetCurrentZone()->RemoveSpawn(tmp, true, true, true, true, true);
 						client->SetTempPlacementSpawn(nullptr);
 					}
 
@@ -4772,7 +4772,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 			if(spawn && !spawn->IsPlayer()){
 				if(spawn->GetSpawnLocationID() > 0){
 					if(database.RemoveSpawnFromSpawnLocation(spawn)){
-						client->GetCurrentZone()->RemoveSpawn(spawn, true, false);
+						client->GetCurrentZone()->RemoveSpawn(spawn, true, false, true, true, true);
 						client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Successfully removed spawn from zone");
 					}
 					else
@@ -5596,7 +5596,7 @@ void Commands::Command_CancelMaintained(Client* client, Seperator* sep)
 	//	if (spell && spell->GetSpellData()->friendly_spell)  -- NOTE::You can cancel hostile maintained spells, 
 		                                                     // just not spelleffects/dets - Foof
 		//{
-			if (!client->GetPlayer()->GetZone()->GetSpellProcess()->DeleteCasterSpell(mEffects.spell, "canceled"))
+			if (!client->GetPlayer()->GetZone()->GetSpellProcess()->DeleteCasterSpell(mEffects.spell, "canceled", false, true))
 				client->Message(CHANNEL_COLOR_RED, "The maintained spell could not be cancelled.");
 	//	}
 		//else

+ 12 - 5
EQ2/source/WorldServer/LuaFunctions.cpp

@@ -1632,6 +1632,7 @@ int EQ2Emu_lua_AddHate(lua_State* state) {
 int EQ2Emu_lua_Zone(lua_State* state) {
 	if (!lua_interface)
 		return 0;
+	LuaSpell* spell = lua_interface->GetCurrentSpell(state);
 	ZoneServer* zone = lua_interface->GetZone(state);
 	Spawn* player = lua_interface->GetSpawn(state, 2);
 	Client* client = 0;
@@ -2120,7 +2121,9 @@ int EQ2Emu_lua_SetSpeed(lua_State* state) {
 	lua_interface->ResetFunctionStack(state);
 	if (spawn) {
 		spawn->SetSpeed(value);
-		((Entity*)spawn)->SetSpeed(value);
+		
+		if(spawn->IsEntity())
+			((Entity*)spawn)->SetSpeed(value);
 		if (spawn->IsPlayer()) {
 			Client* client = spawn->GetZone()->GetClientBySpawn(spawn);
 			if (client) {
@@ -4226,8 +4229,10 @@ int EQ2Emu_lua_Harvest(lua_State* state) {
 			LogWrite(MISC__TODO, 1, "TODO", "Cancel harvest if skill insufficient; Func: %s, Line: %i", __FUNCTION__, __LINE__);
 
 			((GroundSpawn*)node)->ProcessHarvest(client);
-			if (((GroundSpawn*)node)->GetNumberHarvests() == 0)
-				player->GetZone()->RemoveSpawn(node, true);
+			if (((GroundSpawn*)node)->GetNumberHarvests() == 0) {
+				LuaSpell* spell = lua_interface->GetCurrentSpell(state);
+				player->GetZone()->RemoveSpawn(node, true, true, true, true, (spell != nullptr) ? false : true);
+			}
 		}
 	}
 	else if (player && player->IsPlayer()) {
@@ -4283,12 +4288,13 @@ int EQ2Emu_lua_Bind(lua_State* state) {
 int EQ2Emu_lua_Gate(lua_State* state) {
 	if (!lua_interface)
 		return 0;
+	LuaSpell* spell = lua_interface->GetCurrentSpell(state);
 	Spawn* spawn = lua_interface->GetSpawn(state);
 	if (spawn) {
 		if (spawn->IsPlayer()) {
 			Client* client = spawn->GetZone()->GetClientBySpawn(spawn);
 			if (client) {
-				if (!client->Gate())
+				if (!client->Gate((spell != nullptr) ? true : false))
 					client->SimpleMessage(CHANNEL_COLOR_RED, "Unable to gate.");
 			}
 		}
@@ -10962,6 +10968,7 @@ int EQ2Emu_lua_SendTransporters(lua_State* state) {
 	if (!lua_interface)
 		return 0;
 
+	LuaSpell* spell = lua_interface->GetCurrentSpell(state);
 	Spawn* spawn = lua_interface->GetSpawn(state);
 	Spawn* player = lua_interface->GetSpawn(state, 2);
 	int32 transport_id = lua_interface->GetInt32Value(state, 3);
@@ -10981,7 +10988,7 @@ int EQ2Emu_lua_SendTransporters(lua_State* state) {
 		if (destinations.size())
 		{
 			client->SetTemporaryTransportID(transport_id);
-			client->ProcessTeleport(spawn, &destinations, transport_id);
+			client->ProcessTeleport(spawn, &destinations, transport_id, (spell != nullptr) ? true : false);
 		}
 		else
 			client->Message(CHANNEL_COLOR_RED, "There are no transporters available (ID: %u)", transport_id);

+ 16 - 4
EQ2/source/WorldServer/SpellProcess.cpp

@@ -370,11 +370,13 @@ bool SpellProcess::DeleteCasterSpell(Spawn* caster, Spell* spell, string reason)
 	return ret;
 }
 
-bool SpellProcess::DeleteCasterSpell(LuaSpell* spell, string reason, bool removing_all_spells){
+bool SpellProcess::DeleteCasterSpell(LuaSpell* spell, string reason, bool removing_all_spells, bool lock_spell_process){
+	if(lock_spell_process)
+		MSpellProcess.lock();
+
 	bool ret = false;
 	Spawn* target = 0;
 	if(spell) {
-		bool hasTimer = !IsReady(spell->spell, spell->caster);
 		if (active_spells.count(spell) > 0)
 			active_spells.Remove(spell);
 		if (spell->caster) {
@@ -455,7 +457,11 @@ bool SpellProcess::DeleteCasterSpell(LuaSpell* spell, string reason, bool removi
 		}
 		if(lua_interface)
 			lua_interface->RemoveSpell(spell, true, SpellScriptTimersHasSpell(spell), reason, removing_all_spells);
-	}
+	}	
+	
+	if(lock_spell_process)
+		MSpellProcess.unlock();
+	
 	return ret;
 }
 
@@ -1895,7 +1901,10 @@ void SpellProcess::Interrupted(Entity* caster, Spawn* interruptor, int16 error_c
 	}
 }
 
-void SpellProcess::RemoveSpellTimersFromSpawn(Spawn* spawn, bool remove_all, bool delete_recast, bool call_expire_function){
+void SpellProcess::RemoveSpellTimersFromSpawn(Spawn* spawn, bool remove_all, bool delete_recast, bool call_expire_function, bool lock_spell_process){
+	if(lock_spell_process)
+		MSpellProcess.lock();
+
 	int32 i = 0;
 	if(cast_timers.size() > 0){		
 		CastTimer* cast_timer = 0;
@@ -1958,6 +1967,9 @@ void SpellProcess::RemoveSpellTimersFromSpawn(Spawn* spawn, bool remove_all, boo
 			}
 		}
 	}
+	
+	if(lock_spell_process)
+		MSpellProcess.unlock();
 }
 
 void SpellProcess::GetSpellTargets(LuaSpell* luaspell) 

+ 2 - 2
EQ2/source/WorldServer/SpellProcess.h

@@ -262,7 +262,7 @@ public:
 
 	/// <summary>Remove the given spell from the ZpellProcess</summary>
 	/// <param name='spell'>LuaSpell to remove</param>
-	bool DeleteCasterSpell(LuaSpell* spell, string reason="", bool removing_all_spells = false);
+	bool DeleteCasterSpell(LuaSpell* spell, string reason="", bool removing_all_spells = false, bool lock_spell_process = false);
 
 	/// <summary>Interrupt the spell</summary>
 	/// <param name='interrupt'>InterruptStruct that contains all the info</param>
@@ -271,7 +271,7 @@ public:
 	/// <summary>Removes the timers for the given spawn</summary>
 	/// <param name='spawn'>Spawn to remove the timers for</param>
 	/// <param name='remove_all'>Remove all timers (cast, recast, active, queue, interrupted)? If false only cast timers are removed</param>
-	void RemoveSpellTimersFromSpawn(Spawn* spawn, bool remove_all = false, bool delete_recast = false, bool call_expire_function = true);
+	void RemoveSpellTimersFromSpawn(Spawn* spawn, bool remove_all = false, bool delete_recast = false, bool call_expire_function = true, bool lock_spell_process = false);
 
 	/// <summary>Sets the recast timer for the spell </summary>
 	/// <param name='spell'>The spell to set the recast for</param>

+ 1 - 1
EQ2/source/WorldServer/WorldDatabase.cpp

@@ -3448,7 +3448,7 @@ int32 WorldDatabase::SaveCombinedSpawnLocation(ZoneServer* zone, Spawn* in_spawn
 		}
 		for(itr=spawns->begin();itr!=spawns->end();itr++){
 			spawn = *itr;
-			zone->RemoveSpawn(spawn);
+			zone->RemoveSpawn(spawn, true, true, true, true, true);
 		}
 		safe_delete(spawns);
 	}

+ 17 - 17
EQ2/source/WorldServer/client.cpp

@@ -233,7 +233,7 @@ Client::~Client() {
 
 void Client::RemoveClientFromZone() {
 	if(player && player->GetZone())
-		player->GetZone()->GetSpellProcess()->RemoveSpellTimersFromSpawn(player, true);
+		player->GetZone()->GetSpellProcess()->RemoveSpellTimersFromSpawn(player, true, false, true, true);
 
 	if (current_zone && player) {
 		if (player->GetGroupMemberInfo())
@@ -676,7 +676,7 @@ void Client::HandlePlayerRevive(int32 point_id)
 		if(shard->GetSpawnScript() && strlen(shard->GetSpawnScript()) > 0)
 			originalZone->CallSpawnScript(shard, SPAWN_SCRIPT_PRESPAWN);
 
-		originalZone->RemoveSpawn(player, false);
+		originalZone->RemoveSpawn(player, false, true, true, true, true);
 
 		originalZone->AddSpawn(shard);
 		
@@ -1302,7 +1302,7 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
 		if (GetTempPlacementSpawn())
 		{
 			Spawn* tmp = GetTempPlacementSpawn();
-			GetCurrentZone()->RemoveSpawn(tmp);
+			GetCurrentZone()->RemoveSpawn(tmp, true, true, true, true, true);
 			SetTempPlacementSpawn(nullptr);
 			SetPlacementUniqueItemID(0);
 			break; // break out early if we are tied to a temp spawn
@@ -3344,7 +3344,7 @@ void ClientList::Remove(Client* client, bool remove_data) {
 void Client::SetCurrentZone(int32 id) {
 	if (current_zone) {
 		//current_zone->GetCombat()->RemoveHate(player);
-		current_zone->RemoveSpawn(player, false);
+		current_zone->RemoveSpawn(player, false, true, true, true, true);
 	}
 	SetCurrentZone(zone_list.Get(id));
 
@@ -3353,7 +3353,7 @@ void Client::SetCurrentZone(int32 id) {
 void Client::SetCurrentZoneByInstanceID(int32 id, int32 zoneid) {
 	if (current_zone) {
 		//current_zone->GetCombat()->RemoveHate(player);
-		current_zone->RemoveSpawn(player, false);
+		current_zone->RemoveSpawn(player, false, true, true, true, true);
 	}
 	SetCurrentZone(zone_list.GetByInstanceID(id, zoneid));
 
@@ -3798,7 +3798,7 @@ bool Client::TryZoneInstance(int32 zoneID, bool zone_coords_valid) {
 	instance_zone = GetPlayer()->GetGroupMemberInZone(zoneID);
 
 	if (instance_zone != NULL)
-		Zone(instance_zone->GetInstanceID(), zone_coords_valid, true);
+		Zone(instance_zone->GetInstanceID(), zone_coords_valid);
 	else if ((instanceType = database.GetInstanceTypeByZoneID(zoneID)) > 0)
 	{
 		// best to check if we already have our own instance!
@@ -4013,12 +4013,12 @@ bool Client::CheckZoneAccess(const char* zoneName) {
 	return true;
 }
 
-void Client::Zone(int32 instanceid, bool set_coords, bool byInstanceID) {
-	Zone(zone_list.GetByInstanceID(instanceid), set_coords);
+void Client::Zone(int32 instanceid, bool set_coords, bool byInstanceID, bool is_spell) {
+	Zone(zone_list.GetByInstanceID(instanceid), set_coords, is_spell);
 
 }
 
-void Client::Zone(ZoneServer* new_zone, bool set_coords) {
+void Client::Zone(ZoneServer* new_zone, bool set_coords, bool is_spell) {
 	if (!new_zone) {
 		LogWrite(CCLIENT__DEBUG, 0, "Client", "Zone Request Denied! No 'new_zone' value");
 		return;
@@ -4039,7 +4039,7 @@ void Client::Zone(ZoneServer* new_zone, bool set_coords) {
 	((Entity*)player)->DismissAllPets();
 
 	LogWrite(CCLIENT__DEBUG, 0, "Client", "%s: Removing player from current zone...", __FUNCTION__);
-	GetCurrentZone()->RemoveSpawn(player, false);
+	GetCurrentZone()->RemoveSpawn(player, false, true, true, true, !is_spell);
 
 	LogWrite(CCLIENT__DEBUG, 0, "Client", "%s: Setting zone to '%s'...", __FUNCTION__, new_zone->GetZoneName());
 	SetCurrentZone(new_zone);
@@ -4098,10 +4098,10 @@ void Client::Zone(ZoneServer* new_zone, bool set_coords) {
 	}
 }
 
-void Client::Zone(const char* new_zone, bool set_coords)
+void Client::Zone(const char* new_zone, bool set_coords, bool is_spell)
 {
 	LogWrite(CCLIENT__DEBUG, 0, "Client", "Zone Request to '%s'", new_zone);
-	Zone(zone_list.Get(new_zone), set_coords);
+	Zone(zone_list.Get(new_zone), set_coords, is_spell);
 }
 
 float Client::DistanceFrom(Client* client) {
@@ -8256,7 +8256,7 @@ bool Client::Bind() {
 	return true;
 }
 
-bool Client::Gate() {
+bool Client::Gate(bool is_spell) {
 	if (player->GetPlayerInfo()->GetBindZoneID() == 0)
 		return false;
 
@@ -8266,7 +8266,7 @@ bool Client::Gate() {
 		player->SetY(player->GetPlayerInfo()->GetBindZoneY());
 		player->SetZ(player->GetPlayerInfo()->GetBindZoneZ());
 		player->SetHeading(player->GetPlayerInfo()->GetBindZoneHeading());
-		Zone(zone, false);
+		Zone(zone, false, is_spell);
 
 		return true;
 	}
@@ -8274,7 +8274,7 @@ bool Client::Gate() {
 	return false;
 }
 
-void Client::ProcessTeleport(Spawn* spawn, vector<TransportDestination*>* destinations, int32 transport_id) {
+void Client::ProcessTeleport(Spawn* spawn, vector<TransportDestination*>* destinations, int32 transport_id, bool is_spell) {
 	if (!destinations || !spawn) {
 		return;
 	}
@@ -8316,9 +8316,9 @@ void Client::ProcessTeleport(Spawn* spawn, vector<TransportDestination*>* destin
 				GetPlayer()->SetZ(destination->destination_z);
 				GetPlayer()->SetHeading(destination->destination_heading);
 				if (instance_zone)
-					Zone(instance_zone->GetInstanceID(), false, true);
+					Zone(instance_zone->GetInstanceID(), false, true, is_spell);
 				else
-					Zone(new_zone, false);
+					Zone(new_zone, false, is_spell);
 			}
 		}
 		if (destination->message.length() > 0)

+ 5 - 6
EQ2/source/WorldServer/client.h

@@ -163,10 +163,9 @@ public:
 	void	SimpleMessage(int8 color, const char* message);
 	void	Message(int8 type, const char* message, ...);
 	void	SendSpellUpdate(Spell* spell, bool add_silently = false, bool add_to_hotbar = true);
-	void	Zone(ZoneServer* new_zone, bool set_coords = true);
-	void	Zone(const char* new_zone, bool set_coords = true);
-	void	Zone(int32 zoneid, bool set_coords = true);
-	void	Zone(int32 instanceid, bool set_coords = true, bool byInstanceID=false);
+	void	Zone(ZoneServer* new_zone, bool set_coords = true, bool is_spell = false);
+	void	Zone(const char* new_zone, bool set_coords = true, bool is_spell = false);
+	void	Zone(int32 instanceid, bool set_coords = true, bool byInstanceID=false, bool is_spell = false);
 	void	SendZoneInfo();
 	void	SendZoneSpawns();
 	void	HandleVerbRequest(EQApplicationPacket* app);
@@ -203,7 +202,7 @@ public:
 	bool	AddItemToBank(int32 item_id, int16 quantity = 0);
 	bool	AddItemToBank(Item* item);
 	bool	RemoveItem(Item *item, int16 quantity, bool force_override_no_delete = false);
-	void	ProcessTeleport(Spawn* spawn, vector<TransportDestination*>* destinations, int32 transport_id = 0);
+	void	ProcessTeleport(Spawn* spawn, vector<TransportDestination*>* destinations, int32 transport_id = 0, bool is_spell = false);
 	void	ProcessTeleportLocation(EQApplicationPacket* app); 
 
 	void	UpdateCharacterInstances();
@@ -331,7 +330,7 @@ public:
 	bool	GateAllowed();
 	bool	BindAllowed();
 	bool	Bind();
-	bool	Gate();
+	bool	Gate(bool is_spell = false);
 	void	SendChatRelationship(int8 type, const char* name);
 	void	SendFriendList();
 	void	SendIgnoreList();

+ 13 - 13
EQ2/source/WorldServer/zoneserver.cpp

@@ -209,7 +209,7 @@ ZoneServer::~ZoneServer() {
 
 	// moved to the bottom as we want spawns deleted first, this used to be above Spawn deletion which is a big no no
 	safe_delete(spellProcess);
-	
+
 	LogWrite(ZONE__INFO, 0, "Zone", "Completed zone shutdown of '%s'", zone_name);
 	--numzones;
 	UpdateWindowTitle(0);
@@ -478,7 +478,7 @@ void ZoneServer::DeleteData(bool boot_clients){
 			}
 			else{
 				RemoveHeadingTimer(spawn); // called in RemoveSpawnSupportFunctions()
-				RemoveSpawnSupportFunctions(spawn);
+				RemoveSpawnSupportFunctions(spawn, true);
 				AddPendingDelete(spawn);
 			}
 		}
@@ -770,7 +770,7 @@ void ZoneServer::ProcessDepop(bool respawns_allowed, bool repop) {
 				if(spawn->IsPlayer())
 					tmp_player_list.Add(spawn);
 				else {
-					RemoveSpawnSupportFunctions(spawn);	
+				RemoveSpawnSupportFunctions(spawn, true);
 					AddPendingDelete(spawn);
 				}
 			}
@@ -1662,7 +1662,7 @@ void ZoneServer::CheckDeadSpawnRemoval() {
 				{
 					dead_spawns.erase(spawn->GetID());
 					MDeadSpawns.releasewritelock(__FUNCTION__, __LINE__);
-					RemoveSpawn(spawn, true, true, true);
+					RemoveSpawn(spawn, true, true, true, true, true);
 					MDeadSpawns.writelock(__FUNCTION__, __LINE__);
 				}
 			}
@@ -3122,7 +3122,7 @@ void ZoneServer::RemoveClient(Client* client)
 		
 		client->GetPlayer()->DeleteSpellEffects(true);
 		
-		RemoveSpawn(client->GetPlayer(), false);
+		RemoveSpawn(client->GetPlayer(), false, true, true, true, true);
 		connected_clients.Remove(client, true, DisconnectClientTimer); // changed from a hardcoded 30000 (30 sec) to the DisconnectClientTimer rule
 	}
 }
@@ -3926,7 +3926,7 @@ void ZoneServer::RemoveFromRangeMap(Client* client){
 }
 */
 
-void ZoneServer::RemoveSpawn(Spawn* spawn, bool delete_spawn, bool respawn, bool lock, bool erase_from_spawn_list) 
+void ZoneServer::RemoveSpawn(Spawn* spawn, bool delete_spawn, bool respawn, bool lock, bool erase_from_spawn_list, bool lock_spell_process) 
 {
 	LogWrite(ZONE__DEBUG, 3, "Zone", "Processing RemoveSpawn function for %s (%i)...", spawn->GetName(),spawn->GetID());
 
@@ -3937,7 +3937,7 @@ void ZoneServer::RemoveSpawn(Spawn* spawn, bool delete_spawn, bool respawn, bool
 		movementMgr->RemoveMob((Entity*)spawn);
 	}
 
-	RemoveSpawnSupportFunctions(spawn);
+	RemoveSpawnSupportFunctions(spawn, lock_spell_process);
 	if (reloading)
 		RemoveDeadEnemyList(spawn);
 
@@ -3953,7 +3953,7 @@ void ZoneServer::RemoveSpawn(Spawn* spawn, bool delete_spawn, bool respawn, bool
 		spawn_expire_timers.erase(spawn->GetID());
 	
 	spawn->SetDeletedSpawn(true);
-	
+
 	// we will remove the spawn ptr and entry in the spawn_list later.. it is not safe right now (lua? client process? spawn process? etc? too many factors)
 	if(erase_from_spawn_list)
 		AddPendingSpawnRemove(spawn->GetID());
@@ -4302,7 +4302,7 @@ void ZoneServer::Despawn(Spawn* spawn, int32 timer){
 	if(!spawn || spawn->IsPlayer())
 		return;
 
-	RemoveSpawnSupportFunctions(spawn);
+	RemoveSpawnSupportFunctions(spawn, true);
 	if(spawn->IsEntity())
 		((Entity*)spawn)->InCombat(false);
 	if(timer == 0)
@@ -5825,9 +5825,9 @@ void ZoneServer::RemoveLocationGrids() {
 	location_grids.clear(true);
 }
 
-void ZoneServer::RemoveSpellTimersFromSpawn(Spawn* spawn, bool remove_all, bool delete_recast, bool call_expire_function){
+void ZoneServer::RemoveSpellTimersFromSpawn(Spawn* spawn, bool remove_all, bool delete_recast, bool call_expire_function, bool lock_spell_process){
 	if(spellProcess)
-		spellProcess->RemoveSpellTimersFromSpawn(spawn, remove_all, delete_recast, call_expire_function);
+		spellProcess->RemoveSpellTimersFromSpawn(spawn, remove_all, delete_recast, call_expire_function, lock_spell_process);
 }
 
 void ZoneServer::Interrupted(Entity* caster, Spawn* interruptor, int16 error_code, bool cancel, bool from_movement){
@@ -5858,7 +5858,7 @@ void ZoneServer::ProcessEntityCommand(EntityCommand* entity_command, Entity* cas
 		spellProcess->ProcessEntityCommand(this, entity_command, caster, target, lock);
 }
 
-void ZoneServer::RemoveSpawnSupportFunctions(Spawn* spawn) {
+void ZoneServer::RemoveSpawnSupportFunctions(Spawn* spawn, bool lock_spell_process) {
 	if(!spawn)
 		return;	
 
@@ -5866,7 +5866,7 @@ void ZoneServer::RemoveSpawnSupportFunctions(Spawn* spawn) {
 	if(spawn->IsPlayer() && spawn->GetZone())
 		spawn->GetZone()->RemovePlayerPassenger(((Player*)spawn)->GetCharacterID());
 	if(spawn->IsEntity())
-		RemoveSpellTimersFromSpawn((Entity*)spawn, true);
+		RemoveSpellTimersFromSpawn((Entity*)spawn, true, true, true, lock_spell_process);
 
 	RemoveDamagedSpawn(spawn);
 	spawn->SendSpawnChanges(false);

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

@@ -306,7 +306,7 @@ public:
 	
 	void	AddSpawnGroupChance(int32 group_id, float percent);
 	
-	void	RemoveSpawn(Spawn* spawn, bool delete_spawn = true, bool respawn = true, bool lock = true, bool erase_from_spawn_list = true);
+	void	RemoveSpawn(Spawn* spawn, bool delete_spawn = true, bool respawn = true, bool lock = true, bool erase_from_spawn_list = true, bool lock_spell_process = false);
 	void	ProcessSpawnLocations();
 	void	SendQuestUpdates(Client* client, Spawn* spawn = 0);
 	
@@ -394,7 +394,7 @@ public:
 	void	LoadSpellProcess();
 	void	LockAllSpells(Player* player);
 	void	UnlockAllSpells(Player* player);
-	void	RemoveSpellTimersFromSpawn(Spawn* spawn, bool remove_all, bool delete_recast = true, bool call_expire_function = true);
+	void	RemoveSpellTimersFromSpawn(Spawn* spawn, bool remove_all, bool delete_recast = true, bool call_expire_function = true, bool lock_spell_process = false);
 	void	Interrupted(Entity* caster, Spawn* interruptor, int16 error_code, bool cancel = false, bool from_movement = false);
 	Spell*	GetSpell(Entity* caster);
 	void	ProcessSpell(Spell* spell, Entity* caster, Spawn* target = 0, bool lock = true, bool harvest_spell = false, LuaSpell* customSpell = 0, int16 custom_cast_time = 0, bool in_heroic_opp = false);
@@ -742,7 +742,7 @@ private:
 	void	RemoveLocationProximities();																		// never used outside zone server
 	void	CheckLocationProximity();																			// never used outside zone server
 	void	CheckLocationGrids();																				// never used outside zone server
-	void	RemoveSpawnSupportFunctions(Spawn* spawn);															// never used outside zone server
+	void	RemoveSpawnSupportFunctions(Spawn* spawn, bool lock_spell_process = false);															// never used outside zone server
 	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