Browse Source

Fix #262 added /gm sight [on|off] with target to follow pov of spawn, LUA implemented SetPlayerPOVGhost(Player, Target_Spawn) if target_spawn is nil it will disable the ghost pov

Emagi 1 year ago
parent
commit
7c0c5d537e

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

@@ -4006,6 +4006,14 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 					else
 						client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Region Debug Disabled!");
 				}
+				else if (strcmp(sep->arg[0], "sight") == 0)
+				{
+					if(onOff && cmdTarget) {
+						client->SetPlayerPOVGhost(cmdTarget);
+					}
+					else
+						client->SetPlayerPOVGhost(nullptr);
+				}
 				else if (strcmp(sep->arg[0], "luadebug") == 0)
 				{
 					client->SetLuaDebugClient(onOff);

+ 34 - 0
EQ2/source/WorldServer/LuaFunctions.cpp

@@ -13112,4 +13112,38 @@ int EQ2Emu_lua_RemoveRegion(lua_State* state) {
 
 	lua_interface->SetBooleanValue(state, true);
 	return 1;
+}
+
+
+int EQ2Emu_lua_SetPlayerPOVGhost(lua_State* state) {
+	Client* client = nullptr;
+	Spawn* player = lua_interface->GetSpawn(state);
+	if (!player) {
+		lua_interface->LogError("LUA SetPlayerPOVGhost command error: spawn is not valid");
+		lua_interface->SetBooleanValue(state, false);
+		return 1;
+	}
+
+	if (!player->IsPlayer()) {
+		lua_interface->LogError("LUA SetPlayerPOVGhost command error: spawn is not a player");
+		lua_interface->SetBooleanValue(state, false);
+		return 1;
+	}
+
+	client = player->GetClient();
+
+	if (!client) {
+		lua_interface->LogError("LUA SetPlayerPOVGhost command error: could not find client");
+		lua_interface->SetBooleanValue(state, false);
+		return 1;
+	}
+	
+	Spawn* spawn = lua_interface->GetSpawn(state, 2);
+	
+	bool success_sight = client->SetPlayerPOVGhost(spawn);
+	
+	lua_interface->ResetFunctionStack(state);
+
+	lua_interface->SetBooleanValue(state, success_sight);
+	return 1;
 }

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

@@ -626,4 +626,6 @@ int EQ2Emu_lua_DamageEquippedItems(lua_State* state);
 
 int EQ2Emu_lua_CreateWidgetRegion(lua_State* state);
 int EQ2Emu_lua_RemoveRegion(lua_State* state);
+
+int EQ2Emu_lua_SetPlayerPOVGhost(lua_State* state);
 #endif

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

@@ -1488,6 +1488,8 @@ void LuaInterface::RegisterFunctions(lua_State* state) {
 	
 	lua_register(state, "CreateWidgetRegion", EQ2Emu_lua_CreateWidgetRegion);
 	lua_register(state, "RemoveRegion", EQ2Emu_lua_RemoveRegion);
+	
+	lua_register(state, "SetPlayerPOVGhost", EQ2Emu_lua_SetPlayerPOVGhost);
 }
 
 void LuaInterface::LogError(const char* error, ...)  {

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

@@ -216,6 +216,7 @@ Client::Client(EQStream* ieqs) : underworld_cooldown_timer(5000), pos_update(125
 	SetZoningDestination(nullptr);
 	underworld_cooldown_timer.Disable();
 	player_pos_change_count = 0;
+	pov_ghost_spawn_id = 0;
 }
 
 Client::~Client() {
@@ -922,9 +923,23 @@ void Client::SendZoneSpawns() {
 }
 
 void Client::SendCharPOVGhost() {
+	bool use_ghost_pov = false;
 	PacketStruct* set_pov = configReader.getStruct("WS_SetPOVGhostCmd", GetVersion());
+	int32 ghost_id = 0;
 	if (set_pov) {
-		set_pov->setDataByName("spawn_id", player->GetIDWithPlayerSpawn(player));
+		if(pov_ghost_spawn_id) {
+			Spawn* spawn = GetCurrentZone()->GetSpawnByID(pov_ghost_spawn_id);
+			ghost_id = player->GetIDWithPlayerSpawn(spawn);
+			if(spawn) {
+				use_ghost_pov = true;
+			}
+		}
+		if(use_ghost_pov) {
+		set_pov->setDataByName("spawn_id", ghost_id);
+		}
+		else {
+			set_pov->setDataByName("spawn_id", player->GetIDWithPlayerSpawn(player));
+		}
 		EQ2Packet* app_pov = set_pov->serialize();
 		QueuePacket(app_pov);
 		safe_delete(set_pov);
@@ -11353,3 +11368,20 @@ void Client::AddRecipeToPlayer(Recipe* recipe, PacketStruct* packet, int16* i) {
 		}
 	}
 }
+
+bool Client::SetPlayerPOVGhost(Spawn* spawn) {
+	if(!spawn) {
+		pov_ghost_spawn_id = 0;
+		SendCharPOVGhost();
+		return true;
+	}
+	
+	int32 ghost_id = player->GetIDWithPlayerSpawn(spawn);
+	if(ghost_id) {
+		pov_ghost_spawn_id = spawn->GetID();
+		SendCharPOVGhost();
+		return true;
+	}
+	
+	return false;
+}

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

@@ -567,6 +567,9 @@ public:
 	
 	void	AddRecipeToPlayer(Recipe* recipe, PacketStruct* packet, int16* i);
 	
+	bool	SetPlayerPOVGhost(Spawn* spawn);
+	
+	int32	GetPlayerPOVGhostSpawnID() { return pov_ghost_spawn_id; }
 private:
 	void    SavePlayerImages();
 	void	SkillChanged(Skill* skill, int16 previous_value, int16 new_value);
@@ -702,6 +705,9 @@ private:
 	Mutex MSpellDetails;
 	bool disable_save;
 	vector< string > devices;
+	
+	std::atomic<int32> pov_ghost_spawn_id;
+	
 };
 
 class ClientList {

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

@@ -1199,6 +1199,7 @@ void ZoneServer::CheckRemoveSpawnFromClient(Spawn* spawn) {
 				client->GetPlayer()->WasSentSpawn(spawn->GetID()) && 
 				!client->GetPlayer()->IsRemovingSpawn(spawn->GetID()) && 
 				client->GetPlayer()->WasSpawnRemoved(spawn) == false && 
+				(client->GetPlayerPOVGhostSpawnID() == 0 || client->GetPlayerPOVGhostSpawnID() != spawn->GetID()) &&
 				(spawn_range_map.Get(client)->Get(spawn->GetID()) > REMOVE_SPAWN_DISTANCE &&
 					!spawn->IsSign() && !spawn->IsObject() && !spawn->IsWidget() && !spawn->IsTransportSpawn())){
 				SendRemoveSpawn(client, spawn, packet);
@@ -3952,6 +3953,10 @@ bool ZoneServer::SendRemoveSpawn(Client* client, Spawn* spawn, PacketStruct* pac
 	if(!client || !spawn || (client && client->GetPlayer() == spawn))
 		return false;
 
+	if(client->GetPlayerPOVGhostSpawnID() == spawn->GetID()) {
+			client->SetPlayerPOVGhost(nullptr);
+	}
+	
 	spawn->RemoveSpawnFromPlayer(client->GetPlayer());
 //	LogWrite(ZONE__DEBUG, 7, "Zone", "%s: Processing SendRemoveSpawn for spawn index %u (%s)...cur_id: %i, wasremoved:: %i", client->GetPlayer()->GetName(), index, spawn->GetName(), cur_id, wasRemoved);
 /*	if(packet && index > 0 && !wasRemoved)