diff --git a/YRpp b/YRpp index d107962d13..b08060737e 160000 --- a/YRpp +++ b/YRpp @@ -1 +1 @@ -Subproject commit d107962d130d898132c182540a2c218f23548b2f +Subproject commit b08060737e9358f9660d3435888b61066fe62aa2 diff --git a/src/Ext/Anim/Body.cpp b/src/Ext/Anim/Body.cpp index 9fb253a058..e46aa215d5 100644 --- a/src/Ext/Anim/Body.cpp +++ b/src/Ext/Anim/Body.cpp @@ -189,6 +189,43 @@ void AnimExt::HandleDebrisImpact(AnimTypeClass* pExpireAnim, AnimTypeClass* pWak } } +AnimClass* AnimExt::CreateRandomAnim(std::vector AnimList, CoordStruct coords, TechnoClass* pTechno, HouseClass* pHouse, bool invoker) +{ + if (!AnimList.empty()) + { + if (auto const pAnimType = AnimList[ScenarioClass::Instance->Random.RandomRanged(0, AnimList.size() - 1)]) + { + if (auto const pAnim = GameCreate(pAnimType, coords)) + { + if (pTechno) + { + pAnim->SetOwnerObject(pTechno); + pAnim->Owner = pHouse ? pHouse : pTechno->Owner; + + if (invoker) + { + if (auto const pAnimExt = AnimExt::ExtMap.Find(pAnim)) + { + if (pHouse) + pAnimExt->SetInvoker(pTechno, pHouse); + else + pAnimExt->SetInvoker(pTechno); + } + } + } + else if (pHouse) + { + pAnim->Owner = pHouse; + } + + return pAnim; + } + } + } + + return nullptr; +} + // ============================= // load / save diff --git a/src/Ext/Anim/Body.h b/src/Ext/Anim/Body.h index 975779040e..70b52cc3e3 100644 --- a/src/Ext/Anim/Body.h +++ b/src/Ext/Anim/Body.h @@ -80,4 +80,6 @@ class AnimExt static void InvalidateTechnoPointers(TechnoClass* pTechno); static void InvalidateParticleSystemPointers(ParticleSystemClass* pParticleSystem); + + static AnimClass* CreateRandomAnim(std::vector AnimList, CoordStruct coords, TechnoClass* pTechno = nullptr, HouseClass* pHouse = nullptr, bool invoker = false); }; diff --git a/src/Ext/Anim/Hooks.AnimCreateUnit.cpp b/src/Ext/Anim/Hooks.AnimCreateUnit.cpp index 3621b45a21..80b74ca4cf 100644 --- a/src/Ext/Anim/Hooks.AnimCreateUnit.cpp +++ b/src/Ext/Anim/Hooks.AnimCreateUnit.cpp @@ -144,19 +144,8 @@ DEFINE_HOOK(0x424932, AnimClass_AI_CreateUnit_ActualAffects, 0x6) if (success) { - if (!pTypeExt->CreateUnit_SpawnAnim.empty()) - { - if (auto const pAnimType = pTypeExt->CreateUnit_SpawnAnim[ScenarioClass::Instance->Random.RandomRanged(0, pTypeExt->CreateUnit_SpawnAnim.size() - 1)]) - { - if (auto const pAnim = GameCreate(pAnimType, location)) - { - AnimExt::SetAnimOwnerHouseKind(pAnim, pInvokerHouse, nullptr, false, true); - - if (auto const pAnimExt = AnimExt::ExtMap.Find(pAnim)) - pAnimExt->SetInvoker(pInvoker, pInvokerHouse); - } - } - } + if (auto const pAnim = AnimExt::CreateRandomAnim(pTypeExt->CreateUnit_SpawnAnim, location, pInvoker, pInvokerHouse, true)) + AnimExt::SetAnimOwnerHouseKind(pAnim, pInvokerHouse, nullptr, false, true); if (pTechno->HasTurret() && pExt->FromDeathUnit && pExt->DeathUnitHasTurret && pTypeExt->CreateUnit_InheritTurretFacings) { diff --git a/src/Ext/Techno/Body.Update.cpp b/src/Ext/Techno/Body.Update.cpp index 3af7a942d4..69c8f3376f 100644 --- a/src/Ext/Techno/Body.Update.cpp +++ b/src/Ext/Techno/Body.Update.cpp @@ -136,15 +136,11 @@ bool TechnoExt::ExtData::CheckDeathConditions(bool isInLimbo) // Self-destruction must be enabled const auto howToDie = pTypeExt->AutoDeath_Behavior.Get(); - AnimTypeClass* pVanishAnim = nullptr; - - if (!pTypeExt->AutoDeath_VanishAnimation.empty()) - pVanishAnim = pTypeExt->AutoDeath_VanishAnimation[ScenarioClass::Instance->Random.RandomRanged(0, pTypeExt->AutoDeath_VanishAnimation.size() - 1)]; // Death if no ammo if (pType->Ammo > 0 && pThis->Ammo <= 0 && pTypeExt->AutoDeath_OnAmmoDepletion) { - TechnoExt::KillSelf(pThis, howToDie, pVanishAnim, isInLimbo); + TechnoExt::KillSelf(pThis, howToDie, pTypeExt->AutoDeath_VanishAnimation, isInLimbo); return true; } @@ -157,7 +153,7 @@ bool TechnoExt::ExtData::CheckDeathConditions(bool isInLimbo) } else if (this->AutoDeathTimer.Completed()) { - TechnoExt::KillSelf(pThis, howToDie, pVanishAnim, isInLimbo); + TechnoExt::KillSelf(pThis, howToDie, pTypeExt->AutoDeath_VanishAnimation, isInLimbo); return true; } } @@ -186,7 +182,7 @@ bool TechnoExt::ExtData::CheckDeathConditions(bool isInLimbo) { if (!existTechnoTypes(pTypeExt->AutoDeath_TechnosDontExist, pTypeExt->AutoDeath_TechnosDontExist_Houses, !pTypeExt->AutoDeath_TechnosDontExist_Any, pTypeExt->AutoDeath_TechnosDontExist_AllowLimboed)) { - TechnoExt::KillSelf(pThis, howToDie, pVanishAnim, isInLimbo); + TechnoExt::KillSelf(pThis, howToDie, pTypeExt->AutoDeath_VanishAnimation, isInLimbo); return true; } @@ -197,7 +193,7 @@ bool TechnoExt::ExtData::CheckDeathConditions(bool isInLimbo) { if (existTechnoTypes(pTypeExt->AutoDeath_TechnosExist, pTypeExt->AutoDeath_TechnosExist_Houses, pTypeExt->AutoDeath_TechnosExist_Any, pTypeExt->AutoDeath_TechnosExist_AllowLimboed)) { - TechnoExt::KillSelf(pThis, howToDie, pVanishAnim, isInLimbo); + TechnoExt::KillSelf(pThis, howToDie, pTypeExt->AutoDeath_VanishAnimation, isInLimbo); return true; } @@ -286,17 +282,7 @@ void TechnoExt::ExtData::EatPassengers() if (pDelType->ReportSound >= 0) VocClass::PlayAt(pDelType->ReportSound.Get(), pThis->GetCoords(), nullptr); - if (!pDelType->Anim.empty()) - { - if (auto const pAnimType = pDelType->Anim[ScenarioClass::Instance->Random.RandomRanged(0, pDelType->Anim.size() - 1)]) - { - if (auto const pAnim = GameCreate(pAnimType, pThis->Location)) - { - pAnim->SetOwnerObject(pThis); - pAnim->Owner = pThis->Owner; - } - } - } + AnimExt::CreateRandomAnim(pDelType->Anim, pThis->Location, pThis); // Check if there is money refund if (pDelType->Soylent && @@ -694,7 +680,7 @@ void TechnoExt::ApplyMindControlRangeLimit(TechnoClass* pThis) } } -void TechnoExt::KillSelf(TechnoClass* pThis, AutoDeathBehavior deathOption, AnimTypeClass* pVanishAnimation, bool isInLimbo) +void TechnoExt::KillSelf(TechnoClass* pThis, AutoDeathBehavior deathOption, std::vector pVanishAnimation, bool isInLimbo) { if (isInLimbo) { @@ -715,15 +701,7 @@ void TechnoExt::KillSelf(TechnoClass* pThis, AutoDeathBehavior deathOption, Anim case AutoDeathBehavior::Vanish: { - if (pVanishAnimation) - { - if (auto const pAnim = GameCreate(pVanishAnimation, pThis->GetCoords())) - { - auto const pAnimExt = AnimExt::ExtMap.Find(pAnim); - pAnim->Owner = pThis->Owner; - pAnimExt->SetInvoker(pThis); - } - } + AnimExt::CreateRandomAnim(pVanishAnimation, pThis->GetCoords(), pThis, nullptr, true); pThis->KillPassengers(pThis); pThis->Stun(); diff --git a/src/Ext/Techno/Body.h b/src/Ext/Techno/Body.h index 0a90b4f688..99fcb80661 100644 --- a/src/Ext/Techno/Body.h +++ b/src/Ext/Techno/Body.h @@ -143,7 +143,7 @@ class TechnoExt static CoordStruct GetSimpleFLH(InfantryClass* pThis, int weaponIndex, bool& FLHFound); static void ChangeOwnerMissionFix(FootClass* pThis); - static void KillSelf(TechnoClass* pThis, AutoDeathBehavior deathOption, AnimTypeClass* pVanishAnimation, bool isInLimbo = false); + static void KillSelf(TechnoClass* pThis, AutoDeathBehavior deathOption, std::vector pVanishAnimation, bool isInLimbo = false); static void TransferMindControlOnDeploy(TechnoClass* pTechnoFrom, TechnoClass* pTechnoTo); static void ApplyMindControlRangeLimit(TechnoClass* pThis); static void ObjectKilledBy(TechnoClass* pThis, TechnoClass* pKiller); diff --git a/src/Ext/TerrainType/Body.cpp b/src/Ext/TerrainType/Body.cpp index 077259c65b..d20c88e331 100644 --- a/src/Ext/TerrainType/Body.cpp +++ b/src/Ext/TerrainType/Body.cpp @@ -23,12 +23,7 @@ int TerrainTypeExt::ExtData::GetCellsPerAnim() void TerrainTypeExt::ExtData::PlayDestroyEffects(const CoordStruct& coords) { VocClass::PlayIndexAtPos(this->DestroySound, coords); - - if (!this->DestroyAnim.empty()) - { - if (auto const pAnimType = this->DestroyAnim[ScenarioClass::Instance->Random.RandomRanged(0, this->DestroyAnim.size() - 1)]) - GameCreate(pAnimType, coords); - } + AnimExt::CreateRandomAnim(this->DestroyAnim, coords); } void TerrainTypeExt::Remove(TerrainClass* pTerrain) diff --git a/src/Ext/WarheadType/Detonate.cpp b/src/Ext/WarheadType/Detonate.cpp index 00f57ceab9..356e1426a1 100644 --- a/src/Ext/WarheadType/Detonate.cpp +++ b/src/Ext/WarheadType/Detonate.cpp @@ -253,14 +253,7 @@ void WarheadTypeExt::ExtData::ApplyShieldModifiers(TechnoClass* pTarget, TechnoE }; if (this->Shield_Break && pTargetExt->Shield->IsActive() && isShieldTypeEligible(this->Shield_Break_Types.GetElements(this->Shield_AffectTypes))) - { - AnimTypeClass* pAnimType = nullptr; - - if (!this->Shield_BreakAnim.empty()) - pAnimType = this->Shield_BreakAnim[ScenarioClass::Instance->Random.RandomRanged(0, this->Shield_BreakAnim.size() - 1)]; - - pTargetExt->Shield->BreakShield(pAnimType, this->Shield_BreakWeapon); - } + pTargetExt->Shield->BreakShield(this->Shield_BreakAnim, this->Shield_BreakWeapon); if (this->Shield_Respawn_Duration > 0 && isShieldTypeEligible(this->Shield_Respawn_Types.GetElements(this->Shield_AffectTypes))) { diff --git a/src/New/Entity/ShieldClass.cpp b/src/New/Entity/ShieldClass.cpp index 13be87dc94..8d19e92b54 100644 --- a/src/New/Entity/ShieldClass.cpp +++ b/src/New/Entity/ShieldClass.cpp @@ -231,12 +231,7 @@ int ShieldClass::ReceiveDamage(args_ReceiveDamage* args) int actualResidueDamage = Math::max(0, int((double)(originalShieldDamage - this->HP) / GeneralUtils::GetWarheadVersusArmor(args->WH, this->GetArmorType()))); //only absord percentage damage - AnimTypeClass* pAnimType = nullptr; - - if (!pWHExt->Shield_BreakAnim.empty()) - pAnimType = pWHExt->Shield_BreakAnim[ScenarioClass::Instance->Random.RandomRanged(0, pWHExt->Shield_BreakAnim.size() - 1)]; - - this->BreakShield(pAnimType, pWHExt->Shield_BreakWeapon.Get(nullptr)); + this->BreakShield(pWHExt->Shield_BreakAnim, pWHExt->Shield_BreakWeapon.Get(nullptr)); return this->Type->AbsorbOverDamage ? healthDamage : actualResidueDamage + healthDamage; } @@ -265,14 +260,7 @@ int ShieldClass::ReceiveDamage(args_ReceiveDamage* args) } if (!pWHExt->Shield_SkipHitAnim) - { - AnimTypeClass* pAnimType = nullptr; - - if (!pWHExt->Shield_HitAnim.empty()) - pAnimType = pWHExt->Shield_HitAnim[ScenarioClass::Instance->Random.RandomRanged(0, pWHExt->Shield_HitAnim.size() - 1)]; - - this->WeaponNullifyAnim(pAnimType); - } + this->WeaponNullifyAnim(pWHExt->Shield_HitAnim); this->HP = -residueDamage; @@ -331,16 +319,15 @@ void ShieldClass::ResponseAttack() } } -void ShieldClass::WeaponNullifyAnim(AnimTypeClass* pHitAnim) +void ShieldClass::WeaponNullifyAnim(std::vector pHitAnim) { if (this->AreAnimsHidden) return; - if (!pHitAnim && !this->Type->HitAnim.empty()) - pHitAnim = this->Type->HitAnim[ScenarioClass::Instance->Random.RandomRanged(0, this->Type->HitAnim.size() - 1)]; + if (pHitAnim.empty()) + pHitAnim = this->Type->HitAnim; - if (pHitAnim) - GameCreate(pHitAnim, this->Techno->GetCoords()); + AnimExt::CreateRandomAnim(pDelType->Anim, this->Techno->GetCoords(), this->Techno); } bool ShieldClass::CanBeTargeted(WeaponTypeClass* pWeapon) const @@ -664,7 +651,8 @@ void ShieldClass::SelfHealing() } else if (this->HP <= 0) { - this->BreakShield(); + std::vector nothing; + this->BreakShield(nothing); } } } @@ -681,7 +669,7 @@ int ShieldClass::GetPercentageAmount(double iStatus) return (int)trunc(iStatus); } -void ShieldClass::BreakShield(AnimTypeClass* pBreakAnim, WeaponTypeClass* pBreakWeapon) +void ShieldClass::BreakShield(std::vector pBreakAnim, WeaponTypeClass* pBreakWeapon) { this->HP = 0; @@ -693,17 +681,10 @@ void ShieldClass::BreakShield(AnimTypeClass* pBreakAnim, WeaponTypeClass* pBreak if (!this->AreAnimsHidden) { - if (!pBreakAnim && !this->Type->BreakAnim.empty()) - pBreakAnim = this->Type->BreakAnim[ScenarioClass::Instance->Random.RandomRanged(0, this->Type->BreakAnim.size() - 1)]; + if (!pBreakAnim.empty()) + pBreakAnim = this->Type->BreakAnim; - if (pBreakAnim) - { - if (auto const pAnim = GameCreate(pBreakAnim, this->Techno->Location)) - { - pAnim->SetOwnerObject(this->Techno); - pAnim->Owner = this->Techno->Owner; - } - } + AnimExt::CreateRandomAnim(pBreakAnim, this->Techno->Location, this->Techno); } const auto pWeaponType = pBreakWeapon ? pBreakWeapon : this->Type->BreakWeapon; diff --git a/src/New/Entity/ShieldClass.h b/src/New/Entity/ShieldClass.h index 74ab5bea2e..c18a765318 100644 --- a/src/New/Entity/ShieldClass.h +++ b/src/New/Entity/ShieldClass.h @@ -20,7 +20,7 @@ class ShieldClass int ReceiveDamage(args_ReceiveDamage* args); bool CanBeTargeted(WeaponTypeClass* pWeapon) const; bool CanBePenetrated(WarheadTypeClass* pWarhead) const; - void BreakShield(AnimTypeClass* pBreakAnim = nullptr, WeaponTypeClass* pBreakWeapon = nullptr); + void BreakShield(std::vector pBreakAnim, WeaponTypeClass* pBreakWeapon = nullptr); void SetRespawn(int duration, double amount, int rate, bool resetTimer); void SetSelfHealing(int duration, double amount, int rate, bool restartInCombat, int restartInCombatDelay, bool resetTimer); @@ -67,7 +67,7 @@ class ShieldClass void UpdateIdleAnim(); AnimTypeClass* GetIdleAnimType(); - void WeaponNullifyAnim(AnimTypeClass* pHitAnim = nullptr); + void WeaponNullifyAnim(std::vector pHitAnim); void ResponseAttack(); void CloakCheck();