implement rest of equipment scripts (#1714)

This commit is contained in:
David Markowitz 2025-01-03 14:44:20 -08:00 committed by GitHub
parent c8fcb3788d
commit fb32534ae3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 188 additions and 30 deletions

View File

@ -296,6 +296,12 @@ void Character::SaveXMLToDatabase() {
flags->LinkEndChild(s);
}
if (GetPlayerFlag(ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR)) {
auto* s = m_Doc.NewElement("s");
s->SetAttribute("si", ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR);
flags->LinkEndChild(s);
}
SaveXmlRespawnCheckpoints();
//Call upon the entity to update our xmlDoc:
@ -357,6 +363,10 @@ void Character::SetPlayerFlag(const uint32_t flagId, const bool value) {
}
}
if (flagId == EQUPPED_TRIAL_FACTION_GEAR || flagId == IS_NEWS_SCREEN_VISIBLE) {
if (value) m_SessionFlags.insert(flagId);
else m_SessionFlags.erase(flagId);
} else {
// Calculate the index first
auto flagIndex = uint32_t(std::floor(flagId / 64));
@ -382,12 +392,20 @@ void Character::SetPlayerFlag(const uint32_t flagId, const bool value) {
m_PlayerFlags.insert(std::make_pair(flagIndex, flagValue));
}
}
}
// Notify the client that a flag has changed server-side
GameMessages::SendNotifyClientFlagChange(m_ObjectID, flagId, value, m_ParentUser->GetSystemAddress());
}
bool Character::GetPlayerFlag(const uint32_t flagId) const {
using enum ePlayerFlag;
bool toReturn = false; //by def, return false.
// TODO make actual session flag checker using flags table in database.
if (flagId == EQUPPED_TRIAL_FACTION_GEAR || flagId == IS_NEWS_SCREEN_VISIBLE) {
toReturn = m_SessionFlags.contains(flagId);
} else {
// Calculate the index first
const auto flagIndex = uint32_t(std::floor(flagId / 64));
@ -396,10 +414,11 @@ bool Character::GetPlayerFlag(const uint32_t flagId) const {
auto it = m_PlayerFlags.find(flagIndex);
if (it != m_PlayerFlags.end()) {
// Don't set the data if we don't have to
return (it->second & shiftedValue) != 0;
toReturn = (it->second & shiftedValue) != 0;
}
}
return false; //by def, return false.
return toReturn;
}
void Character::SetRetroactiveFlags() {

View File

@ -620,6 +620,12 @@ private:
*/
uint64_t m_LastLogin{};
/**
* Flags only set for the duration of a session
*
*/
std::set<uint32_t> m_SessionFlags;
/**
* The gameplay flags this character has (not just true values)
*/

View File

@ -860,6 +860,9 @@ void Entity::Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd, co
auto* destroyableComponent = GetComponent<DestroyableComponent>();
if (!destroyableComponent) return;
destroyableComponent->Subscribe(scriptObjId, scriptToAdd);
} else if (notificationName == "PlayerResurrectionFinished") {
LOG("Subscribing to PlayerResurrectionFinished");
m_Subscriptions[scriptObjId][notificationName] = scriptToAdd;
}
}
@ -868,6 +871,9 @@ void Entity::Unsubscribe(LWOOBJID scriptObjId, const std::string& notificationNa
auto* destroyableComponent = GetComponent<DestroyableComponent>();
if (!destroyableComponent) return;
destroyableComponent->Unsubscribe(scriptObjId);
} else if (notificationName == "PlayerResurrectionFinished") {
LOG("Unsubscribing from PlayerResurrectionFinished");
m_Subscriptions[scriptObjId].erase(notificationName);
}
}
@ -1511,6 +1517,15 @@ void Entity::OnChildLoaded(GameMessages::ChildLoaded& childLoaded) {
GetScript()->OnChildLoaded(*this, childLoaded);
}
void Entity::NotifyPlayerResurrectionFinished(GameMessages::PlayerResurrectionFinished& msg) {
for (const auto& [id, scriptList] : m_Subscriptions) {
auto it = scriptList.find("PlayerResurrectionFinished");
if (it == scriptList.end()) continue;
it->second->NotifyPlayerResurrectionFinished(*this, msg);
}
}
void Entity::RequestActivityExit(Entity* sender, LWOOBJID player, bool canceled) {
GetScript()->OnRequestActivityExit(sender, player, canceled);
}

View File

@ -17,6 +17,7 @@ namespace GameMessages {
struct ActivityNotify;
struct ShootingGalleryFire;
struct ChildLoaded;
struct PlayerResurrectionFinished;
};
namespace Loot {
@ -219,6 +220,7 @@ public:
void OnActivityNotify(GameMessages::ActivityNotify& notify);
void OnShootingGalleryFire(GameMessages::ShootingGalleryFire& notify);
void OnChildLoaded(GameMessages::ChildLoaded& childLoaded);
void NotifyPlayerResurrectionFinished(GameMessages::PlayerResurrectionFinished& msg);
void OnMessageBoxResponse(Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData);
void OnChoiceBoxResponse(Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier);
@ -372,6 +374,9 @@ protected:
* Collision
*/
std::vector<LWOOBJID> m_TargetsInPhantom;
// objectID of receiver and map of notification name to script
std::map<LWOOBJID, std::map<std::string, CppScripts::Script*>> m_Subscriptions;
};
/**

View File

@ -968,6 +968,8 @@ void GameMessages::SendResurrect(Entity* entity) {
// and just make sure the client has time to be ready.
constexpr float respawnTime = 3.66700005531311f + 0.5f;
entity->AddCallbackTimer(respawnTime, [=]() {
GameMessages::PlayerResurrectionFinished msg;
entity->NotifyPlayerResurrectionFinished(msg);
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent != nullptr && entity->GetLOT() == 1) {

View File

@ -765,6 +765,10 @@ namespace GameMessages {
LOT templateID{};
LWOOBJID childID{};
};
struct PlayerResurrectionFinished : public GameMsg {
PlayerResurrectionFinished() : GameMsg(MessageType::Game::PLAYER_RESURRECTION_FINISHED) {}
};
};
#endif // GAMEMESSAGES_H

View File

@ -334,6 +334,8 @@
#include "AgSpiderBossMessage.h"
#include "GfRaceInstancer.h"
#include "NsRaceServer.h"
#include "TrialFactionArmorServer.h"
#include "ImaginationBackPack.h"
#include <map>
#include <string>
@ -700,6 +702,8 @@ namespace {
{"scripts\\ai\\RACING\\TRACK_GF\\GF_RACE_SERVER.lua", []() {return new GfRaceServer();}},
{"scripts\\ai\\RACING\\TRACK_FV\\FV_RACE_SERVER.lua", []() {return new FvRaceServer();}},
{"scripts\\ai\\RACING\\OBJECTS\\VEHICLE_DEATH_TRIGGER_WATER_SERVER.lua", []() {return new VehicleDeathTriggerWaterServer();}},
{"scripts\\equipmenttriggers\\L_TRIAL_FACTION_ARMOR_SERVER.lua", []() {return new TrialFactionArmorServer();}},
{"scripts\\equipmenttriggers\\ImaginationBackPack.lua", []() {return new ImaginationBackPack();}},
};

View File

@ -186,6 +186,8 @@ namespace CppScripts {
*/
virtual void NotifyHitOrHealResult(Entity* self, Entity* attacker, int32_t damage) {};
virtual void NotifyPlayerResurrectionFinished(Entity& self, GameMessages::PlayerResurrectionFinished& msg) {};
/**
* Invoked when a player has responsed to a mission.
*

View File

@ -1,5 +1,7 @@
set(DSCRIPTS_SOURCES_EQUIPMENTTRIGGERSSCRIPTS
"CoilBackpackBase.cpp")
"CoilBackpackBase.cpp"
"ImaginationBackPack.cpp"
"TrialFactionArmorServer.cpp")
add_library(dScriptsEquipmentTriggers OBJECT ${DSCRIPTS_SOURCES_EQUIPMENTTRIGGERSSCRIPTS})
target_include_directories(dScriptsEquipmentTriggers PUBLIC ".")

View File

@ -0,0 +1,22 @@
#include "ImaginationBackPack.h"
#include "SkillComponent.h"
void ImaginationBackPack::OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) {
LOG("Subscribing to PlayerResurrectionFinished");
itemOwner->Subscribe(itemObjId, this, "PlayerResurrectionFinished");
}
void ImaginationBackPack::NotifyPlayerResurrectionFinished(Entity& self, GameMessages::PlayerResurrectionFinished& msg) {
LOG("PlayerResurrectionFinished");
auto* skillComponent = self.GetComponent<SkillComponent>();
if (!skillComponent) return;
LOG("Casting skill 1334");
skillComponent->CastSkill(1334);
}
void ImaginationBackPack::OnFactionTriggerItemUnequipped(Entity* itemOwner, LWOOBJID itemObjId) {
LOG("Unsubscribing from PlayerResurrectionFinished");
itemOwner->Unsubscribe(itemObjId, "PlayerResurrectionFinished");
}

View File

@ -0,0 +1,13 @@
#ifndef IMAGINATIONBACKPACK_H
#define IMAGINATIONBACKPACK_H
#include "CppScripts.h"
class ImaginationBackPack : public CppScripts::Script {
public:
void OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) override;
void NotifyPlayerResurrectionFinished(Entity& self, GameMessages::PlayerResurrectionFinished& msg) override;
void OnFactionTriggerItemUnequipped(Entity* itemOwner, LWOOBJID itemObjId) override;
};
#endif //!IMAGINATIONBACKPACK_H

View File

@ -0,0 +1,13 @@
#ifndef __OBYXSHARDPACK__H__
#define __OBYXSHARDPACK__H__
#include "CoilBackpackBase.h"
class ObyxShardPack : public CoilBackpackBase {
public:
ObyxShardPack() : CoilBackpackBase(skillId) {};
private:
static const uint32_t skillId = 1751;
};
#endif //!__OBYXSHARDPACK__H__

View File

@ -0,0 +1,13 @@
#ifndef __RUBYSHARDPACK__H__
#define __RUBYSHARDPACK__H__
#include "CoilBackpackBase.h"
class RubyShardPack : public CoilBackpackBase {
public:
RubyShardPack() : CoilBackpackBase(skillId) {};
private:
static const uint32_t skillId = 1750;
};
#endif //!__RUBYSHARDPACK__H__

View File

@ -0,0 +1,27 @@
#include "TrialFactionArmorServer.h"
#include "Character.h"
#include "ePlayerFlag.h"
#include "DestroyableComponent.h"
void TrialFactionArmorServer::OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) {
auto* character = itemOwner->GetCharacter();
if (!character) return;
auto flag = character->GetPlayerFlag(ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR);
if (!flag) {
character->SetPlayerFlag(ePlayerFlag::EQUPPED_TRIAL_FACTION_GEAR, true);
// technically a TimerWithCancel but our current implementation doesnt support this.
itemOwner->AddCallbackTimer(1.0f, [itemOwner]() {
auto* destroyableComponent = itemOwner->GetComponent<DestroyableComponent>();
if (!destroyableComponent) return;
destroyableComponent->SetHealth(destroyableComponent->GetMaxHealth());
destroyableComponent->SetArmor(destroyableComponent->GetMaxArmor());
destroyableComponent->SetImagination(destroyableComponent->GetMaxImagination());
Game::entityManager->SerializeEntity(itemOwner);
});
}
}

View File

@ -0,0 +1,11 @@
#ifndef TRIALFACTIONARMORSERVER_
#define TRIALFACTIONARMORSERVER_
#include "CppScripts.h"
class TrialFactionArmorServer : public CppScripts::Script {
public:
void OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) override;
};
#endif //!TRIALFACTIONARMORSERVER_