Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leveled 1.1.0 #2

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/generate-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ jobs:
if: ${{ !vars.WINDOWS_RUNNER }}
run: |
choco install ninja
Remove-Item -Path "C:\ProgramData\Chocolatey\bin\ccache.exe" -Force
Remove-Item -Path "C:\ProgramData\Chocolatey\bin\ccache.exe" -Force -ErrorAction SilentlyContinue
- uses: actions/checkout@v3
with:
submodules: true
Expand Down
8 changes: 7 additions & 1 deletion soh/include/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ void TitleCard_InitBossName(PlayState* play, TitleCardContext* titleCtx, void* t
void TitleCard_InitPlaceName(PlayState* play, TitleCardContext* titleCtx, void* texture, s32 x, s32 y,
s32 width, s32 height, s32 delay);
s32 func_8002D53C(PlayState* play, TitleCardContext* titleCtx);
void Actor_RefreshLeveledStats(Actor* actor, Player* player);
void Actor_Kill(Actor* actor);
void Actor_SetFocus(Actor* actor, f32 offset);
void Actor_SetScale(Actor* actor, f32 scale);
Expand Down Expand Up @@ -547,7 +548,7 @@ s32 func_800354B4(PlayState* play, Actor* actor, f32 range, s16 arg3, s16 arg4,
void func_8003555C(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel);
void func_800355B8(PlayState* play, Vec3f* pos);
u8 func_800355E4(PlayState* play, Collider* collider);
u8 Actor_ApplyDamage(Actor* actor);
u16 Actor_ApplyDamage(Actor* actor);
void Actor_SetDropFlag(Actor* actor, ColliderInfo* colBody, s32 freezeFlag);
void Actor_SetDropFlagJntSph(Actor* actor, ColliderJntSph* colBody, s32 freezeFlag);
void func_80035844(Vec3f* arg0, Vec3f* arg1, Vec3s* arg2, s32 arg3);
Expand Down Expand Up @@ -1064,6 +1065,10 @@ void Minimap_Draw(PlayState* play);
void Map_Update(PlayState* play);
void Interface_ChangeAlpha(u16 alphaType);
void Interface_SetSceneRestrictions(PlayState* play);
Gfx* Gfx_TextureIA8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 textureHeight, s16 rectLeft, s16 rectTop,
s16 rectWidth, s16 rectHeight, u16 dsdx, u16 dtdy);
Gfx* Gfx_TextureI8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 textureHeight, s16 rectLeft, s16 rectTop,
s16 rectWidth, s16 rectHeight, u16 dsdx, u16 dtdy);
void Inventory_SwapAgeEquipment(void);
void Interface_InitHorsebackArchery(PlayState* play);
void func_800849EC(PlayState* play);
Expand Down Expand Up @@ -1122,6 +1127,7 @@ void func_8008EE08(Player* player);
void func_8008EEAC(PlayState* play, Actor* actor);
s32 func_8008EF44(PlayState* play, s32 ammo);
s32 Player_IsBurningStickInRange(PlayState* play, Vec3f* pos, f32 radius, f32 arg3);
void Player_GainExperience(PlayState* play, u16 experience);
s32 Player_GetStrength(void);
u8 Player_GetMask(PlayState* play);
Player* Player_UnsetMask(PlayState* play);
Expand Down
3 changes: 3 additions & 0 deletions soh/include/global.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include "functions.h"
#include "variables.h"
#include "macros.h"
#include "leveled_overlays.h"
#include "leveled_stat_math.h"
#include "leveled_actor_level_table.h"
#include "soh/OTRGlobals.h"
#include "soh/Enhancements/gameconsole.h"
#include "soh/Enhancements/gameplaystats.h"
Expand Down
6 changes: 6 additions & 0 deletions soh/include/leveled_actor_level_table.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef LEVELED_ACTOR_LEVEL_TABLE_H
#define LEVELED_ACTOR_LEVEL_TABLE_H
#include "z64.h"
#endif

void Actor_GetLevelAndExperience(PlayState* play, Actor* actor, u16 actorIdOverride);
15 changes: 15 additions & 0 deletions soh/include/leveled_overlays.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef LEVELED_OVERLAYS_H
#define LEVELED_OVERLAYS_H
#include "z64.h"
#endif

void ActorDamageNumber_New(Actor* actor, u16 damage);
void ActorExperienceNumber_New(Actor* actor, u16 experience);
void ActorLevelUp_New(Actor* actor, u8 powerDiff, u8 courageDiff, u16 healthDiff, u8 magicDiff);
void ActorDamageNumber_Draw(PlayState* play, Actor* actor);
void ActorExperienceNumber_Draw(PlayState* play, Actor* actor);
void Actor_LevelUpDraw(PlayState* play, Actor* actor);
void Leveled_ValueNumberDraw(PlayState* play, u16 x, u16 y, u32 value, u8 r, u8 g, u8 b);
void Leveled_BigValueNumberDraw(PlayState* play, u16 x, u16 y, u32 value, u8 r, u8 g, u8 b, u8 a);
void Leveled_KaleidoEquip_Stats(PlayState* play);
void Leveled_Interface_DrawNextLevel(PlayState* play);
34 changes: 34 additions & 0 deletions soh/include/leveled_stat_math.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef LEVELED_STAT_MATH_H
#define LEVELED_STAT_MATH_H
#define HEALTH_ATTACK_MULTIPLIER 7
#include "z64.h"

#ifdef __cplusplus
extern "C"
{
#endif

u16 GetActorStat_DisplayAttack(u16 attack, u8 power);
u16 GetActorStat_Attack(u16 attack, u8 power);
u8 GetActorStat_Power(u8 level);
u8 GetActorStat_Courage(u8 level);
u8 GetActorStat_PlayerPower(u8 level);
u8 GetActorStat_PlayerCourage(u8 level);
u16 GetActorStat_EnemyMaxHealth(u16 baseHealth, u8 level);
u8 GetPlayerStat_BonusHearts(u8 level);
u8 GetPlayerStat_MagicUnits(u8 level);
u16 GetPlayerStat_GetModifiedHealthCapacity(u16 baseHealth, u8 level);
u16 GetPlayerStat_NextLevelExpAtLevel(u8 level);
u16 GetActorStat_NextLevelExp(u8 level, u32 currentExp);
u16 GetEnemyExperienceReward(u8 level, u16 expRate);
f32 Leveled_DamageFormula(f32 attack, u8 power, u8 courage);
f32 Leveled_DamageModify(Actor * actor, Actor * attackingActor, f32 attack);
u16 Leveled_GoldSkulltulaExperience(u8 tokens);
void Leveled_SetPlayerModifiedStats(Player * player);
s8 Leveled_GetSceneLevel(s16 sceneId);

#ifdef __cplusplus
}
#endif

#endif
20 changes: 16 additions & 4 deletions soh/include/z64actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ typedef struct {
} DamageTable;

typedef struct {
/* 0x00 */ u8 health;
/* 0x00 */ u16 health;
/* 0x02 */ s16 cylRadius;
/* 0x04 */ s16 cylHeight;
/* 0x06 */ u8 mass;
} CollisionCheckInfoInit;

typedef struct {
/* 0x00 */ u8 health;
/* 0x00 */ u16 health;
/* 0x02 */ s16 cylRadius;
/* 0x04 */ s16 cylHeight;
/* 0x06 */ s16 cylYShift;
Expand All @@ -74,8 +74,8 @@ typedef struct {
/* 0x12 */ s16 cylHeight; // Used for various purposes
/* 0x14 */ s16 cylYShift; // Unused. Purpose inferred from Cylinder16 and CollisionCheck_CylSideVsLineSeg
/* 0x16 */ u8 mass; // Used to compute displacement for OC collisions
/* 0x17 */ u8 health; // Note: some actors may use their own health variable instead of this one
/* 0x18 */ u8 damage; // Amount to decrement health by
/* 0x17 */ u16 health; // Note: some actors may use their own health variable instead of this one
/* 0x18 */ u16 damage; // Amount to decrement health by
/* 0x19 */ u8 damageEffect; // Stores what effect should occur when hit by a weapon
/* 0x1A */ u8 atHitEffect; // Stores what effect should occur when AT connects with an AC
/* 0x1B */ u8 acHitEffect; // Stores what effect should occur when AC is touched by an AT
Expand Down Expand Up @@ -178,6 +178,18 @@ typedef struct Actor {
/* 0x134 */ ActorFunc draw; // Draw Routine. Called by `Actor_Draw`
/* 0x138 */ ActorResetFunc reset;
/* 0x13C */ char dbgPad[0x10]; // Padding that only exists in the debug rom
u16 exp; // Experience
u8 level; // Actor Level
u8 power; // e.g. Strength
u8 courage; // e.g. Defense
s8 powerModifier; // Modifies Power
s8 courageModifier; // Modifies Courage
u16 maximumHealth; // Health after Leveled math for enemies (Some don't use this)
u16 floatingNumber[7];
u8 floatingNumberLife[7];
Vec2f floatingNumberPosition[7];
Vec2f floatingNumberVelocity[7];
bool ignoreExpReward; // Actor handles exp reward differently
} Actor; // size = 0x14C

typedef enum {
Expand Down
2 changes: 1 addition & 1 deletion soh/include/z64player.h
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ typedef struct Player {
/* 0x089A */ s16 unk_89A;
/* 0x089C */ s16 unk_89C;
/* 0x089E */ u16 unk_89E;
/* 0x08A0 */ u8 unk_8A0;
/* 0x08A0 */ u16 unk_8A0;
/* 0x08A1 */ u8 unk_8A1;
/* 0x08A2 */ s16 unk_8A2;
/* 0x08A4 */ f32 unk_8A4;
Expand Down
7 changes: 6 additions & 1 deletion soh/include/z64save.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ typedef struct {
/* 0x002E */ s16 healthCapacity; // "max_life"
/* 0x0030 */ s16 health; // "now_life"
/* 0x0032 */ s8 magicLevel; // 0 for no magic/new load, 1 for magic, 2 for double magic
/* 0x0033 */ s8 magic; // current magic available for use
/* 0x0033 */ u8 magic; // current magic available for use
/* 0x0034 */ s16 rupees;
/* 0x0036 */ u16 swordHealth;
/* 0x0038 */ u16 naviTimer;
Expand Down Expand Up @@ -319,6 +319,11 @@ typedef struct {
/* */ u8 seedIcons[5];
/* */ u16 randomizerInf[9];
/* */ u16 adultTradeItems;
u32 experience;
s16 heartContainers;
s16 healthCapacity2; // Modified max health
u8 magicUnits; // Modified magic units per magic level
s16 showNeededExpTimer; // Shows EXP required in the hud when greater than 0
// #endregion
} SaveContext; // size = 0x1428

Expand Down
2 changes: 1 addition & 1 deletion soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1138,7 +1138,7 @@ void Draw_Placements(){
DrawPositionsRadioBoxes("gHeartsCount");
DrawPositionSlider("gHeartsCount",-22,ImGui::GetWindowViewport()->Size.y,-125,ImGui::GetWindowViewport()->Size.x);
DrawScaleSlider("gHeartsCount",0.7f);
UIWidgets::EnhancementSliderInt("Heart line length : %d", "##HeartLineLength", "gHeartsLineLength", 0, 20, "", 10);
UIWidgets::EnhancementSliderInt("Heart line length : %d", "##HeartLineLength", "gHeartsLineLength", 0, 20, "", 15);
UIWidgets::Tooltip("This will set the length of a row of hearts. Set to 0 for unlimited length.");
ImGui::NewLine();
ImGui::EndTable();
Expand Down
6 changes: 5 additions & 1 deletion soh/soh/Enhancements/debugger/actorViewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ void ActorViewerWindow::DrawElement() {
ImGui::Text("Name: %s", ActorDB::Instance->RetrieveEntry(display->id).name.c_str());
ImGui::Text("Description: %s", GetActorDescription(display->id).c_str());
ImGui::Text("Category: %s", acMapping[display->category]);
if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) {
ImGui::Text("Level: %d", display->level);
ImGui::Text("EXP: %d", display->exp);
}
ImGui::Text("ID: %d", display->id);
ImGui::Text("Parameters: %d", display->params);
});
Expand All @@ -191,7 +195,7 @@ void ActorViewerWindow::DrawElement() {
});

if (display->category == ACTORCAT_BOSS || display->category == ACTORCAT_ENEMY) {
ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display->colChkInfo.health);
ImGui::InputScalar("Enemy Health", ImGuiDataType_U16, &display->colChkInfo.health);
UIWidgets::InsertHelpHoverText("Some actors might not use this!");
}

Expand Down
10 changes: 5 additions & 5 deletions soh/soh/Enhancements/debugger/debugSaveEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,12 +336,12 @@ void DrawInfoTab() {
gSaveContext.healthCapacity = healthIntermediary;
}
UIWidgets::InsertHelpHoverText("Maximum health. 16 units per full heart");
if (gSaveContext.health > gSaveContext.healthCapacity) {
gSaveContext.health = gSaveContext.healthCapacity; // Clamp health to new max
if (gSaveContext.health > gSaveContext.healthCapacity2) {
gSaveContext.health = gSaveContext.healthCapacity2; // Clamp health to new max
}

const uint16_t healthMin = 0;
const uint16_t healthMax = gSaveContext.healthCapacity;
const uint16_t healthMax = gSaveContext.healthCapacity2;
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
ImGui::SliderScalar("Health", ImGuiDataType_S16, &gSaveContext.health, &healthMin, &healthMax);
UIWidgets::InsertHelpHoverText("Current health. 16 units per full heart");
Expand Down Expand Up @@ -383,15 +383,15 @@ void DrawInfoTab() {
ImGui::EndCombo();
}
UIWidgets::InsertHelpHoverText("Current magic level");
gSaveContext.magicCapacity = gSaveContext.magicLevel * 0x30; // Set to get the bar drawn in the UI
gSaveContext.magicCapacity = gSaveContext.magicLevel * gSaveContext.magicUnits; // Set to get the bar drawn in the UI
if (gSaveContext.magic > gSaveContext.magicCapacity) {
gSaveContext.magic = gSaveContext.magicCapacity; // Clamp magic to new max
}

const uint8_t magicMin = 0;
const uint8_t magicMax = gSaveContext.magicCapacity;
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
ImGui::SliderScalar("Magic", ImGuiDataType_S8, &gSaveContext.magic, &magicMin, &magicMax);
ImGui::SliderScalar("Magic", ImGuiDataType_U8, &gSaveContext.magic, &magicMin, &magicMax);
UIWidgets::InsertHelpHoverText("Current magic. 48 units per magic level");

ImGui::InputScalar("Rupees", ImGuiDataType_S16, &gSaveContext.rupees);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,17 @@ void GameInteractor::RawAction::AddOrRemoveMagic(int8_t amount) {

void GameInteractor::RawAction::HealOrDamagePlayer(int16_t hearts) {
if (hearts > 0) {
Health_ChangeBy(gPlayState, hearts * 0x10);
Health_ChangeBy(gPlayState, hearts * CVarGetInteger("gLeveledHeartUnits", 4) << 2);
} else if (hearts < 0) {
Player* player = GET_PLAYER(gPlayState);
Health_ChangeBy(gPlayState, hearts * 0x10);
Health_ChangeBy(gPlayState, hearts * CVarGetInteger("gLeveledHeartUnits", 4) << 2);
func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0);
player->invincibilityTimer = 28;
}
}

void GameInteractor::RawAction::SetPlayerHealth(int16_t hearts) {
gSaveContext.health = hearts * 0x10;
gSaveContext.health = hearts * CVarGetInteger("gLeveledHeartUnits", 4) << 2;
}

void GameInteractor::RawAction::SetLinkInvisibility(bool active) {
Expand Down
4 changes: 2 additions & 2 deletions soh/soh/Enhancements/mods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ void RegisterInfiniteMoney() {
void RegisterInfiniteHealth() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
if (CVarGetInteger("gInfiniteHealth", 0) != 0) {
if (gSaveContext.health < gSaveContext.healthCapacity) {
gSaveContext.health = gSaveContext.healthCapacity;
if (gSaveContext.health < gSaveContext.healthCapacity2) {
gSaveContext.health = gSaveContext.healthCapacity2;
}
}
});
Expand Down
44 changes: 44 additions & 0 deletions soh/soh/OTRGlobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1793,6 +1793,50 @@ extern "C" int GetEquipNowMessage(char* buffer, char* src, const int maxBufferSi
return 0;
}

extern "C" int GetLeveledNaviEnemyInfo(char* buffer, char* src, const int maxBufferSize, Actor* actor) {
std::string postfix;

if (!actor)
return 0;

if (gSaveContext.language == LANGUAGE_FRA) {
postfix = "";
} else if (gSaveContext.language == LANGUAGE_GER) {
postfix = "";
} else {
postfix = "";
if (CVarGetInteger("gLeveledNaviLevel", 1)) {
postfix += " \x05"
"F"
"Lv" +
std::to_string(actor->level);
}
if (CVarGetInteger("gLeveledNaviMaxHP", 1) && actor->maximumHealth > 0) {
postfix += " \x05"
"A"
"MaxHP " +
std::to_string(actor->maximumHealth);
}
}
std::string str;
std::string FixedBaseStr(src);
int FoundControlChar = FixedBaseStr.find_first_of("\x01");

if (FoundControlChar != std::string::npos) {
FixedBaseStr = FixedBaseStr.insert(FoundControlChar, postfix);
}

str = FixedBaseStr;

if (!str.empty()) {
memset(buffer, 0, maxBufferSize);
const int copiedCharLen = std::min<int>(maxBufferSize - 1, str.length());
memcpy(buffer, str.c_str(), copiedCharLen);
return copiedCharLen;
}
return 0;
}

extern "C" void Randomizer_LoadSettings(const char* spoilerFileName) {
OTRGlobals::Instance->gRandomizer->LoadRandomizerSettings(spoilerFileName);
}
Expand Down
1 change: 1 addition & 0 deletions soh/soh/OTRGlobals.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ void Controller_BlockGameInput();
void Controller_UnblockGameInput();
void* getN64WeirdFrame(s32 i);
int GetEquipNowMessage(char* buffer, char* src, const int maxBufferSize);
int GetLeveledNaviEnemyInfo(char* buffer, char* src, const int maxBufferSize, Actor* actor);
u32 SpoilerFileExists(const char* spoilerFileName);
Sprite* GetSeedTexture(uint8_t index);
void Randomizer_LoadSettings(const char* spoilerFileName);
Expand Down
Loading