From 92a87fa73587d230ec6f5ce04b1d81cbfcd72518 Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Mon, 28 Sep 2026 11:53:48 -0500 Subject: [PATCH] fix: save_property_location saves the position on the property too The zone was saved on a property but the position wasn't (the physics component kept its own "not a property" check), so logging back in put the character at their old main world coordinates on the property map, outside it. Both now use Character::SavesLocationInThisZone. Co-Authored-By: Claude Opus 5.5 --- dGame/Character.cpp | 12 ++++++++---- dGame/Character.h | 5 +++++ dGame/dComponents/ControllablePhysicsComponent.cpp | 4 +--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/dGame/Character.cpp b/dGame/Character.cpp index bd498b362..ba1ce034a 100644 --- a/dGame/Character.cpp +++ b/dGame/Character.cpp @@ -283,11 +283,8 @@ void Character::SaveXMLToDatabase() { character->SetAttribute("cc", m_Coins); auto zoneInfo = Game::zoneManager->GetZone()->GetZoneID(); - // Where the character logs back in. Not a property (a clone) unless save_property_location is 1: by default - // logging in from a property goes to the last world before it. - const bool savesHere = zoneInfo.GetCloneID() == 0 || (Game::config && Game::config->GetValue("save_property_location") == "1"); // lzid garbage, binary concat of zoneID, zoneInstance and zoneClone - if (zoneInfo.GetMapID() != 0 && savesHere && !Game::zoneManager->GetDisableSaveLocation()) { + if (SavesLocationInThisZone()) { uint64_t lzidConcat = zoneInfo.GetCloneID(); lzidConcat = (lzidConcat << 16) | uint16_t(zoneInfo.GetInstanceID()); lzidConcat = (lzidConcat << 16) | uint16_t(zoneInfo.GetMapID()); @@ -657,3 +654,10 @@ void Character::SetBillboardVisible(bool visible) { ownerBillboardState.target = m_OurEntity->GetObjectID(); ownerBillboardState.Send(m_OurEntity->GetSystemAddress()); } + +bool Character::SavesLocationInThisZone() { + const auto zoneInfo = Game::zoneManager->GetZone()->GetZoneID(); + if (zoneInfo.GetMapID() == 0 || Game::zoneManager->GetDisableSaveLocation()) return false; + // By default logging in from a property goes to the last world before it + return zoneInfo.GetCloneID() == 0 || (Game::config && Game::config->GetValue("save_property_location") == "1"); +} diff --git a/dGame/Character.h b/dGame/Character.h index e7ddfb37e..b5fd33284 100644 --- a/dGame/Character.h +++ b/dGame/Character.h @@ -102,6 +102,11 @@ public: */ uint32_t GetPropertyCloneID() const { return m_PropertyCloneID; } + // Whether a character's location (zone and position) is saved in the zone this world runs, for logging back in + // there: not the character select world, nor where the zone says not to, nor a property (a clone) unless + // save_property_location is 1 + static bool SavesLocationInThisZone(); + /** * Gets the last login of this character in MS * @return the last login of this character diff --git a/dGame/dComponents/ControllablePhysicsComponent.cpp b/dGame/dComponents/ControllablePhysicsComponent.cpp index a4e5fdc12..563380e73 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.cpp +++ b/dGame/dComponents/ControllablePhysicsComponent.cpp @@ -191,9 +191,7 @@ void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument& doc) { return; } - auto zoneInfo = Game::zoneManager->GetZone()->GetZoneID(); - - if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0 && !Game::zoneManager->GetDisableSaveLocation()) { + if (Character::SavesLocationInThisZone()) { character->SetAttribute("lzx", m_Position.x); character->SetAttribute("lzy", m_Position.y); character->SetAttribute("lzz", m_Position.z);