Browse Source

Fix #441 - house lore support, mapping item ids to spawn and spawn id to to item id.
Also fixed a crash when placing a item and there is no item script assigned to the item

Emagi 1 year ago
parent
commit
57cd568e69

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

@@ -3785,6 +3785,10 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 						client->Message(CHANNEL_COLOR_RED, "This item has not been configured in the database, %s (%u) needs an entry where ?? has the model type id, eg. insert into item_appearances set item_id=%u,equip_type=??;", item->name.c_str(), item->details.item_id, item->details.item_id);
 						break;
 					}
+					else if(item->CheckFlag2(HOUSE_LORE) && client->GetCurrentZone()->HouseItemSpawnExists(item->details.item_id)) {
+						client->Message(CHANNEL_COLOR_RED, "Item %s is house lore and you cannot place another.", item->name.c_str());
+						break;
+					}
 
 					if (client->GetTempPlacementSpawn())
 					{
@@ -3792,6 +3796,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 						client->GetCurrentZone()->RemoveSpawn(tmp, true, true, true, true, true);
 						client->SetTempPlacementSpawn(nullptr);
 					}
+					
 
 					Object* obj = new Object();
 					Spawn* spawn = (Spawn*)obj;

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

@@ -2634,8 +2634,6 @@ void Player::ResortSpellBook(int32 sort_by, int32 order, int32 pattern, int32 ma
 		}
 		spell->slot = i;
 		
-			Spell* tmpspell = 0;
-			tmpspell = master_spell_list.GetSpell(spell->spell_id, spell->tier);
 		GetSpellBookSlotSort(pattern, &i, &page_book_count, &last_start_point);
 	} // end for loop for setting slots
 	

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

@@ -1364,6 +1364,16 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
 				SimpleMessage(CHANNEL_COLOR_RED, "This is not your home!");
 				break;
 			}
+			
+			
+			int32 uniqueID = spawn->GetPickupUniqueItemID();
+			if(uniqueID) {
+				Item* uniqueItem = GetPlayer()->item_list.GetItemFromUniqueID(uniqueID);
+				if(uniqueItem && uniqueItem->CheckFlag2(HOUSE_LORE) && GetCurrentZone()->HouseItemSpawnExists(uniqueItem->details.item_id)) {
+					Message(CHANNEL_COLOR_RED, "Item %s is house lore and you cannot place another.", uniqueItem->name.c_str());
+					break;
+				}
+			}
 
 			// handles instantiation logic + adding to zone of a new house object
 			PopulateHouseSpawn(place_object);
@@ -10607,7 +10617,8 @@ bool Client::PopulateHouseSpawnFinalize()
 				query.RunQuery2(Q_INSERT, "insert into spawn_instance_data set spawn_id = %u, spawn_location_id = %u, pickup_item_id = %u, pickup_unique_item_id = %u", tmp->GetDatabaseID(), tmp->GetSpawnLocationID(), tmp->GetPickupItemID(), uniqueID);
 			}
 
-			if(lua_interface->RunItemScript(uniqueItem->GetItemScript(), "placed", uniqueItem, GetPlayer(), tmp))
+			if(uniqueItem->GetItemScript() && 
+				lua_interface->RunItemScript(uniqueItem->GetItemScript(), "placed", uniqueItem, GetPlayer(), tmp))
 			{
 				uniqueItem = GetPlayer()->item_list.GetItemFromUniqueID(uniqueID);
 			}

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

@@ -1280,6 +1280,15 @@ void ZoneServer::DeleteSpawns(bool delete_all) {
 						subspawn_list[SUBSPAWN_TYPES::COLLECTOR].erase(subitr);
 					}
 				}
+				
+				if(spawn->GetPickupItemID()) {
+					std::map<int32, Spawn*>::iterator subitr = subspawn_list[SUBSPAWN_TYPES::HOUSE_ITEM_SPAWN].find(spawn->GetPickupItemID());
+					if(subitr != subspawn_list[SUBSPAWN_TYPES::HOUSE_ITEM_SPAWN].end() && subitr->second == spawn) {
+						subspawn_list[SUBSPAWN_TYPES::HOUSE_ITEM_SPAWN].erase(subitr);
+					}
+					housing_spawn_map.erase(spawn->GetID());
+				}
+				
 				MSpawnList.releasewritelock(__FUNCTION__, __LINE__);
 			
 				safe_delete(spawn);
@@ -1635,6 +1644,12 @@ bool ZoneServer::SpawnProcess(){
 			for (itr2 = pending_spawn_list_remove.begin(); itr2 != pending_spawn_list_remove.end(); itr2++) {
 				spawn_list.erase(*itr2);
 				subspawn_list[SUBSPAWN_TYPES::COLLECTOR].erase(*itr2);
+				
+				std::map<int32,int32>::iterator hsmitr = housing_spawn_map.find(*itr2);
+				if(hsmitr != housing_spawn_map.end()) {
+					subspawn_list[SUBSPAWN_TYPES::HOUSE_ITEM_SPAWN].erase(hsmitr->second);
+					housing_spawn_map.erase(hsmitr);
+				}
 			}
 
 			pending_spawn_list_remove.clear();
@@ -1658,6 +1673,10 @@ bool ZoneServer::SpawnProcess(){
 				if(spawn->IsCollector()) {
 					subspawn_list[SUBSPAWN_TYPES::COLLECTOR].insert(make_pair(spawn->GetID(),spawn));
 				}
+				if(spawn->GetPickupItemID()) {
+					subspawn_list[SUBSPAWN_TYPES::HOUSE_ITEM_SPAWN].insert(make_pair(spawn->GetPickupItemID(),spawn));
+					housing_spawn_map.insert(make_pair(spawn->GetID(), spawn->GetPickupItemID()));
+				}
 			}
 
 			pending_spawn_list_add.clear();
@@ -8239,6 +8258,12 @@ void ZoneServer::ProcessSpawnRemovals()
 		for (itr2 = m_pendingSpawnRemove.begin(); itr2 != m_pendingSpawnRemove.end(); itr2++) {
 			spawn_list.erase(itr2->first);
 			subspawn_list[SUBSPAWN_TYPES::COLLECTOR].erase(itr2->first);
+			
+			std::map<int32,int32>::iterator hsmitr = housing_spawn_map.find(itr2->first);
+			if(hsmitr != housing_spawn_map.end()) {
+				subspawn_list[SUBSPAWN_TYPES::HOUSE_ITEM_SPAWN].erase(hsmitr->second);
+				housing_spawn_map.erase(hsmitr);
+			}
 		}
 
 		m_pendingSpawnRemove.clear();
@@ -8371,4 +8396,16 @@ void ZoneServer::SendSubSpawnUpdates(SUBSPAWN_TYPES subtype) {
 		AddChangedSpawn(subitr->second);
 	}
 	MSpawnList.releasereadlock(__FUNCTION__, __LINE__);
+}
+
+bool ZoneServer::HouseItemSpawnExists(int32 item_id) {
+	bool exists = false;
+	std::map<int32, Spawn*>::iterator subitr;
+	MSpawnList.readlock(__FUNCTION__, __LINE__);
+	subitr = subspawn_list[SUBSPAWN_TYPES::HOUSE_ITEM_SPAWN].find(item_id);
+	if(subitr != subspawn_list[SUBSPAWN_TYPES::HOUSE_ITEM_SPAWN].end()) {
+		exists = true;
+	}
+	MSpawnList.releasereadlock(__FUNCTION__, __LINE__);
+	return exists;
 }

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

@@ -259,6 +259,7 @@ struct ZoneInfoSlideStruct {
 
 enum SUBSPAWN_TYPES {
 	COLLECTOR = 0,
+	HOUSE_ITEM_SPAWN = 1,
 	MAX_SUBSPAWN_TYPE = 20
 };
 
@@ -697,6 +698,7 @@ public:
 	Client*	RemoveZoneServerFromClient(ZoneServer* zone);
 	
 	void	SendSubSpawnUpdates(SUBSPAWN_TYPES subtype);
+	bool	HouseItemSpawnExists(int32 item_id);	
 private:
 #ifndef WIN32
 	pthread_t ZoneThread;
@@ -844,6 +846,7 @@ private:
 	
 	/* Specialized Lists to update specific scenarios */
 	std::map<int32, Spawn*>	subspawn_list[SUBSPAWN_TYPES::MAX_SUBSPAWN_TYPE];
+	std::map<int32, int32>	housing_spawn_map;
 	
 	/* Vectors */
 	vector<RevivePoint*>*	revive_points;