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

Damaged Unit image #1446

Open
wants to merge 2 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
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ This page lists all the individual contributions to the project by their author.
- Auto-deploy/Deploy block on ammo change
- Flashing Technos on selecting
- Promotion animation
- Damaged unit image changes
- **ZivDero**
- Re-enable the Veinhole Monster and Weeds from TS
- Recreate the weed-charging of SWs like the TS Chemical Missile
Expand Down
18 changes: 18 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,24 @@ Convert.HumanToComputer = ; TechnoType
Convert.ComputerToHuman = ; TechnoType
```

### Damaged unit image changes

- When a unit is damaged (health points percentage is lower than `ConditionYellow` percentage), it now may use different image set by `DamagedImage.ConditionYellow` UnitType. Similar, `DamagedImage.ConditionRed` is used as image if unit health points percentage is lower than `ConditionRed` percentage.
- It is also works on water by setting `WaterDamagedImage.ConditionYellow` and `WaterDamagedImage.ConditionRed` UnitType, similar to Ares' `WaterImage`.

In `rulesmd.ini`:
```ini
[SOMEUNIT] ; UnitType
DamagedImage.ConditionYellow= ; UnitType entry
DamagedImage.ConditionRed= ; UnitType entry
WaterDamagedImage.ConditionYellow= ; UnitType entry
WaterDamagedImage.ConditionRed= ; UnitType entry
```

```{warning}
Note that the UnitTypes had to be defined under [VehicleTypes] and use same image type (SHP/VXL) for vanilla/damaged states.
```

## Terrain

### Destroy animation & sound
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ New:
- `<Player @ X>` can now be used as owner for pre-placed objects on skirmish and multiplayer maps (by Starkku)
- Allow customizing charge turret delays per burst on a weapon (by Starkku)
- Unit `Speed` setting now accepts floating point values (by Starkku)
- Damaged unit image changes (by Fryone)

Vanilla fixes:
- Allow AI to repair structures built from base nodes/trigger action 125/SW delivery in single player missions (by Trsdy)
Expand Down
14 changes: 14 additions & 0 deletions src/Ext/Techno/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,20 @@ int TechnoExt::ExtData::GetAttachedEffectCumulativeCount(AttachEffectTypeClass*
return foundCount;
}

UnitTypeClass* TechnoExt::ExtData::GetUnitTypeExtra(bool isRedHP) const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you should move the health checks into the extra function. Thus others can reuse this function if they want to further expand the image.

if (auto pUnit = abstract_cast<UnitClass*>(this->OwnerObject()))
{
auto pData = TechnoTypeExt::ExtMap.Find(pUnit->Type);

if (!pUnit->OnBridge && pUnit->GetCell()->LandType == LandType::Water && (pData->WaterDamagedImage_ConditionRed || pData->WaterDamagedImage_ConditionYellow))
return (isRedHP && pData->WaterDamagedImage_ConditionRed) ? pData->WaterDamagedImage_ConditionRed : pData->WaterDamagedImage_ConditionYellow;
else if (pData->DamagedImage_ConditionRed || pData->DamagedImage_ConditionYellow)
return (isRedHP && pData->DamagedImage_ConditionRed) ? pData->DamagedImage_ConditionRed : pData->DamagedImage_ConditionYellow;

}
return nullptr;
}

// =============================
// load / save

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 @@ -116,6 +116,8 @@ class TechnoExt
bool HasAttachedEffects(std::vector<AttachEffectTypeClass*> attachEffectTypes, bool requireAll, bool ignoreSameSource, TechnoClass* pInvoker, AbstractClass* pSource, std::vector<int> const* minCounts, std::vector<int> const* maxCounts) const;
int GetAttachedEffectCumulativeCount(AttachEffectTypeClass* pAttachEffectType, bool ignoreSameSource = false, TechnoClass* pInvoker = nullptr, AbstractClass* pSource = nullptr) const;

UnitTypeClass* GetUnitTypeExtra(bool isRedHP) const;

virtual ~ExtData() override;
virtual void InvalidatePointer(void* ptr, bool bRemoved) override { }
virtual void LoadFromStream(PhobosStreamReader& Stm) override;
Expand Down
40 changes: 40 additions & 0 deletions src/Ext/Techno/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -543,3 +543,43 @@ DEFINE_HOOK(0x70EFE0, TechnoClass_GetMaxSpeed, 0x6)
return SkipGameCode;
}

DEFINE_HOOK(0x73B4DA, UnitClass_DrawVXL_WaterType_Extra, 0x6)
{
enum { Continue = 0x73B4E0 };

GET(UnitClass*, pThis, EBP);
TechnoExt::ExtData *pData = TechnoExt::ExtMap.Find(pThis);

if (pThis->IsClearlyVisibleTo(HouseClass::CurrentPlayer) && !pThis->Deployed && (pThis->IsYellowHP() || pThis->IsRedHP()))
{
if (UnitTypeClass* pCustomType = pData->GetUnitTypeExtra(pThis->IsRedHP()))
{
ObjectTypeClass* Image = pCustomType;
R->EBX<ObjectTypeClass *>(Image);
}
}

R->EAX(pThis->WalkedFramesSoFar);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just return 0 and the overlapped assembly will be recovered. As far as I know, you only need to restore the assembly manually if you overlapped some jump code, like jz or jmp.

return Continue;
}

DEFINE_HOOK(0x73C602, UnitClass_DrawSHP_WaterType_Extra, 0x6)
{
enum { Continue = 0x73C608 };

GET(UnitClass*, pThis, EBP);
TechnoExt::ExtData *pData = TechnoExt::ExtMap.Find(pThis);

if(pThis->IsYellowHP() || pThis->IsRedHP())
{
if(UnitTypeClass* pCustomType = pData->GetUnitTypeExtra(pThis->IsRedHP()))
{
SHPStruct* Image = pCustomType->GetImage();
if(Image)
R->EAX<SHPStruct *>(Image);
}
}

R->ECX(pThis->GetType());
return Continue;
}
10 changes: 10 additions & 0 deletions src/Ext/TechnoType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,11 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->Wake_Grapple.Read(exINI, pSection, "Wake.Grapple");
this->Wake_Sinking.Read(exINI, pSection, "Wake.Sinking");

this->DamagedImage_ConditionYellow.Read(exINI, pSection, "DamagedImage.ConditionYellow");
this->DamagedImage_ConditionRed.Read(exINI, pSection, "DamagedImage.ConditionRed");
this->WaterDamagedImage_ConditionYellow.Read(exINI, pSection, "WaterDamagedImage.ConditionYellow");
this->WaterDamagedImage_ConditionRed.Read(exINI, pSection, "WaterDamagedImage.ConditionRed");

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

Expand Down Expand Up @@ -828,6 +833,11 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm)
.Process(this->Wake)
.Process(this->Wake_Grapple)
.Process(this->Wake_Sinking)

.Process(this->DamagedImage_ConditionYellow)
.Process(this->DamagedImage_ConditionRed)
.Process(this->WaterDamagedImage_ConditionYellow)
.Process(this->WaterDamagedImage_ConditionRed)
;
}
void TechnoTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm)
Expand Down
10 changes: 10 additions & 0 deletions src/Ext/TechnoType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,11 @@ class TechnoTypeExt
Nullable<AnimTypeClass*> Wake_Grapple;
Nullable<AnimTypeClass*> Wake_Sinking;

Nullable<UnitTypeClass*> DamagedImage_ConditionYellow;
Nullable<UnitTypeClass*> DamagedImage_ConditionRed;
Nullable<UnitTypeClass*> WaterDamagedImage_ConditionYellow;
Nullable<UnitTypeClass*> WaterDamagedImage_ConditionRed;

struct LaserTrailDataEntry
{
ValueableIdx<LaserTrailTypeClass> idxType;
Expand Down Expand Up @@ -452,6 +457,11 @@ class TechnoTypeExt
, Wake { }
, Wake_Grapple { }
, Wake_Sinking { }

, DamagedImage_ConditionYellow { }
, DamagedImage_ConditionRed { }
, WaterDamagedImage_ConditionYellow { }
, WaterDamagedImage_ConditionRed { }
{ }

virtual ~ExtData() = default;
Expand Down
Loading