#pragma once #include #include #include #include #include #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(), DebugTag()) {} static auto StripVariantPrefix(FName CharacterId) -> std::optional { 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 { struct P { FName RowName; int32 ReturnValue; } p{ RowName, 0 }; return CallForReturn(STR("GetZukanIndex"), p, &P::ReturnValue); } auto GetZukanIndexResolved(FName CharacterId) -> std::optional { 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( STR("[PalDatabase] ZukanIndex: '{}' had none, resolved via base '{}' -> {}\n"), CharacterId.ToString(), Base->ToString(), *Fallback); } return Fallback; } auto GetLocalizedBaseCharacterName(FName CharacterId) -> std::optional { return GetLocalizedCharacterName(ResolveBaseRowName(CharacterId)); } auto GetTribe(FName RowName) -> std::optional { struct P { FName RowName; EPalTribeID_ ReturnValue; } p{ RowName, 0 }; return CallForReturn(STR("GetTribe"), p, &P::ReturnValue); } auto GetSize(FName RowName) -> std::optional { struct P { FName RowName; EPalSizeType_ ReturnValue; } p{ RowName, EPalSizeType_::None }; return CallForReturn(STR("GetSize"), p, &P::ReturnValue); } auto GetGenusCategory(FName RowName) -> std::optional { struct P { FName RowName; EPalGenusCategoryType_ ReturnValue; } p{ RowName, EPalGenusCategoryType_::None }; return CallForReturn(STR("GetGenusCategory"), p, &P::ReturnValue); } auto GetOrganizationType(FName RowName) -> std::optional { struct P { FName RowName; EPalOrganizationType_ ReturnValue; } p{ RowName, EPalOrganizationType_::None }; return CallForReturn(STR("GetOrganizationType"), p, &P::ReturnValue); } auto GetWeaponType(FName RowName) -> std::optional { struct P { FName RowName; EPalWeaponType_ ReturnValue; } p{ RowName, EPalWeaponType_::None }; return CallForReturn(STR("GetWeaponType"), p, &P::ReturnValue); } auto GetBattleBGM(FName RowName) -> std::optional { struct P { FName RowName; EPalBattleBGMType_ ReturnValue; } p{ RowName, EPalBattleBGMType_::None }; return CallForReturn(STR("GetBattleBGM"), p, &P::ReturnValue); } auto GetPalAwakeningItemElement(FName ItemId) -> std::optional { 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 { 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 { 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 { struct P { FName RowName; bool ReturnValue; } p{ RowName, false }; return CallForReturn(STR("GetWeaponEquip"), p, &P::ReturnValue); } auto GetUseBossHPGauge(FName RowName) -> std::optional { struct P { FName RowName; bool ReturnValue; } p{ RowName, false }; return CallForReturn(STR("GetUseBossHPGauge"), p, &P::ReturnValue); } auto GetNocturnal(FName RowName) -> std::optional { struct P { FName RowName; bool ReturnValue; } p{ RowName, false }; return CallForReturn(STR("GetNocturnal"), p, &P::ReturnValue); } auto GetIsTowerBoss(FName RowName) -> std::optional { struct P { FName RowName; bool ReturnValue; } p{ RowName, false }; return CallForReturn(STR("GetIsTowerBoss"), p, &P::ReturnValue); } auto GetIsRaidBoss(FName RowName) -> std::optional { struct P { FName RowName; bool ReturnValue; } p{ RowName, false }; return CallForReturn(STR("GetIsRaidBoss"), p, &P::ReturnValue); } auto GetIsPredatorBoss(FName RowName) -> std::optional { struct P { FName RowName; bool ReturnValue; } p{ RowName, false }; return CallForReturn(STR("GetIsPredatorBoss"), p, &P::ReturnValue); } auto GetIsPal(FName RowName) -> std::optional { struct P { FName RowName; bool ReturnValue; } p{ RowName, false }; return CallForReturn(STR("GetIsPal"), p, &P::ReturnValue); } auto GetIsLegend(FName RowName) -> std::optional { struct P { FName RowName; bool ReturnValue; } p{ RowName, false }; return CallForReturn(STR("GetIsLegend"), p, &P::ReturnValue); } auto GetIsBoss(FName RowName) -> std::optional { struct P { FName RowName; bool ReturnValue; } p{ RowName, false }; return CallForReturn(STR("GetIsBoss"), p, &P::ReturnValue); } auto IsArenaUnusableItem(FName ItemId) -> std::optional { struct P { FName ItemId; bool ReturnValue; } p{ ItemId, false }; return CallForReturn(STR("IsArenaUnusableItem"), p, &P::ReturnValue); } auto GetViewingDistance_cm(FName RowName) -> std::optional { struct P { FName RowName; int32 ReturnValue; } p{ RowName, 0 }; return CallForReturn(STR("GetViewingDistance_cm"), p, &P::ReturnValue); } auto GetViewingAngle_Degree(FName RowName) -> std::optional { struct P { FName RowName; int32 ReturnValue; } p{ RowName, 0 }; return CallForReturn(STR("GetViewingAngle_Degree"), p, &P::ReturnValue); } auto GetRarity(FName RowName) -> std::optional { struct P { FName RowName; int32 ReturnValue; } p{ RowName, 0 }; return CallForReturn(STR("GetRarity"), p, &P::ReturnValue); } auto GetFoodAmount(FName RowName) -> std::optional { struct P { FName RowName; int32 ReturnValue; } p{ RowName, 0 }; return CallForReturn(STR("GetFoodAmount"), p, &P::ReturnValue); } auto GetPriceRate(FName RowName) -> std::optional { struct P { FName RowName; float ReturnValue; } p{ RowName, 0.f }; return CallForReturn(STR("GetPriceRate"), p, &P::ReturnValue); } auto GetHearingRate(FName RowName) -> std::optional { struct P { FName RowName; float ReturnValue; } p{ RowName, 0.f }; return CallForReturn(STR("GetHearingRate"), p, &P::ReturnValue); } auto GetExpRatio(FName RowName) -> std::optional { struct P { FName RowName; float ReturnValue; } p{ RowName, 0.f }; return CallForReturn(STR("GetExpRatio"), p, &P::ReturnValue); } auto GetCaptureRateCorrect(FName RowName) -> std::optional { struct P { FName RowName; float ReturnValue; } p{ RowName, 0.f }; return CallForReturn(STR("GetCaptureRateCorrect"), p, &P::ReturnValue); } auto GetBPClassName(FName RowName) -> std::optional { struct P { FName RowName; FName ReturnValue; } p{ RowName, {} }; return CallForReturn(STR("GetBPClassName"), p, &P::ReturnValue); } auto GetFirstDefeatRewardItemID(FName CharacterID) -> std::optional { 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 { 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 { 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 { struct P { FName UniqueNPCID; FText OutText; } p{ UniqueNPCID, {} }; if (!Call(STR("GetLocalizedUniqueNPCName"), p)) return std::nullopt; return p.OutText; } // ---- friendship ------------------------------------------------ auto GetMinFriendshipRank() -> std::optional { return CallForReturn(STR("GetMinFriendshipRank")); } auto GetMaxFriendshipRank() -> std::optional { return CallForReturn(STR("GetMaxFriendshipRank")); } auto GetFriendshipRank(int32 FriendshipPoint) -> std::optional { struct P { int32 FriendshipPoint; int32 ReturnValue; } p{ FriendshipPoint, 0 }; return CallForReturn(STR("GetFriendshipRank"), p, &P::ReturnValue); } auto CalcFriendshipProgress(int32 FriendshipPoint) -> std::optional { 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 { 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 { struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 }; return CallForReturn(STR("GetHP"), p, &P::ReturnValue); } auto GetMeleeAttack(UObject* IndividualParameter) -> std::optional { struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 }; return CallForReturn(STR("GetMeleeAttack"), p, &P::ReturnValue); } auto GetShotAttack(UObject* IndividualParameter) -> std::optional { struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 }; return CallForReturn(STR("GetShotAttack"), p, &P::ReturnValue); } auto GetDefense(UObject* IndividualParameter) -> std::optional { struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 }; return CallForReturn(STR("GetDefense"), p, &P::ReturnValue); } auto GetCraftSpeed(UObject* IndividualParameter) -> std::optional { struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 }; return CallForReturn(STR("GetCraftSpeed"), p, &P::ReturnValue); } auto GetSupport(UObject* IndividualParameter) -> std::optional { struct P { UObject* IndividualParameter; int32 ReturnValue; } p{ IndividualParameter, 0 }; return CallForReturn(STR("GetSupport"), p, &P::ReturnValue); } auto HigherLevelOtomoFromTrainer(UObject* IndividualCharacterParameter) -> std::optional { 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 { 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(A - STR('a') + STR('A')); if (B >= STR('a') && B <= STR('z')) B = static_cast(B - STR('a') + STR('A')); if (A != B) return false; } return true; } }; }