Files
PalUIExtension/Api/Pal/PalDatabaseCharacterParameter.hpp

370 lines
17 KiB
C++
Raw Normal View History

2026-09-07 19:33:58 -04:00
#pragma once
#include <optional>
#include <Unreal/FText.hpp>
#include <Unreal/NameTypes.hpp>
#include <Api/UnrealWrapper.hpp>
#include <Static/LogGate.hpp>
#include "PalIndividual.hpp"
#include "PalTypes.hpp"
namespace PalUIExtension::Api::Pal
{
class PalDatabaseCharacterParameter : public UnrealWrapper
{
public:
static auto ClassPath() -> const TCHAR* { return STR("/Script/Pal.PalDatabaseCharacterParameter"); }
static auto DebugTag() -> const TCHAR* { return STR("PalDatabase"); }
PalDatabaseCharacterParameter() = default;
explicit PalDatabaseCharacterParameter(UObject* Obj) : UnrealWrapper(Obj, ClassOf<PalDatabaseCharacterParameter>(), DebugTag()) {}
static auto StripVariantPrefix(FName CharacterId) -> std::optional<FName>
{
const StringType Id = CharacterId.ToString();
static const StringType Prefixes[] = {
STR("BOSS_"), STR("PREDATOR_"), STR("RAID_"), STR("GYM_"),
};
for (const StringType& Prefix : Prefixes)
{
if (Id.size() <= Prefix.size()) continue;
if (!StartsWithNoCase(Id, Prefix)) continue;
return FName(StringViewType(Id).substr(Prefix.size()), FNAME_Add);
}
return std::nullopt;
}
static auto ResolveBaseRowName(FName CharacterId) -> FName
{
return StripVariantPrefix(CharacterId).value_or(CharacterId);
}
// ---- row lookups by species FName -----------------------------
auto GetZukanIndex(FName RowName) -> std::optional<int32>
{
struct P { FName RowName; int32 ReturnValue; } p{ RowName, 0 };
return CallForReturn(STR("GetZukanIndex"), p, &P::ReturnValue);
}
auto GetZukanIndexResolved(FName CharacterId) -> std::optional<int32>
{
if (auto Direct = GetZukanIndex(CharacterId); Direct.has_value() && *Direct > 0)
{
return Direct;
}
auto Base = StripVariantPrefix(CharacterId);
if (!Base.has_value()) return std::nullopt;
auto Fallback = GetZukanIndex(*Base);
if (!Fallback.has_value() || *Fallback <= 0) return std::nullopt;
if constexpr (Static::kVerboseLogging)
{
Output::send<LogLevel::Verbose>(
STR("[PalDatabase] ZukanIndex: '{}' had none, resolved via base '{}' -> {}\n"),
CharacterId.ToString(), Base->ToString(), *Fallback);
}
return Fallback;
}
auto GetLocalizedBaseCharacterName(FName CharacterId) -> std::optional<FText>
{
return GetLocalizedCharacterName(ResolveBaseRowName(CharacterId));
}
auto GetTribe(FName RowName) -> std::optional<EPalTribeID_>
{
struct P { FName RowName; EPalTribeID_ ReturnValue; } p{ RowName, 0 };
return CallForReturn(STR("GetTribe"), p, &P::ReturnValue);
}
auto GetSize(FName RowName) -> std::optional<EPalSizeType_>
{
struct P { FName RowName; EPalSizeType_ ReturnValue; } p{ RowName, EPalSizeType_::None };
return CallForReturn(STR("GetSize"), p, &P::ReturnValue);
}
auto GetGenusCategory(FName RowName) -> std::optional<EPalGenusCategoryType_>
{
struct P { FName RowName; EPalGenusCategoryType_ ReturnValue; } p{ RowName, EPalGenusCategoryType_::None };
return CallForReturn(STR("GetGenusCategory"), p, &P::ReturnValue);
}
auto GetOrganizationType(FName RowName) -> std::optional<EPalOrganizationType_>
{
struct P { FName RowName; EPalOrganizationType_ ReturnValue; } p{ RowName, EPalOrganizationType_::None };
return CallForReturn(STR("GetOrganizationType"), p, &P::ReturnValue);
}
auto GetWeaponType(FName RowName) -> std::optional<EPalWeaponType_>
{
struct P { FName RowName; EPalWeaponType_ ReturnValue; } p{ RowName, EPalWeaponType_::None };
return CallForReturn(STR("GetWeaponType"), p, &P::ReturnValue);
}
auto GetBattleBGM(FName RowName) -> std::optional<EPalBattleBGMType_>
{
struct P { FName RowName; EPalBattleBGMType_ ReturnValue; } p{ RowName, EPalBattleBGMType_::None };
return CallForReturn(STR("GetBattleBGM"), p, &P::ReturnValue);
}
auto GetPalAwakeningItemElement(FName ItemId) -> std::optional<EPalElementType_>
{
struct P { FName ItemId; EPalElementType_ ReturnValue; } p{ ItemId, EPalElementType_::None };
return CallForReturn(STR("GetPalAwakeningItemElement"), p, &P::ReturnValue);
}
struct ElementTypePair { EPalElementType_ Primary{}; EPalElementType_ Secondary{}; };
// void return, two out-params -- not CallForReturn's shape.
auto GetElementType(FName RowName) -> std::optional<ElementTypePair>
{
struct P { FName RowName; EPalElementType_ Element1; EPalElementType_ Element2; }
p{ RowName, EPalElementType_::None, EPalElementType_::None };
if (!Call(STR("GetElementType"), p)) return std::nullopt;
return ElementTypePair{ p.Element1, p.Element2 };
}
// void return, one out-param.
auto GetBestWorkSuitability(FName RowName) -> std::optional<EPalWorkSuitability_>
{
struct P { FName RowName; EPalWorkSuitability_ BestWorkSuitability; }
p{ RowName, EPalWorkSuitability_::None };
if (!Call(STR("GetBestWorkSuitability"), p)) return std::nullopt;
return p.BestWorkSuitability;
}
auto GetWeaponEquip(FName RowName) -> std::optional<bool>
{
struct P { FName RowName; bool ReturnValue; } p{ RowName, false };
return CallForReturn(STR("GetWeaponEquip"), p, &P::ReturnValue);
}
auto GetUseBossHPGauge(FName RowName) -> std::optional<bool>
{
struct P { FName RowName; bool ReturnValue; } p{ RowName, false };
return CallForReturn(STR("GetUseBossHPGauge"), p, &P::ReturnValue);
}
auto GetNocturnal(FName RowName) -> std::optional<bool>
{
struct P { FName RowName; bool ReturnValue; } p{ RowName, false };
return CallForReturn(STR("GetNocturnal"), p, &P::ReturnValue);
}
auto GetIsTowerBoss(FName RowName) -> std::optional<bool>
{
struct P { FName RowName; bool ReturnValue; } p{ RowName, false };
return CallForReturn(STR("GetIsTowerBoss"), p, &P::ReturnValue);
}
auto GetIsRaidBoss(FName RowName) -> std::optional<bool>
{
struct P { FName RowName; bool ReturnValue; } p{ RowName, false };
return CallForReturn(STR("GetIsRaidBoss"), p, &P::ReturnValue);
}
auto GetIsPredatorBoss(FName RowName) -> std::optional<bool>
{
struct P { FName RowName; bool ReturnValue; } p{ RowName, false };
return CallForReturn(STR("GetIsPredatorBoss"), p, &P::ReturnValue);
}
auto GetIsPal(FName RowName) -> std::optional<bool>
{
struct P { FName RowName; bool ReturnValue; } p{ RowName, false };
return CallForReturn(STR("GetIsPal"), p, &P::ReturnValue);
}
auto GetIsLegend(FName RowName) -> std::optional<bool>
{
struct P { FName RowName; bool ReturnValue; } p{ RowName, false };
return CallForReturn(STR("GetIsLegend"), p, &P::ReturnValue);
}
auto GetIsBoss(FName RowName) -> std::optional<bool>
{
struct P { FName RowName; bool ReturnValue; } p{ RowName, false };
return CallForReturn(STR("GetIsBoss"), p, &P::ReturnValue);
}
auto IsArenaUnusableItem(FName ItemId) -> std::optional<bool>
{
struct P { FName ItemId; bool ReturnValue; } p{ ItemId, false };
return CallForReturn(STR("IsArenaUnusableItem"), p, &P::ReturnValue);
}
auto GetViewingDistance_cm(FName RowName) -> std::optional<int32>
{
struct P { FName RowName; int32 ReturnValue; } p{ RowName, 0 };
return CallForReturn(STR("GetViewingDistance_cm"), p, &P::ReturnValue);
}
auto GetViewingAngle_Degree(FName RowName) -> std::optional<int32>
{
struct P { FName RowName; int32 ReturnValue; } p{ RowName, 0 };
return CallForReturn(STR("GetViewingAngle_Degree"), p, &P::ReturnValue);
}
auto GetRarity(FName RowName) -> std::optional<int32>
{
struct P { FName RowName; int32 ReturnValue; } p{ RowName, 0 };
return CallForReturn(STR("GetRarity"), p, &P::ReturnValue);
}
auto GetFoodAmount(FName RowName) -> std::optional<int32>
{
struct P { FName RowName; int32 ReturnValue; } p{ RowName, 0 };
return CallForReturn(STR("GetFoodAmount"), p, &P::ReturnValue);
}
auto GetPriceRate(FName RowName) -> std::optional<float>
{
struct P { FName RowName; float ReturnValue; } p{ RowName, 0.f };
return CallForReturn(STR("GetPriceRate"), p, &P::ReturnValue);
}
auto GetHearingRate(FName RowName) -> std::optional<float>
{
struct P { FName RowName; float ReturnValue; } p{ RowName, 0.f };
return CallForReturn(STR("GetHearingRate"), p, &P::ReturnValue);
}
auto GetExpRatio(FName RowName) -> std::optional<float>
{
struct P { FName RowName; float ReturnValue; } p{ RowName, 0.f };
return CallForReturn(STR("GetExpRatio"), p, &P::ReturnValue);
}
auto GetCaptureRateCorrect(FName RowName) -> std::optional<float>
{
struct P { FName RowName; float ReturnValue; } p{ RowName, 0.f };
return CallForReturn(STR("GetCaptureRateCorrect"), p, &P::ReturnValue);
}
auto GetBPClassName(FName RowName) -> std::optional<FName>
{
struct P { FName RowName; FName ReturnValue; } p{ RowName, {} };
return CallForReturn(STR("GetBPClassName"), p, &P::ReturnValue);
}
auto GetFirstDefeatRewardItemID(FName CharacterID) -> std::optional<FName>
{
struct P { FName CharacterID; FName ReturnValue; } p{ CharacterID, {} };
return CallForReturn(STR("GetFirstDefeatRewardItemID"), p, &P::ReturnValue);
}
// void return, FName out-param -- not a FString, no ownership question, just an index pair like every other FName here.
auto GetPrefixNameMsgID(FName CharacterID) -> std::optional<FName>
{
struct P { FName CharacterID; FName OutMsgID; } p{ CharacterID, {} };
if (!Call(STR("GetPrefixNameMsgID"), p)) return std::nullopt;
return p.OutMsgID;
}
auto GetLocalizedCharacterName(FName CharacterID) -> std::optional<FText>
{
struct P { FName CharacterID; FText OutText; } p{ CharacterID, {} };
if (!Call(STR("GetLocalizedCharacterName"), p)) return std::nullopt;
return p.OutText;
}
auto GetLocalizedUniqueNPCName(FName UniqueNPCID) -> std::optional<FText>
{
struct P { FName UniqueNPCID; FText OutText; } p{ UniqueNPCID, {} };
if (!Call(STR("GetLocalizedUniqueNPCName"), p)) return std::nullopt;
return p.OutText;
}
// ---- friendship ------------------------------------------------
auto GetMinFriendshipRank() -> std::optional<int32> { return CallForReturn<int32>(STR("GetMinFriendshipRank")); }
auto GetMaxFriendshipRank() -> std::optional<int32> { return CallForReturn<int32>(STR("GetMaxFriendshipRank")); }
auto GetFriendshipRank(int32 FriendshipPoint) -> std::optional<int32>
{
struct P { int32 FriendshipPoint; int32 ReturnValue; } p{ FriendshipPoint, 0 };
return CallForReturn(STR("GetFriendshipRank"), p, &P::ReturnValue);
}
auto CalcFriendshipProgress(int32 FriendshipPoint) -> std::optional<float>
{
struct P { int32 FriendshipPoint; float ReturnValue; } p{ FriendshipPoint, 0.f };
return CallForReturn(STR("CalcFriendshipProgress"), p, &P::ReturnValue);
}
// bool return + int32& out-param.
auto GetFriendshipRequiredPointByRank(int32 FriendshipRank) -> std::optional<int32>
{
struct P { int32 FriendshipRank; int32 OutRequiredPoint; bool ReturnValue; }
p{ FriendshipRank, 0, false };
if (!Call(STR("GetFriendshipRequiredPointByRank"), p) || !p.ReturnValue) return std::nullopt;
return p.OutRequiredPoint;
}
// ---- derived from a live UPalIndividualCharacterParameter* ---------
auto GetHP(UObject* IndividualParameter) -> std::optional<int32>
{
struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 };
return CallForReturn(STR("GetHP"), p, &P::ReturnValue);
}
auto GetMeleeAttack(UObject* IndividualParameter) -> std::optional<int32>
{
struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 };
return CallForReturn(STR("GetMeleeAttack"), p, &P::ReturnValue);
}
auto GetShotAttack(UObject* IndividualParameter) -> std::optional<int32>
{
struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 };
return CallForReturn(STR("GetShotAttack"), p, &P::ReturnValue);
}
auto GetDefense(UObject* IndividualParameter) -> std::optional<int32>
{
struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 };
return CallForReturn(STR("GetDefense"), p, &P::ReturnValue);
}
auto GetCraftSpeed(UObject* IndividualParameter) -> std::optional<int32>
{
struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 };
return CallForReturn(STR("GetCraftSpeed"), p, &P::ReturnValue);
}
auto GetSupport(UObject* IndividualParameter) -> std::optional<int32>
{
struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 };
return CallForReturn(STR("GetSupport"), p, &P::ReturnValue);
}
auto HigherLevelOtomoFromTrainer(UObject* IndividualCharacterParameter) -> std::optional<int32>
{
struct P { UObject* IndividualCharacterParameter; int32 ReturnValue; } p{ IndividualCharacterParameter, 0 };
return CallForReturn(STR("HigherLevelOtomoFromTrainer"), p, &P::ReturnValue);
}
auto UpdateApplyDatabaseToIndividualParameter(UObject* IndividualParameter) -> bool
{
struct P { UObject* IndividualParameter; } p{ IndividualParameter };
return Call(STR("UpdateApplyDatabaseToIndividualParameter"), p);
}
// Raw UObject* return -- UPalPettingPresset isn't modeled anywhere
auto GetPettingPreset() -> UObject*
{
struct P { UObject* ReturnValue; } p{ nullptr };
auto Result = CallForReturn(STR("GetPettingPreset"), p, &P::ReturnValue);
return (Result && *Result) ? *Result : nullptr;
}
// WorldContextObject is a plain UObject* at the native signature
// level -- the meta=(WorldContext=...) annotation only affects
// the Blueprint editor node, not the ProcessEvent frame. Pass
// any live UObject with a valid world (a player controller, an
// actor, etc.).
auto CalcCorrectedLevel(int32 TrainerLevel, int32 TargetCharacterLevel, UObject* WorldContextObject) -> std::optional<int32>
{
struct P { int32 TrainerLevel; int32 TargetCharacterLevel; UObject* WorldContextObject; int32 ReturnValue; }
p{ TrainerLevel, TargetCharacterLevel, WorldContextObject, 0 };
return CallForReturn(STR("CalcCorrectedLevel"), p, &P::ReturnValue);
}
private:
static auto StartsWithNoCase(const StringType& Str, const StringType& Prefix) -> bool
{
if (Str.size() < Prefix.size()) return false;
for (size_t i = 0; i < Prefix.size(); ++i)
{
CharType A = Str[i];
CharType B = Prefix[i];
if (A >= STR('a') && A <= STR('z')) A = static_cast<CharType>(A - STR('a') + STR('A'));
if (B >= STR('a') && B <= STR('z')) B = static_cast<CharType>(B - STR('a') + STR('A'));
if (A != B) return false;
}
return true;
}
};
}