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.
This commit is contained in:
Image 2020-03-09 23:20:12 -04:00
parent 006d4ac447
commit 0d9c901e0e
5 changed files with 91 additions and 20 deletions

View file

@ -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));

View file

@ -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 = "";

View file

@ -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();

View file

@ -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)

View file

@ -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);
};