ModeBallon: Implement RankingLocalFunction (#906)

This commit is contained in:
Narr the Reg 2026-02-16 17:47:51 -06:00 committed by GitHub
parent 86d07c8f34
commit 92f78b4e52
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 183 additions and 17 deletions

View file

@ -94280,35 +94280,35 @@ ModeBalloon/RankingLocalFunction.h:
- offset: 0x35c158
size: 16
label: _ZN20RankingLocalFunction27isValidCourceIdYukimaruRaceEi
status: NotDecompiled
status: Matching
- offset: 0x35c168
size: 32
label: _ZN20RankingLocalFunction30getRankingCategoryYukimaruRaceEi
status: NotDecompiled
status: Matching
- offset: 0x35c188
size: 40
label: _ZN20RankingLocalFunction25isValidWorldIdRaceManRaceEi
status: NotDecompiled
status: Matching
- offset: 0x35c1b0
size: 32
label: _ZN20RankingLocalFunction29getRankingCategoryRaceManRaceEi
status: NotDecompiled
status: Matching
- offset: 0x35c1d0
size: 16
label: _ZN20RankingLocalFunction29isRankingCategoryYukimaruRaceE15RankingCategory
status: NotDecompiled
status: Matching
- offset: 0x35c1e0
size: 52
label: _ZN20RankingLocalFunction28isRankingCategoryRaceManRaceE15RankingCategory
status: NotDecompiled
status: Matching
- offset: 0x35c214
size: 56
label: _ZN20RankingLocalFunction21getRaceManRaceWorldIdE15RankingCategory
status: NotDecompiled
status: Matching
- offset: 0x35c24c
size: 84
label: _ZN20RankingLocalFunction21isRankingCategoryRaceE15RankingCategory
status: NotDecompiled
status: Matching
- offset: 0x35c2a0
size: 100
label: _ZN20RankingLocalFunction26tryGetRankingCategoryIndexEPi15RankingCategoryRKN4sead8ObjArrayIS1_EE
@ -94320,11 +94320,11 @@ ModeBalloon/RankingLocalFunction.h:
- offset: 0x35c354
size: 232
label: _ZN20RankingLocalFunction35findRankingCategoryByRaceRecordNameEPKc
status: NotDecompiled
status: Matching
- offset: 0x35c43c
size: 136
label: _ZN20RankingLocalFunction24isRankingUploadableScoreEj15RankingCategory
status: NotDecompiled
status: Matching
- offset: 0x35c4c4
size: 36
label: _ZN20RankingDataOneRecord5clearEv

View file

@ -7,6 +7,8 @@
#include "Library/LiveActor/LiveActor.h"
#include "Library/Ranking/IUseRanking.h"
#include "ModeBalloon/RankingCategory.h"
namespace al {
struct ActorInitInfo;
class IUseDataStore;
@ -30,8 +32,6 @@ class BalloonDataServer;
class NoticeDataServer;
} // namespace TimeBalloon
enum class RankingCategory : s32;
class NexRankingUploader : public al::IUseRanking, public al::LiveActor {
public:
NexRankingUploader(const char*, const char*);

View file

@ -0,0 +1,24 @@
#pragma once
#include <prim/seadEnum.h>
SEAD_ENUM(RankingCategory,
JumpingRope,
Volleyball,
Radicon,
Yukimaru_1,
Yukimaru_2,
RaceManRace_1,
RaceManRace_2,
RaceManRace_3,
RaceManRace_4,
RaceManRace_5,
RaceManRace_6,
RaceManRace_7,
RaceManRace_8,
RaceManRace_9,
RaceManRace_10,
RaceManRace_11,
RaceManRace_12,
RaceManRace_13,
)

View file

@ -0,0 +1,141 @@
#include "ModeBalloon/RankingLocalFunction.h"
#include <prim/seadStringUtil.h>
#include "Library/Base/StringUtil.h"
#include "Util/SequentialUtil.h"
namespace RankingLocalFunction {
bool isValidCourceIdYukimaruRace(s32 courseId) {
return courseId == 0 || courseId == 1;
}
RankingCategory getRankingCategoryYukimaruRace(s32 courseId) {
RankingCategory yukimaruCourseIdToCategory[2]{
RankingCategory::Yukimaru_1,
RankingCategory::Yukimaru_2,
};
return yukimaruCourseIdToCategory[courseId];
}
bool isValidWorldIdRaceManRace(s32 worldId) {
// NOTE: Cloud (5), Ruined (11), Dark (15) and Darker Side (16) do not have a KFR
return worldId >= 0 && worldId != 5 && worldId != 11 && (u32)worldId < 15;
}
RankingCategory getRankingCategoryRaceManRace(s32 worldId) {
switch (worldId) {
case 0:
return RankingCategory::RaceManRace_1;
case 1:
return RankingCategory::RaceManRace_2;
case 2:
return RankingCategory::RaceManRace_3;
case 3:
return RankingCategory::RaceManRace_4;
case 4:
return RankingCategory::RaceManRace_5;
case 6:
return RankingCategory::RaceManRace_6;
case 7:
return RankingCategory::RaceManRace_7;
case 8:
return RankingCategory::RaceManRace_8;
case 9:
return RankingCategory::RaceManRace_9;
case 10:
return RankingCategory::RaceManRace_10;
case 12:
return RankingCategory::RaceManRace_11;
case 13:
return RankingCategory::RaceManRace_12;
case 14:
return RankingCategory::RaceManRace_13;
default:
return RankingCategory::RaceManRace_1;
}
}
bool isRankingCategoryYukimaruRace(RankingCategory category) {
return category == RankingCategory::Yukimaru_1 || category == RankingCategory::Yukimaru_2;
}
bool isRankingCategoryRaceManRace(RankingCategory category) {
return category >= RankingCategory::RaceManRace_1 &&
category <= RankingCategory::RaceManRace_13;
}
s32 getRaceManRaceWorldId(RankingCategory category) {
switch (category) {
case RankingCategory::RaceManRace_1:
return 0;
case RankingCategory::RaceManRace_2:
return 1;
case RankingCategory::RaceManRace_3:
return 2;
case RankingCategory::RaceManRace_4:
return 3;
case RankingCategory::RaceManRace_5:
return 4;
case RankingCategory::RaceManRace_6:
return 6;
case RankingCategory::RaceManRace_7:
return 7;
case RankingCategory::RaceManRace_8:
return 8;
case RankingCategory::RaceManRace_9:
return 9;
case RankingCategory::RaceManRace_10:
return 10;
case RankingCategory::RaceManRace_11:
return 12;
case RankingCategory::RaceManRace_12:
return 13;
case RankingCategory::RaceManRace_13:
return 14;
default:
return -1;
}
}
bool isRankingCategoryRace(RankingCategory category) {
return isRankingCategoryYukimaruRace(category) || isRankingCategoryRaceManRace(category) ||
category == RankingCategory::Radicon;
}
RankingCategory findRankingCategoryByRaceRecordName(const char* name) {
if (al::isEqualString(name, "Yukimaru_1"))
return RankingCategory::Yukimaru_1;
if (al::isEqualString(name, "Yukimaru_2"))
return RankingCategory::Yukimaru_2;
if (al::isEqualString(name, "Radicon"))
return RankingCategory::Radicon;
if (al::isEqualSubString(name, "RaceManRace")) {
const char* worldIdStr = al::searchSubString(name, "_") + 1;
s32 worldId = 0;
sead::StringUtil::tryParseS32(&worldId, worldIdStr,
sead::StringUtil::CardinalNumber::BaseAuto);
return getRankingCategoryRaceManRace(worldId);
}
return RankingCategory::Yukimaru_1;
}
bool isRankingUploadableScore(u32 score, RankingCategory category) {
if (category == RankingCategory::JumpingRope)
return score != 0;
if (category == RankingCategory::Volleyball)
return score != 0;
if (isRankingCategoryRace(category))
return score <= RaceTimeFunction::getRaceTimeMaxCsec();
return true;
}
} // namespace RankingLocalFunction

View file

@ -3,7 +3,7 @@
#include <basis/seadTypes.h>
#include <container/seadObjArray.h>
enum class alignas(8) RankingCategory : s32;
#include "ModeBalloon/RankingCategory.h"
namespace RankingLocalFunction {
bool isValidCourceIdYukimaruRace(s32);
@ -26,6 +26,8 @@ struct RankingDataOneRecord {
void* filler_0[14];
};
static_assert(sizeof(RankingDataOneRecord) == 0x70);
class RankingDataOneCategory {
public:
RankingDataOneCategory(RankingCategory, s32);
@ -37,5 +39,4 @@ private:
void* filler_8[3];
};
static_assert(sizeof(RankingDataOneRecord) == 0x70);
static_assert(sizeof(RankingDataOneCategory) == 0x20);

View file

@ -2,13 +2,13 @@
#include <basis/seadTypes.h>
#include "ModeBalloon/RankingCategory.h"
#include "System/ByamlSave.h"
namespace al {
class ByamlIter;
class ByamlWriter;
} // namespace al
enum class RankingCategory : s32;
class NetworkUploadFlag : public ByamlSave {
public:

View file

@ -12,7 +12,7 @@ s32 RaceTimeFunction::getRaceTimeMaxFrame() {
return 215999;
}
s32 RaceTimeFunction::getRaceTimeMaxCsec() {
u32 RaceTimeFunction::getRaceTimeMaxCsec() {
return 359999;
}

View file

@ -8,6 +8,6 @@ void convertCsecTo(s32* minutes, s32* seconds, s32* csec, s32 time);
namespace RaceTimeFunction {
s32 getRaceTimeMaxFrame();
s32 getRaceTimeMaxCsec();
u32 getRaceTimeMaxCsec();
s32 clampRaceRecordCsec(s32 csec);
} // namespace RaceTimeFunction