-
Notifications
You must be signed in to change notification settings - Fork 10
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
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
@@ -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) | ||
{ | ||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A space between the |
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A space between the |
||
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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
*/ | ||
|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A space between the |
||
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. | ||
*/ | ||
|
@@ -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); | ||
} |
There was a problem hiding this comment.
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
.