mirror of
https://github.com/zeldaret/botw
synced 2026-10-20 16:57:22 -04:00
Actor: PlayerInfo/PlayerBase are game, GameConfig ksys
Every decomp user of PlayerInfo is game code, and PlayerBase sits right above Player. GameConfig.h models the engine base that links at GameConfig's slot in KingSystem/System. (AI assisted using Claude Fable 5.1 and Claude Opus 5.5)
This commit is contained in:
@@ -1,2 +1,11 @@
|
||||
add_subdirectory(AI)
|
||||
add_subdirectory(Action)
|
||||
|
||||
target_sources(uking PRIVATE
|
||||
actPlayerBase.cpp
|
||||
actPlayerBase.h
|
||||
actPlayerInfo.cpp
|
||||
actPlayerInfo.h
|
||||
actPlayerInfoBase.cpp
|
||||
actPlayerInfoStub.cpp
|
||||
)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "Game/Actor/Player/actPlayerBase.h"
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <prim/seadSafeString.h>
|
||||
#include "KingSystem/ActorSystem/actActor.h"
|
||||
|
||||
namespace uking::act {
|
||||
|
||||
// TODO
|
||||
class PlayerBase : public ksys::act::Actor {
|
||||
public:
|
||||
// FIXME: name for x and name+type for y
|
||||
void switchEquipment(const sead::SafeString& slot, int frames, int x = -1,
|
||||
const uintptr_t& y = {});
|
||||
|
||||
// FIXME: name for x
|
||||
void setExtraLife(s32 extra_life, f32 x);
|
||||
};
|
||||
|
||||
} // namespace uking::act
|
||||
@@ -0,0 +1,134 @@
|
||||
#include "Game/Actor/Player/actPlayerInfo.h"
|
||||
#include "Game/Actor/Player/actPlayerBase.h"
|
||||
#include "KingSystem/ActorSystem/actActorConstDataAccess.h"
|
||||
#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h"
|
||||
#include "KingSystem/ActorSystem/actBaseProc.h"
|
||||
#include "KingSystem/ActorSystem/actBaseProcMgr.h"
|
||||
#include "KingSystem/GameData/gdtCommonFlagsUtils.h"
|
||||
#include "KingSystem/ksys.h"
|
||||
|
||||
namespace uking::act {
|
||||
|
||||
SEAD_SINGLETON_DISPOSER_IMPL(PlayerInfo)
|
||||
|
||||
PlayerInfo::PlayerInfo() = default;
|
||||
PlayerInfo::~PlayerInfo() = default;
|
||||
|
||||
bool PlayerInfo::init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerInfo::resetPlayer(PlayerBase* player) {
|
||||
if (mPlayerActor == player) {
|
||||
mPlayerActor = nullptr;
|
||||
ksys::setPlayerLink(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool PlayerInfo::acquireHorse(ksys::act::BaseProc* horse) {
|
||||
return mHorseLink.acquire(horse, false);
|
||||
}
|
||||
|
||||
void PlayerInfo::setHorseLink(const ksys::act::BaseProcLink& horse_link) {
|
||||
mHorseLink = horse_link;
|
||||
}
|
||||
|
||||
PlayerBase* PlayerInfo::getPlayer() const {
|
||||
if (!mPlayerActor) {
|
||||
return nullptr;
|
||||
}
|
||||
ksys::act::BaseProcMgr::instance()->isAccessingProcSafe(mPlayerActor, nullptr);
|
||||
return mPlayerActor;
|
||||
}
|
||||
|
||||
PlayerBase* PlayerInfo::getPlayer_() const {
|
||||
if (!mPlayerActor) {
|
||||
return nullptr;
|
||||
}
|
||||
ksys::act::BaseProcMgr::instance()->isAccessingProcSafe(mPlayerActor, nullptr);
|
||||
return mPlayerActor;
|
||||
}
|
||||
|
||||
s32 PlayerInfo::getMaxLifeFromPlayerActor() const {
|
||||
return mPlayerActor ? mPlayerActor->getMaxLife() : 0;
|
||||
}
|
||||
|
||||
void PlayerInfo::setMaxHeartValue(s32 quarter_hearts) {
|
||||
ksys::gdt::setFlag_MaxHartValue(quarter_hearts);
|
||||
mMaxHeartValue = static_cast<f32>(quarter_hearts);
|
||||
}
|
||||
|
||||
u32 PlayerInfo::getMaxHeartValue() const {
|
||||
// Return type is unsigned, but the conversion is signed
|
||||
return static_cast<s32>(mMaxHeartValue);
|
||||
}
|
||||
|
||||
void PlayerInfo::updateMaxHeartValueFromGameData() {
|
||||
mMaxHeartValue = static_cast<f32>(ksys::gdt::getFlag_MaxHartValue());
|
||||
}
|
||||
|
||||
void PlayerInfo::setLifeForPlayerActor(s32 life) {
|
||||
if (mPlayerActor) {
|
||||
*mPlayerActor->getLife() = life;
|
||||
}
|
||||
}
|
||||
|
||||
s32 PlayerInfo::getLifeFromPlayerActor() const {
|
||||
if (!mPlayerActor) {
|
||||
return 0;
|
||||
}
|
||||
auto* life = mPlayerActor->getLife();
|
||||
return life ? *life : 1;
|
||||
}
|
||||
|
||||
void PlayerInfo::recoverLife() {
|
||||
setLifeForPlayerActor(getMaxLifeFromPlayerActor());
|
||||
}
|
||||
|
||||
void PlayerInfo::setStaminaCurrentMax(f32 max_stamina) {
|
||||
ksys::gdt::setFlag_StaminaCurrentMax(max_stamina);
|
||||
mStaminaCurrentMax = max_stamina;
|
||||
}
|
||||
|
||||
f32 PlayerInfo::getStaminaCurrentMax() const {
|
||||
return mStaminaCurrentMax;
|
||||
}
|
||||
|
||||
void PlayerInfo::updateStaminaCurrentMaxFromGameData() {
|
||||
mStaminaCurrentMax = ksys::gdt::getFlag_StaminaCurrentMax();
|
||||
}
|
||||
|
||||
void PlayerInfo::setStaminaMax(f32 max_stamina) {
|
||||
ksys::gdt::setFlag_StaminaMax(max_stamina);
|
||||
mStaminaMax = max_stamina;
|
||||
}
|
||||
|
||||
f32 PlayerInfo::getStaminaMax() const {
|
||||
return mStaminaMax;
|
||||
}
|
||||
|
||||
void PlayerInfo::updateStaminaMaxFromGameData() {
|
||||
mStaminaMax = ksys::gdt::getFlag_StaminaMax();
|
||||
}
|
||||
|
||||
PlayerBase* PlayerInfo::getPlayerUnchecked() {
|
||||
return mPlayerActor;
|
||||
}
|
||||
|
||||
sead::Vector3f& PlayerInfo::getPlayerPos() {
|
||||
ksys::act::ActorConstDataAccess accessor;
|
||||
|
||||
ksys::act::acquireActor(&mPlayerLink, &accessor);
|
||||
accessor.debugLog(1, "getPlayerPos");
|
||||
return mPlayerPos;
|
||||
}
|
||||
|
||||
sead::Vector3f& PlayerInfo::getPlayerPosForPostCalc() {
|
||||
ksys::act::ActorConstDataAccess accessor;
|
||||
|
||||
ksys::act::acquireActor(&mPlayerLink, &accessor);
|
||||
accessor.debugLog(0, "getPlayerPosForPostCalc");
|
||||
return mPlayerPosForPostCalc;
|
||||
}
|
||||
|
||||
} // namespace uking::act
|
||||
@@ -0,0 +1,123 @@
|
||||
#pragma once
|
||||
|
||||
#include <heap/seadDisposer.h>
|
||||
#include <math/seadVector.h>
|
||||
#include "KingSystem/ActorSystem/actBaseProcLink.h"
|
||||
#include "container/seadRingBuffer.h"
|
||||
|
||||
namespace ksys::act {
|
||||
class Actor;
|
||||
}
|
||||
|
||||
namespace uking::act {
|
||||
|
||||
class PlayerBase;
|
||||
|
||||
class PlayerInfoBase {
|
||||
public:
|
||||
PlayerInfoBase();
|
||||
virtual ~PlayerInfoBase();
|
||||
};
|
||||
|
||||
class PlayerInfo : public PlayerInfoBase {
|
||||
SEAD_SINGLETON_DISPOSER(PlayerInfo)
|
||||
PlayerInfo();
|
||||
~PlayerInfo() override;
|
||||
|
||||
public:
|
||||
ksys::act::BaseProcLink& getPlayerLink() { return mPlayerLink; }
|
||||
bool init();
|
||||
void setAndAcquirePlayer(PlayerBase* player); // requires PlayerOrEnemy and PlayerBase
|
||||
void resetPlayer(PlayerBase* player);
|
||||
bool acquireHorse(ksys::act::BaseProc* horse);
|
||||
void setHorseLink(const ksys::act::BaseProcLink& horse_link);
|
||||
PlayerBase* getPlayer() const;
|
||||
PlayerBase* getPlayer_() const; // possibly duped by compiler?
|
||||
ksys::act::Actor* getRiddenHorse() const; // requires PlayerBase vtable
|
||||
void setMaxLifeForPlayerActor(s32 max_heart); // requires PlayerBase
|
||||
s32 getMaxLifeFromPlayerActor() const;
|
||||
void setMaxHeartValue(s32 quarter_hearts);
|
||||
u32 getMaxHeartValue() const;
|
||||
void updateMaxHeartValueFromGameData();
|
||||
void setLifeForPlayerActor(s32 life);
|
||||
s32 getLifeFromPlayerActor() const;
|
||||
void updateCurrentHartFlagFromPlayerActor(); // TODO
|
||||
void updateLifeAfterGameOver(); // requires a global flag
|
||||
void
|
||||
resetLifeToBeforeSwordPull(); // requires HeartDisplayMgr (0x25D6578) and PlayerBase vtable
|
||||
void saveLifeInfoForSwordPull(); // requires PlayerBase vtable
|
||||
void recoverLife();
|
||||
void setStaminaCurrentMax(f32 max_stamina);
|
||||
f32 getStaminaCurrentMax() const;
|
||||
void updateStaminaCurrentMaxFromGameData();
|
||||
void setStaminaMax(f32 max_stamina);
|
||||
f32 getStaminaMax() const;
|
||||
void updateStaminaMaxFromGameData();
|
||||
void setMaxStaminaForPlayerActor(f32 max_stamina); // requires PlayerBase
|
||||
f32 getMaxStaminaFromPlayerActor() const; // requires PlayerBase
|
||||
void recoverStamina(); // requires PlayerBase
|
||||
void recoverCondition(); // requires PlayerBase
|
||||
|
||||
PlayerBase* getPlayerUnchecked();
|
||||
|
||||
sead::Vector3f& getPlayerPos();
|
||||
sead::Vector3f& getPlayerPosForPostCalc();
|
||||
|
||||
// TODO: name and PlayerBase vtable
|
||||
sead::Vector3f& getPlayerM265();
|
||||
|
||||
private:
|
||||
// These are probably debug stuff that were removed
|
||||
class Info1 : public PlayerInfoBase {
|
||||
public:
|
||||
Info1();
|
||||
~Info1() override;
|
||||
} mInfo1;
|
||||
class Info2 : public PlayerInfoBase {
|
||||
public:
|
||||
Info2();
|
||||
~Info2() override;
|
||||
} mInfo2;
|
||||
class Info3 : public PlayerInfoBase {
|
||||
public:
|
||||
Info3();
|
||||
~Info3() override;
|
||||
} mInfo3;
|
||||
class Info4 : public PlayerInfoBase {
|
||||
public:
|
||||
Info4();
|
||||
~Info4() override;
|
||||
} mInfo4;
|
||||
class Info5 : public PlayerInfoBase {
|
||||
public:
|
||||
Info5();
|
||||
~Info5() override;
|
||||
} mInfo5;
|
||||
class Info6 : public PlayerInfoBase {
|
||||
public:
|
||||
Info6();
|
||||
~Info6() override;
|
||||
} mInfo6;
|
||||
class Info7 : public PlayerInfoBase {
|
||||
public:
|
||||
Info7();
|
||||
~Info7() override;
|
||||
} mInfo7;
|
||||
PlayerBase* mPlayerActor = nullptr;
|
||||
ksys::act::BaseProcLink mPlayerLink;
|
||||
ksys::act::BaseProcLink mHorseLink;
|
||||
sead::Vector3f mPlayerPos{0, 0, 0};
|
||||
sead::Vector3f mPlayerPosForPostCalc{0, 0, 0};
|
||||
f32 mMaxHeartValue = 0;
|
||||
f32 mStaminaCurrentMax = 1000; // 1000 = 1 wheel
|
||||
f32 mStaminaMax = 1000;
|
||||
f32 mLifeBeforeSwordPull = 0;
|
||||
f32 mExtraLifeBeforeSwordPull = 0;
|
||||
sead::FixedRingBuffer<sead::Vector3f, 60> mPreviousPositions;
|
||||
f32 _3a0 = 65535;
|
||||
f32 _3a4 = 65535;
|
||||
f32 _3a8 = -1;
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(PlayerInfo, 0x3B0);
|
||||
|
||||
} // namespace uking::act
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "Game/Actor/Player/actPlayerInfo.h"
|
||||
namespace uking::act {
|
||||
// these are separate from actPlayerInfo.cpp so clang doesn't inline/dedupe them
|
||||
[[gnu::noinline]] PlayerInfoBase::PlayerInfoBase() = default;
|
||||
[[gnu::noinline]] PlayerInfoBase::~PlayerInfoBase() = default;
|
||||
} // namespace uking::act
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "Game/Actor/Player/actPlayerInfo.h"
|
||||
namespace uking::act {
|
||||
// these are separate from actPlayerInfo.cpp so clang doesn't inline/dedupe them
|
||||
PlayerInfo::Info1::Info1() = default;
|
||||
PlayerInfo::Info1::~Info1() = default;
|
||||
PlayerInfo::Info2::Info2() = default;
|
||||
PlayerInfo::Info2::~Info2() = default;
|
||||
PlayerInfo::Info3::Info3() = default;
|
||||
PlayerInfo::Info3::~Info3() = default;
|
||||
PlayerInfo::Info4::Info4() = default;
|
||||
PlayerInfo::Info4::~Info4() = default;
|
||||
PlayerInfo::Info5::Info5() = default;
|
||||
PlayerInfo::Info5::~Info5() = default;
|
||||
PlayerInfo::Info6::Info6() = default;
|
||||
PlayerInfo::Info6::~Info6() = default;
|
||||
PlayerInfo::Info7::Info7() = default;
|
||||
PlayerInfo::Info7::~Info7() = default;
|
||||
|
||||
} // namespace uking::act
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "Game/Actor/Query/queryComparePlayerHeart.h"
|
||||
#include <evfl/Query.h>
|
||||
#include "KingSystem/ActorSystem/actPlayerInfo.h"
|
||||
#include "Game/Actor/Player/actPlayerInfo.h"
|
||||
|
||||
namespace uking::query {
|
||||
|
||||
@@ -9,7 +9,7 @@ ComparePlayerHeart::ComparePlayerHeart(const InitArg& arg) : ksys::act::ai::Quer
|
||||
ComparePlayerHeart::~ComparePlayerHeart() = default;
|
||||
|
||||
int ComparePlayerHeart::doQuery() {
|
||||
auto* pi = ksys::act::PlayerInfo::instance();
|
||||
auto* pi = uking::act::PlayerInfo::instance();
|
||||
if (pi == nullptr)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "Game/Actor/Query/queryComparePlayerMaxHeart.h"
|
||||
#include <evfl/Query.h>
|
||||
#include "KingSystem/ActorSystem/actPlayerInfo.h"
|
||||
#include "Game/Actor/Player/actPlayerInfo.h"
|
||||
|
||||
namespace uking::query {
|
||||
|
||||
@@ -9,7 +9,7 @@ ComparePlayerMaxHeart::ComparePlayerMaxHeart(const InitArg& arg) : ksys::act::ai
|
||||
ComparePlayerMaxHeart::~ComparePlayerMaxHeart() = default;
|
||||
|
||||
int ComparePlayerMaxHeart::doQuery() {
|
||||
auto* pi = ksys::act::PlayerInfo::instance();
|
||||
auto* pi = uking::act::PlayerInfo::instance();
|
||||
if (pi == nullptr)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "Game/Actor/Query/queryComparePlayerMaxStamina.h"
|
||||
#include <evfl/Query.h>
|
||||
#include "KingSystem/ActorSystem/actPlayerInfo.h"
|
||||
#include "Game/Actor/Player/actPlayerInfo.h"
|
||||
|
||||
namespace uking::query {
|
||||
|
||||
@@ -9,7 +9,7 @@ ComparePlayerMaxStamina::ComparePlayerMaxStamina(const InitArg& arg) : ksys::act
|
||||
ComparePlayerMaxStamina::~ComparePlayerMaxStamina() = default;
|
||||
|
||||
int ComparePlayerMaxStamina::doQuery() {
|
||||
auto* pi = ksys::act::PlayerInfo::instance();
|
||||
auto* pi = uking::act::PlayerInfo::instance();
|
||||
if (pi == nullptr)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "Game/Actor/Query/queryComparePlayerOriginalHeart.h"
|
||||
#include <evfl/Query.h>
|
||||
#include "KingSystem/ActorSystem/actPlayerInfo.h"
|
||||
#include "Game/Actor/Player/actPlayerInfo.h"
|
||||
|
||||
namespace uking::query {
|
||||
|
||||
@@ -10,7 +10,7 @@ ComparePlayerOriginalHeart::ComparePlayerOriginalHeart(const InitArg& arg)
|
||||
ComparePlayerOriginalHeart::~ComparePlayerOriginalHeart() = default;
|
||||
|
||||
int ComparePlayerOriginalHeart::doQuery() {
|
||||
using PlayerInfo = ksys::act::PlayerInfo;
|
||||
using PlayerInfo = uking::act::PlayerInfo;
|
||||
|
||||
if (PlayerInfo::instance() == nullptr)
|
||||
return 0;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include "Game/Actor/actPlayerCreateMgr.h"
|
||||
#include <prim/seadRuntimeTypeInfo.h>
|
||||
#include <prim/seadStringBuilder.h>
|
||||
#include "Game/Actor/Player/actPlayerBase.h"
|
||||
#include "Game/Actor/Player/actPlayerInfo.h"
|
||||
#include "Game/Actor/actPlayerCreateUtils.h"
|
||||
#include "Game/Actor/actWeapon.h"
|
||||
#include "Game/UI/uiPauseMenuDataMgr.h"
|
||||
#include "KingSystem/ActorSystem/Profiles/actPlayerBase.h"
|
||||
#include "KingSystem/ActorSystem/Profiles/actWeaponBase.h"
|
||||
#include "KingSystem/ActorSystem/actActorConstDataAccess.h"
|
||||
#include "KingSystem/ActorSystem/actActorCreator.h"
|
||||
@@ -13,7 +14,6 @@
|
||||
#include "KingSystem/ActorSystem/actInfoCommon.h"
|
||||
#include "KingSystem/ActorSystem/actInfoData.h"
|
||||
#include "KingSystem/ActorSystem/actInstParamPack.h"
|
||||
#include "KingSystem/ActorSystem/actPlayerInfo.h"
|
||||
#include "KingSystem/GameData/gdtCommonFlagsUtils.h"
|
||||
|
||||
namespace uking::act {
|
||||
@@ -154,7 +154,7 @@ void CreatePlayerEquipActorMgr::requestCreateWeapon(s32 slot_idx, const sead::Sa
|
||||
auto scope = mTracer.trace()->makeScope("requestCreateWeapon", caller, 1);
|
||||
|
||||
deleteLoadingProc(slot_idx);
|
||||
auto* player = ksys::act::PlayerInfo::instance()->getPlayer();
|
||||
auto* player = PlayerInfo::instance()->getPlayer();
|
||||
|
||||
sead::Matrix34f pos;
|
||||
pos.makeT(player->getMtx().getTranslation());
|
||||
@@ -213,7 +213,7 @@ void CreatePlayerEquipActorMgr::requestCreateArmor(s32 slot_idx, const sead::Saf
|
||||
|
||||
{
|
||||
ksys::act::ActorConstDataAccess access;
|
||||
ksys::act::acquireActor(&ksys::act::PlayerInfo::instance()->getPlayerLink(), &access);
|
||||
ksys::act::acquireActor(&PlayerInfo::instance()->getPlayerLink(), &access);
|
||||
sead::Vector3f pos;
|
||||
access.getActorMtx().getTranslation(pos);
|
||||
params->addPosition(pos);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <limits>
|
||||
#include <math/seadMathCalcCommon.h>
|
||||
#include <prim/seadScopedLock.h>
|
||||
#include "Game/Actor/Player/actPlayerBase.h"
|
||||
#include "Game/Actor/Player/actPlayerInfo.h"
|
||||
#include "Game/Actor/actPlayerCreateMgr.h"
|
||||
#include "Game/Actor/actPlayerCreateUtils.h"
|
||||
#include "Game/Actor/actWeapon.h"
|
||||
@@ -12,14 +14,12 @@
|
||||
#include "Game/Scene/gameScene.h"
|
||||
#include "Game/UI/uiUtils.h"
|
||||
#include "Game/gameItemUtils.h"
|
||||
#include "KingSystem/ActorSystem/Profiles/actPlayerBase.h"
|
||||
#include "KingSystem/ActorSystem/actActorConstDataAccess.h"
|
||||
#include "KingSystem/ActorSystem/actActorHeapUtil.h"
|
||||
#include "KingSystem/ActorSystem/actActorUtil.h"
|
||||
#include "KingSystem/ActorSystem/actBaseProcLink.h"
|
||||
#include "KingSystem/ActorSystem/actInfoCommon.h"
|
||||
#include "KingSystem/ActorSystem/actInfoData.h"
|
||||
#include "KingSystem/ActorSystem/actPlayerInfo.h"
|
||||
#include "KingSystem/GameData/gdtCommonFlagsUtils.h"
|
||||
#include "KingSystem/GameData/gdtManager.h"
|
||||
#include "KingSystem/GameData/gdtSpecialFlagNames.h"
|
||||
@@ -315,7 +315,7 @@ void PauseMenuDataMgr::initForNewSave() {
|
||||
mCanSeeHealthBar = false;
|
||||
mEquippedWeapons.fill({});
|
||||
|
||||
auto* player = ksys::act::PlayerInfo::instance()->getPlayer();
|
||||
auto* player = uking::act::PlayerInfo::instance()->getPlayer();
|
||||
if (player) {
|
||||
player->switchEquipment(getDefaultEquipment(EquipmentSlot::WeaponRight), 1);
|
||||
player->switchEquipment(getDefaultEquipment(EquipmentSlot::WeaponLeft), 1);
|
||||
@@ -1357,7 +1357,7 @@ void PauseMenuDataMgr::removeItem(const sead::SafeString& name) {
|
||||
|
||||
void PauseMenuDataMgr::removeWeaponIfEquipped(const sead::SafeString& name) {
|
||||
const auto lock = sead::makeScopedLock(mCritSection);
|
||||
if (!ksys::act::PlayerInfo::instance()->getPlayer())
|
||||
if (!uking::act::PlayerInfo::instance()->getPlayer())
|
||||
return;
|
||||
|
||||
const auto& items = getItems();
|
||||
@@ -1502,7 +1502,7 @@ void PauseMenuDataMgr::createPlayerEquipment() {
|
||||
}
|
||||
}
|
||||
|
||||
auto* player = ksys::act::PlayerInfo::instance()->getPlayer();
|
||||
auto* player = uking::act::PlayerInfo::instance()->getPlayer();
|
||||
|
||||
s32 slot = 0; // <- this is required to match
|
||||
for (u64 i = 0; i != equipment_items.size(); slot = s32(++i)) {
|
||||
|
||||
Reference in New Issue
Block a user