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
+};