Merge pull request 'Fix music system inconsistencies and add dimension-aware boss bar handling' (#15) from GeorgeV22/LegacyEvolved:main into main

Reviewed-on: https://codeberg.org/piebot/LegacyEvolved/pulls/15
This commit is contained in:
piebot 2026-04-08 12:41:38 +02:00
commit 1256671dbf
9 changed files with 136 additions and 116 deletions

View file

@ -1,16 +1,25 @@
#include "stdafx.h"
#include "BossMobGuiInfo.h"
#include "../Minecraft.World/BossMob.h"
#include "../Minecraft.World/LevelData.h"
float BossMobGuiInfo::healthProgress = 0.0f;
int BossMobGuiInfo::displayTicks = 0;
wstring BossMobGuiInfo::name = L"";
bool BossMobGuiInfo::darkenWorld = false;
float BossMobGuiInfo::healthProgress[3] = { 0.0f, 0.0f, 0.0f };
int BossMobGuiInfo::displayTicks[3] = { 0, 0, 0 };
wstring BossMobGuiInfo::name[3];
bool BossMobGuiInfo::darkenWorld[3] = { false, false, false };
void BossMobGuiInfo::setBossHealth(shared_ptr<BossMob> boss, bool darkenWorld)
{
healthProgress = (float) boss->getHealth() / (float) boss->getMaxHealth();
displayTicks = SharedConstants::TICKS_PER_SECOND * 5;
name = boss->getAName();
BossMobGuiInfo::darkenWorld = darkenWorld;
int idx = getIndexFromDimension(boss->getDimension());
healthProgress[idx] = (float) boss->getHealth() / (float) boss->getMaxHealth();
displayTicks[idx] = SharedConstants::TICKS_PER_SECOND * 5;
name[idx] = boss->getAName();
BossMobGuiInfo::darkenWorld[idx] = darkenWorld;
}
int BossMobGuiInfo::getIndexFromDimension(int dimension)
{
if (dimension == LevelData::DIMENSION_NETHER) return 1;
if (dimension == LevelData::DIMENSION_END) return 2;
return 0;
}

View file

@ -5,10 +5,12 @@ class BossMob;
class BossMobGuiInfo
{
public:
static float healthProgress;
static int displayTicks;
static wstring name;
static bool darkenWorld;
static float healthProgress[3];
static int displayTicks[3];
static wstring name[3];
static bool darkenWorld[3];
static void setBossHealth(shared_ptr<BossMob> boss, bool darkenWorld);
static int getIndexFromDimension(int dimension);
};

View file

@ -1,6 +1,8 @@
#include "stdafx.h"
#include "stdafx.h"
#include "SoundEngine.h"
#include "BossMobGuiInfo.h"
#include "../Consoles_App.h"
#include "../../MultiPlayerLocalPlayer.h"
#include "../../../Minecraft.World/net.minecraft.world.level.h"
@ -323,6 +325,22 @@ void SoundEngine::updateMiniAudio()
}
}
/////////////////////////////////////////////
//
// getGameModeMusicID
//
/////////////////////////////////////////////
inline void SoundEngine::getGameModeMusicID(Minecraft* pMinecraft, unsigned int i)
{
if (pMinecraft->localplayers[i] != nullptr && pMinecraft->localplayers[i]->abilities.instabuild && pMinecraft->localplayers[i]->abilities.mayfly)
m_musicID = getMusicID(eMusicType_Creative);
// TODO(3UR): this is a part of minigames also in the future other minigame ids will need to be handled for now TU30 only checks for BATTLE
//else if (pMinecraft->GetCustomGameMode() && CustomGameModeInst::GetId() == EMiniGameId::BATTLE) // @3UR: thanks https://github.com/GRAnimated/MinecraftLCE/blob/6947670d152582457bfe02bd909ee30a7ab7eb55/src/Minecraft.World/net/minecraft/world/level/gamemode/minigames/EMiniGameId.h#L3
// m_musicID = getMusicID(eMusicType_Battle);
else
m_musicID = getMusicID(eMusicType_Overworld);
}
/////////////////////////////////////////////
//
// tick
@ -422,7 +440,7 @@ SoundEngine::SoundEngine()
eStream_BattleMode1, eStream_BattleMode4,
eStream_CD_1);
m_musicID = getMusicID(eMusicDomain_Menu);
m_musicID = getMusicID(eMusicType_Menu);
m_StreamingAudioInfo.bIs3D=false;
m_StreamingAudioInfo.x=0;
@ -710,8 +728,6 @@ void SoundEngine::playStreaming(const wstring& name, float x, float y, float z,
bool playerInEnd = false;
bool playerInNether = false;
// @3UR: the pseudo is so cancer but i am pretty sure this is what they did
// IF it is wrong please correct it.
unsigned int i = 0;
for(i = 0; i < MAX_LOCAL_PLAYERS; i++)
{
@ -725,22 +741,11 @@ void SoundEngine::playStreaming(const wstring& name, float x, float y, float z,
}
if(playerInEnd)
m_musicID = getMusicID(eMusicDomain_End);
m_musicID = getMusicID(eMusicType_End);
else if(playerInNether)
m_musicID = getMusicID(eMusicDomain_Nether);
m_musicID = getMusicID(eMusicType_Nether);
else
{
// @3UR: in ida it looks like they didnt have a var for the player but idc its cleaner
MultiplayerLocalPlayer* pPlayer = pMinecraft->localplayers[i-1].get();
if(pPlayer != nullptr && pPlayer->abilities.instabuild && pPlayer->abilities.mayfly)
m_musicID = getMusicID(eMusicDomain_Creative);
// TODO(3UR): this is a part of minigames also in the future other minigame ids will need to be handled for now TU30 only checks for BATTLE
//else if(pMinecraft->GetCustomGameMode() && CustomGameModeInst::GetId() == EMiniGameId::BATTLE) // @3UR: thanks https://github.com/GRAnimated/MinecraftLCE/blob/6947670d152582457bfe02bd909ee30a7ab7eb55/src/Minecraft.World/net/minecraft/world/level/gamemode/minigames/EMiniGameId.h#L3
// m_musicID = getMusicID(eMuszicDomain_Battle);
else
m_musicID = getMusicID(eMusicDomain_Overworld);
}
getGameModeMusicID(pMinecraft, i);
}
else
{
@ -806,48 +811,55 @@ int SoundEngine::GetRandomishTrack(int iStart,int iEnd)
// getMusicID
//
/////////////////////////////////////////////
int SoundEngine::getMusicID(int iDomain)
int SoundEngine::getMusicID(eMusicType iDomain)
{
int iRandomVal=0;
Minecraft *pMinecraft=Minecraft::GetInstance();
// Before the game has started?
if(pMinecraft==nullptr)
if(pMinecraft && !pMinecraft->skins->isUsingDefaultSkin())
{
// any track from the overworld
return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
// using a texture pack - may have multiple End music tracks
switch(iDomain)
{
case eMusicType_Nether:
return GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max);
//return m_iStream_Nether_Min + random->nextInt(m_iStream_Nether_Max-m_iStream_Nether_Min);
case eMusicType_Menu:
return GetRandomishTrack(m_iStream_Menu_Min, m_iStream_Menu_Max);
case eMusicType_End:
return GetRandomishTrack(m_iStream_End_Min, m_iStream_End_Max);
case eMusicType_Creative:
return GetRandomishTrack(m_iStream_Creative_Min, m_iStream_Creative_Max);
case eMusicType_Battle:
return GetRandomishTrack(m_iStream_Battle_Min, m_iStream_Battle_Max);
default: //overworld
//return m_iStream_Overworld_Min + random->nextInt(m_iStream_Overworld_Max-m_iStream_Overworld_Min);
return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
}
}
switch(iDomain)
{
case eMusicType_Nether:
return GetRandomishTrack(m_iStream_Nether_Min, m_iStream_Nether_Max);
case eMusicType_Menu:
return GetRandomishTrack(m_iStream_Menu_Min, m_iStream_Menu_Max);
case eMusicType_End:
// the end isn't random - it has different music depending on whether the dragon is alive or not, but we've not added the dead dragon music yet
{
int idx = BossMobGuiInfo::getIndexFromDimension(LevelData::DIMENSION_END);
if (!BossMobGuiInfo::name[idx].empty() && BossMobGuiInfo::displayTicks[idx] > 0)
return m_iStream_End_Min;
else
return m_iStream_End_Max;
if(pMinecraft->skins->isUsingDefaultSkin())
{
switch(iDomain)
{
case LevelData::DIMENSION_END:
// the end isn't random - it has different music depending on whether the dragon is alive or not, but we've not added the dead dragon music yet
return m_iStream_End_Min;
case LevelData::DIMENSION_NETHER:
return GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max);
//return m_iStream_Nether_Min + random->nextInt(m_iStream_Nether_Max-m_iStream_Nether_Min);
default: //overworld
//return m_iStream_Overworld_Min + random->nextInt(m_iStream_Overworld_Max-m_iStream_Overworld_Min);
return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
}
}
else
{
// using a texture pack - may have multiple End music tracks
switch(iDomain)
{
case LevelData::DIMENSION_END:
return GetRandomishTrack(m_iStream_End_Min,m_iStream_End_Max);
case LevelData::DIMENSION_NETHER:
//return m_iStream_Nether_Min + random->nextInt(m_iStream_Nether_Max-m_iStream_Nether_Min);
return GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max);
default: //overworld
//return m_iStream_Overworld_Min + random->nextInt(m_iStream_Overworld_Max-m_iStream_Overworld_Min);
return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
}
}
}
case eMusicType_Creative:
return GetRandomishTrack(m_iStream_Creative_Min, m_iStream_Creative_Max);
case eMusicType_Battle:
return GetRandomishTrack(m_iStream_Battle_Min, m_iStream_Battle_Max);
default:
return GetRandomishTrack(m_iStream_Overworld_Min, m_iStream_Overworld_Max);
}
}
/////////////////////////////////////////////
@ -1044,7 +1056,6 @@ void SoundEngine::playMusicUpdate()
{
SetIsPlayingStreamingGameMusic(true);
SetIsPlayingStreamingCDMusic(false);
m_MusicType=eMusicType_Game;
m_StreamingAudioInfo.bIs3D=false;
#ifdef _XBOX_ONE
@ -1070,7 +1081,6 @@ void SoundEngine::playMusicUpdate()
{
SetIsPlayingStreamingGameMusic(false);
SetIsPlayingStreamingCDMusic(true);
m_MusicType=eMusicType_CD;
m_StreamingAudioInfo.bIs3D=true;
// Need to adjust to index into the cds in the game's m_szStreamFileA
@ -1130,7 +1140,6 @@ void SoundEngine::playMusicUpdate()
{
SetIsPlayingStreamingGameMusic(true);
SetIsPlayingStreamingCDMusic(false);
m_MusicType=eMusicType_Game;
m_StreamingAudioInfo.bIs3D=false;
// build the name
strcat((char *)m_szStreamName,"music/");
@ -1139,7 +1148,6 @@ void SoundEngine::playMusicUpdate()
{
SetIsPlayingStreamingGameMusic(false);
SetIsPlayingStreamingCDMusic(true);
m_MusicType=eMusicType_CD;
m_StreamingAudioInfo.bIs3D=true;
// build the name
strcat((char *)m_szStreamName,"cds/");
@ -1302,7 +1310,8 @@ void SoundEngine::playMusicUpdate()
bool playerInEnd = false;
bool playerInNether=false;
Minecraft *pMinecraft = Minecraft::GetInstance();
for(unsigned int i = 0; i < MAX_LOCAL_PLAYERS; ++i)
unsigned int i = 0;
for(i = 0; i < MAX_LOCAL_PLAYERS; ++i)
{
if(pMinecraft->localplayers[i]!=nullptr)
{
@ -1322,7 +1331,7 @@ void SoundEngine::playMusicUpdate()
m_StreamState=eMusicStreamState_Stop;
// Set the end track
m_musicID = getMusicID(eMusicDomain_End);
m_musicID = getMusicID(eMusicType_End);
SetIsPlayingEndMusic(true);
SetIsPlayingNetherMusic(false);
}
@ -1333,7 +1342,7 @@ void SoundEngine::playMusicUpdate()
m_StreamState=eMusicStreamState_Stop;
// Set the end track
m_musicID = getMusicID(eMusicDomain_Nether);
m_musicID = getMusicID(eMusicType_Nether);
SetIsPlayingEndMusic(false);
SetIsPlayingNetherMusic(true);
}
@ -1342,7 +1351,7 @@ void SoundEngine::playMusicUpdate()
m_StreamState=eMusicStreamState_Stop;
// Set the end track
m_musicID = getMusicID(eMusicDomain_Overworld);
m_musicID = getMusicID(eMusicType_Overworld);
SetIsPlayingEndMusic(false);
SetIsPlayingNetherMusic(false);
}
@ -1351,7 +1360,7 @@ void SoundEngine::playMusicUpdate()
{
m_StreamState=eMusicStreamState_Stop;
// set the Nether track
m_musicID = getMusicID(eMusicDomain_Nether);
m_musicID = getMusicID(eMusicType_Nether);
SetIsPlayingNetherMusic(true);
SetIsPlayingEndMusic(false);
}
@ -1361,7 +1370,7 @@ void SoundEngine::playMusicUpdate()
{
m_StreamState=eMusicStreamState_Stop;
// set the Nether track
m_musicID = getMusicID(eMusicDomain_End);
m_musicID = getMusicID(eMusicType_End);
SetIsPlayingNetherMusic(false);
SetIsPlayingEndMusic(true);
}
@ -1369,11 +1378,13 @@ void SoundEngine::playMusicUpdate()
{
m_StreamState=eMusicStreamState_Stop;
// set the Nether track
m_musicID = getMusicID(eMusicDomain_Overworld);
m_musicID = getMusicID(eMusicType_Overworld);
SetIsPlayingNetherMusic(false);
SetIsPlayingEndMusic(false);
}
}
else if(!playerInEnd && !playerInNether)
getGameModeMusicID(pMinecraft, i);
// volume change required?
if (m_musicStreamActive)
@ -1449,19 +1460,19 @@ void SoundEngine::playMusicUpdate()
}
if(playerInEnd)
{
m_musicID = getMusicID(eMusicDomain_End);
m_musicID = getMusicID(eMusicType_End);
SetIsPlayingEndMusic(true);
SetIsPlayingNetherMusic(false);
}
else if(playerInNether)
{
m_musicID = getMusicID(eMusicDomain_Nether);
m_musicID = getMusicID(eMusicType_Nether);
SetIsPlayingNetherMusic(true);
SetIsPlayingEndMusic(false);
}
else
{
m_musicID = getMusicID(eMusicDomain_Overworld);
m_musicID = getMusicID(eMusicType_Overworld);
SetIsPlayingNetherMusic(false);
SetIsPlayingEndMusic(false);
}

View file

@ -12,7 +12,7 @@ constexpr float SFX_3D_ROLLOFF = 0.5f;
constexpr float SFX_VOLUME_MULTIPLIER = 1.5f;
constexpr float SFX_MAX_GAIN = 1.5f;
enum eMUSICFILES
enum eMusicFiles
{
eStream_Overworld_Calm1 = 0,
eStream_Overworld_Calm2,
@ -67,35 +67,20 @@ enum eMUSICFILES
eStream_Max,
};
// @3UR: This may not even be an enum—this is mostly guesswork.
// Why? Previously it used LevelData::DIMENSION_XXX enum, and it's unlikely they
// would have extended that with all this additional data.
// It also does not match up in IDA: LevelData::DIMENSION_END is 1,
// but now we see getMusicId(v5, 4); instead of 1.
//
// This suggests they likely introduced an entirely new enum.
//
// Additionally, there was never a case for 3, so it's skipped.
// That might indicate they extended an existing enum, but it's unclear.
enum eMUSICDOMAIN
enum eMusicType
{
eMusicDomain_Nether = 0,
eMusicDomain_Overworld = 1,
eMusicDomain_Menu = 2,
eMusicDomain_End = 4,
eMusicDomain_Creative = 5,
eMusicDomain_Battle = 6,
};
enum eMUSICTYPE
{
eMusicType_None,
eMusicType_Game,
eMusicType_CD,
eMusicType_Nether = 0,
// ???
eMusicType_Menu = 2,
// ???
eMusicType_End = 4,
eMusicType_Creative = 5,
eMusicType_Battle = 6,
eMusicType_Overworld = 7,
};
enum MUSIC_STREAMSTATE
enum eMusicStreamState
{
eMusicStreamState_Idle=0,
eMusicStreamState_Stop,
@ -157,10 +142,11 @@ public:
void addStreaming(const wstring& name, File *file) override;
char *ConvertSoundPathToName(const wstring& name, bool bConvertSpaces=false) override;
bool isStreamingWavebankReady(); // 4J Added
int getMusicID(int iDomain);
int getMusicID(eMusicType iDomain);
int getMusicID(const wstring& name);
void SetStreamingSounds(int iOverworldMin, int iOverWorldMax, int iNetherMin, int iNetherMax, int iEndMin, int iEndMax, int iCreativeMin, int iCreativeMax, int iMenuMin, int iMenuMax, int iBattleMin, int iBattleMax, int iCD1);
void updateMiniAudio();
inline void getGameModeMusicID(Minecraft* pMinecraft, unsigned int i);
void playMusicUpdate();
private:
@ -193,7 +179,6 @@ private:
int m_musicID;
int m_iMusicDelay;
int m_StreamState;
int m_MusicType;
AUDIO_INFO m_StreamingAudioInfo;
wstring m_CDMusic;
BOOL m_bSystemMusicPlaying;

View file

@ -124,8 +124,9 @@ void UIScene_HUD::tick()
return;
}
int idx = BossMobGuiInfo::getIndexFromDimension(pMinecraft->localplayers[m_iPad]->dimension);
// Is boss present?
bool noBoss = BossMobGuiInfo::name.empty() || BossMobGuiInfo::displayTicks <= 0;
bool noBoss = BossMobGuiInfo::name[idx].empty() || BossMobGuiInfo::displayTicks[idx] <= 0;
if (noBoss)
{
if (m_showDragonHealth)
@ -143,14 +144,14 @@ void UIScene_HUD::tick()
}
else
{
BossMobGuiInfo::displayTicks--;
BossMobGuiInfo::displayTicks[idx]--;
m_ticksWithNoBoss = 0;
SetDragonHealth(BossMobGuiInfo::healthProgress);
SetDragonHealth(BossMobGuiInfo::healthProgress[idx]);
if (!m_showDragonHealth)
{
SetDragonLabel(BossMobGuiInfo::name);
SetDragonLabel(BossMobGuiInfo::name[idx]);
ShowDragonHealth(true);
}
}
@ -248,7 +249,15 @@ void UIScene_HUD::handleReload()
m_labelDisplayName.setVisible(m_lastShowDisplayName);
SetDragonLabel(BossMobGuiInfo::name);
Minecraft* pMinecraft = Minecraft::GetInstance();
int idx = 0;
if(pMinecraft->localplayers[m_iPad] != nullptr)
{
idx = BossMobGuiInfo::getIndexFromDimension(pMinecraft->localplayers[m_iPad]->dimension);
}
SetDragonLabel(BossMobGuiInfo::name[idx]);
SetSelectedLabel(L"");
for(unsigned int i = 0; i < CHAT_LINES_COUNT; ++i)
@ -258,7 +267,7 @@ void UIScene_HUD::handleReload()
m_labelJukebox.init(L"");
int iGuiScale;
Minecraft *pMinecraft = Minecraft::GetInstance();
if(pMinecraft->localplayers[m_iPad] == nullptr || pMinecraft->localplayers[m_iPad]->m_iScreenSection == C4JRender::VIEWPORT_TYPE_FULLSCREEN)
{
iGuiScale=app.GetGameSettings(m_iPad,eGameSetting_UISize);

View file

@ -228,14 +228,15 @@ void GameRenderer::tick(bool first) // 4J - add bFirst
PIXEndNamedEvent();
darkenWorldAmountO = darkenWorldAmount;
if (BossMobGuiInfo::darkenWorld)
int idx = BossMobGuiInfo::getIndexFromDimension((int)mc->level->dimension);
if (BossMobGuiInfo::darkenWorld[idx])
{
darkenWorldAmount += 1.0f / (static_cast<float>(SharedConstants::TICKS_PER_SECOND) * 1);
if (darkenWorldAmount > 1)
{
darkenWorldAmount = 1;
}
BossMobGuiInfo::darkenWorld = false;
BossMobGuiInfo::darkenWorld[idx] = false;
}
else if (darkenWorldAmount > 0)
{

View file

@ -6,4 +6,5 @@ public:
virtual float getMaxHealth() = 0;
virtual float getHealth() = 0;
virtual wstring getAName() = 0;
virtual int getDimension() = 0;
};

View file

@ -186,4 +186,5 @@ public:
virtual wstring getAName() { return app.GetString(IDS_ENDERDRAGON); };
virtual float getHealth() { return LivingEntity::getHealth(); };
virtual float getMaxHealth() { return LivingEntity::getMaxHealth(); };
virtual int getDimension() { return Entity::dimension; }
};

View file

@ -106,4 +106,5 @@ public:
virtual float getMaxHealth() { return Monster::getMaxHealth(); };
virtual float getHealth() { return Monster::getHealth(); };
virtual wstring getAName() { return app.GetString(IDS_WITHER); };
virtual int getDimension() { return Entity::dimension; }
};