From 6e18c35bf5e9b0b06b3fc607bad363e235f823ee Mon Sep 17 00:00:00 2001 From: CCHyper <73803386+CCHyper@users.noreply.github.com> Date: Wed, 29 Sep 2021 17:16:44 +0100 Subject: [PATCH] Implements IsOmniFire for WeaponTypes. --- src/extensions/unit/unitext_hooks.cpp | 96 +++++++++++++++++++++ src/extensions/weapontype/weapontypeext.cpp | 3 + src/extensions/weapontype/weapontypeext.h | 5 ++ 3 files changed, 104 insertions(+) diff --git a/src/extensions/unit/unitext_hooks.cpp b/src/extensions/unit/unitext_hooks.cpp index 0e54d509f..bf5d588c1 100644 --- a/src/extensions/unit/unitext_hooks.cpp +++ b/src/extensions/unit/unitext_hooks.cpp @@ -31,8 +31,11 @@ #include "vinifera_globals.h" #include "tibsun_globals.h" #include "tibsun_functions.h" +#include "unittypeext.h" #include "technotype.h" #include "technotypeext.h" +#include "weapontype.h" +#include "weapontypeext.h" #include "unit.h" #include "unittype.h" #include "unittypeext.h" @@ -49,6 +52,97 @@ #include "hooker_macros.h" +/** + * #issue-550 + * + * Implements IsOmniFire for units. + * + * @author: CCHyper + */ +DECLARE_PATCH(_UnitClass_Can_Fire_IsOmniFire_Patch) +{ + GET_REGISTER_STATIC(UnitClass *, this_ptr, esi); + GET_REGISTER_STATIC(WeaponTypeClass *, weapon, ebx); + static WeaponTypeClassExtension *weapontypeext; + + weapontypeext = Extension::Fetch(weapon); + + /** + * Do we need to perform a turn to face the target before firing? + */ + if (weapontypeext->IsOmniFire) { + goto locomotor_Can_Fire; + } + + /** + * Stolen bytes/code. + */ + if (this_ptr->Class->IsLargeVisceroid) { + goto locomotor_Can_Fire; + } + +continue_facing_check: + static UnitTypeClass *class_ptr; // Restore EAX pointer. + class_ptr = this_ptr->Class; + _asm { mov eax, class_ptr } + + /** + * Final check to make sure the locomotor allows firing. + */ +locomotor_Can_Fire: + JMP(0x00656FA7); +} + + +/** + * #issue-550 + * + * Implements IsOmniFire for units. + * + * @author: CCHyper + */ +DECLARE_PATCH(_UnitClass_Rotation_AI_IsOmniFire_Patch) +{ + GET_REGISTER_STATIC(UnitClass *, this_ptr, esi); + GET_STACK_STATIC(DirStruct *, tarcom_dir, esp, 0x8); + static const WeaponInfoStruct *weaponinfo; + static WeaponTypeClass *weapontype; + static WeaponTypeClassExtension *weapontypeext; + + /** + * Fetch this units primary weapon. + */ + weaponinfo = this_ptr->Get_Weapon(WEAPON_SLOT_PRIMARY); + if (weaponinfo->Weapon) { + + weapontypeext = Extension::Fetch(weaponinfo->Weapon); + + /** + * Do we need turn to face the target? + */ + if (weapontypeext->IsOmniFire) { + goto continue_rotation_checks; + } + + } + + /** + * Original code. + * + * Set the desired facing for the turret to that of the target. + */ + this_ptr->SecondaryFacing.Set_Desired(*tarcom_dir); + + JMP(0x0064E612); + + /** + * Skip setting turret facing, continue rotation checks. + */ +continue_rotation_checks: + JMP(0x0064E612); +} + + #if 0 /** * #issue-510 @@ -701,4 +795,6 @@ void UnitClassExtension_Hooks() Patch_Jump(0x0065665D, &_UnitClass_What_Action_ACTION_HARVEST_Block_On_Bridge_Patch); // IsToVeinHarvest //Patch_Jump(0x0065054F, &_UnitClass_Enter_Idle_Mode_Block_Harvesting_On_Bridge_Patch); // Removed, keeping code for reference. //Patch_Jump(0x00654AB0, &_UnitClass_Mission_Harvest_Block_Harvesting_On_Bridge_Patch); // Removed, keeping code for reference. + Patch_Jump(0x0064E5A6, &_UnitClass_Rotation_AI_IsOmniFire_Patch); + Patch_Jump(0x00656F99, &_UnitClass_Can_Fire_IsOmniFire_Patch); } diff --git a/src/extensions/weapontype/weapontypeext.cpp b/src/extensions/weapontype/weapontypeext.cpp index 3a4a8418f..7b2af0039 100644 --- a/src/extensions/weapontype/weapontypeext.cpp +++ b/src/extensions/weapontype/weapontypeext.cpp @@ -44,6 +44,7 @@ WeaponTypeClassExtension::WeaponTypeClassExtension(const WeaponTypeClass *this_p AbstractTypeClassExtension(this_ptr), IsSuicide(false), IsDeleteOnSuicide(false), + IsOmniFire(true), IsElectricBolt(false), ElectricBoltColor1(EBOLT_DEFAULT_COLOR_1), ElectricBoltColor2(EBOLT_DEFAULT_COLOR_2), @@ -173,6 +174,7 @@ void WeaponTypeClassExtension::Compute_CRC(WWCRCEngine &crc) const { //EXT_DEBUG_TRACE("WeaponTypeClassExtension::Compute_CRC - Name: %s (0x%08X)\n", Name(), (uintptr_t)(This())); + crc(IsOmniFire); crc(IsElectricBolt); } @@ -194,6 +196,7 @@ bool WeaponTypeClassExtension::Read_INI(CCINIClass &ini) IsSuicide = ini.Get_Bool(ini_name, "Suicide", IsSuicide); IsDeleteOnSuicide = ini.Get_Bool(ini_name, "DeleteOnSuicide", IsDeleteOnSuicide); + IsOmniFire = ini.Get_Bool(ini_name, "OmniFire", IsOmniFire); IsElectricBolt = ini.Get_Bool(ini_name, "IsElectricBolt", IsElectricBolt); ElectricBoltColor1 = ini.Get_RGB(ini_name, "EBoltColor1", ElectricBoltColor1); diff --git a/src/extensions/weapontype/weapontypeext.h b/src/extensions/weapontype/weapontypeext.h index 4d662c3e8..9b35ff8c2 100644 --- a/src/extensions/weapontype/weapontypeext.h +++ b/src/extensions/weapontype/weapontypeext.h @@ -72,6 +72,11 @@ WeaponTypeClassExtension final : public AbstractTypeClassExtension */ bool IsDeleteOnSuicide; + /** + * Does the unit firing this weapon have to perform a turn to face its target before firing? + */ + bool IsOmniFire; + /** * Is this a electric bolt weapon (Uses custom drawing)? */