| 
1 | 1 | #include "Body.h"  | 
2 | 2 | #include <Randomizer.h>  | 
3 | 3 | 
 
  | 
 | 4 | +#include <Ext/Techno/Body.h>  | 
 | 5 | + | 
4 | 6 | DEFINE_HOOK(0x7128B2, TechnoTypeClass_ReadINI_MultiWeapon, 0x6)  | 
5 | 7 | {  | 
6 | 8 | 	GET(TechnoTypeClass*, pThis, EBP);  | 
@@ -141,3 +143,118 @@ DEFINE_HOOK(0x7090A0, TechnoClass_VoiceAttack, 0x7)  | 
141 | 143 | 
 
  | 
142 | 144 | 	return 0x7091C7;  | 
143 | 145 | }  | 
 | 146 | + | 
 | 147 | +ThreatType __forceinline GetThreatType(TechnoClass* pThis, TechnoTypeExt::ExtData* pTypeExt, ThreatType result)  | 
 | 148 | +{  | 
 | 149 | +	const ThreatType flags = pThis->Veterancy.IsElite() ? pTypeExt->ThreatTypes.Y : pTypeExt->ThreatTypes.X;  | 
 | 150 | +	return result | flags;  | 
 | 151 | +}  | 
 | 152 | + | 
 | 153 | +DEFINE_HOOK_AGAIN(0x51E2CF, FootClass_SelectAutoTarget_MultiWeapon, 0x6)	// InfantryClass_SelectAutoTarget  | 
 | 154 | +DEFINE_HOOK(0x7431C9, FootClass_SelectAutoTarget_MultiWeapon, 0x7)			// UnitClass_SelectAutoTarget  | 
 | 155 | +{  | 
 | 156 | +	enum { InfantryReturn = 0x51E31B, UnitReturn = 0x74324F, UnitGunner = 0x7431E4 };  | 
 | 157 | + | 
 | 158 | +	GET(FootClass*, pThis, ESI);  | 
 | 159 | +	GET(const ThreatType, result, EDI);  | 
 | 160 | + | 
 | 161 | +	const bool isUnit = R->Origin() == 0x7431C9;  | 
 | 162 | +	const auto pType = pThis->GetTechnoType();  | 
 | 163 | +	const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType);  | 
 | 164 | + | 
 | 165 | +	if (isUnit  | 
 | 166 | +		&& !pType->IsGattling && pType->TurretCount > 0  | 
 | 167 | +		&& (pType->Gunner || !pTypeExt->MultiWeapon))  | 
 | 168 | +	{  | 
 | 169 | +		return UnitGunner;  | 
 | 170 | +	}  | 
 | 171 | + | 
 | 172 | +	R->EDI(GetThreatType(pThis, pTypeExt, result));  | 
 | 173 | +	return isUnit ? UnitReturn : InfantryReturn;  | 
 | 174 | +}  | 
 | 175 | + | 
 | 176 | +DEFINE_HOOK(0x445F04, BuildingClass_SelectAutoTarget_MultiWeapon, 0xA)  | 
 | 177 | +{  | 
 | 178 | +	enum { ReturnThreatType = 0x445F58, Continue = 0x445F0E };  | 
 | 179 | + | 
 | 180 | +	GET(BuildingClass*, pThis, ESI);  | 
 | 181 | +	GET_STACK(const ThreatType, result, STACK_OFFSET(0x8, 0x4));  | 
 | 182 | + | 
 | 183 | +	if (pThis->UpgradeLevel > 0 || pThis->CanOccupyFire())  | 
 | 184 | +	{  | 
 | 185 | +		R->EAX(pThis->GetWeapon(0));  | 
 | 186 | +		return Continue;  | 
 | 187 | +	}  | 
 | 188 | + | 
 | 189 | +	R->EDI(GetThreatType(pThis, TechnoTypeExt::ExtMap.Find(pThis->Type), result));  | 
 | 190 | +	return ReturnThreatType;  | 
 | 191 | +}  | 
 | 192 | + | 
 | 193 | +DEFINE_HOOK(0x6F398E, TechnoClass_CombatDamage_MultiWeapon, 0x7)  | 
 | 194 | +{  | 
 | 195 | +	enum { ReturnDamage = 0x6F3ABB, GunnerDamage = 0x6F39AD, Continue = 0x6F39F4 };  | 
 | 196 | + | 
 | 197 | +	GET(TechnoClass*, pThis, ESI);  | 
 | 198 | + | 
 | 199 | +	const AbstractType rtti = pThis->WhatAmI();  | 
 | 200 | + | 
 | 201 | +	if (rtti == AbstractType::Building)  | 
 | 202 | +	{  | 
 | 203 | +		const auto pBuilding = static_cast<BuildingClass*>(pThis);  | 
 | 204 | + | 
 | 205 | +		if (pBuilding->UpgradeLevel > 0 || pBuilding->CanOccupyFire())  | 
 | 206 | +			return Continue;  | 
 | 207 | +	}  | 
 | 208 | + | 
 | 209 | +	const auto pType = pThis->GetTechnoType();  | 
 | 210 | +	const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType);  | 
 | 211 | + | 
 | 212 | +	if (rtti == AbstractType::Unit  | 
 | 213 | +		&& !pType->IsGattling && pType->TurretCount > 0  | 
 | 214 | +		&& (pType->Gunner || !pTypeExt->MultiWeapon))  | 
 | 215 | +	{  | 
 | 216 | +		return GunnerDamage;  | 
 | 217 | +	}  | 
 | 218 | + | 
 | 219 | +	R->EAX(pThis->Veterancy.IsElite() ? pTypeExt->CombatDamages.Y : pTypeExt->CombatDamages.X);  | 
 | 220 | +	return ReturnDamage;  | 
 | 221 | +}  | 
 | 222 | + | 
 | 223 | +DEFINE_HOOK(0x707ED0, TechnoClass_GetGuardRange_MultiWeapon, 0x6)  | 
 | 224 | +{  | 
 | 225 | +	enum { ReturnRange = 0x707F08 };  | 
 | 226 | + | 
 | 227 | +	GET(TechnoClass*, pThis, ESI);  | 
 | 228 | + | 
 | 229 | +	const auto pType = pThis->GetTechnoType();  | 
 | 230 | +	const bool specialWeapon = !pType->IsGattling && (!pType->HasMultipleTurrets() || !pType->Gunner);  | 
 | 231 | + | 
 | 232 | +	if (!pType->IsGattling && pType->TurretCount > 0  | 
 | 233 | +		&& (pType->Gunner || !specialWeapon)  | 
 | 234 | +		&& pThis->WhatAmI() == AbstractType::Unit)  | 
 | 235 | +	{  | 
 | 236 | +		R->EAX(pThis->GetWeaponRange(pThis->CurrentWeaponNumber));  | 
 | 237 | +		return ReturnRange;  | 
 | 238 | +	}  | 
 | 239 | + | 
 | 240 | +	const auto pTypeExt = TechnoTypeExt::ExtMap.Find(pType);  | 
 | 241 | + | 
 | 242 | +	if (pTypeExt->MultiWeapon && specialWeapon)  | 
 | 243 | +	{  | 
 | 244 | +		const int selectCount = Math::min(pType->WeaponCount, pTypeExt->MultiWeapon_SelectCount);  | 
 | 245 | +		int range = 0;  | 
 | 246 | + | 
 | 247 | +		for (int index = selectCount - 1; index >= 0; --index)  | 
 | 248 | +		{  | 
 | 249 | +			const auto weaponRange = pThis->GetWeaponRange(index);  | 
 | 250 | + | 
 | 251 | +			if (weaponRange > range)  | 
 | 252 | +				range = weaponRange;  | 
 | 253 | +		}  | 
 | 254 | + | 
 | 255 | +		R->EAX(range);  | 
 | 256 | +		return ReturnRange;  | 
 | 257 | +	}  | 
 | 258 | + | 
 | 259 | +	return 0;  | 
 | 260 | +}  | 
0 commit comments