mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-11-14 07:47:13 +00:00
fix: a launch pad checks its GM level and launch precondition
LWORocketLaunchComponentCommon does not launch a player under the row's gmLevel (msgFireEventClientSide 0x00cb78b0) or, with useLaunchPrecondition, one that fails the row's launchPrecondition (msgCheckUseRequirements 0x00c7d0d0). The server launched on any request. Rows: the test launcher asks for GM level 9, the pads to Gnarled Forest and Forbidden Valley for mission 474, Starbase 3001's for mission 956. The alternative landing precondition pointer also starts out null for a pad without a row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,7 @@ RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent,
|
||||
// The RocketLaunchpadControlComponent row
|
||||
void RocketLaunchpadControlComponent::LoadDataFromTemplate() {
|
||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
||||
"SELECT targetZone, defaultZoneID, targetScene, altLandingPrecondition, altLandingSpawnPointName FROM RocketLaunchpadControlComponent WHERE id = ?;");
|
||||
"SELECT targetZone, defaultZoneID, targetScene, altLandingPrecondition, altLandingSpawnPointName, gmLevel, useLaunchPrecondition, launchPrecondition FROM RocketLaunchpadControlComponent WHERE id = ?;");
|
||||
query.bind(1, m_ComponentID);
|
||||
|
||||
auto result = query.execQuery();
|
||||
@@ -41,6 +41,8 @@ void RocketLaunchpadControlComponent::LoadDataFromTemplate() {
|
||||
m_TargetScene = result.getStringField("targetScene");
|
||||
m_AltPrecondition = new PreconditionExpression(result.getStringField("altLandingPrecondition"));
|
||||
m_AltLandingScene = result.getStringField("altLandingSpawnPointName");
|
||||
m_GMLevel = result.getIntField("gmLevel", 0);
|
||||
if (result.getIntField("useLaunchPrecondition", 0) != 0) m_LaunchPrecondition = result.getStringField("launchPrecondition", "");
|
||||
}
|
||||
|
||||
result.finalize();
|
||||
@@ -57,6 +59,11 @@ GameMessages::FireEventClientSide RocketLaunchpadControlComponent::MakeRocketEqu
|
||||
return rocketEquipped;
|
||||
}
|
||||
|
||||
bool RocketLaunchpadControlComponent::MayLaunch(Entity& player) const {
|
||||
if (static_cast<int32_t>(player.GetGMLevel()) < m_GMLevel) return false;
|
||||
return m_LaunchPrecondition.empty() || PreconditionExpression(m_LaunchPrecondition).Check(&player);
|
||||
}
|
||||
|
||||
void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOMAPID mapId, LWOCLONEID cloneId, int32_t worldIndex) {
|
||||
auto zone = mapId == LWOMAPID_INVALID ? m_TargetZone : mapId;
|
||||
|
||||
@@ -64,6 +71,8 @@ void RocketLaunchpadControlComponent::Launch(Entity* originator, LWOMAPID mapId,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MayLaunch(*originator)) return;
|
||||
|
||||
// This also gets triggered by a proximity monitor + item equip, I will set that up when havok is ready
|
||||
auto* characterComponent = originator->GetComponent<CharacterComponent>();
|
||||
auto* character = originator->GetCharacter();
|
||||
|
||||
@@ -29,6 +29,13 @@ public:
|
||||
|
||||
void LoadDataFromTemplate() override;
|
||||
|
||||
/**
|
||||
* Whether the player may launch from this pad: LWORocketLaunchComponentCommon refuses a player under the pad's GM
|
||||
* level (msgFireEventClientSide 0x00cb78b0) or that fails its launch precondition (msgCheckUseRequirements
|
||||
* 0x00c7d0d0), so a client does not ask
|
||||
*/
|
||||
bool MayLaunch(Entity& player) const;
|
||||
|
||||
/**
|
||||
* Launches some entity to another world
|
||||
* @param originator the entity to launch
|
||||
@@ -136,7 +143,17 @@ private:
|
||||
/**
|
||||
* Some precondition that needs to be met to trigger the alternative landing scene
|
||||
*/
|
||||
PreconditionExpression* m_AltPrecondition;
|
||||
PreconditionExpression* m_AltPrecondition{};
|
||||
|
||||
/**
|
||||
* The GM level a player needs to launch from this pad (the row's gmLevel)
|
||||
*/
|
||||
int32_t m_GMLevel{};
|
||||
|
||||
/**
|
||||
* The row's launchPrecondition, when its useLaunchPrecondition is set: what a player has to pass to launch
|
||||
*/
|
||||
std::string m_LaunchPrecondition;
|
||||
|
||||
/**
|
||||
* Notifies the master server to prepare some world for a player to be able to travel to it
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "GameDependencies.h"
|
||||
#include "dGameMessagesTests/GameMessageTestUtils.h"
|
||||
|
||||
#include "CDClientDatabase.h"
|
||||
#include "Entity.h"
|
||||
#include "ObjectMessages.h"
|
||||
#include "RocketLaunchpadControlComponent.h"
|
||||
|
||||
@@ -49,3 +51,25 @@ TEST_F(RocketLaunchTests, RocketEquippedIsBroadcast) {
|
||||
ASSERT_EQ(sent.size(), 1u);
|
||||
EXPECT_TRUE(sent[0].broadcast);
|
||||
}
|
||||
|
||||
// A pad's row can ask for a GM level (the AG test pad: 9); LWORocketLaunchComponentCommon::msgFireEventClientSide
|
||||
// (0x00cb78b0) does not launch a player under it
|
||||
TEST_F(RocketLaunchTests, APadWithAGmLevelLaunchesOnlyThoseAtIt) {
|
||||
CDClientDatabase::Connect(":memory:");
|
||||
CDClientDatabase::ExecuteDML("CREATE TABLE RocketLaunchpadControlComponent (id INTEGER, targetZone INTEGER, defaultZoneID INTEGER, targetScene TEXT, gmLevel INTEGER, useLaunchPrecondition INTEGER, launchPrecondition TEXT, useAltLandingPrecondition INTEGER, altLandingPrecondition TEXT, altLandingSpawnPointName TEXT);");
|
||||
CDClientDatabase::ExecuteDML("INSERT INTO RocketLaunchpadControlComponent VALUES (1, 1100, 0, 'AGLaunch', 9, 0, '', 0, '', '');");
|
||||
CDClientDatabase::ExecuteDML("INSERT INTO RocketLaunchpadControlComponent VALUES (2, 1200, 0, 'NS_NT', 0, 0, '47', 0, '', '');");
|
||||
|
||||
Entity gmPad(PAD, info);
|
||||
auto* const gmOnly = gmPad.AddComponent<RocketLaunchpadControlComponent>(1);
|
||||
gmOnly->LoadDataFromTemplate();
|
||||
Entity openPad(PAD + 1, info);
|
||||
auto* const open = openPad.AddComponent<RocketLaunchpadControlComponent>(2);
|
||||
open->LoadDataFromTemplate();
|
||||
|
||||
Entity player(PLAYER, info);
|
||||
EXPECT_FALSE(gmOnly->MayLaunch(player));
|
||||
EXPECT_TRUE(open->MayLaunch(player)); // its precondition is not in use
|
||||
player.SetGMLevel(eGameMasterLevel::OPERATOR);
|
||||
EXPECT_TRUE(gmOnly->MayLaunch(player));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user