Browse Source

added /waypoint command

LethalEncounter 1 year ago
parent
commit
339071500e

+ 57 - 0
DB/updates/spell_errors_and_commands_10_21_2020.sql

@@ -0,0 +1,57 @@
+UPDATE `eq2emu`.`commands` SET `handler`='523' WHERE  `id`=164;
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '1','7','SPELL_ERROR_NOT_ENOUGH_KNOWLEDGE');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '2','9','SPELL_ERROR_INTERRUPTED');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '3','10','SPELL_ERROR_TAKE_EFFECT_MOREPOWERFUL');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '4','11','SPELL_ERROR_TAKE_EFFECT_SAMESPELL');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '5','15','SPELL_ERROR_CANNOT_CAST_DEAD');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '6','16','SPELL_ERROR_NOT_ALIVE');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '7','17','SPELL_ERROR_NOT_DEAD');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '8','18','SPELL_ERROR_CANNOT_CAST_SITTING');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '9','19','SPELL_ERROR_CANNOT_CAST_UNCON');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '10','20','SPELL_ERROR_ALREADY_CASTING');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '11','21','SPELL_ERROR_RECOVERING');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '12','22','SPELL_ERROR_NON_COMBAT_ONLY');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '13','23','SPELL_ERROR_CANNOT_CAST_STUNNED');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '14','24','SPELL_ERROR_CANNOT_CAST_STIFFLED');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '16','25','SPELL_ERROR_NOT_WHILE_MOUNTED');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '18','26','SPELL_ERROR_NOT_WHILE_CLIMBING');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '19','27','SPELL_ERROR_NOT_READY');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '20','28','SPELL_ERROR_CANT_SEE_TARGET');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '22','30','SPELL_ERROR_CANNOT_CAST_FEIGNDEATH');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '23','31','SPELL_ERROR_INVENTORY_FULL');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '24','32','SPELL_ERROR_NOT_ENOUGH_COIN');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '25','33','SPELL_ERROR_NOT_ALLOWED_HERE');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '26','34','SPELL_ERROR_NOT_WHILE_CRAFTING');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '27','35','SPELL_ERROR_ONLY_WHEN_CRAFTING');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '28','38','SPELL_ERROR_ITEM_NOT_ATTUNED');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '37','39','SPELL_ERROR_CANNOT_PREPARE');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '38','40','SPELL_ERROR_NO_ELIGIBLE_TARGET');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '39','41','SPELL_ERROR_NO_TARGETS_IN_RANGE');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '40','42','SPELL_ERROR_TOO_CLOSE');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '41','43','SPELL_ERROR_TOO_FAR_AWAY');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '42','44','SPELL_ERROR_TARGET_TOO_WEAK');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '43','45','SPELL_ERROR_TARGET_TOO_POWERFUL');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '44','46','SPELL_ERROR_WONT_WORK_ON_TARGET');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '45','47','SPELL_ERROR_TARGET_INVULNERABLE');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '47','48','SPELL_ERROR_TARGET_ENGAGED');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '48','49','SPELL_ERROR_TARGET_NOT_GROUPED');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '51','51','SPELL_ERROR_TARGET_ALREADY_ENGAGED');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '52','52','SPELL_ERROR_CANNOT_ENGAGE');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '53','53','SPELL_ERROR_NOT_A_FRIEND');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '54','54','SPELL_ERROR_NOT_AN_ENEMY');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '55','55','SPELL_ERROR_TARGET_INVENTORY_FULL');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '56','56','SPELL_ERROR_FINISH_DUELING_FIRST');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '57','57','SPELL_ERROR_ILLEGAL_TARGET_ATTACK');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '62','58','SPELL_ERROR_NOT_ENOUGH_POWER');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '63','59','SPELL_ERROR_NOT_ENOUGH_HEALTH');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '64','60','SPELL_ERROR_NOT_ENOUGH_CONC');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '65','61','SPELL_ERROR_MISSING_COMPONENT');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '66','62','SPELL_ERROR_OUT_OF_CHARGES');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '72','65','SPELL_ERROR_ALREADY_PREPARED');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '73','66','SPELL_ERROR_ALREADY_HAVE_SPELL');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '74','68','SPELL_ERROR_NOT_SMART_ENOUGH');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '77','71','SPELL_ERROR_CANNOT_MOUNT_NOW_SITTING');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '78','72','SPELL_ERROR_CANNOT_MOUNT_NOW_DEAD');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '79','73','SPELL_ERROR_CANNOT_MOUNT_NOW_CLIMBING');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '80','74','SPELL_ERROR_CANNOT_MOUNT_NOW_FORM');
+insert into spell_error_versions (`version`, `error_index`, `value`, `name`) values('546', '81','75','SPELL_ERROR_CANNOT_MOUNT_NOW_WATER_TO_DEEP');

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

@@ -1605,6 +1605,18 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 			}
 			break;
 		}
+		case COMMAND_WAYPOINT: {
+			bool success = false;
+			if (sep && sep->IsNumber(0) && sep->IsNumber(1) && sep->IsNumber(2)) {
+				if (!client->ShowPathToTarget(atof(sep->arg[0]), atof(sep->arg[1]), atof(sep->arg[2]), 0))
+					client->Message(CHANNEL_COLOR_RED, "Invalid coordinates given");
+			}
+			else {
+				client->ClearWaypoint();
+				client->Message(CHANNEL_COLOR_YELLOW, "Usage: /waypoint x y z");
+			}
+			break;
+		}
 		case COMMAND_WHO:{
 			const char* who = 0;
 			if(sep && sep->arg[0]){

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

@@ -862,6 +862,7 @@ private:
 #define COMMAND_RELOAD_STARTABILITIES	522
 
 #define COMMAND_FINDSPAWN				521
+#define COMMAND_WAYPOINT				523
 
 #define GET_AA_XML						751
 #define ADD_AA							752

+ 5 - 0
EQ2/source/WorldServer/Zone/map.h

@@ -77,6 +77,11 @@ public:
 		CheckMapMutex.releasereadlock();
 		return isMapLoading;
 	}
+	float GetMinX() { return m_MinX; }
+	float GetMaxX() { return m_MaxX; }
+	float GetMinZ() { return m_MinZ; }
+	float GetMaxZ() { return m_MaxZ; }
+
 private:
 	void RotateVertex(glm::vec3 &v, float rx, float ry, float rz);
 	void ScaleVertex(glm::vec3 &v, float sx, float sy, float sz);

+ 38 - 13
EQ2/source/WorldServer/client.cpp

@@ -8092,12 +8092,10 @@ void Client::SendWaypoints() {
 		for (itr = waypoints.begin(); itr != waypoints.end(); itr++) {
 			packet->setArrayDataByName("waypoint_name", itr->first.c_str(), i);
 			packet->setArrayDataByName("waypoint_category", itr->second.type, i);
-			if(itr->second.type == 3)
-				packet->setArrayDataByName("spawn_id", 0xFFFFFFFF, i);
-			else
-				packet->setArrayDataByName("spawn_id", itr->second.id, i);			
+			packet->setArrayDataByName("spawn_id", itr->second.id, i);			
 			i++;
-		}		
+		}
+		packet->setDataByName("unknown", 0xFFFFFFFF);
 		QueuePacket(packet->serialize());
 		safe_delete(packet);
 	}
@@ -8128,24 +8126,42 @@ void Client::AddWaypoint(const char* waypoint_name, int8 waypoint_category, int3
 			packet->setArrayDataByName("spawn_id", spawn_id, 0);
 			packet->setArrayDataByName("waypoint_category2", waypoint_category, 0);
 			packet->setArrayDataByName("spawn_id2", spawn_id, 0);
+			packet->setDataByName("unknown", 0xFFFFFFFF); 
 			QueuePacket(packet->serialize());
 			safe_delete(packet);
 		}
 	}
 }
 
-void Client::ShowPathToTarget(Spawn* spawn) {
-	if (spawn && current_zone->pathing) {
+void Client::ClearWaypoint() {
+	PacketStruct* packet = configReader.getStruct("WS_GlowPath", GetVersion());
+	if (packet) {
+		QueuePacket(packet->serialize());
+		safe_delete(packet);		
+	}
+}
+
+bool Client::ShowPathToTarget(float x, float y, float z, float y_offset) {
+	if (current_zone->pathing) {
+		if (current_zone->zonemap) {
+			if (x < current_zone->zonemap->GetMinX() || x > current_zone->zonemap->GetMaxX())
+				return false;
+			if (z < current_zone->zonemap->GetMinZ() || z > current_zone->zonemap->GetMaxZ())
+				return false;
+			float new_z = current_zone->zonemap->FindBestZ(glm::vec3(x, z, y), nullptr);
+			if (new_z != BEST_Z_INVALID) //this is actually y
+				y = new_z;
+		}
 		bool partial = false;
 		bool stuck = false;
 		PathfinderOptions opts;
 		opts.smooth_path = true;
 		opts.step_size = 100.0f;//RuleR(Pathing, NavmeshStepSize);
-		opts.offset = spawn->GetYOffset() + 1.0f;
+		opts.offset = y_offset + 1.0f;
 		opts.flags = PathingNotDisabled ^ PathingZoneLine;
 		PacketStruct* packet = configReader.getStruct("WS_GlowPath", GetVersion());
 		if (packet) {
-			auto path = current_zone->pathing->FindPath(glm::vec3(player->GetX(), player->GetZ(), player->GetY()), glm::vec3(spawn->GetX(), spawn->GetZ(), spawn->GetY()), partial, stuck, opts);
+			auto path = current_zone->pathing->FindPath(glm::vec3(player->GetX(), player->GetZ(), player->GetY()), glm::vec3(x, z, y), partial, stuck, opts);
 			packet->setArrayLengthByName("num_points", path.size());
 			int i = 0;
 			for (auto& node : path)
@@ -8153,16 +8169,25 @@ void Client::ShowPathToTarget(Spawn* spawn) {
 				packet->setArrayDataByName("x", node.pos.x, i);
 				packet->setArrayDataByName("y", node.pos.z, i);
 				packet->setArrayDataByName("z", node.pos.y, i);
-				packet->setDataByName("waypoint_x", spawn->GetX());
-				packet->setDataByName("waypoint_y", spawn->GetY());
-				packet->setDataByName("waypoint_z", spawn->GetZ());
+				packet->setDataByName("waypoint_x", x);
+				packet->setDataByName("waypoint_y", y);
+				packet->setDataByName("waypoint_z", z);
 				i++;
 			}
-			if(i>0)
+			if (i > 0)
 				QueuePacket(packet->serialize());
 			safe_delete(packet);
+			return (i > 0);
 		}
 	}
+	return false;
+}
+
+bool Client::ShowPathToTarget(Spawn* spawn) {
+	if (spawn) {
+		return ShowPathToTarget(spawn->GetX(), spawn->GetY(), spawn->GetZ(), spawn->GetYOffset());	
+	}
+	return false;
 }
 
 void Client::BeginWaypoint(const char* waypoint_name, float x, float y, float z) {

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

@@ -455,7 +455,9 @@ public:
 		}
 	}
 	void SelectWaypoint(int32 id);
-	void ShowPathToTarget(Spawn* spawn);
+	void ClearWaypoint();
+	bool ShowPathToTarget(float x, float y, float z, float y_offset);
+	bool ShowPathToTarget(Spawn* spawn);
 
 private:
 	void    SavePlayerImages();

BIN
server/EQ2World__Debug_x64.exe


+ 1 - 0
server/WorldStructs.xml

@@ -7561,6 +7561,7 @@ to zero and treated like placeholders." />
 		<Data ElementName="waypoint_category" Type="int8" />
 		<Data ElementName="spawn_id" Type="int32" />
 	</Data>
+	<Data ElementName="unknown" Type="int32" />
 </Struct>
 <Struct Name="WS_WaypointUpdate" ClientVersion="547" OpcodeName="OP_WaypointUpdateMsg">
 	<Data ElementName="num_updates" Type="int32" />