Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
514420d
custom health bar types
Fryone Sep 25, 2024
35350e4
changed to BarTypes
Fryone Sep 28, 2024
89c0cfb
Update src/Ext/Techno/Body.Visuals.cpp
Fryone Nov 16, 2024
da0e53d
Update src/Ext/Techno/Body.Visuals.cpp
Fryone Nov 16, 2024
df0c9a0
Update src/Ext/Techno/Hooks.Pips.cpp
Fryone Nov 16, 2024
4dd8b34
Update src/Ext/Techno/Hooks.Pips.cpp
Fryone Nov 16, 2024
39b2679
Update src/Ext/Techno/Body.Visuals.cpp
Fryone Nov 16, 2024
6e75804
Update src/New/Type/BarTypeClass.h
Fryone Nov 16, 2024
496f884
Update src/Ext/Techno/Body.Visuals.cpp
Fryone Nov 16, 2024
d41b3c1
Update src/Ext/Techno/Hooks.Pips.cpp
Fryone Nov 16, 2024
1519333
Update src/Ext/Techno/Hooks.Pips.cpp
Fryone Nov 16, 2024
7cd1aae
Update src/Ext/Techno/Hooks.Pips.cpp
Fryone Nov 16, 2024
35111af
Rework 1
Fryone Nov 17, 2024
08d29ff
Merge remote-tracking branch 'upstream/develop' into fryone/healthbar…
Fryone Dec 7, 2024
f169caa
rework update
Fryone Dec 7, 2024
107ec11
Merge remote-tracking branch 'upstream/develop' into fryone/healthbar…
Fryone Apr 19, 2025
b3cf904
Merge remote-tracking branch 'upstream/develop' into fryone/healthbar…
Fryone Jun 23, 2025
aa17db5
latest state
Fryone Jun 23, 2025
b184b9f
Merge remote-tracking branch 'upstream/develop' into fryone/healthbar…
Fryone Nov 24, 2025
1c1b822
update renewed 1
Fryone Nov 24, 2025
d7c6acb
update renewed 1.1
Fryone Nov 24, 2025
dc7ee7a
update renewed 2
Fryone Nov 26, 2025
7a66283
update renewed 3
Fryone Nov 28, 2025
f8ba662
update renewed 4
Fryone Dec 4, 2025
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: 2 additions & 0 deletions Phobos.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
<ClCompile Include="src\New\Type\Affiliated\DroppodTypeClass.cpp" />
<ClCompile Include="src\New\Type\DigitalDisplayTypeClass.cpp" />
<ClCompile Include="src\New\Type\InsigniaTypeClass.cpp" />
<ClCompile Include="src\New\Type\BarTypeClass.cpp" />
<ClCompile Include="src\New\Type\RadTypeClass.cpp" />
<ClCompile Include="src\New\Type\SelectBoxTypeClass.cpp" />
<ClCompile Include="src\New\Type\ShieldTypeClass.cpp" />
Expand Down Expand Up @@ -269,6 +270,7 @@
<ClInclude Include="src\New\Type\Affiliated\DroppodTypeClass.h" />
<ClInclude Include="src\New\Type\DigitalDisplayTypeClass.h" />
<ClInclude Include="src\New\Type\InsigniaTypeClass.h" />
<ClInclude Include="src\New\Type\BarTypeClass.h" />
<ClInclude Include="src\New\Type\RadTypeClass.h" />
<ClInclude Include="src\New\Type\SelectBoxTypeClass.h" />
<ClInclude Include="src\New\Type\ShieldTypeClass.h" />
Expand Down
10 changes: 10 additions & 0 deletions src/Ext/Rules/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <New/Type/BannerTypeClass.h>
#include <New/Type/InsigniaTypeClass.h>
#include <New/Type/SelectBoxTypeClass.h>
#include <New/Type/BarTypeClass.h>
#include <Utilities/Patch.h>

std::unique_ptr<RulesExt::ExtData> RulesExt::Data = nullptr;
Expand Down Expand Up @@ -44,6 +45,7 @@ void RulesExt::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI)
AttachEffectTypeClass::LoadFromINIList(pINI);
BannerTypeClass::LoadFromINIList(pINI);
InsigniaTypeClass::LoadFromINIList(pINI);
BarTypeClass::LoadFromINIList(pINI);

Data->LoadBeforeTypeData(pThis, pINI);
}
Expand Down Expand Up @@ -232,6 +234,10 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI)

this->DefaultInfantrySelectBox.Read(exINI, GameStrings::AudioVisual, "DefaultInfantrySelectBox");
this->DefaultUnitSelectBox.Read(exINI, GameStrings::AudioVisual, "DefaultUnitSelectBox");
this->Buildings_DefaultBarTypes.Read(exINI, GameStrings::AudioVisual, "Buildings.DefaultBarTypes");
this->Infantry_DefaultBarTypes.Read(exINI, GameStrings::AudioVisual, "Infantry.DefaultBarTypes");
this->Vehicles_DefaultBarTypes.Read(exINI, GameStrings::AudioVisual, "Vehicles.DefaultBarTypes");
this->Aircraft_DefaultBarTypes.Read(exINI, GameStrings::AudioVisual, "Aircraft.DefaultBarTypes");

this->JumpjetClimbPredictHeight.Read(exINI, GameStrings::General, "JumpjetClimbPredictHeight");
this->JumpjetClimbWithoutCutOut.Read(exINI, GameStrings::General, "JumpjetClimbWithoutCutOut");
Expand Down Expand Up @@ -527,6 +533,10 @@ void RulesExt::ExtData::Serialize(T& Stm)
.Process(this->Aircraft_DefaultDigitalDisplayTypes)
.Process(this->DefaultInfantrySelectBox)
.Process(this->DefaultUnitSelectBox)
.Process(this->Buildings_DefaultBarTypes)
.Process(this->Infantry_DefaultBarTypes)
.Process(this->Vehicles_DefaultBarTypes)
.Process(this->Aircraft_DefaultBarTypes)
.Process(this->VisualScatter_Min)
.Process(this->VisualScatter_Max)
.Process(this->ShowDesignatorRange)
Expand Down
11 changes: 10 additions & 1 deletion src/Ext/Rules/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class VocClass;
class WarheadTypeClass;
class DigitalDisplayTypeClass;
class SelectBoxTypeClass;
class BarTypeClass;

class RulesExt
{
Expand Down Expand Up @@ -156,6 +157,10 @@ class RulesExt
ValueableVector<DigitalDisplayTypeClass*> Infantry_DefaultDigitalDisplayTypes;
ValueableVector<DigitalDisplayTypeClass*> Vehicles_DefaultDigitalDisplayTypes;
ValueableVector<DigitalDisplayTypeClass*> Aircraft_DefaultDigitalDisplayTypes;
ValueableVector<BarTypeClass*> Buildings_DefaultBarTypes;
ValueableVector<BarTypeClass*> Infantry_DefaultBarTypes;
ValueableVector<BarTypeClass*> Vehicles_DefaultBarTypes;
ValueableVector<BarTypeClass*> Aircraft_DefaultBarTypes;

Valueable<SelectBoxTypeClass*> DefaultInfantrySelectBox;
Valueable<SelectBoxTypeClass*> DefaultUnitSelectBox;
Expand Down Expand Up @@ -284,7 +289,7 @@ class RulesExt
Valueable<bool> AIAirTargetingFix;

Valueable<bool> SortCameoByName;

ExtData(RulesClass* OwnerObject) : Extension<RulesClass>(OwnerObject)
, Storage_TiberiumIndex { -1 }
, HarvesterDumpAmount { 0.0f }
Expand Down Expand Up @@ -410,6 +415,10 @@ class RulesExt
, Infantry_DefaultDigitalDisplayTypes {}
, Vehicles_DefaultDigitalDisplayTypes {}
, Aircraft_DefaultDigitalDisplayTypes {}
, Buildings_DefaultBarTypes {}
, Infantry_DefaultBarTypes {}
, Vehicles_DefaultBarTypes {}
, Aircraft_DefaultBarTypes {}
, DefaultInfantrySelectBox {}
, DefaultUnitSelectBox {}
, VisualScatter_Min { Leptons(8) }
Expand Down
175 changes: 175 additions & 0 deletions src/Ext/Techno/Body.Visuals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,181 @@ void TechnoExt::GetDigitalDisplayFakeHealth(TechnoClass* pThis, int& value, int&
}
}

void TechnoExt::ProcessBars(TechnoClass* pThis, Point2D pLocation, RectangleStruct* pBounds)
{
const auto pType = pThis->GetTechnoType();
const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType());
ValueableVector<BarTypeClass*>* pBarTypes = nullptr;

if (!pTypeExt->BarTypes.empty())
{
pBarTypes = &pTypeExt->BarTypes;
}
else
{
switch (pThis->WhatAmI())
{
case AbstractType::Building:
{
pBarTypes = &RulesExt::Global()->Buildings_DefaultBarTypes;
const auto pBuildingType = static_cast<BuildingTypeClass*>(pType);
pLocation.Y -= (pBuildingType->Height + 1) * Unsorted::CellHeightInPixels / 2;
break;
}
case AbstractType::Infantry:
{
pBarTypes = &RulesExt::Global()->Infantry_DefaultBarTypes;
pLocation.Y -= Unsorted::HealthBarYOffsetInfantry - pType->PixelSelectionBracketDelta;
break;
}
case AbstractType::Unit:
{
pBarTypes = &RulesExt::Global()->Vehicles_DefaultBarTypes;
pLocation.Y -= Unsorted::HealthBarYOffsetOther - pType->PixelSelectionBracketDelta;
break;
}
case AbstractType::Aircraft:
{
pBarTypes = &RulesExt::Global()->Aircraft_DefaultBarTypes;
pLocation.Y -= Unsorted::HealthBarYOffsetOther - pType->PixelSelectionBracketDelta;
break;
}
default:
break;
}
}

if (pBarTypes->empty())
return;

for (BarTypeClass*& pBarType : *pBarTypes)
{
double pConditionYellow = pBarType->Bar_ConditionYellow;
double pConditionRed = pBarType->Bar_ConditionRed;

switch (pBarType->InfoType)
{
case DisplayInfoType::Health:
{
pConditionYellow = pConditionYellow > 0 ? pConditionYellow : RulesClass::Instance->ConditionYellow;
pConditionRed = pConditionRed > 0 ? pConditionRed : RulesClass::Instance->ConditionRed;
break;
}
case DisplayInfoType::Shield:
{
const auto pShield = TechnoExt::ExtMap.Find(pThis)->Shield.get();
const bool hasShield = pShield != nullptr && !pShield->IsBrokenAndNonRespawning();

if (!hasShield)
continue;

pConditionYellow = pConditionYellow > 0 ? pConditionYellow : (pShield->GetType()->ConditionYellow ? pShield->GetType()->ConditionYellow : RulesClass::Instance->ConditionYellow);
pConditionRed = pConditionYellow > 0 ? pConditionYellow : (pShield->GetType()->ConditionRed ? pShield->GetType()->ConditionRed : RulesClass::Instance->ConditionRed);
break;
}
default:
{
break;
}
}

int value = -1;
int maxValue = 0;

GetValuesForDisplay(pThis, pType, pBarType->InfoType, value, maxValue, pBarType->InfoIndex);

if (value <= -1 || maxValue <= 0)
continue;

double pValuePercentage = static_cast<double>(value) / maxValue;
TechnoExt::DrawBar(pThis, pBarType, pLocation, pBounds, pValuePercentage, pConditionYellow, pConditionRed);
}
}

void TechnoExt::DrawBar(TechnoClass* pThis, BarTypeClass* barType, Point2D pLocation, RectangleStruct* pBounds, double barPercentage, double conditionYellow, double conditionRed)
{
const BlitterFlags blitFlagsBG = barType->PipBrd_Background_Translucency.Get(0);
const BlitterFlags blitFlagsFG = barType->PipBrd_Foreground_Translucency.Get(0);
const Point2D sectionOffset = barType->Pips_PositionDelta;
const Vector3D<int> sectionFrames = barType->Pips_Frames;
const int sectionAmount = barType->Pips_Amount;
const int sectionEmptyFrame = barType->Pips_EmptyFrame;
const bool bySection = barType->Pips_ChangePerSection;
const bool drawBackwards = barType->Pips_DrawBackwards;
int sectionsToDraw = (int)round(sectionAmount * barPercentage);
int sign = drawBackwards ? 1 : -1;

if(barType->InfoType == DisplayInfoType::Health)
sectionsToDraw = sectionsToDraw == 0 ? 1 : sectionsToDraw;


pLocation += barType->Bar_Offset;
Point2D boardPosition = pLocation + barType->PipBrd_Offset;

if (barType->PipBrd_Background_File && (pThis->IsSelected || barType->PipBrd_Background_ShowWhenNotSelected))
DSurface::Temp->DrawSHP(FileSystem::PALETTE_PAL, barType->PipBrd_Background_File.Get(),
0, &boardPosition, pBounds, BlitterFlags::Centered | BlitterFlags::bf_400 | BlitterFlags::Alpha | blitFlagsBG, 0, 0, ZGradient::Ground, 1000, 0, 0, 0, 0, 0);

Point2D position = pLocation;
position += {sign * (int)round(sectionAmount * sectionOffset.X / 2), sign * (int)round(sectionAmount * sectionOffset.Y / 2)};

if (sectionEmptyFrame != -1)
{
for (int i = 0; i < sectionAmount; ++i)
{
position -= {sign * sectionOffset.X, sign * sectionOffset.Y};
DSurface::Temp->DrawSHP(FileSystem::PALETTE_PAL, barType->Pips_File.Get(),
sectionEmptyFrame, &position, pBounds, BlitterFlags::Centered | BlitterFlags::bf_400, 0, 0, ZGradient::Ground, 1000, 0, 0, 0, 0, 0);
}

position = pLocation;
position += {sign * (int)round(sectionAmount * sectionOffset.X / 2), sign * (int)round(sectionAmount * sectionOffset.Y / 2)};
}

if (drawBackwards)
{
for (int i = 0; i < (sectionAmount - sectionsToDraw); ++i)
position -= sectionOffset;
}

if(bySection)
barPercentage = 1 - ((int)ceil(sectionAmount * barPercentage) - barPercentage * sectionAmount);

int frameIdxa = sectionFrames.Z;

if (barPercentage > conditionYellow)
frameIdxa = sectionFrames.X;
else if (barPercentage > conditionRed)
frameIdxa = sectionFrames.Y;

if(!bySection)
{
for (int i = 0; i < sectionsToDraw; ++i)
{
position -= {sign * sectionOffset.X, sign * sectionOffset.Y};
DSurface::Temp->DrawSHP(FileSystem::PALETTE_PAL, barType->Pips_File.Get(),
frameIdxa, &position, pBounds, BlitterFlags::Centered | BlitterFlags::bf_400, 0, 0, ZGradient::Ground, 1000, 0, 0, 0, 0, 0);
}
}
else
{
for (int i = 0; i < (sectionsToDraw - 1); ++i)
{
position -= {sign * sectionOffset.X, sign * sectionOffset.Y};
DSurface::Temp->DrawSHP(FileSystem::PALETTE_PAL, barType->Pips_File.Get(),
sectionFrames.X, &position, pBounds, BlitterFlags::Centered | BlitterFlags::bf_400, 0, 0, ZGradient::Ground, 1000, 0, 0, 0, 0, 0);
}

position -= {sign * sectionOffset.X, sign * sectionOffset.Y};
DSurface::Temp->DrawSHP(FileSystem::PALETTE_PAL, barType->Pips_File.Get(),
frameIdxa, &position, pBounds, BlitterFlags::Centered | BlitterFlags::bf_400, 0, 0, ZGradient::Ground, 1000, 0, 0, 0, 0, 0);
}

if (barType->PipBrd_Foreground_File && (pThis->IsSelected || barType->PipBrd_Foreground_ShowWhenNotSelected))
DSurface::Temp->DrawSHP(FileSystem::PALETTE_PAL, barType->PipBrd_Foreground_File.Get(),
0, &boardPosition, pBounds, BlitterFlags::Centered | BlitterFlags::bf_400 | BlitterFlags::Alpha | blitFlagsFG, 0, 0, ZGradient::Ground, 1000, 0, 0, 0, 0, 0);
}

void TechnoExt::ShowPromoteAnim(TechnoClass* pThis)
{
auto const pTypeExt = TechnoExt::ExtMap.Find(pThis)->TypeExtData;
Expand Down
2 changes: 2 additions & 0 deletions src/Ext/Techno/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ class TechnoExt
static void HandleOnDeployAmmoChange(TechnoClass* pThis, int maxAmmoOverride = -1);
static bool SimpleDeployerAllowedToDeploy(UnitClass* pThis, bool defaultValue, bool alwaysCheckLandTypes);
static void ShowPromoteAnim(TechnoClass* pThis);
static void ProcessBars(TechnoClass* pThis, Point2D pLocation, RectangleStruct* pBounds);
static void DrawBar(TechnoClass* pThis, BarTypeClass* barType, Point2D pLocation, RectangleStruct* pBounds, double barPercentage, double conditionYellow, double conditionRed);

// WeaponHelpers.cpp
static int PickWeaponIndex(TechnoClass* pThis, TechnoClass* pTargetTechno, AbstractClass* pTarget, int weaponIndexOne, int weaponIndexTwo, bool allowFallback = true, bool allowAAFallback = true);
Expand Down
12 changes: 8 additions & 4 deletions src/Ext/Techno/Hooks.Pips.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ DEFINE_HOOK(0x6F5E37, TechnoClass_DrawExtras_DrawHealthBar, 0x6)
return 0;
}

DEFINE_HOOK(0x6F64A9, TechnoClass_DrawHealthBar_Hide, 0x5)
/*DEFINE_HOOK(0x6F64A9, TechnoClass_DrawHealthBar_Hide, 0x5) //replaced with new bars
{
enum { SkipDraw = 0x6F6AB6 };

Expand All @@ -50,7 +50,7 @@ DEFINE_HOOK(0x6F64A9, TechnoClass_DrawHealthBar_Hide, 0x5)
return SkipDraw;

return 0;
}
}*/

DEFINE_HOOK(0x6F6637, TechnoClass_DrawHealthBar_HideBuildingsPips, 0x5)
{
Expand Down Expand Up @@ -80,22 +80,25 @@ DEFINE_HOOK(0x6F65D1, TechnoClass_DrawHealthBar_Buildings, 0x6)
GET(BuildingClass*, pThis, ESI);
GET(const int, length, EBX);
GET_STACK(RectangleStruct*, pBound, STACK_OFFSET(0x4C, 0x8));
GET_STACK(Point2D*, pLocation, STACK_OFFSET(0x4C, 0x4));

const auto pExt = TechnoExt::ExtMap.Find(pThis);

if (pThis->IsSelected && Phobos::Config::EnableSelectBox && !pExt->TypeExtData->HideSelectBox)
{
GET_STACK(Point2D*, pLocation, STACK_OFFSET(0x4C, 0x4));
UNREFERENCED_PARAMETER(pLocation); // choom thought he was clever and recomputed the same shit again and again
TechnoExt::DrawSelectBox(pThis, pLocation, pBound);
}

if (const auto pShieldData = pExt->Shield.get())
{
if (pShieldData->IsAvailable() && !pShieldData->IsBrokenAndNonRespawning())
{
pShieldData->DrawShieldBar_Building(length, pBound);
}
}

TechnoExt::ProcessBars(pThis, *pLocation, pBound);
TechnoExt::ProcessDigitalDisplays(pThis);

return 0;
Expand All @@ -121,11 +124,12 @@ DEFINE_HOOK(0x6F683C, TechnoClass_DrawHealthBar_Units, 0x7)
{
if (pShieldData->IsAvailable() && !pShieldData->IsBrokenAndNonRespawning())
{
const int length = pThis->WhatAmI() == AbstractType::Infantry ? 8 : 17;
const int length = pThis->WhatAmI() == AbstractType::Infantry ? Unsorted::HealthBarSectionsInfantry : Unsorted::HealthBarSectionsOther;
pShieldData->DrawShieldBar_Other(length, pBound);
}
}

TechnoExt::ProcessBars(pThis, *pLocation, pBound);
TechnoExt::ProcessDigitalDisplays(pThis);

if (pExt->TypeExtData->HealthBar_HidePips)
Expand Down
5 changes: 4 additions & 1 deletion src/Ext/TechnoType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,8 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->AttackMove_PursuitTarget.Read(exINI, pSection, "AttackMove.PursuitTarget");

this->InfantryAutoDeploy.Read(exINI, pSection, "InfantryAutoDeploy");

this->BarTypes.Read(exINI, pSection, "BarTypes");

// Ares 0.2
this->RadarJamRadius.Read(exINI, pSection, "RadarJamRadius");

Expand Down Expand Up @@ -1668,6 +1669,8 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm)
.Process(this->InfantryAutoDeploy)

.Process(this->TurretResponse)

.Process(this->BarTypes)
;
}
void TechnoTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm)
Expand Down
4 changes: 4 additions & 0 deletions src/Ext/TechnoType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <New/Type/Affiliated/DroppodTypeClass.h>
#include <New/Type/Affiliated/TiberiumEaterTypeClass.h>
#include <New/Type/Affiliated/CreateUnitTypeClass.h>
#include <New/Type/BarTypeClass.h>

class Matrix3D;
class ParticleSystemTypeClass;
Expand Down Expand Up @@ -360,6 +361,7 @@ class TechnoTypeExt

ValueableVector<AnimTypeClass*> Promote_VeteranAnimation;
ValueableVector<AnimTypeClass*> Promote_EliteAnimation;
ValueableVector<BarTypeClass*> BarTypes;

Nullable<AffectedHouse> RadarInvisibleToHouse;

Expand Down Expand Up @@ -826,6 +828,8 @@ class TechnoTypeExt
, InfantryAutoDeploy {}

, TurretResponse {}

, BarTypes { }
{ }

virtual ~ExtData() = default;
Expand Down
Loading
Loading