@@ -51,8 +51,8 @@ DEFINE_HOOK(0x6F33CD, TechnoClass_WhatWeaponShouldIUse_ForceFire, 0x6)
51
51
auto const pWeaponSecondary = pThis->GetWeapon (1 )->WeaponType ;
52
52
auto const pPrimaryExt = WeaponTypeExt::ExtMap.Find (pWeaponPrimary);
53
53
54
- if (pWeaponSecondary && (!EnumFunctions::IsCellEligible (pCell, pPrimaryExt->CanTarget , true , true )
55
- || (pPrimaryExt->AttachEffect_CheckOnFirer && !pPrimaryExt->HasRequiredAttachedEffects (pThis, pThis))))
54
+ if (pWeaponSecondary && !pPrimaryExt-> SkipWeaponPicking && (!EnumFunctions::IsCellEligible (pCell, pPrimaryExt->CanTarget , true , true )
55
+ || !pPrimaryExt-> IsHealthRatioEligible (pThis) || (pPrimaryExt->AttachEffect_CheckOnFirer && !pPrimaryExt->HasRequiredAttachedEffects (pThis, pThis))))
56
56
{
57
57
R->EAX (1 );
58
58
return ReturnWeaponIndex;
@@ -83,6 +83,7 @@ DEFINE_HOOK(0x6F3428, TechnoClass_WhatWeaponShouldIUse_ForceWeapon, 0x6)
83
83
84
84
// Force weapon
85
85
const int forceWeaponIndex = pTypeExt->SelectForceWeapon (pThis, pTarget);
86
+
86
87
if (forceWeaponIndex >= 0 )
87
88
{
88
89
R->EAX (forceWeaponIndex);
@@ -101,9 +102,9 @@ DEFINE_HOOK(0x6F36DB, TechnoClass_WhatWeaponShouldIUse, 0x8)
101
102
102
103
const auto pTargetTechno = abstract_cast<TechnoClass*>(pTarget);
103
104
const auto pTypeExt = TechnoTypeExt::ExtMap.Find (pThis->GetTechnoType ());
104
- bool allowFallback = !pTypeExt->NoSecondaryWeaponFallback ;
105
- bool allowAAFallback = allowFallback ? true : pTypeExt->NoSecondaryWeaponFallback_AllowAA ;
106
- int weaponIndex = TechnoExt::PickWeaponIndex (pThis, pTargetTechno, pTarget, 0 , 1 , allowFallback, allowAAFallback);
105
+ const bool allowFallback = !pTypeExt->NoSecondaryWeaponFallback ;
106
+ const bool allowAAFallback = allowFallback ? true : pTypeExt->NoSecondaryWeaponFallback_AllowAA ;
107
+ const int weaponIndex = TechnoExt::PickWeaponIndex (pThis, pTargetTechno, pTarget, 0 , 1 , allowFallback, allowAAFallback);
107
108
108
109
if (weaponIndex != -1 )
109
110
return weaponIndex == 1 ? Secondary : Primary;
@@ -117,8 +118,8 @@ DEFINE_HOOK(0x6F36DB, TechnoClass_WhatWeaponShouldIUse, 0x8)
117
118
{
118
119
if (pShield->IsActive ())
119
120
{
120
- auto const secondary = pThis->GetWeapon (1 )->WeaponType ;
121
- bool secondaryIsAA = pTargetTechno && pTargetTechno->IsInAir () && secondary && secondary->Projectile ->AA ;
121
+ const auto secondary = pThis->GetWeapon (1 )->WeaponType ;
122
+ const bool secondaryIsAA = pTargetTechno && pTargetTechno->IsInAir () && secondary && secondary->Projectile ->AA ;
122
123
123
124
if (secondary && (allowFallback || (allowAAFallback && secondaryIsAA) || TechnoExt::CanFireNoAmmoWeapon (pThis, 1 )))
124
125
{
@@ -162,10 +163,10 @@ DEFINE_HOOK(0x6F3432, TechnoClass_WhatWeaponShouldIUse_Gattling, 0xA)
162
163
GET_STACK (AbstractClass*, pTarget, STACK_OFFSET (0x18 , 0x4 ));
163
164
164
165
auto const pTargetTechno = abstract_cast<TechnoClass*>(pTarget);
165
- int oddWeaponIndex = 2 * pThis->CurrentGattlingStage ;
166
- int evenWeaponIndex = oddWeaponIndex + 1 ;
166
+ const int oddWeaponIndex = 2 * pThis->CurrentGattlingStage ;
167
+ const int evenWeaponIndex = oddWeaponIndex + 1 ;
167
168
int chosenWeaponIndex = oddWeaponIndex;
168
- int eligibleWeaponIndex = TechnoExt::PickWeaponIndex (pThis, pTargetTechno, pTarget, oddWeaponIndex, evenWeaponIndex, true );
169
+ const int eligibleWeaponIndex = TechnoExt::PickWeaponIndex (pThis, pTargetTechno, pTarget, oddWeaponIndex, evenWeaponIndex, true );
169
170
170
171
if (eligibleWeaponIndex != -1 )
171
172
{
@@ -196,7 +197,7 @@ DEFINE_HOOK(0x6F3432, TechnoClass_WhatWeaponShouldIUse_Gattling, 0xA)
196
197
else
197
198
{
198
199
auto const landType = pTargetTechno->GetCell ()->LandType ;
199
- bool isOnWater = (landType == LandType::Water || landType == LandType::Beach) && !pTargetTechno->IsInAir ();
200
+ const bool isOnWater = (landType == LandType::Water || landType == LandType::Beach) && !pTargetTechno->IsInAir ();
200
201
201
202
if (!pTargetTechno->OnBridge && isOnWater)
202
203
{
@@ -255,59 +256,62 @@ DEFINE_HOOK(0x6FC339, TechnoClass_CanFire, 0x6)
255
256
return CannotFire;
256
257
}
257
258
258
- if (const auto pWeaponExt = WeaponTypeExt::ExtMap.Find (pWeapon))
259
+ // AAOnly doesn't need to be checked if LandTargeting=1.
260
+ if (pThis->GetTechnoType ()->LandTargeting != LandTargetingType::Land_Not_OK && pWeapon->Projectile ->AA && pTarget && !pTarget->IsInAir ())
259
261
{
260
- const auto pTechno = abstract_cast<TechnoClass*>(pTarget);
261
- CellClass* pTargetCell = nullptr ;
262
+ const auto pBulletTypeExt = BulletTypeExt::ExtMap.Find (pWeapon->Projectile );
262
263
263
- // AAOnly doesn't need to be checked if LandTargeting=1.
264
- if (pThis->GetTechnoType ()->LandTargeting != LandTargetingType::Land_Not_OK && pWeapon->Projectile ->AA && pTarget && !pTarget->IsInAir ())
265
- {
266
- auto const pBulletTypeExt = BulletTypeExt::ExtMap.Find (pWeapon->Projectile );
264
+ if (pBulletTypeExt->AAOnly )
265
+ return CannotFire;
266
+ }
267
267
268
- if (pBulletTypeExt->AAOnly )
269
- return CannotFire;
270
- }
268
+ const auto pTechno = abstract_cast<TechnoClass*>(pTarget);
269
+ CellClass* pTargetCell = nullptr ;
271
270
272
- if (pTarget)
271
+ if (pTarget)
272
+ {
273
+ if (const auto pCell = abstract_cast<CellClass*>(pTarget))
273
274
{
274
- if (const auto pCell = abstract_cast<CellClass*>(pTarget))
275
- {
276
- pTargetCell = pCell;
277
- }
278
- else if (const auto pObject = abstract_cast<ObjectClass*>(pTarget))
279
- {
280
- // Ignore target cell for technos that are in air.
281
- if ((pTechno && !pTechno->IsInAir ()) || pObject != pTechno)
282
- pTargetCell = pObject->GetCell ();
283
- }
275
+ pTargetCell = pCell;
284
276
}
285
-
286
- if (pTargetCell)
277
+ else if (const auto pObject = abstract_cast<ObjectClass*>(pTarget))
287
278
{
288
- if (!EnumFunctions::IsCellEligible (pTargetCell, pWeaponExt->CanTarget , true , true ))
289
- return CannotFire;
279
+ // Ignore target cell for technos that are in air.
280
+ if ((pTechno && !pTechno->IsInAir ()) || pObject != pTechno)
281
+ pTargetCell = pObject->GetCell ();
290
282
}
283
+ }
291
284
292
- if (pTechno)
285
+ const auto pWeaponExt = WeaponTypeExt::ExtMap.Find (pWeapon);
286
+
287
+ if (!pWeaponExt->SkipWeaponPicking && pTargetCell)
288
+ {
289
+ if (!EnumFunctions::IsCellEligible (pTargetCell, pWeaponExt->CanTarget , true , true ))
290
+ return CannotFire;
291
+ }
292
+
293
+ if (pTechno)
294
+ {
295
+ if (!pWeaponExt->SkipWeaponPicking )
293
296
{
294
297
if (!EnumFunctions::IsTechnoEligible (pTechno, pWeaponExt->CanTarget ) ||
295
- !EnumFunctions::CanTargetHouse (pWeaponExt->CanTargetHouses , pThis->Owner , pTechno->Owner ))
298
+ !EnumFunctions::CanTargetHouse (pWeaponExt->CanTargetHouses , pThis->Owner , pTechno->Owner ) ||
299
+ !pWeaponExt->IsHealthRatioEligible (pTechno))
296
300
{
297
301
return CannotFire;
298
302
}
299
303
300
304
if (!pWeaponExt->HasRequiredAttachedEffects (pTechno, pThis))
301
305
return CannotFire;
306
+ }
302
307
303
- if (pWH->Airstrike )
304
- {
305
- if (!pWHExt || !EnumFunctions::IsTechnoEligible (pTechno, pWHExt->AirstrikeTargets ))
306
- return CannotFire;
308
+ if (pWH->Airstrike )
309
+ {
310
+ if (!pWHExt || !EnumFunctions::IsTechnoEligible (pTechno, pWHExt->AirstrikeTargets ))
311
+ return CannotFire;
307
312
308
- if (!TechnoTypeExt::ExtMap.Find (pTechno->GetTechnoType ())->AllowAirstrike .Get (pTechno->AbstractFlags & AbstractFlags::Foot ? true : static_cast <BuildingClass*>(pTechno)->Type ->CanC4 ))
309
- return CannotFire;
310
- }
313
+ if (!TechnoTypeExt::ExtMap.Find (pTechno->GetTechnoType ())->AllowAirstrike .Get (pTechno->AbstractFlags & AbstractFlags::Foot ? true : static_cast <BuildingClass*>(pTechno)->Type ->CanC4 ))
314
+ return CannotFire;
311
315
}
312
316
}
313
317
@@ -499,22 +503,29 @@ DEFINE_HOOK(0x6FE19A, TechnoClass_FireAt_AreaFire, 0x6)
499
503
500
504
if (auto pExt = WeaponTypeExt::ExtMap.Find (pWeaponType))
501
505
{
506
+ const auto canTarget = pExt->CanTarget ;
507
+ const auto canTargetHouses = pExt->CanTargetHouses ;
508
+ const bool skipWeaponPicking = pExt->SkipWeaponPicking ;
509
+ const bool onBridge = pThis->OnBridge ;
510
+ const int level = pThis->GetCell ()->Level ;
511
+
502
512
if (pExt->AreaFire_Target == AreaFireTarget::Random)
503
513
{
504
- auto const range = WeaponTypeExt::GetRangeWithModifiers (pWeaponType, pThis) / static_cast <double >(Unsorted::LeptonsPerCell);
505
-
514
+ const auto range = WeaponTypeExt::GetRangeWithModifiers (pWeaponType, pThis) / static_cast <double >(Unsorted::LeptonsPerCell);
515
+ const auto pOwner = pThis->Owner ;
516
+ const auto mapCoords = pCell->MapCoords ;
506
517
std::vector<CellStruct> adjacentCells = GeneralUtils::AdjacentCellsInRange (static_cast <size_t >(range + 0.99 ));
507
- size_t size = adjacentCells.size ();
518
+ const size_t size = adjacentCells.size ();
508
519
509
520
for (unsigned int i = 0 ; i < size; i++)
510
521
{
511
522
int rand = ScenarioClass::Instance->Random .RandomRanged (0 , size - 1 );
512
523
unsigned int cellIndex = (i + rand) % size;
513
- CellStruct tgtPos = pCell-> MapCoords + adjacentCells[cellIndex];
524
+ CellStruct tgtPos = mapCoords + adjacentCells[cellIndex];
514
525
CellClass* tgtCell = MapClass::Instance.TryGetCellAt (tgtPos);
515
- bool allowBridges = tgtCell && tgtCell->ContainsBridge () && (pThis-> OnBridge || tgtCell->Level + CellClass::BridgeLevels == pThis-> GetCell ()-> Level );
526
+ bool allowBridges = tgtCell && tgtCell->ContainsBridge () && (onBridge || tgtCell->Level + CellClass::BridgeLevels == level );
516
527
517
- if (EnumFunctions::AreCellAndObjectsEligible (tgtCell, pExt-> CanTarget , pExt-> CanTargetHouses , pThis-> Owner , true , false , allowBridges))
528
+ if (skipWeaponPicking || EnumFunctions::AreCellAndObjectsEligible (tgtCell, canTarget, canTargetHouses, pOwner , true , false , allowBridges))
518
529
{
519
530
R->EAX (tgtCell);
520
531
return 0 ;
@@ -525,16 +536,16 @@ DEFINE_HOOK(0x6FE19A, TechnoClass_FireAt_AreaFire, 0x6)
525
536
}
526
537
else if (pExt->AreaFire_Target == AreaFireTarget::Self)
527
538
{
528
- if (!EnumFunctions::AreCellAndObjectsEligible (pThis->GetCell (), pExt-> CanTarget , pExt-> CanTargetHouses , nullptr , false , false , pThis->OnBridge ))
539
+ if (!skipWeaponPicking && ! EnumFunctions::AreCellAndObjectsEligible (pThis->GetCell (), canTarget, canTargetHouses , nullptr , false , false , pThis->OnBridge ))
529
540
return DoNotFire;
530
541
531
542
R->EAX (pThis);
532
543
return SkipSetTarget;
533
544
}
534
545
535
- bool allowBridges = pCell && pCell ->ContainsBridge () && (pThis-> OnBridge || pCell->Level + CellClass::BridgeLevels == pThis-> GetCell ()-> Level );
546
+ bool allowBridges = pCell->ContainsBridge () && (onBridge || pCell->Level + CellClass::BridgeLevels == level );
536
547
537
- if (!EnumFunctions::AreCellAndObjectsEligible (pCell, pExt-> CanTarget , pExt-> CanTargetHouses , nullptr , false , false , allowBridges))
548
+ if (!skipWeaponPicking && ! EnumFunctions::AreCellAndObjectsEligible (pCell, canTarget, canTargetHouses , nullptr , false , false , allowBridges))
538
549
return DoNotFire;
539
550
}
540
551
@@ -625,9 +636,9 @@ static inline void SetChargeTurretDelay(TechnoClass* pThis, int rearmDelay, Weap
625
636
626
637
if (pWeaponExt->ChargeTurret_Delays .size () > 0 )
627
638
{
628
- size_t burstIndex = pWeapon->Burst > 1 ? pThis->CurrentBurstIndex - 1 : 0 ;
629
- size_t index = burstIndex < pWeaponExt->ChargeTurret_Delays .size () ? burstIndex : pWeaponExt->ChargeTurret_Delays .size () - 1 ;
630
- int delay = pWeaponExt->ChargeTurret_Delays [index];
639
+ const size_t burstIndex = pWeapon->Burst > 1 ? pThis->CurrentBurstIndex - 1 : 0 ;
640
+ const size_t index = burstIndex < pWeaponExt->ChargeTurret_Delays .size () ? burstIndex : pWeaponExt->ChargeTurret_Delays .size () - 1 ;
641
+ const int delay = pWeaponExt->ChargeTurret_Delays [index];
631
642
632
643
if (delay <= 0 )
633
644
return ;
@@ -769,8 +780,8 @@ DEFINE_HOOK(0x6FD0B5, TechnoClass_RearmDelay_ROF, 0x6)
769
780
770
781
auto const pWeaponExt = WeaponTypeExt::ExtMap.Find (pWeapon);
771
782
auto const pExt = TechnoExt::ExtMap.Find (pThis);
772
- auto range = pWeaponExt->ROF_RandomDelay .Get (RulesExt::Global ()->ROF_RandomDelay );
773
- double rof = pWeapon->ROF * pExt->AE .ROFMultiplier ;
783
+ auto const range = pWeaponExt->ROF_RandomDelay .Get (RulesExt::Global ()->ROF_RandomDelay );
784
+ const double rof = pWeapon->ROF * pExt->AE .ROFMultiplier ;
774
785
pExt->LastRearmWasFullDelay = true ;
775
786
776
787
R->EAX (GeneralUtils::GetRangedRandomOrSingleValue (range));
@@ -803,7 +814,7 @@ DEFINE_HOOK(0x6FD05E, TechnoClass_RearmDelay_BurstDelays, 0x7)
803
814
GET (int , idxCurrentBurst, ECX);
804
815
805
816
const auto pWeaponExt = WeaponTypeExt::ExtMap.Find (pWeapon);
806
- int burstDelay = pWeaponExt->GetBurstDelay (pThis->CurrentBurstIndex );
817
+ const int burstDelay = pWeaponExt->GetBurstDelay (pThis->CurrentBurstIndex );
807
818
808
819
if (burstDelay >= 0 )
809
820
{
@@ -848,7 +859,7 @@ DEFINE_HOOK(0x5209AF, InfantryClass_FiringAI_BurstDelays, 0x6)
848
859
849
860
int cumulativeDelay = 0 ;
850
861
int projectedDelay = 0 ;
851
- int weaponIndex = FiringAITemp::weaponIndex;
862
+ const int weaponIndex = FiringAITemp::weaponIndex;
852
863
auto const pWeapon = pThis->GetWeapon (weaponIndex)->WeaponType ;
853
864
auto const pWeaponExt = WeaponTypeExt::ExtMap.Find (pWeapon);
854
865
@@ -857,7 +868,7 @@ DEFINE_HOOK(0x5209AF, InfantryClass_FiringAI_BurstDelays, 0x6)
857
868
{
858
869
for (int i = 0 ; i <= pThis->CurrentBurstIndex ; i++)
859
870
{
860
- int burstDelay = pWeaponExt->GetBurstDelay (i);
871
+ const int burstDelay = pWeaponExt->GetBurstDelay (i);
861
872
int delay = 0 ;
862
873
863
874
if (burstDelay > -1 )
@@ -880,7 +891,7 @@ DEFINE_HOOK(0x5209AF, InfantryClass_FiringAI_BurstDelays, 0x6)
880
891
{
881
892
if (pWeaponExt && pWeaponExt->Burst_FireWithinSequence )
882
893
{
883
- int frameCount = pThis->Type ->Sequence ->GetSequence (pThis->SequenceAnim ).CountFrames ;
894
+ const int frameCount = pThis->Type ->Sequence ->GetSequence (pThis->SequenceAnim ).CountFrames ;
884
895
885
896
// If projected frame for firing next shot goes beyond the sequence frame count, cease firing after this shot and start rearm timer.
886
897
if (firingFrame + projectedDelay > frameCount)
0 commit comments