Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements TransformsInto for UnitType's. #933

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions src/extensions/house/houseext_hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@
#include "house.h"
#include "housetype.h"
#include "technotype.h"
#include "buildingtype.h"
#include "techno.h"
#include "factory.h"
#include "super.h"
#include "unittypeext.h"
#include "extension.h"
#include "fatal.h"
#include "debughandler.h"
#include "asserthandler.h"
Expand Down Expand Up @@ -154,6 +159,128 @@ DECLARE_PATCH(_HouseClass_Can_Build_BuildCheat_Patch)
}


/**
* #issue-611, #issue-715
*
* Gets the number of queued objects when determining whether a cameo
* should be disabled.
*
* Author: Rampastring
*/
int _HouseClass_ShouldDisableCameo_Get_Queued_Count(FactoryClass* factory, TechnoTypeClass* technotype)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be best to move this to HouseClassExtension.

{
int count = factory->Total_Queued(*technotype);
TechnoClass* factoryobject = factory->Get_Object();

if (factoryobject == nullptr || count == 0) {
return 0;
}

/**
* Check that the factory is trying to create the object that the player is trying to queue
* If not, we don't need to mess with the count
*/
if (factoryobject->Techno_Type_Class() != technotype) {
return count;
}

/**
* #issue-611
*
* If the object has a build limit, then reduce count by 1
*/
if (technotype->BuildLimit > 0) {
count--;
}

/**
* #issue-715
*
* If the object can transform into another object through our special logic,
* then check that doing so doesn't allow circumventing build limits
*/
if (technotype->What_Am_I() == RTTI_UNITTYPE) {
UnitTypeClass* unittype = reinterpret_cast<UnitTypeClass*>(technotype);
UnitTypeClassExtension* unittypeext = Extension::Fetch<UnitTypeClassExtension>(unittype);

if (unittype->DeploysInto == nullptr && unittypeext->TransformsInto != nullptr) {
count += factory->House->UQuantity.Count_Of((UnitType)(unittypeext->TransformsInto->Get_Heap_ID()));
}
}

return count;
}


/**
* #issue-611, #issue-715
*
* Fixes the game allowing the player to queue one unit too few
* when a unit has BuildLimit > 1.
*
* Also updates the logic to take our unit transformation logic
* into account.
*/
DECLARE_PATCH(_HouseClass_ShouldDisableCameo_BuildLimit_Fix)
{
GET_REGISTER_STATIC(FactoryClass*, factory, ecx);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A space between the FactoryClass/TechnoTypeClass and * please.

GET_REGISTER_STATIC(TechnoTypeClass*, technotype, esi);
static int queuedcount;

queuedcount = _HouseClass_ShouldDisableCameo_Get_Queued_Count(factory, technotype);

_asm { mov eax, [queuedcount] }
JMP_REG(ecx, 0x004CB77D);
}


/**
* #issue-715
*
* Take vehicles that can transform into other vehicles into acccount when
* determining whether a build limit has been met/exceeded.
* Otherwise these kinds of units could be used to bypass build limits
* (build a limited vehicle, transform it, now you can build another vehicle).
*
* Author: Rampastring
*/
DECLARE_PATCH(_HouseClass_Can_Build_BuildLimit_Handle_Vehicle_Transform)
{
GET_REGISTER_STATIC(UnitTypeClass*, unittype, edi);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A space between the HouseClass/UnitTypeClass and * please.

GET_REGISTER_STATIC(HouseClass*, house, ebp);
static UnitTypeClassExtension* unittypeext;
static int objectcount;

unittypeext = Extension::Fetch<UnitTypeClassExtension>(unittype);

/**
* Stolen bytes / code.
*/
objectcount = house->UQuantity.Count_Of((UnitType)unittype->Get_Heap_ID());

/**
* Check whether this unit can deploy into a building.
* If it can, increment the object count by the number of buildings.
*/
if (unittype->DeploysInto != nullptr) {
objectcount += house->BQuantity.Count_Of((BuildingType)unittype->DeploysInto->Get_Heap_ID());
}
else if (unittypeext->TransformsInto != nullptr) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reformat to;

    if (unittype->DeploysInto != nullptr) {
        objectcount += house->BQuantity.Count_Of((BuildingType)unittype->DeploysInto->Get_Heap_ID());
        
    } else if (unittypeext->TransformsInto != nullptr) {


/**
* This unit can transform into another unit, increment the object count
* by the number of transformed units.
*/
objectcount += house->UQuantity.Count_Of((UnitType)(unittypeext->TransformsInto->Get_Heap_ID()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be careful of such a large operation here. Check the assembly, hopefully, this only uses EAX for each operation.

}

_asm { mov esi, objectcount }

continue_function:
JMP(0x004BC1B9);
}


/**
* Main function for patching the hooks.
*/
Expand All @@ -166,4 +293,6 @@ void HouseClassExtension_Hooks()

Patch_Jump(0x004BBD26, &_HouseClass_Can_Build_BuildCheat_Patch);
Patch_Jump(0x004BD30B, &_HouseClass_Super_Weapon_Handler_InstantRecharge_Patch);
Patch_Jump(0x004CB777, &_HouseClass_ShouldDisableCameo_BuildLimit_Fix);
Patch_Jump(0x004BC187, _HouseClass_Can_Build_BuildLimit_Handle_Vehicle_Transform);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing & before the label.

}
53 changes: 53 additions & 0 deletions src/extensions/techno/technoext_hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#include "infantry.h"
#include "infantrytype.h"
#include "infantrytypeext.h"
#include "unittype.h"
#include "unittypeext.h"
#include "voc.h"
#include "vinifera_util.h"
#include "extension.h"
Expand Down Expand Up @@ -684,6 +686,56 @@ DECLARE_PATCH(_TechnoClass_Null_House_Warning_Patch)
}


/**
* #issue-356
*
* Enables the deploy keyboard command to work for units that
* transform into a different unit on deploy.
*
* @author: Rampastring
*/
DECLARE_PATCH(_TechnoClass_2A0_Is_Allowed_To_Deploy_Unit_Transform_Patch)
{
GET_REGISTER_STATIC(UnitTypeClass*, unittype, eax);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A space between the UnitTypeClass and * please.

static UnitTypeClassExtension* unittypeext;

/**
* Stolen bytes/code.
*/
if (unittype->DeploysInto != nullptr) {
goto has_deploy_ability;

} else if (unittype->MaxPassengers > 0) {
goto has_deploy_ability;

} else if (unittype->IsMobileEMP) {
goto has_deploy_ability;
}

unittypeext = Extension::Fetch<UnitTypeClassExtension>(unittype);

if (unittypeext->TransformsInto != nullptr) {
goto has_deploy_ability;
}

/**
* The unit has no ability that allows it to deploy / unload.
* Mark that and continue function after the check.
*/
has_no_deploy_ability:
_asm { mov eax, unittype }
JMP_REG(ecx, 0x006320E0);

/**
* The unit has some kind of an ability that allows it to deploy / unload.
* Continue function after the check.
*/
has_deploy_ability:
_asm { mov eax, unittype }
JMP_REG(ecx, 0x006320E5);
}


/**
* Main function for patching the hooks.
*/
Expand All @@ -703,4 +755,5 @@ void TechnoClassExtension_Hooks()
Patch_Jump(0x00630390, &_TechnoClass_Fire_At_Suicide_Patch);
Patch_Jump(0x00631223, &_TechnoClass_Fire_At_Electric_Bolt_Patch);
Patch_Jump(0x00636F09, &_TechnoClass_Is_Allowed_To_Retaliate_Can_Retaliate_Patch);
Patch_Jump(0x006320C2, &_TechnoClass_2A0_Is_Allowed_To_Deploy_Unit_Transform_Patch);
}
Loading