From 3523748bf8b10d5adf9d8278463ab5777126da21 Mon Sep 17 00:00:00 2001 From: CCHyper <73803386+CCHyper@users.noreply.github.com> Date: Sat, 12 Jun 2021 14:22:57 +0100 Subject: [PATCH] Implements "Give credits to house..." trigger action. --- src/extensions/ext_hooks.cpp | 2 + .../taction/tactionext_functions.cpp | 105 +++++++++ src/extensions/taction/tactionext_functions.h | 40 ++++ src/extensions/taction/tactionext_hooks.cpp | 206 ++++++++++++++++++ src/extensions/taction/tactionext_hooks.h | 31 +++ src/vinifera_defines.h | 51 +++++ 6 files changed, 435 insertions(+) create mode 100644 src/extensions/taction/tactionext_functions.cpp create mode 100644 src/extensions/taction/tactionext_functions.h create mode 100644 src/extensions/taction/tactionext_hooks.cpp create mode 100644 src/extensions/taction/tactionext_hooks.h create mode 100644 src/vinifera_defines.h diff --git a/src/extensions/ext_hooks.cpp b/src/extensions/ext_hooks.cpp index 29fd232c9..83b445e41 100644 --- a/src/extensions/ext_hooks.cpp +++ b/src/extensions/ext_hooks.cpp @@ -84,6 +84,7 @@ #include "cellext_hooks.h" #include "houseext_hooks.h" #include "teamext_hooks.h" +#include "tactionext_hooks.h" #include "factoryext_hooks.h" #include "animext_hooks.h" #include "bulletext_hooks.h" @@ -171,6 +172,7 @@ void Extension_Hooks() CellClassExtension_Hooks(); HouseClassExtension_Hooks(); TeamClassExtension_Hooks(); + TActionClassExtension_Hooks(); FactoryClassExtension_Hooks(); TechnoClassExtension_Hooks(); FootClassExtension_Hooks(); diff --git a/src/extensions/taction/tactionext_functions.cpp b/src/extensions/taction/tactionext_functions.cpp new file mode 100644 index 000000000..7a4b9ef45 --- /dev/null +++ b/src/extensions/taction/tactionext_functions.cpp @@ -0,0 +1,105 @@ +/******************************************************************************* +/* O P E N S O U R C E -- V I N I F E R A ** +/******************************************************************************* + * + * @project Vinifera + * + * @file TACTIONEXT_FUNCTIONS.CPP + * + * @author CCHyper + * + * @brief Contains the supporting functions for the extended TActionClass. + * + * @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 "tactionext_functions.h" +#include "vinifera_defines.h" +#include "taction.h" +#include "house.h" +#include "housetype.h" +#include "object.h" +#include "objecttype.h" +#include "trigger.h" +#include "triggertype.h" +#include "debughandler.h" +#include "asserthandler.h" + + +/** + * Helper info for writing new actions. + * + * TActionClass::Data = First Param (PARAM1) + * TActionClass::Bounds.X = Second Para (PARAM2) + * TActionClass::Bounds.Y = Second Para (PARAM3) + * TActionClass::Bounds.W = Second Para (PARAM4) + * TActionClass::Bounds.H = Second Para (PARAM5) + * + * + * Example action line from a scenario file; + * + * [Actions] + * NAME = [Action Count], [TActionType], [TActionFormatType], [PARAM1], [PARAM2], [PARAM3], [PARAM4], [PARAM5], [OPTIONAL] + * + * To allow the use of TActionClass::Data (PARAM1), you must have the TActionFormatType set + * to "0", otherwise this param is ignored! + */ + + +/** + * #issue-158 + * + * Give credits to the specified house. + * + * Expected INI format; + * NAME = [Action Count], 106, 0, [PARAM1 = House ID], [PARAM2 = Credits], 0, 0, 0 + * + * @author: CCHyper + */ +bool TAction_Give_Credits_To_House(TActionClass *taction, HouseClass *house, ObjectClass *object, TriggerClass *trigger, Cell *cell) +{ + if (!taction || !house) { + return false; + } + + /** + * Fetch the param values. + */ + int param_one = taction->Data.Value; + int param_two = taction->Bounds.X; + int param_three = taction->Bounds.Y; + int param_four = taction->Bounds.Width; + int param_five = taction->Bounds.Height; + + /** + * Fetch the house pointer and credit amount. + */ + HouseClass *hptr = HouseClass::As_Pointer(HousesType(param_one)); + int amount = param_two; + + /** + * If positive, grant the cash bonus. + * If negative, take money from the house. + */ + if (amount != 0) { + if (amount < 0) { + hptr->Spend_Money(std::abs(amount)); + } else { + hptr->Refund_Money(amount); + } + } + + return true; +} diff --git a/src/extensions/taction/tactionext_functions.h b/src/extensions/taction/tactionext_functions.h new file mode 100644 index 000000000..2fa947bd9 --- /dev/null +++ b/src/extensions/taction/tactionext_functions.h @@ -0,0 +1,40 @@ +/******************************************************************************* +/* O P E N S O U R C E -- V I N I F E R A ** +/******************************************************************************* + * + * @project Vinifera + * + * @file TACTIONEXT_FUNCTIONS.H + * + * @author CCHyper + * + * @brief Contains the supporting functions for the extended TActionClass. + * + * @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 + +#include "always.h" +#include "tibsun_defines.h" + + +class TActionClass; +class HouseClass; +class ObjectClass; +class TriggerClass; + + +bool TAction_Give_Credits_To_House(TActionClass *taction, HouseClass *house, ObjectClass *object, TriggerClass *trigger, Cell *cell); diff --git a/src/extensions/taction/tactionext_hooks.cpp b/src/extensions/taction/tactionext_hooks.cpp new file mode 100644 index 000000000..194812e11 --- /dev/null +++ b/src/extensions/taction/tactionext_hooks.cpp @@ -0,0 +1,206 @@ +/******************************************************************************* +/* O P E N S O U R C E -- V I N I F E R A ** +/******************************************************************************* + * + * @project Vinifera + * + * @file TACTIONEXT_HOOKS.CPP + * + * @author CCHyper + * + * @brief Contains the hooks for the extended TriggerClass. + * + * @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 "tactionext_hooks.h" +#include "tactionext_functions.h" +#include "taction.h" +#include "vinifera_defines.h" +#include "house.h" +#include "housetype.h" +#include "object.h" +#include "objecttype.h" +#include "trigger.h" +#include "triggertype.h" +#include "fatal.h" +#include "debughandler.h" +#include "asserthandler.h" + +#include "hooker.h" +#include "hooker_macros.h" + + +/** + * Returns the name of the TActionType. + * + * @author: CCHyper + */ +static const char *TActionClass_New_Action_Name(int action) +{ + if (action < TACTION_COUNT) { + return TActionClass::Action_Name(TActionType(action)); + } + + switch (action) { + + case TACTION_CREDITS: + return "Give credits to house..."; + + default: + return ""; + } +} + + +/** + * Returns the description of the TActionType. + * + * @author: CCHyper + */ +static const char *TActionClass_New_Action_Description(int action) +{ + if (action < TACTION_COUNT) { + return TActionClass::Action_Description(TActionType(action)); + } + + switch (action) { + + case TACTION_CREDITS: + return "Gives credits to the specified house."; + + default: + return ""; + } +} + + +/** + * Executes the new trigger action. + * + * @author: CCHyper + */ +static bool TActionClass_New_Action_Switch(TActionClass *this_ptr, HouseClass *house, ObjectClass *object, TriggerClass *trigger, Cell *cell) +{ + bool success = false; + + switch (this_ptr->Action) { + + /** + * #issue-158 + * + * Gives credits to the specified house. + * + * @author: CCHyper + */ + case TACTION_CREDITS: + success = TAction_Give_Credits_To_House(this_ptr, house, object, trigger, cell); + break; + + /** + * Unexpected TActionType. + */ + default: + DEV_DEBUG_WARNING("Invalid action type!\n"); + break; + }; + + return success; +} + + +/** + * This patch extends the TActionClass operator. + * + * @author: CCHyper + */ +DECLARE_PATCH(_TAction_Operator_Extend_Switch_Patch) +{ + GET_REGISTER_STATIC(bool, success, al); + GET_REGISTER_STATIC(TActionClass *, this_ptr, esi); + + /** + * Function arguments + */ + GET_STACK_STATIC(HouseClass *, house, esp, 0x1C4); + GET_STACK_STATIC(ObjectClass *, object, esp, 0x1C8); + GET_STACK_STATIC(TriggerClass *, trigger, esp, 0x1CC); + GET_STACK_STATIC(Cell *, cell, esp, 0x1D0); + +#ifndef NDEBUG + /** + * Helper info for debugging when adding new actions. + */ + DEV_DEBUG_INFO("TActionClass::operator()\n"); + if (house) DEV_DEBUG_INFO(" House: \"%s\"\n", house->Class->Name()); + if (object) DEV_DEBUG_INFO(" Object: \"%s\"\n", object->Name()); + if (trigger) DEV_DEBUG_INFO(" Trigger: \"%s\"\n", trigger->Class_Of()->Name()); + if (cell && *cell) DEV_DEBUG_INFO(" Cell: %d,%d\n", cell->X, cell->Y); +#endif + + /** + * Skip null actions. + */ + if (this_ptr->Action == TACTION_NONE) { + goto do_nothing; + } + + /** + * Handle the original TActionTypes. + */ + if (this_ptr->Action < TACTION_COUNT) { +#ifndef NDEBUG + DEV_DEBUG_INFO("Executing action: \"%s\"\n", TActionClass::Action_Name(this_ptr->Action)); +#endif + goto taction_switch; + } + + /** + * New TActionType switch. + */ + if (this_ptr->Action < NEW_TACTION_COUNT) { + DEV_DEBUG_INFO("Executing new action: \"%s\"\n", TActionClass_New_Action_Name(this_ptr->Action)); + } + + /** + * Execute the new trigger action. + */ + TActionClass_New_Action_Switch(this_ptr, house, object, trigger, cell); + + /** + * The default case, return doing nothing. + */ +do_nothing: + _asm { mov al, success } + JMP(0x0061A9C5); + + /** + * The switch case for the original TActionTypes + */ +taction_switch: + _asm { mov esi, this_ptr } + _asm { mov edx, [esi+0x1C] } // this->Action + _asm { dec edx } + JMP_REG(eax, 0x00619141); +} + + +/** + * Main function for patching the hooks. + */ +void TActionClassExtension_Hooks() +{ + Patch_Jump(0x00619134, &_TAction_Operator_Extend_Switch_Patch); +} diff --git a/src/extensions/taction/tactionext_hooks.h b/src/extensions/taction/tactionext_hooks.h new file mode 100644 index 000000000..afc254ea6 --- /dev/null +++ b/src/extensions/taction/tactionext_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 + * + * @file TACTIONEXT_HOOKS.H + * + * @author CCHyper + * + * @brief Contains the hooks for the extended TActionClass. + * + * @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 TActionClassExtension_Hooks(); diff --git a/src/vinifera_defines.h b/src/vinifera_defines.h new file mode 100644 index 000000000..bcc381b07 --- /dev/null +++ b/src/vinifera_defines.h @@ -0,0 +1,51 @@ +/******************************************************************************* +/* O P E N S O U R C E -- V I N I F E R A ** +/******************************************************************************* + * + * @project Vinifera + * + * @file VINIFERA_GLOBALS.H + * + * @authors CCHyper + * + * @brief Vinifera defines and constants. + * + * @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 + +#include "always.h" +#include "tibsun_defines.h" + + +typedef enum NewTActionType +{ + /** + * This offsets the new TAction enum so they are correctly numbered. + */ + NEW_TACTION_PAD = TACTION_TALK_BUBBLE, // The last TActionType + + /** + * Add new TActionTypes from here, do not reorder these! + */ + + TACTION_CREDITS, // Gives credits to the specified house. + + /** + * The new total TActionType count. + */ + NEW_TACTION_COUNT +};