Browse Source

spawn move openheading and closeheading

Added support for /spawn move openheading and /spawn move closeheading -- this works on widgets only.  You can set the heading without worrying about the x,y,z position, will auto update and new headings will be used.

include_heading is also updated in the DB to 1.

Fixes #32.
Image 4 years ago
parent
commit
0d9c901e0e

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

@@ -1513,13 +1513,24 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 				if(packet){
 					float unknown2_3 = 0;
 					int8 placement_mode = 0;
+					client->SetSpawnPlacementMode(Client::ServerSpawnPlacementMode::DEFAULT);
 					if(sep && sep->arg[0][0]){
 						if(strcmp(sep->arg[0], "wall") == 0){
 							placement_mode = 2;
 							unknown2_3 = 150;
 						}
-						else if(strcmp(sep->arg[0], "ceiling") == 0)
+						else if (strcmp(sep->arg[0], "ceiling") == 0)
 							placement_mode = 1;
+						else if (strcmp(sep->arg[0], "openheading") == 0 && cmdTarget->IsWidget())
+						{
+							client->SimpleMessage(CHANNEL_COLOR_YELLOW, "[PlacementMode] WIDGET OPEN HEADING MODE");
+							client->SetSpawnPlacementMode(Client::ServerSpawnPlacementMode::OPEN_HEADING);
+						}
+						else if (strcmp(sep->arg[0], "closeheading") == 0 && cmdTarget->IsWidget())
+						{
+							client->SimpleMessage(CHANNEL_COLOR_YELLOW, "[PlacementMode] WIDGET CLOSE HEADING MODE");
+							client->SetSpawnPlacementMode(Client::ServerSpawnPlacementMode::CLOSE_HEADING);
+						}
 					}
 					packet->setDataByName("placement_mode", placement_mode);
 					packet->setDataByName("spawn_id", client->GetPlayer()->GetIDWithPlayerSpawn(cmdTarget));

+ 13 - 2
EQ2/source/WorldServer/WorldDatabase.cpp

@@ -2878,17 +2878,28 @@ void WorldDatabase::LoadSpawns(ZoneServer* zone)
 
 }
 
-bool WorldDatabase::UpdateSpawnLocationSpawns(Spawn* spawn){
+bool WorldDatabase::UpdateSpawnLocationSpawns(Spawn* spawn) {
 	Query query;
 	query.RunQuery2(Q_UPDATE, "update spawn_location_placement set x=%f, y=%f, z=%f, heading=%f, x_offset=%f, y_offset=%f, z_offset=%f, respawn=%u, expire_timer=%u, expire_offset=%u, grid_id=%u, pitch=%f, roll=%f where id = %u",
 		spawn->GetX(), spawn->GetY(), spawn->GetZ(), spawn->GetHeading(), spawn->GetXOffset(), spawn->GetYOffset(), spawn->GetZOffset(), spawn->GetRespawnTime(), spawn->GetExpireTime(), spawn->GetExpireOffsetTime(), spawn->appearance.pos.grid_id, spawn->GetPitch(), spawn->GetRoll(), spawn->GetSpawnLocationPlacementID());
-	if(query.GetErrorNumber() && query.GetError() && query.GetErrorNumber() < 0xFFFFFFFF){
+	if (query.GetErrorNumber() && query.GetError() && query.GetErrorNumber() < 0xFFFFFFFF) {
 		LogWrite(WORLD__ERROR, 0, "World", "Error in UpdateSpawnLocationSpawns query '%s': %s", query.GetQuery(), query.GetError());
 		return false;
 	}
 	return true;
 }
 
+bool WorldDatabase::UpdateSpawnWidget(int32 widget_id, char* queryString) {
+	Query query;
+	query.RunQuery2(Q_UPDATE, "update spawn_widgets set %s where widget_id = %u",
+		queryString, widget_id);
+	if (query.GetErrorNumber() && query.GetError() && query.GetErrorNumber() < 0xFFFFFFFF) {
+		LogWrite(WORLD__ERROR, 0, "World", "Error in UpdateSpawnWidget query '%s': %s", query.GetQuery(), query.GetError());
+		return false;
+	}
+	return true;
+}
+
 vector<string>* WorldDatabase::GetSpawnNameList(const char* in_name){
 	Query query;
 	string names = "";

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

@@ -203,6 +203,7 @@ public:
 	void	UpdateStartingSkillbar(int32 char_id, int8 class_id, int8 race_id);
 	void	UpdateStartingTitles(int32 char_id, int8 class_id, int8 race_id, int8 gender_id);
 	bool	UpdateSpawnLocationSpawns(Spawn* spawn);
+	bool	UpdateSpawnWidget(int32 widget_id, char* query);
 	bool	CheckVersionTable();
 	void	LoadFactionAlliances();
 	void	LoadFactionList();

+ 62 - 18
EQ2/source/WorldServer/client.cpp

@@ -178,6 +178,7 @@ Client::Client(EQStream* ieqs) : pos_update(125), quest_pos_timer(2000), lua_deb
 	memset(&incoming_paperdoll, 0, sizeof(incoming_paperdoll));
 	on_auto_mount = false;
 	should_load_spells = true;
+	spawnPlacementMode = ServerSpawnPlacementMode::DEFAULT;
 }
 
 Client::~Client() {
@@ -1168,32 +1169,75 @@ bool Client::HandlePacket(EQApplicationPacket *app) {
 			}
 			break;
 								}
-		case OP_PositionMoveableObject:{
+		case OP_PositionMoveableObject: {
 			LogWrite(OPCODE__DEBUG, 1, "Opcode", "Opcode 0x%X (%i): OP_PositionMoveableObject", opcode, opcode);
-			PacketStruct* place_object=configReader.getStruct("WS_PlaceMoveableObject",GetVersion());
-			if(place_object && place_object->LoadPacketData(app->pBuffer, app->size)){
+			PacketStruct* place_object = configReader.getStruct("WS_PlaceMoveableObject", GetVersion());
+			if (place_object && place_object->LoadPacketData(app->pBuffer, app->size)) {
 				Spawn* spawn = GetPlayer()->GetSpawnWithPlayerID(place_object->getType_int32_ByName("spawn_id"));
-				if(!spawn){
+				if (!spawn) {
 					SimpleMessage(CHANNEL_COLOR_YELLOW, "Unable to find spawn.");
 					break;
 				}
-				spawn->SetX(place_object->getType_float_ByName("x"));
-				spawn->SetY(place_object->getType_float_ByName("y"));
-				spawn->SetZ(place_object->getType_float_ByName("z"));
-				spawn->SetHeading(place_object->getType_float_ByName("heading") + 180);
-				spawn->SetSpawnOrigX(spawn->GetX());
-				spawn->SetSpawnOrigY(spawn->GetY());
-				spawn->SetSpawnOrigZ(spawn->GetZ());
-				spawn->SetSpawnOrigHeading(spawn->GetHeading());
-
-				if(spawn->GetSpawnLocationID() > 0 && database.UpdateSpawnLocationSpawns(spawn))
-					SimpleMessage(CHANNEL_COLOR_YELLOW, "Successfully saved spawn information.");
-				else if(spawn->GetSpawnLocationID() > 0)
-					SimpleMessage(CHANNEL_COLOR_YELLOW, "Error saving spawn information, see console window for details.");
+
+				float newHeading = place_object->getType_float_ByName("heading") + 180;
+
+				char query[256];
+
+				switch (GetSpawnPlacementMode())
+				{
+				case ServerSpawnPlacementMode::OPEN_HEADING:
+				{
+					if (spawn && spawn->IsWidget())
+					{
+						Widget* widget = (Widget*)spawn;
+						widget->SetOpenHeading(newHeading);
+
+						spawn->position_changed = true;
+						_snprintf(query, 256, "open_heading=%f,include_heading=1", newHeading);
+						if (database.UpdateSpawnWidget(widget->GetWidgetID(), query))
+							SimpleMessage(CHANNEL_COLOR_YELLOW, "Successfully saved widget open heading information.");
+					}
+					else
+						SimpleMessage(CHANNEL_COLOR_YELLOW, "Spawn is not widget, unable to set close heading information.");
+					break;
+				}
+				case ServerSpawnPlacementMode::CLOSE_HEADING:
+				{
+					if (spawn && spawn->IsWidget())
+					{
+						Widget* widget = (Widget*)spawn;
+						widget->SetClosedHeading(newHeading);
+
+						spawn->position_changed = true;
+						_snprintf(query, 256, "close_heading=%f,include_heading=1", newHeading);
+						if (database.UpdateSpawnWidget(widget->GetWidgetID(), query))
+							SimpleMessage(CHANNEL_COLOR_YELLOW, "Successfully saved widget close heading information.");
+					}
+					else
+						SimpleMessage(CHANNEL_COLOR_YELLOW, "Spawn is not widget, unable to set close heading information.");
+					break;
+				}
+				default:
+				{
+					spawn->SetX(place_object->getType_float_ByName("x"));
+					spawn->SetY(place_object->getType_float_ByName("y"));
+					spawn->SetZ(place_object->getType_float_ByName("z"));
+					spawn->SetHeading(newHeading);
+					spawn->SetSpawnOrigX(spawn->GetX());
+					spawn->SetSpawnOrigY(spawn->GetY());
+					spawn->SetSpawnOrigZ(spawn->GetZ());
+					spawn->SetSpawnOrigHeading(spawn->GetHeading());
+					if (spawn->GetSpawnLocationID() > 0 && database.UpdateSpawnLocationSpawns(spawn))
+						SimpleMessage(CHANNEL_COLOR_YELLOW, "Successfully saved spawn information.");
+					else if (spawn->GetSpawnLocationID() > 0)
+						SimpleMessage(CHANNEL_COLOR_YELLOW, "Error saving spawn information, see console window for details.");
+				}
+				}
+
 				safe_delete(place_object);
 			}
 			break;
-									   }
+		}
 		case OP_CampAbortedMsg:{
 			LogWrite(OPCODE__DEBUG, 1, "Opcode", "Opcode 0x%X (%i): OP_CampAbortedMsg", opcode, opcode);
 			if(camp_timer)

+ 4 - 0
EQ2/source/WorldServer/client.h

@@ -391,6 +391,9 @@ public:
 	void SetTransmuteID(int32 trans_id);
 	int32 GetTransmuteID();
 
+	enum ServerSpawnPlacementMode { DEFAULT, OPEN_HEADING, CLOSE_HEADING };
+	void SetSpawnPlacementMode(ServerSpawnPlacementMode mode) { spawnPlacementMode = mode; }
+	ServerSpawnPlacementMode GetSpawnPlacementMode() { return spawnPlacementMode; }
 private:
 	void    SavePlayerImages();
 	void	SkillChanged(Skill* skill, int16 previous_value, int16 new_value);
@@ -480,6 +483,7 @@ private:
 
 	int32 pending_flight_path;
 
+	ServerSpawnPlacementMode spawnPlacementMode;
 	bool on_auto_mount;
 	bool EntityCommandPrecheck(Spawn* spawn, const char* command);
 };