소스 검색

Functionality:
- Corner cases with examine inventory in DoF resolved. Now tracked through a max index id to avoid mis-indexing an item as "new" to the client array or building on the old array the client has already created (items get removed/added/so on, but this max id remains unchanged from the initial zone-in).
- Unfriendly spells are now removed from Entity/NPCs when ClearEncounter is called
- Food/Drink can be accessed equip/unequip on DoF client.

Performance:
- Improvements to ProcessMovement loop
- lua interface process cleanup now handled at World level (since zones may not be running to process it). Every zone used to call lua process (ick).

Memory leaks:
- Spells no longer leak into memory (NPC spell lists, player spells and passive spells)
- Player languages no longer leaks memory
- No more memory leak from player mail
- Fixed memory leak in Map loading of V3
- item memory leak fix with lore conflict/no space in inventory
- Addressed a hangup issue shutting down the world server in that pthread_cond_destroy(&cond) cannot be called until pthread_cond_broadcast(&cond) is called first

Emagi 5 달 전
부모
커밋
427964b7a0

+ 10 - 2
EQ2/source/WorldServer/Commands/Commands.cpp

@@ -2095,6 +2095,8 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 			if(sep && sep->arg[1][0] && sep->IsNumber(1)){
 				if(strcmp(sep->arg[0], "inventory") == 0){
 					int32 item_index = atol(sep->arg[1]);
+					
+					LogWrite(COMMAND__DEBUG, 5, "Command", "/info inventory item original index %u", item_index);
 					if(client->GetVersion() <= 546) {
 						if(item_index <= 255) {
 							item_index = 255 - item_index;
@@ -2113,8 +2115,14 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 					if(item){
 						if (item->IsCollectable() && client->SendCollectionsForItem(item))
 							break;
-
-						EQ2Packet* app = item->serialize(client->GetVersion(), (!item->GetItemScript() || !lua_interface), client->GetPlayer());
+						
+						EQ2Packet* app = 0;
+						if(client->GetVersion() <= 546) {
+							app = item->serialize(client->GetVersion(), true, client->GetPlayer());
+						}
+						else {
+							app = item->serialize(client->GetVersion(), (!item->GetItemScript() || !lua_interface), client->GetPlayer());
+						}
 						//DumpPacket(app);
 						client->QueuePacket(app);
 						if(item->GetItemScript() && lua_interface)

+ 12 - 4
EQ2/source/WorldServer/Entity.cpp

@@ -104,7 +104,7 @@ Entity::~Entity(){
 		safe_delete(itr4->second);
 	immunities.clear();
 	if(!IsPlayer())
-		DeleteSpellEffects();
+		DeleteSpellEffects(true);
 	safe_delete(m_threatTransfer);
 }
 
@@ -131,25 +131,33 @@ void Entity::DeleteSpellEffects(bool removeClient)
 		}
 		if(GetInfoStruct()->spell_effects[i].spell_id != 0xFFFFFFFF)
 		{
+			if(GetInfoStruct()->spell_effects[i].spell && GetInfoStruct()->spell_effects[i].spell->spell && 
+				GetInfoStruct()->spell_effects[i].spell->spell->GetSpellData()->spell_book_type == SPELL_BOOK_TYPE_NOT_SHOWN) {
+				lua_interface->RemoveSpell(GetInfoStruct()->spell_effects[i].spell, false, removeClient, "", removeClient);
+			}
 			GetInfoStruct()->spell_effects[i].spell_id = 0xFFFFFFFF;
 			GetInfoStruct()->spell_effects[i].spell = nullptr;
 		}
 	}
 }
 
-void Entity::RemoveSpells()
+void Entity::RemoveSpells(bool unfriendlyOnly)
 {
 	
 	for(int i=0;i<45;i++){
 		if(i<30){
 			if(GetInfoStruct()->maintained_effects[i].spell_id != 0xFFFFFFFF)
 			{
-				GetZone()->GetSpellProcess()->AddSpellCancel(GetInfoStruct()->maintained_effects[i].spell);
+				if(!unfriendlyOnly || (unfriendlyOnly && GetInfoStruct()->maintained_effects[i].spell && 
+					!GetInfoStruct()->maintained_effects[i].spell->spell->GetSpellData()->friendly_spell))
+					GetZone()->GetSpellProcess()->AddSpellCancel(GetInfoStruct()->maintained_effects[i].spell);
 			}
 		}
 		if(GetInfoStruct()->spell_effects[i].spell_id != 0xFFFFFFFF)
 		{
-			RemoveSpellEffect(GetInfoStruct()->spell_effects[i].spell);
+				if(!unfriendlyOnly || (unfriendlyOnly && GetInfoStruct()->spell_effects[i].spell && 
+					!GetInfoStruct()->spell_effects[i].spell->spell->GetSpellData()->friendly_spell))
+					RemoveSpellEffect(GetInfoStruct()->spell_effects[i].spell);
 		}
 	}
 }

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

@@ -1298,7 +1298,7 @@ public:
 	virtual ~Entity();
 
 	void DeleteSpellEffects(bool removeClient = false);
-	void RemoveSpells();
+	void RemoveSpells(bool unfriendlyOnly = false);
 	void MapInfoStruct();
 	virtual float GetDodgeChance();
 	virtual void AddMaintainedSpell(LuaSpell* spell);

+ 28 - 2
EQ2/source/WorldServer/Items/Items.cpp

@@ -2870,6 +2870,7 @@ PlayerItemList::PlayerItemList(){
 	packet_count = 0;
 	xor_packet = 0;
 	orig_packet = 0;
+	max_saved_index = 0;
 	MPlayerItems.SetName("PlayerItemList::MPlayerItems");
 }
 
@@ -2920,6 +2921,21 @@ Item* PlayerItemList::GetItem(sint32 bag_slot, int16 slot, int8 appearance_type)
 	return ret;
 }
 
+int32 PlayerItemList::SetMaxItemIndex() {
+	int32 max_index = indexed_items.size();
+	int32 new_index = 0;
+	map<int32, Item*>::iterator itr;
+	MPlayerItems.writelock(__FUNCTION__, __LINE__);
+	for(itr = indexed_items.begin();itr != indexed_items.end(); itr++){
+		if(itr->first > max_index) //just grab the highest index val for next loop
+			max_index = itr->first;
+	}
+	max_saved_index = max_index;
+	MPlayerItems.releasewritelock(__FUNCTION__, __LINE__);
+	
+	return max_index;
+}
+
 bool PlayerItemList::AddItem(Item* item){ //is called with a slot already set
 	//quick check to verify item
 	if(!item)
@@ -2948,7 +2964,8 @@ bool PlayerItemList::AddItem(Item* item){ //is called with a slot already set
 	}
 	
 	bool doNotOverrideIndex = false;
-	for(int32 i=0;i<max_index;i++){
+	int32 i=0;
+	for(i=0;i<max_index;i++){
 		if(!indexed_items[i]){
 			new_index = i;
 			LogWrite(ITEM__DEBUG, 0, "Item %s assigned to %u",item->name.c_str(), i);
@@ -2958,6 +2975,15 @@ bool PlayerItemList::AddItem(Item* item){ //is called with a slot already set
 			break;
 		}
 	}
+	
+	if(doNotOverrideIndex) {
+		if(i < max_saved_index) {
+		item->details.new_item = false;
+		} else {
+		item->details.new_item = true;
+		}
+	}
+	
 	// may break non DoF clients
 	if(!doNotOverrideIndex && new_index == 0 && max_index > 0)
 		new_index = max_index;
@@ -3569,7 +3595,7 @@ int16 PlayerItemList::GetNewItemByIndex(int16 in_index) {
 			new_item_slot++;
 			int16 actual_index = in_index - new_item_slot;
 			// this isn't compiling right
-			//LogWrite(ITEM__DEBUG, 0, "In index: %u new index %u actual %u and %u, new slot num %u", in_index, item->details.new_index, actual_index, i, new_item_slot);
+			//printf("In index: %u new index %u actual %u and %u, new slot num %u\n", in_index, item->details.new_index, actual_index, i, new_item_slot);
 			if(actual_index == i) {
 				return i;
 			}

+ 2 - 0
EQ2/source/WorldServer/Items/Items.h

@@ -1076,10 +1076,12 @@ public:
 	PlayerItemList();
 	~PlayerItemList();
 //	int16 number;
+	int32 max_saved_index;
 	map<int32, Item*> indexed_items;
 	map<sint32, map<int8, map<int16, Item*>> > items;
 //	map< int8, Item* > inv_items;
 //	map< int8, Item* > bank_items;
+	int32 SetMaxItemIndex();
 	bool  SharedBankAddAllowed(Item* item);
 	vector<Item*>* GetItemsFromBagID(sint32 bag_id);
 	vector<Item*>* GetItemsInBag(Item* bag);

+ 12 - 0
EQ2/source/WorldServer/Languages.cpp

@@ -102,6 +102,18 @@ PlayerLanguagesList::PlayerLanguagesList(){
 PlayerLanguagesList::~PlayerLanguagesList(){
 }
 
+void PlayerLanguagesList::Clear() {
+	list<Language*>::iterator itr;
+	Language* language = 0;
+	Language* ret = 0;
+	for(itr = player_languages_list.begin(); itr != player_languages_list.end(); itr++){
+		language = *itr;
+		safe_delete(language);
+	}
+	
+	player_languages_list.clear();
+}
+
 void PlayerLanguagesList::Add(Language* language){
 	player_languages_list.push_back(language);
 }

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

@@ -64,6 +64,7 @@ class PlayerLanguagesList {
 public:
 	PlayerLanguagesList();
 	~PlayerLanguagesList();
+	void Clear();
 	void Add(Language* language);
 	Language*	GetLanguage(int32 id);
 	Language*	GetLanguageByName(const char* name);

+ 49 - 49
EQ2/source/WorldServer/LuaInterface.cpp

@@ -808,9 +808,6 @@ lua_State* LuaInterface::LoadLuaFile(const char* name) {
 }
 
 void LuaInterface::RemoveSpell(LuaSpell* spell, bool call_remove_function, bool can_delete, string reason, bool removing_all_spells) {
-	if(shutting_down)
-		return;
-
 	if(call_remove_function){
 		lua_getglobal(spell->state, "remove");
 		LUASpawnWrapper* spawn_wrapper = new LUASpawnWrapper();
@@ -875,43 +872,45 @@ void LuaInterface::RemoveSpell(LuaSpell* spell, bool call_remove_function, bool
 	spell->char_id_targets.clear(); // TODO: reach out to those clients in different
 	spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__);
 
-	// we need to make sure all memory is purged for a copied spell, its only used once
-	if (spell->spell->IsCopiedSpell())
-		can_delete = true;
-
-	if (can_delete) {
-		AddPendingSpellDelete(spell);
-	}
-	if (spell->caster)
-	{
-		if(spell->caster->GetZone()) {
+	if(removing_all_spells) {
+		if(spell->caster && spell->caster->GetZone()) {
 			spell->caster->GetZone()->GetSpellProcess()->RemoveSpellScriptTimerBySpell(spell);
+			spell->caster->GetZone()->GetSpellProcess()->DeleteSpell(spell);
 		}
-		spell->caster->RemoveProc(0, spell);
-		spell->caster->RemoveMaintainedSpell(spell);
-
-		int8 spell_type = spell->spell->GetSpellData()->spell_type;
-		if(spell->caster->IsPlayer() && !removing_all_spells)
+	}
+	else {
+		AddPendingSpellDelete(spell);
+		if (spell->caster)
 		{
-			Player* player = (Player*)spell->caster;
-			switch(spell_type)
+			if(spell->caster->GetZone()) {
+				spell->caster->GetZone()->GetSpellProcess()->RemoveSpellScriptTimerBySpell(spell);
+			}
+			spell->caster->RemoveProc(0, spell);
+			spell->caster->RemoveMaintainedSpell(spell);
+
+			int8 spell_type = spell->spell->GetSpellData()->spell_type;
+			if(spell->caster->IsPlayer() && !removing_all_spells)
 			{
-				case SPELL_TYPE_FOOD:
-					if(player->get_character_flag(CF_FOOD_AUTO_CONSUME))
-					{
-						Item* item = player->GetEquipmentList()->GetItem(EQ2_FOOD_SLOT);
-						if(item && player->GetClient())
-							player->GetClient()->ConsumeFoodDrink(item, EQ2_FOOD_SLOT);
-					}
-				break;
-				case SPELL_TYPE_DRINK:
-					if(player->get_character_flag(CF_DRINK_AUTO_CONSUME))
-					{
-						Item* item = player->GetEquipmentList()->GetItem(EQ2_DRINK_SLOT);
-						if(item && player->GetClient())
-							player->GetClient()->ConsumeFoodDrink(item, EQ2_DRINK_SLOT);
-					}
-				break;
+				Player* player = (Player*)spell->caster;
+				switch(spell_type)
+				{
+					case SPELL_TYPE_FOOD:
+						if(player->get_character_flag(CF_FOOD_AUTO_CONSUME))
+						{
+							Item* item = player->GetEquipmentList()->GetItem(EQ2_FOOD_SLOT);
+							if(item && player->GetClient())
+								player->GetClient()->ConsumeFoodDrink(item, EQ2_FOOD_SLOT);
+						}
+					break;
+					case SPELL_TYPE_DRINK:
+						if(player->get_character_flag(CF_DRINK_AUTO_CONSUME))
+						{
+							Item* item = player->GetEquipmentList()->GetItem(EQ2_DRINK_SLOT);
+							if(item && player->GetClient())
+								player->GetClient()->ConsumeFoodDrink(item, EQ2_DRINK_SLOT);
+						}
+					break;
+				}
 			}
 		}
 	}
@@ -1565,21 +1564,22 @@ void LuaInterface::DeletePendingSpells(bool all) {
 		for (del_itr = tmp_deletes.begin(); del_itr != tmp_deletes.end(); del_itr++) {
 			spell = *del_itr;
 			
-			
-			if (spell->caster && spell->caster->GetZone()) {
-				spell->caster->GetZone()->GetSpellProcess()->DeleteActiveSpell(spell);
-			}
-			else if(spell->targets.size() > 0 && spell->caster && spell->caster->GetZone()) {
-				spell->MSpellTargets.readlock(__FUNCTION__, __LINE__);
-				for (int8 i = 0; i < spell->targets.size(); i++) {
-					Spawn* target = spell->caster->GetZone()->GetSpawnByID(spell->targets.at(i));
-					if (!target || !target->IsEntity())
-						continue;
-					target->GetZone()->GetSpellProcess()->DeleteActiveSpell(spell);
+			if(!all) {
+				if (spell->caster && spell->caster->GetZone()) {
+					spell->caster->GetZone()->GetSpellProcess()->DeleteActiveSpell(spell);
+				}
+				else if(spell->targets.size() > 0 && spell->caster && spell->caster->GetZone()) {
+					spell->MSpellTargets.readlock(__FUNCTION__, __LINE__);
+					for (int8 i = 0; i < spell->targets.size(); i++) {
+						Spawn* target = spell->caster->GetZone()->GetSpawnByID(spell->targets.at(i));
+						if (!target || !target->IsEntity())
+							continue;
+						target->GetZone()->GetSpellProcess()->DeleteActiveSpell(spell);
+					}
+					spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__);
 				}
-				spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__);
 			}
-
+			
 			spells_pending_delete.erase(spell);
 
 			if (spell->spell->IsCopiedSpell())

+ 7 - 0
EQ2/source/WorldServer/NPC.cpp

@@ -118,6 +118,13 @@ NPC::~NPC(){
 		}
 		safe_delete(skills);
 	}
+	if(spells) {
+		vector<NPCSpell*>::iterator itr;
+		for(itr = spells->begin(); itr != spells->end(); itr++){
+			safe_delete((*itr));
+		}
+		spells->clear();
+	}
 	safe_delete(spells);
 	MutexMap<int32, SkillBonus*>::iterator sb_itr = skill_bonus_list.begin();
 	while (sb_itr.Next())

+ 5 - 2
EQ2/source/WorldServer/NPC_AI.cpp

@@ -49,7 +49,7 @@ Brain::Brain(NPC* npc) {
 }
 
 Brain::~Brain() {
-
+	
 }
 
 void Brain::Think() {
@@ -503,7 +503,7 @@ void Brain::ProcessMelee(Entity* target, float distance) {
 bool Brain::HasRecovered() {
 	if(m_spellRecovery > Timer::GetCurrentTime2())
 		return false;
-
+	
 	m_spellRecovery = 0;
 	return true;
 }
@@ -693,6 +693,9 @@ bool Brain::AddToEncounter(int32 id) {
 
 void Brain::ClearEncounter() {
 	MEncounter.writelock(__FUNCTION__, __LINE__);
+	if(m_body) {
+		m_body->RemoveSpells(true);
+	}
 	m_encounter.clear();
 	m_encounter_playerlist.clear();
 	m_playerInEncounter = false;

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

@@ -137,7 +137,6 @@ protected:
 	NPC*					m_body;
 	// m_spellRecovery = time stamp for when the npc can cast again
 	int32					m_spellRecovery;
-
 private:
 	// MHateList = mutex to lock and unlock the hate list
 	Mutex					MHateList;

+ 12 - 3
EQ2/source/WorldServer/Player.cpp

@@ -203,6 +203,10 @@ Player::~Player(){
 	safe_delete(spawn_pos_struct);
 	ClearPendingSelectableItemRewards(0, true);
 	ClearPendingItemRewards();
+	ClearEverything();
+	
+	// leak fix on Language* pointer from Player::AddLanguage
+	player_languages_list.Clear();
 }
 
 EQ2Packet* Player::serialize(Player* player, int16 version){
@@ -1422,7 +1426,7 @@ vector<EQ2Packet*>	Player::UnequipItem(int16 index, sint32 bag_id, int8 slot, in
 	if(appearance_type)
 		equipList = &appearance_equipment_list;
 		
-	if(index >= GetNumSlotsEquip(version)) {
+	if(index >= NUM_SLOTS) {
 		LogWrite(PLAYER__ERROR, 0, "Player", "%u index is out of range for equip items, bag_id: %i, slot: %u, version: %u, appearance: %u", index, bag_id, slot, version, appearance_type);
 		return packets;
 	}
@@ -1961,6 +1965,7 @@ bool Player::AddItem(Item* item, AddItemType type) {
 				client->Message(CHANNEL_COLOR_CHAT_RELATIONSHIP, "You cannot obtain %s due to lore conflict.", item->name.c_str());
 				break;			
 			}
+			safe_delete(item);
 			return false;
 		}
 		else if(conflictItemList == STACK_LORE || conflictequipmentList == STACK_LORE || 
@@ -1971,6 +1976,7 @@ bool Player::AddItem(Item* item, AddItemType type) {
 						client->Message(CHANNEL_COLOR_CHAT_RELATIONSHIP, "You already have one stack of the LORE item: %s.", item->name.c_str());
 						break;			
 					}
+			safe_delete(item);
 			return false;
 		}
 		else if (item_list.AssignItemToFreeSlot(item)) {
@@ -3154,6 +3160,9 @@ void Player::AddSpellEffect(LuaSpell* luaspell, int32 override_expire_time){
 		GetZone()->RemoveTargetFromSpell(old_effect->spell, this);
 		RemoveSpellEffect(old_effect->spell);
 	}
+	
+	LogWrite(SPELL__DEBUG, 0, "Spell", "%s AddSpellEffect %s (%u).", spell->GetName(), GetName(), GetID());
+	
 	effect = GetFreeSpellEffectSlot();
 
 	if(effect){
@@ -3489,7 +3498,7 @@ void Player::PrepareIncomingMovementPacket(int32 len, uchar* data, int16 version
 	{
 		if (!IsRooted() && !IsMezzedOrStunned()) {
 			SetX(x);
-			SetY(y);
+			SetY(y, true, true);
 			SetZ(z);
 			SetSpeedX(x_speed);
 			SetSpeedY(y_speed);
@@ -5819,7 +5828,7 @@ void Player::DeleteMail(int32 mail_id, bool from_database) {
 	if (mail_list.count(mail_id) > 0) {
 		if (from_database)
 			database.DeletePlayerMail(mail_list.Get(mail_id));
-		mail_list.erase(mail_id);
+		mail_list.erase(mail_id, true, true); // need to delete the mail ptr
 	}
 }
 

+ 110 - 80
EQ2/source/WorldServer/Spawn.cpp

@@ -91,7 +91,6 @@ Spawn::Spawn(){
 	spawn_group_list = 0;
 	MSpawnGroup = 0;
 	movement_locations = 0;
-	MMovementLocations = 0;
 	target = 0;
 	primary_command_list_id = 0;
 	secondary_command_list_id = 0;
@@ -145,6 +144,8 @@ Spawn::Spawn(){
 }
 
 Spawn::~Spawn(){
+	is_running = false;
+	
 	vector<Item*>::iterator itr;
 	for (itr = loot_items.begin(); itr != loot_items.end(); itr++)
 		safe_delete(*itr);
@@ -158,8 +159,8 @@ Spawn::~Spawn(){
 	secondary_command_list.clear();
 
 	RemoveSpawnFromGroup();
-	if (MMovementLocations)
-		MMovementLocations->writelock(__FUNCTION__, __LINE__);
+	
+	MMovementLocations.lock();
 	if(movement_locations){
 		while(movement_locations->size()){
 			safe_delete(movement_locations->front());
@@ -167,9 +168,7 @@ Spawn::~Spawn(){
 		}
 		safe_delete(movement_locations);
 	}
-	if (MMovementLocations)
-		MMovementLocations->releasewritelock(__FUNCTION__, __LINE__);
-	safe_delete(MMovementLocations);
+	MMovementLocations.unlock();
 
 	MMovementLoop.lock();
 	for (int32 i = 0; i < movement_loop.size(); i++)
@@ -2867,15 +2866,17 @@ void Spawn::ProcessMovement(bool isSpawnListLocked){
 			return;
 		}
 		int locations = 0;
-		if (movement_locations && MMovementLocations)
-		{
-			MMovementLocations->readlock(__FUNCTION__, __LINE__);
+		
+		MMovementLocations.lock_shared();
+		if (movement_locations) {
 			locations = movement_locations->size();
-			MMovementLocations->releasereadlock(__FUNCTION__, __LINE__);
 		}
+		MMovementLocations.unlock_shared();
+		
 		if (locations < 1 && GetZone() && ((Entity*)this)->IsFeared())
 		{
 			CalculateNewFearpoint();
+			ValidateRunning(true, true);
 		}
 	}
 
@@ -2905,27 +2906,24 @@ void Spawn::ProcessMovement(bool isSpawnListLocked){
 			}
 			MovementLocation tmpLoc;
 			MovementLocation* loc = 0;
-			if(MMovementLocations) {
-				MMovementLocations->readlock(__FUNCTION__, __LINE__);
-				
-				if(movement_locations && movement_locations->size() > 0){
-					loc = movement_locations->front();
-					if(loc) {
-						tmpLoc.attackable = loc->attackable;
-						tmpLoc.gridid = loc->gridid;
-						tmpLoc.lua_function = string(loc->lua_function);
-						tmpLoc.mapped = loc->mapped;
-						tmpLoc.reset_hp_on_runback = loc->reset_hp_on_runback;
-						tmpLoc.speed = loc->speed;
-						tmpLoc.stage = loc->stage;
-						tmpLoc.x = loc->x;
-						tmpLoc.y = loc->y;
-						tmpLoc.z = loc->z;
-						loc = &tmpLoc;
-					}
+			MMovementLocations.lock_shared();
+			if(movement_locations && movement_locations->size() > 0){
+				loc = movement_locations->front();
+				if(loc) {
+					tmpLoc.attackable = loc->attackable;
+					tmpLoc.gridid = loc->gridid;
+					tmpLoc.lua_function = string(loc->lua_function);
+					tmpLoc.mapped = loc->mapped;
+					tmpLoc.reset_hp_on_runback = loc->reset_hp_on_runback;
+					tmpLoc.speed = loc->speed;
+					tmpLoc.stage = loc->stage;
+					tmpLoc.x = loc->x;
+					tmpLoc.y = loc->y;
+					tmpLoc.z = loc->z;
+					loc = &tmpLoc;
 				}
-				MMovementLocations->releasereadlock(__FUNCTION__, __LINE__);
 			}
+			MMovementLocations.unlock_shared();
 
 			float dist = GetDistance(followTarget, true);
 			if ((!EngagedInCombat() && m_followDistance > 0 && dist <= m_followDistance) || 
@@ -2959,15 +2957,15 @@ void Spawn::ProcessMovement(bool isSpawnListLocked){
 			MovementData* data = movement_loop[movement_index];
 			// need to resume our movement
 			if(resume_movement){
-				if (movement_locations && MMovementLocations){
-					MMovementLocations->writelock(__FUNCTION__, __LINE__);
+				MMovementLocations.lock();
+				if (movement_locations){
 					while (movement_locations->size()){
 						safe_delete(movement_locations->front());
 						movement_locations->pop_front();
 					}
 					movement_locations->clear();
-					MMovementLocations->releasewritelock(__FUNCTION__, __LINE__);
 				}
+				MMovementLocations.unlock();
 
 				data = movement_loop[movement_index];
 				
@@ -3046,17 +3044,17 @@ void Spawn::ProcessMovement(bool isSpawnListLocked){
 							FaceTarget(data->x, data->z);
 						// If 0 delay at location get and set data for the point after it
 						if(data->delay == 0 && movement_loop.size() > 0){
-							if(movement_locations && MMovementLocations)
+							MMovementLocations.lock();
+							if(movement_locations)
 							{
-								MMovementLocations->writelock(__FUNCTION__, __LINE__);
 								while (movement_locations->size()){
 									safe_delete(movement_locations->front());
 									movement_locations->pop_front();
 								}
 								// clear current target locations
 								movement_locations->clear();
-								MMovementLocations->releasewritelock(__FUNCTION__, __LINE__);
 							}
+							MMovementLocations.unlock();
 							// get the data for the location after out new location
 							int16 tmp_index = movement_index+1;
 							MovementData* data2 = 0;
@@ -3121,6 +3119,8 @@ void Spawn::ResetMovement(bool inFlight){
 
 	if(!inFlight)
 		MMovementLoop.releasewritelock();
+	
+	ValidateRunning(true, (inFlight == false));
 }
 
 void Spawn::AddMovementLocation(float x, float y, float z, float speed, int16 delay, const char* lua_function, float heading, bool include_heading){
@@ -3144,27 +3144,58 @@ void Spawn::AddMovementLocation(float x, float y, float z, float speed, int16 de
 	MMovementLoop.unlock();
 }
 
-bool Spawn::IsRunning(){
+bool Spawn::ValidateRunning(bool lockMovementLocation, bool lockMovementLoop) {
 	bool movement = false;
 
-	if(movement_locations && MMovementLocations)
-	{
-		MMovementLocations->readlock(__FUNCTION__, __LINE__);
-		movement = movement_locations->size() > 0;
-		MMovementLocations->releasereadlock(__FUNCTION__, __LINE__);
-		if(movement)
-			return true;
+	if(lockMovementLocation) {
+		MMovementLocations.lock_shared();
+	}
+	
+	if(movement_locations) {
+	movement = movement_locations->size() > 0;
+	}
+	
+	if(lockMovementLocation) {
+		MMovementLocations.unlock_shared();
+	}
+	
+	if(IsPauseMovementTimerActive() || (IsEntity() && (((Entity*)this)->IsMezzedOrStunned() || ((Entity*)this)->IsRooted()))) {
+		is_running = false;
+		return false;
+	}
+	
+	if(movement) {
+		is_running = true;
+		return true;
 	}
 
-	MMovementLoop.lock();
+	if(lockMovementLoop) {
+		MMovementLoop.lock();
+	}
+	
 	movement = movement_loop.size() > 0;
-	MMovementLoop.unlock();
+	
+	if(movement) {
+		is_running = true;
+	}
+	else {
+		is_running = false;
+	}
+	
+	if(lockMovementLoop) {
+		MMovementLoop.unlock();
+	}
 	return movement;
 }
+bool Spawn::IsRunning(){
+	return is_running;
+}
 
 void Spawn::RunToLocation(float x, float y, float z, float following_x, float following_y, float following_z){
-	if(IsPauseMovementTimerActive() || (IsEntity() && (((Entity*)this)->IsMezzedOrStunned() || ((Entity*)this)->IsRooted())))
+	if(IsPauseMovementTimerActive() || (IsEntity() && (((Entity*)this)->IsMezzedOrStunned() || ((Entity*)this)->IsRooted()))) {
+		is_running = false;
 		return;
+	}
 	
 	if(!IsWidget())
 		FaceTarget(x, z);
@@ -3182,6 +3213,7 @@ void Spawn::RunToLocation(float x, float y, float z, float following_x, float fo
 		SetPos(&appearance.pos.Z3, following_z, false);
 	}
 
+	is_running = true;
 	position_changed = true;
 	changed = true;
 	GetZone()->AddChangedSpawn(this);
@@ -3189,29 +3221,21 @@ void Spawn::RunToLocation(float x, float y, float z, float following_x, float fo
 
 MovementLocation* Spawn::GetCurrentRunningLocation(){
 	MovementLocation* ret = 0;
-	if(MMovementLocations)
-		MMovementLocations->readlock(__FUNCTION__, __LINE__);
-	
+	MMovementLocations.lock_shared();
 	if(movement_locations && movement_locations->size() > 0){
 		ret = movement_locations->front();
 	}
-
-	if(MMovementLocations)
-		MMovementLocations->releasereadlock(__FUNCTION__, __LINE__);
+	MMovementLocations.unlock_shared();
 	return ret;
 }
 
 MovementLocation* Spawn::GetLastRunningLocation(){
 	MovementLocation* ret = 0;
-	if(MMovementLocations)
-		MMovementLocations->readlock(__FUNCTION__, __LINE__);
-		
+	MMovementLocations.lock_shared();
 	if(movement_locations && movement_locations->size() > 0){
 		ret = movement_locations->back();
 	}
-
-	if(MMovementLocations)
-		MMovementLocations->releasereadlock(__FUNCTION__, __LINE__);
+	MMovementLocations.unlock_shared();
 	return ret;
 }
 
@@ -3234,11 +3258,12 @@ void Spawn::AddRunningLocation(float x, float y, float z, float speed, float dis
 		z = z - (GetZ() - z)*distance_away/distance;
 	}
 	
+	MMovementLocations.lock();
 	if(!movement_locations){
 		movement_locations = new deque<MovementLocation*>();
-		safe_delete(MMovementLocations);
-		MMovementLocations = new Mutex();
 	}
+	MMovementLocations.unlock();
+	
 	MovementLocation* data = new MovementLocation;
 	data->mapped = isMapped;
 	data->x = x;
@@ -3250,19 +3275,24 @@ void Spawn::AddRunningLocation(float x, float y, float z, float speed, float dis
 	data->gridid = 0; // used for runback defaults
 	data->reset_hp_on_runback = false;
 
-	MMovementLocations->writelock(__FUNCTION__, __LINE__);
+	MMovementLocations.lock_shared();
 	if(movement_locations->size() > 0)
 		current_location = movement_locations->back();
+	MMovementLocations.unlock_shared();
+	
 	if(!current_location){
 		SetSpawnOrigX(GetX());
 		SetSpawnOrigY(GetY());
 		SetSpawnOrigZ(GetZ());
 		SetSpawnOrigHeading(GetHeading());
 	}
+	is_running = true;
+	
+	MMovementLocations.lock();
 	movement_locations->push_back(data);
-	MMovementLocations->releasewritelock(__FUNCTION__, __LINE__);	
+	MMovementLocations.unlock();
 	if(!IsPauseMovementTimerActive() && finished_adding_locations){
-		MMovementLocations->writelock(__FUNCTION__, __LINE__);
+		MMovementLocations.lock();
 		current_location = movement_locations->front();
 		SetSpeed(current_location->speed);
 		if(movement_locations->size() > 1){		
@@ -3271,21 +3301,21 @@ void Spawn::AddRunningLocation(float x, float y, float z, float speed, float dis
 		}
 		else
 			RunToLocation(current_location->x, current_location->y, current_location->z, 0, 0, 0);
-		MMovementLocations->releasewritelock(__FUNCTION__, __LINE__);	
+		MMovementLocations.unlock();
 	}
 }
 
 bool Spawn::RemoveRunningLocation(){
 	bool ret = false;
-	if(movement_locations){
-		MMovementLocations->writelock(__FUNCTION__, __LINE__);
-		if(movement_locations->size() > 0){
-			delete movement_locations->front();
-			movement_locations->pop_front();
-			ret = true;
-		}
-		MMovementLocations->releasewritelock(__FUNCTION__, __LINE__);
+	MMovementLocations.lock();
+	if(movement_locations && movement_locations->size() > 0){
+		delete movement_locations->front();
+		movement_locations->pop_front();
+		ret = true;
 	}
+	MMovementLocations.unlock();
+	
+	ValidateRunning(true, false);
 	return ret;
 }
 
@@ -3313,8 +3343,8 @@ bool Spawn::CalculateChange(){
 	bool remove_needed = false;
 	MovementLocation* data = 0;
 	MovementLocation tmpLoc;
-	if(movement_locations && MMovementLocations){
-		MMovementLocations->readlock(__FUNCTION__, __LINE__);
+	MMovementLocations.lock_shared();
+	if(movement_locations){
 		if(movement_locations->size() > 0){
 			// Target location
 			data = movement_locations->front();
@@ -3335,8 +3365,8 @@ bool Spawn::CalculateChange(){
 			if(!data || (data->x == GetX() && data->y == GetY() && data->z == GetZ()))
 				remove_needed = true;
 			}
-		MMovementLocations->releasereadlock(__FUNCTION__, __LINE__);
 	}
+	MMovementLocations.unlock_shared();
 		
 	if(remove_needed){
 		NewWaypointChange(data);
@@ -3436,9 +3466,9 @@ void Spawn::CalculateRunningLocation(bool stop){
 		SetPos(&appearance.pos.Z3, GetZ(), false);
 		continueElseIf = false;
 	}
-	else if (removed && movement_locations && MMovementLocations) {
-		if (MMovementLocations)
-			MMovementLocations->readlock(__FUNCTION__, __LINE__);
+	else if (removed) {
+		MMovementLocations.lock_shared();
+		if(movement_locations) {
 			if(movement_locations->size() > 0) {
 				MovementLocation* current_location = movement_locations->at(0);
 				if (movement_locations->size() > 1) {
@@ -3450,8 +3480,8 @@ void Spawn::CalculateRunningLocation(bool stop){
 				
 				continueElseIf = false;
 			}
-		if (MMovementLocations)
-			MMovementLocations->releasereadlock(__FUNCTION__, __LINE__);
+		}
+		MMovementLocations.unlock_shared();
 	}
 	
 	if (continueElseIf && GetZone() && GetTarget() != NULL && EngagedInCombat())

+ 6 - 21
EQ2/source/WorldServer/Spawn.h

@@ -1070,6 +1070,7 @@ public:
 	void	AddMovementLocation(float x, float y, float z, float speed, int16 delay, const char* lua_function, float heading, bool include_heading = false);
 	void	ProcessMovement(bool isSpawnListLocked=false);
 	void	ResetMovement(bool inFlight=false);
+	bool	ValidateRunning(bool lockMovementLocation, bool lockMovementLoop);
 	bool	IsRunning();
 	void	CalculateRunningLocation(bool stop = false);
 	void	RunToLocation(float x, float y, float z, float following_x = 0, float following_y = 0, float following_z = 0);
@@ -1091,13 +1092,9 @@ public:
 	bool	HasMovementLoop(){ return movement_loop.size() > 0; }
 	bool	HasMovementLocations() { 
 			bool hasLocations = false;
-			if (MMovementLocations) {
-				MMovementLocations->readlock(__FUNCTION__, __LINE__);
-			}
-				hasLocations = movement_locations ? movement_locations->size() > 0 : false;
-			if (MMovementLocations) {
-				MMovementLocations->releasereadlock(__FUNCTION__, __LINE__);
-			}
+			MMovementLocations.lock_shared();
+			hasLocations = movement_locations ? movement_locations->size() > 0 : false;
+			MMovementLocations.unlock_shared();
 			return hasLocations;
 	}
 
@@ -1113,6 +1110,7 @@ public:
 	std::atomic<bool>	position_changed;
 	std::atomic<bool> 	info_changed;
 	std::atomic<bool>	vis_changed;
+	std::atomic<bool>	is_running;
 	int16				size;
 	int32				faction_id;
 	int8				oversized_packet; //0xff
@@ -1188,19 +1186,6 @@ public:
 
 	void CalculateNewFearpoint();
 
-	void StopMoving() {
-		if (movement_locations && MMovementLocations)
-		{
-			MMovementLocations->writelock(__FUNCTION__, __LINE__);
-			while (movement_locations->size()){
-				safe_delete(movement_locations->front());
-				movement_locations->pop_front();
-			}
-			movement_locations->clear();
-			MMovementLocations->releasewritelock(__FUNCTION__, __LINE__);
-		}
-	}
-
 	enum SpawnProximityType {
 		SPAWNPROXIMITY_DATABASE_ID = 0,
 		SPAWNPROXIMITY_LOCATION_ID = 1
@@ -1370,7 +1355,7 @@ private:
 	int32			trap_opened_time;
 	deque<MovementLocation*>* movement_locations;
 	Mutex			MLootItems;
-	Mutex*			MMovementLocations;
+	mutable std::shared_mutex MMovementLocations;
 	Mutex*			MSpawnGroup;
 	int8			size_offset;
 	int				tmp_visual_state;

+ 18 - 45
EQ2/source/WorldServer/SpellProcess.cpp

@@ -81,7 +81,11 @@ void SpellProcess::RemoveAllSpells(bool reload_spells){
 		recast_timers.Remove(recast_timers_itr->value, true);
 	}
 
+	map<LuaSpell*, vector<int32>*>::iterator remove_itr;
 	MRemoveTargetList.writelock(__FUNCTION__, __LINE__);
+	for (remove_itr = remove_target_list.begin(); remove_itr != remove_target_list.end(); remove_itr++){
+		safe_delete(remove_itr->second);
+	}
 	remove_target_list.clear();
 	MRemoveTargetList.releasewritelock(__FUNCTION__, __LINE__);
 
@@ -644,12 +648,20 @@ bool SpellProcess::CastInstant(Spell* spell, Entity* caster, Entity* target, boo
 	}
 
 	bool result = CastProcessedSpell(lua_spell, passive);
-
+	
 	caster->GetZone()->SendCastSpellPacket(lua_spell, caster);
 	
+	if(!result) {
+		lua_spell->caster->GetZone()->GetSpellProcess()->RemoveSpellScriptTimerBySpell(lua_spell);
+		DeleteSpell(lua_spell);
+		return result;
+	}
+		
 	if(!remove)
 		return result;
 	
+	printf("%s: RemoveSpell %s\n", caster->GetName(), lua_spell->spell->GetName());
+	
 	lua_interface->RemoveSpell(lua_spell, true, SpellScriptTimersHasSpell(lua_spell));
 	return true;
 }
@@ -1671,40 +1683,6 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her
 	
 	MutexList<LuaSpell*>::iterator itr = active_spells.begin();
 	bool processedSpell = false;
-	LuaSpell* replace_spell = 0;
-	// Check to see if we already casted this spell and it is in the active_spells list
-	/*while (itr.Next()) {
-		LuaSpell* luaspell = itr.value;
-		// Check to see if this is the same spell by comparing caster, spell id, and spell tier
-		if (luaspell->caster == spell->caster && luaspell->spell->GetSpellID() == spell->spell->GetSpellID() && luaspell->spell->GetSpellTier() == spell->spell->GetSpellTier() && luaspell->targets.size() == spell->targets.size()) {
-			vector<Spawn*>::iterator itr;
-			vector<Spawn*>::iterator itr2;
-			bool all_match = true;
-			// compare the target vector to make sure this is the same spell
-			for (itr = luaspell->targets.begin(); itr != luaspell->targets.end(); itr++) {
-				bool match = false;
-				for (itr2 = spell->targets.begin(); itr2 != spell->targets.end(); itr2++) {
-					if ((*itr) == (*itr2)) {
-						match = true;
-						break;
-					}
-				}
-				if (!match) {
-					all_match = false;
-					break;
-				}
-			}
-			if (all_match) {
-				// set a pointer to replace the spell in the active spell list so we don't have to run this loop again
-				replace_spell = luaspell;
-				// if friendly skip the calling of the lua function as they have already been called for the previous version of this spell
-				if (spell->spell->GetSpellData()->friendly_spell == 1)
-					processedSpell = true;
-
-				break;
-			}
-		}
-	}*/
 	
 	bool allTargets = (spell->spell->GetSpellData()->spell_type == SPELL_TYPE_ALLGROUPTARGETS);
 	if (!processedSpell)
@@ -1767,7 +1745,7 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her
 			SendFinishedCast(spell, client);
 		return false;
 	}
-	if(!spell->resisted && (spell->spell->GetSpellDuration() > 0 || spell->spell->GetSpellData()->duration_until_cancel)) {
+	if(!spell->resisted && (spell->spell->GetSpellDuration() > 0 || spell->spell->GetSpellData()->duration_until_cancel || spell->spell->GetSpellData()->spell_book_type == SPELL_BOOK_TYPE_NOT_SHOWN)) {
 		for (int32 i = 0; i < spell->targets.size(); i++) {
 			
 			//LogWrite(SPELL__ERROR, 0, "Spell", "No precast function found for %s", ((Entity*)target)->GetName());
@@ -1801,13 +1779,7 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her
 			}
 		}
 
-		if (replace_spell) {
-			active_spells.Remove(replace_spell);
-			active_spells.Add(spell);
-		}
-		else {
-			active_spells.Add(spell);
-		}
+		active_spells.Add(spell);
 
 		if (spell->num_triggers > 0)
 			ClientPacketFunctions::SendMaintainedExamineUpdate(client, spell->slot_pos, spell->num_triggers, 0);
@@ -1823,7 +1795,7 @@ bool SpellProcess::CastProcessedSpell(LuaSpell* spell, bool passive, bool in_her
 			spell->timer.SetTimer(spell->spell->GetSpellData()->call_frequency*100);
 		else
 			spell->timer.SetTimer(spell->spell->GetSpellData()->duration1*100);
-		if (active_spells.count(spell) > 0) {
+		if (active_spells.count(spell) < 1) {
 			active_spells.Add(spell);
 		}
 	}
@@ -2648,7 +2620,6 @@ void SpellProcess::RemoveSpellScriptTimer(SpellScriptTimer* timer, bool locked)
 void SpellProcess::RemoveSpellScriptTimerBySpell(LuaSpell* spell, bool clearPendingDeletes) {
 	vector<SpellScriptTimer*>::iterator itr;
 	MSpellScriptTimers.writelock(__FUNCTION__, __LINE__);
-
 	if (lua_interface && clearPendingDeletes)
 		lua_interface->DeletePendingSpell(spell);
 
@@ -2945,6 +2916,8 @@ void SpellProcess::DeleteSpell(LuaSpell* spell)
 {
 	RemoveSpellFromQueue(spell->spell, spell->caster);
 
+	DeleteActiveSpell(spell);
+	
 	if (spell->spell->IsCopiedSpell())
 	{
 		lua_interface->RemoveCustomSpell(spell->spell->GetSpellID());

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

@@ -366,7 +366,8 @@ public:
 
 	void RemoveTargetFromSpell(LuaSpell* spell, Spawn* target, bool remove_caster = false);
 	void CheckRemoveTargetFromSpell(LuaSpell* spell, bool allow_delete = true, bool removing_all_spells = false);
-
+	void RemoveTargetList(LuaSpell* spell);
+	
 	/// <summary>Adds a solo HO to the SpellProcess</summary>
 	/// <param name='client'>The client who is starting the HO</param>
 	/// <param name='ho'>The HO that is being started</param>

+ 5 - 0
EQ2/source/WorldServer/World.cpp

@@ -47,6 +47,7 @@
 #include "LuaInterface.h"
 #include "HeroicOp/HeroicOp.h"
 #include "RaceTypes/RaceTypes.h"
+#include "LuaInterface.h"
 
 #include <boost/algorithm/string.hpp>
 
@@ -86,6 +87,7 @@ extern ConfigReader configReader;
 extern LoginServer loginserver;
 extern World world;
 extern RuleManager rule_manager;
+extern LuaInterface* lua_interface;
 
 World::World() : save_time_timer(300000), time_tick_timer(3000), vitality_timer(3600000), player_stats_timer(60000), server_stats_timer(60000), /*remove_grouped_player(30000),*/ guilds_timer(60000), lotto_players_timer(500), watchdog_timer(10000) {
 	save_time_timer.Start();
@@ -272,6 +274,9 @@ void World::Process(){
 		WorldTimeTick();
 		MWorldTime.releasewritelock(__FUNCTION__, __LINE__);
 	}
+	
+	if(lua_interface)
+		lua_interface->Process();
 
 	if(vitality_timer.Check())
 		UpdateVitality();

+ 1 - 0
EQ2/source/WorldServer/Zone/map.cpp

@@ -641,6 +641,7 @@ bool Map::LoadV2Deflated(FILE* f) {
 	string fileName(name);
 	
 	if(fileName.find("EQ2EmuMapTool") != std::string::npos) {
+		safe_delete_array(buf);
 		return(LoadV3Deflated(&file, srcbuf));
 	}
 	

+ 0 - 4
EQ2/source/WorldServer/Zone/mob_movement_manager.cpp

@@ -422,10 +422,6 @@ public:
 
 	virtual bool Process(MobMovementManager* mob_movement_manager, Entity* mob)
 	{
-		if (mob->IsRunning()) {
-			mob->StopMoving();
-		}
-
 		return true;
 	}
 

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

@@ -266,15 +266,15 @@ Client::~Client() {
 
 
 void Client::RemoveClientFromZone() {
+	if(player && player->GetZone())
+		player->GetZone()->GetSpellProcess()->RemoveSpellTimersFromSpawn(player, true, false, true, true);
+	
 	if (GetTempPlacementSpawn() && GetCurrentZone()) {
 		Spawn* tmp = GetTempPlacementSpawn();
 		SetTempPlacementSpawn(nullptr);
 		GetCurrentZone()->RemoveSpawn(tmp, true, false, true, true, true);
 	}
 
-	if(player && player->GetZone())
-		player->GetZone()->GetSpellProcess()->RemoveSpellTimersFromSpawn(player, true, false, true, true);
-
 	if (current_zone && player) {
 		if (player->GetGroupMemberInfo()) {
 				TempRemoveGroup();
@@ -296,6 +296,7 @@ void Client::RemoveClientFromZone() {
 	MDeletePlayer.writelock(__FUNCTION__, __LINE__);
 	if (player && !player->GetPendingDeletion())
 		safe_delete(player);
+	player = nullptr;
 	MDeletePlayer.releasewritelock(__FUNCTION__, __LINE__);
 	
 	deque<BuyBackItem*>::iterator itr;
@@ -397,6 +398,7 @@ void Client::SendLoginInfo() {
 			database.UpdateStartingItems(GetCharacterID(), player->GetAdventureClass(), player->GetRace());
 			database.LoadCharacterItemList(GetAccountID(), GetCharacterID(), player, GetVersion());
 		}
+		GetPlayer()->item_list.SetMaxItemIndex();
 		database.LoadPlayerFactions(this);
 		database.LoadCharacterQuests(this);
 		database.LoadCharacterQuestRewards(this);
@@ -3408,7 +3410,6 @@ bool Client::Process(bool zone_process) {
 	}
 
 	if (GetCurrentZone() && !GetCurrentZone()->IsLoading() && GetCurrentZone()->GetSpawnByID(GetPlayer()->GetID()) && should_load_spells) {
-		player->ApplyPassiveSpells();
 		//database.LoadCharacterActiveSpells(player);
 		player->UnlockAllSpells(true);
 
@@ -3781,6 +3782,13 @@ void ClientList::Remove(Client* client, bool remove_data) {
 
 }
 
+void Client::SetCurrentZone(ZoneServer* zone) { 
+	current_zone = zone;
+	if(player) {
+		player->SetZone(zone, GetVersion());
+	}
+}
+
 void Client::SetCurrentZone(int32 id) {
 	if (current_zone) {
 		//current_zone->GetCombat()->RemoveHate(player);
@@ -7132,7 +7140,6 @@ bool Client::AddItem(Item* item, bool* item_deleted, AddItemType type) {
 	else {
 		lua_interface->SetLuaUserDataStale(item);
 		// likely lore conflict
-		safe_delete(item);
 
 		if(item_deleted)
 			*item_deleted = true;

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

@@ -224,12 +224,7 @@ public:
 	void	SetCurrentZoneByInstanceID(int32 id, int32 zoneid);
 	//void	SetCurrentZoneByInstanceID(instanceid, zoneid);
 	void	SetCurrentZone(int32 id);
-	void	SetCurrentZone(ZoneServer* zone) { 
-		current_zone = zone;
-		if(player) {
-			player->SetZone(zone, GetVersion());
-		}
-	}
+	void	SetCurrentZone(ZoneServer* zone);
 	void	SetZoningDestination(ZoneServer* zone) {
 		zoning_destination = zone;
 	}

+ 0 - 2
EQ2/source/WorldServer/zoneserver.cpp

@@ -1560,8 +1560,6 @@ bool ZoneServer::Process()
 		if (sync_game_time_timer.Check() && !zoneShuttingDown)
 			SendTimeUpdateToAllClients();
 
-		if(lua_interface)
-			lua_interface->Process();
 		world.MWorldTime.readlock(__FUNCTION__, __LINE__);
 		int hour = world.GetWorldTimeStruct()->hour;
 		int minute = world.GetWorldTimeStruct()->minute;

+ 1 - 0
EQ2/source/common/Condition.cpp

@@ -124,6 +124,7 @@ int retcode=0;
 Condition::~Condition()
 {
 	pthread_mutex_lock(&mutex);
+	pthread_cond_broadcast(&cond);
 	pthread_cond_destroy(&cond);
 	pthread_mutex_unlock(&mutex);
 	pthread_mutex_destroy(&mutex);