From 9b775fe76585a7812922facd4a7aa85a183596d5 Mon Sep 17 00:00:00 2001 From: Rampastring Date: Wed, 19 Feb 2025 17:52:10 +0200 Subject: [PATCH] Fix visceroids getting spawned when gas destroys non-crewed vehicles, buildings, and terrain objects --- CREDITS.md | 1 + docs/Bugfixes.md | 1 + src/extensions/particle/particleext_hooks.cpp | 104 ++++++++++++++++++ src/extensions/particle/particleext_hooks.h | 31 ++++++ 4 files changed, 137 insertions(+) create mode 100644 src/extensions/particle/particleext_hooks.cpp create mode 100644 src/extensions/particle/particleext_hooks.h diff --git a/CREDITS.md b/CREDITS.md index c24bc564e..88cc77128 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -167,6 +167,7 @@ This page lists all the individual contributions to the project by their author. - Allow scenarios to have custom score screen bar colors. - Add `Inaccuracy` to RocketTypes. - Add `TargetZoneScan` to TechnoTypes. + - Fix a bug where a visceroid was spawned when poison gas destroyed a non-crewed vehicle, building, or terrain object. - **secsome**: - Add support for up to 32767 waypoints to be used in scenarios. - **Starkku**: diff --git a/docs/Bugfixes.md b/docs/Bugfixes.md index dee8f9dae..f3f812c9a 100644 --- a/docs/Bugfixes.md +++ b/docs/Bugfixes.md @@ -65,3 +65,4 @@ This page lists all vanilla bugs fixed by Vinifera. - `[CombatDamage]->MinDamage` now works as expected and damage is no long always a minimum of `1`. - VehicleTypes with Jumpjet locomotion now take damage in flight. - Fix the map glitching around when scrolling if the map is not large enough to fill the entire screen. +- Fix a bug where a visceroid was spawned when poison gas destroyed a non-crewed vehicle, building, or terrain object. diff --git a/src/extensions/particle/particleext_hooks.cpp b/src/extensions/particle/particleext_hooks.cpp new file mode 100644 index 000000000..f6bc63af3 --- /dev/null +++ b/src/extensions/particle/particleext_hooks.cpp @@ -0,0 +1,104 @@ +/******************************************************************************* +/* O P E N S O U R C E -- V I N I F E R A ** +/******************************************************************************* + * + * @project Vinifera (Dawn of the Tiberium Age Build) + * + * @file PARTICLEEXT_HOOKS.CPP + * + * @author Rampastring + * + * @brief Contains the hooks for the extended ParticleClass. + * + * @license Vinifera is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version + * 3 of the License, or (at your option) any later version. + * + * Vinifera is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. + * If not, see . + * + ******************************************************************************/ +#include "building.h" +#include "house.h" +#include "housetype.h" +#include "particlesysext_hooks.h" +#include "particlesys.h" +#include "rules.h" +#include "scenario.h" +#include "unit.h" +#include "tibsun_globals.h" +#include "tibsun_defines.h" +#include "fatal.h" +#include "debughandler.h" +#include "asserthandler.h" + +#include "hooker.h" +#include "hooker_macros.h" + + +UnitClass* Create_Visceroid(ObjectClass* destroyedobject) +{ + if (destroyedobject->What_Am_I() == RTTI_INFANTRY || + (destroyedobject->What_Am_I() == RTTI_UNIT && reinterpret_cast(destroyedobject)->Class->IsCrew) || + (destroyedobject->What_Am_I() == RTTI_BUILDING && reinterpret_cast(destroyedobject)->Class->IsCrew)) + { + return new UnitClass(Rule->SmallVisceroid, HouseClass::As_Pointer(HouseTypeClass::From_Name("Neutral"))); + } + + return nullptr; +} + + +/** + * Fixes a bug where gas clouds are able to turn everything into visceroids, including + * non-crewed vehicles and even terrain objects. + */ +DECLARE_PATCH(_ParticleClass_Smoke_And_WeakGas_Behaviour_AI_Tiberium_Death_Patch) +{ + GET_REGISTER_STATIC(ObjectClass*, destroyedobject, esi); + GET_REGISTER_STATIC(ResultType, result, eax); + GET_STACK_STATIC(ObjectClass*, nextobject, esp, 0x40); + static UnitClass* visceroid; + + enum { + ContinueVisceroidPlacement = 0x005A38FC, + SkipToNextObjectOnCell = 0x005A3965 + }; + + _asm { mov esi, dword ptr ds:nextobject } + + if (result != RESULT_DESTROYED) { + // Object was not destroyed, do not create visceroid. + JMP(SkipToNextObjectOnCell); + } + + if (!Scen->IsTiberiumDeathToVisceroid) { + // Visceroids spawning from Tiberium death is disabled, do not create visceroid. + JMP(SkipToNextObjectOnCell); + } + + visceroid = Create_Visceroid(destroyedobject); + if (visceroid == nullptr) { + // No visceroid was created. + JMP(SkipToNextObjectOnCell); + } + + _asm { mov edi, dword ptr ds:visceroid } + JMP(ContinueVisceroidPlacement); +} + + +/** + * Main function for patching the hooks. + */ +void ParticleClassExtension_Hooks() +{ + Patch_Jump(0x005A389C, &_ParticleClass_Smoke_And_WeakGas_Behaviour_AI_Tiberium_Death_Patch); +} diff --git a/src/extensions/particle/particleext_hooks.h b/src/extensions/particle/particleext_hooks.h new file mode 100644 index 000000000..7450fa5dc --- /dev/null +++ b/src/extensions/particle/particleext_hooks.h @@ -0,0 +1,31 @@ +/******************************************************************************* +/* O P E N S O U R C E -- V I N I F E R A ** +/******************************************************************************* + * + * @project Vinifera (Dawn of the Tiberium Age Build) + * + * @file PARTICLEEXT_HOOKS.H + * + * @author Rampastring + * + * @brief Contains the hooks for the extended ParticleClass. + * + * @license Vinifera is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version + * 3 of the License, or (at your option) any later version. + * + * Vinifera is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. + * If not, see . + * + ******************************************************************************/ +#pragma once + + +void ParticleClassExtension_Hooks();