Phobos icon indicating copy to clipboard operation
Phobos copied to clipboard

[BugFix]Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix

Open NetsuNegi opened this issue 1 year ago • 10 comments

this is just a bugfix.

NetsuNegi avatar Sep 25 '24 02:09 NetsuNegi

Nightly build for this pull request:

This comment is automatic and is meant to allow guests to get latest nightly builds for this pull request without registering. It is updated on every successful build.

github-actions[bot] avatar Sep 25 '24 03:09 github-actions[bot]

Does this fix handle corner cases such as a Magnetron lifting a Chrono Miner out of a Service Depot while the Chrono Miner is being repaired? Does the Chrono Miner still work afterwards?

tyuah8 avatar Sep 25 '24 04:09 tyuah8

Does this fix handle corner cases such as a Magnetron lifting a Chrono Miner out of a Service Depot while the Chrono Miner is being repaired? Does the Chrono Miner still work afterwards?

no, but I'll try to fix it

NetsuNegi avatar Sep 25 '24 04:09 NetsuNegi

Does this fix handle corner cases such as a Magnetron lifting a Chrono Miner out of a Service Depot while the Chrono Miner is being repaired? Does the Chrono Miner still work afterwards?

Alright, idk how to fix it

NetsuNegi avatar Sep 25 '24 05:09 NetsuNegi

The following is code I am using for my own project.

static bool IsOnline ( TechnoClass* This )
{
	if (  This->Deactivated || This->IsUnderEMP() )
		return false;
	if (  auto Building = abstract_cast<BuildingClass*>( This ) )
	if ( !Building->IsPowerOnline() )
		return false;
	return true;
}

static void PowerOnIf ( ILocomotion* Locomotion )
{
	//
	LocomotionClass* Locomotor = static_cast<LocomotionClass*>( Locomotion );
	FootClass* Foot = Locomotor->LinkedTo;
	bool On = IsOnline( Foot );
	//

	if ( On ) Locomotor->Power_On ();
	else      Locomotor->Power_Off();
}

////

DEFINE_HOOK( 0x4AF94D,    DriveLocomotionClass__End_Piggyback__PowerOn, 0x7 )
{
	GET( ILocomotion**, Pointer, EDX );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x54DADC,  JumpjetLocomotionClass__End_Piggyback__PowerOn, 0x5 )
{
	GET( ILocomotion**, Pointer, EDI );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x69F05D,     ShipLocomotionClass__End_Piggyback__PowerOn, 0x7 )
{
	GET( ILocomotion**, Pointer, EDX );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x719F17, TeleportLocomotionClass__End_Piggyback__PowerOn, 0x5 )
{
	GET( ILocomotion**, Pointer, ESI );
	PowerOnIf( *Pointer );
	return NULL;
}

I don't remember if there is anything else that is needed...

...but what the above code is doing is detecting the end of a piggyback, and restoring power to the locomotor that was piggybacked.

By the way, if you do decide to use the code I provided, I don't believe your UnitClass_SetDestination_HarvesterFix is necessary anymore.


Here is an explanation for what the code above is doing:

A Chrono Miner uses the teleport locomotor, but switches to the drive locomotor when it is driving, and switches back when it is stationary. When it switches to the drive locomotor, the teleport locomotor becomes "piggybacked" onto the drive locomotor; and when it switches back to the teleport locomotor, the "piggybacking" ends, and the teleport locomotor is un-piggybacked from the drive locomotor.

When a Magnetron lifts a target, that target switches to the jumpjet locomotor, and whatever locomotor that target was using is "piggybacked" onto the jumpjet locomotor. When the target is dropped and hits the floor, that "piggybacked" locomotor is un-piggybacked and is restored.

You can think of piggybacking as a form of "backing-up" where the game, essentially, backs-up the previous locomotor so that it can be restored later.

The original game code did not power on a locomotor when it is un-piggybacked, so I wrote code to do the power on, which is the code you see above.

tyuah8 avatar Sep 25 '24 12:09 tyuah8

The following is code I am using for my own project.

static bool IsOnline ( TechnoClass* This )
{
	if (  This->Deactivated || This->IsUnderEMP() )
		return false;
	if (  auto Building = abstract_cast<BuildingClass*>( This ) )
	if ( !Building->IsPowerOnline() )
		return false;
	return true;
}

static void PowerOnIf ( ILocomotion* Locomotion )
{
	//
	LocomotionClass* Locomotor = static_cast<LocomotionClass*>( Locomotion );
	FootClass* Foot = Locomotor->LinkedTo;
	bool On = IsOnline( Foot );
	//

	if ( On ) Locomotor->Power_On ();
	else      Locomotor->Power_Off();
}

////

DEFINE_HOOK( 0x4AF94D,    DriveLocomotionClass__End_Piggyback__PowerOn, 0x7 )
{
	GET( ILocomotion**, Pointer, EDX );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x54DADC,  JumpjetLocomotionClass__End_Piggyback__PowerOn, 0x5 )
{
	GET( ILocomotion**, Pointer, EDI );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x69F05D,     ShipLocomotionClass__End_Piggyback__PowerOn, 0x7 )
{
	GET( ILocomotion**, Pointer, EDX );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x719F17, TeleportLocomotionClass__End_Piggyback__PowerOn, 0x5 )
{
	GET( ILocomotion**, Pointer, ESI );
	PowerOnIf( *Pointer );
	return NULL;
}

I don't remember if there is anything else that is needed...

...but what the above code is doing is detecting the end of a piggyback, and restoring power to the locomotor that was piggybacked.

By the way, if you do decide to use the code I provided, I don't believe your UnitClass_SetDestination_HarvesterFix is necessary anymore.

Here is an explanation for what the code above is doing:

A Chrono Miner uses the teleport locomotor, but switches to the drive locomotor when it is driving, and switches back when it is stationary. When it switches to the drive locomotor, the teleport locomotor becomes "piggybacked" onto the drive locomotor; and when it switches back to the teleport locomotor, the "piggybacking" ends, and the teleport locomotor is un-piggybacked from the drive locomotor.

When a Magnetron lifts a target, that target switches to the jumpjet locomotor, and whatever locomotor that target was using is "piggybacked" onto the jumpjet locomotor. When the target is dropped and hits the floor, that "piggybacked" locomotor is un-piggybacked and is restored.

You can think of piggybacking as a form of "backing-up" where the game, essentially, backs-up the previous locomotor so that it can be restored later.

The original game code did not power on a locomotor when it is un-piggybacked, so I wrote code to do the power on, which is the code you see above.

ok, I will test it soon

NetsuNegi avatar Sep 25 '24 13:09 NetsuNegi

The following is code I am using for my own project.

static bool IsOnline ( TechnoClass* This )
{
	if (  This->Deactivated || This->IsUnderEMP() )
		return false;
	if (  auto Building = abstract_cast<BuildingClass*>( This ) )
	if ( !Building->IsPowerOnline() )
		return false;
	return true;
}

static void PowerOnIf ( ILocomotion* Locomotion )
{
	//
	LocomotionClass* Locomotor = static_cast<LocomotionClass*>( Locomotion );
	FootClass* Foot = Locomotor->LinkedTo;
	bool On = IsOnline( Foot );
	//

	if ( On ) Locomotor->Power_On ();
	else      Locomotor->Power_Off();
}

////

DEFINE_HOOK( 0x4AF94D,    DriveLocomotionClass__End_Piggyback__PowerOn, 0x7 )
{
	GET( ILocomotion**, Pointer, EDX );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x54DADC,  JumpjetLocomotionClass__End_Piggyback__PowerOn, 0x5 )
{
	GET( ILocomotion**, Pointer, EDI );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x69F05D,     ShipLocomotionClass__End_Piggyback__PowerOn, 0x7 )
{
	GET( ILocomotion**, Pointer, EDX );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x719F17, TeleportLocomotionClass__End_Piggyback__PowerOn, 0x5 )
{
	GET( ILocomotion**, Pointer, ESI );
	PowerOnIf( *Pointer );
	return NULL;
}

I don't remember if there is anything else that is needed...

...but what the above code is doing is detecting the end of a piggyback, and restoring power to the locomotor that was piggybacked.

By the way, if you do decide to use the code I provided, I don't believe your UnitClass_SetDestination_HarvesterFix is necessary anymore.

Here is an explanation for what the code above is doing:

A Chrono Miner uses the teleport locomotor, but switches to the drive locomotor when it is driving, and switches back when it is stationary. When it switches to the drive locomotor, the teleport locomotor becomes "piggybacked" onto the drive locomotor; and when it switches back to the teleport locomotor, the "piggybacking" ends, and the teleport locomotor is un-piggybacked from the drive locomotor.

When a Magnetron lifts a target, that target switches to the jumpjet locomotor, and whatever locomotor that target was using is "piggybacked" onto the jumpjet locomotor. When the target is dropped and hits the floor, that "piggybacked" locomotor is un-piggybacked and is restored.

You can think of piggybacking as a form of "backing-up" where the game, essentially, backs-up the previous locomotor so that it can be restored later.

The original game code did not power on a locomotor when it is un-piggybacked, so I wrote code to do the power on, which is the code you see above.

works very better than my code

NetsuNegi avatar Sep 25 '24 13:09 NetsuNegi

The following is code I am using for my own project.

static bool IsOnline ( TechnoClass* This )
{
	if (  This->Deactivated || This->IsUnderEMP() )
		return false;
	if (  auto Building = abstract_cast<BuildingClass*>( This ) )
	if ( !Building->IsPowerOnline() )
		return false;
	return true;
}

static void PowerOnIf ( ILocomotion* Locomotion )
{
	//
	LocomotionClass* Locomotor = static_cast<LocomotionClass*>( Locomotion );
	FootClass* Foot = Locomotor->LinkedTo;
	bool On = IsOnline( Foot );
	//

	if ( On ) Locomotor->Power_On ();
	else      Locomotor->Power_Off();
}

////

DEFINE_HOOK( 0x4AF94D,    DriveLocomotionClass__End_Piggyback__PowerOn, 0x7 )
{
	GET( ILocomotion**, Pointer, EDX );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x54DADC,  JumpjetLocomotionClass__End_Piggyback__PowerOn, 0x5 )
{
	GET( ILocomotion**, Pointer, EDI );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x69F05D,     ShipLocomotionClass__End_Piggyback__PowerOn, 0x7 )
{
	GET( ILocomotion**, Pointer, EDX );
	PowerOnIf( *Pointer );
	return NULL;
}

DEFINE_HOOK( 0x719F17, TeleportLocomotionClass__End_Piggyback__PowerOn, 0x5 )
{
	GET( ILocomotion**, Pointer, ESI );
	PowerOnIf( *Pointer );
	return NULL;
}

I don't remember if there is anything else that is needed...

...but what the above code is doing is detecting the end of a piggyback, and restoring power to the locomotor that was piggybacked.

By the way, if you do decide to use the code I provided, I don't believe your UnitClass_SetDestination_HarvesterFix is necessary anymore.

Here is an explanation for what the code above is doing:

A Chrono Miner uses the teleport locomotor, but switches to the drive locomotor when it is driving, and switches back when it is stationary. When it switches to the drive locomotor, the teleport locomotor becomes "piggybacked" onto the drive locomotor; and when it switches back to the teleport locomotor, the "piggybacking" ends, and the teleport locomotor is un-piggybacked from the drive locomotor.

When a Magnetron lifts a target, that target switches to the jumpjet locomotor, and whatever locomotor that target was using is "piggybacked" onto the jumpjet locomotor. When the target is dropped and hits the floor, that "piggybacked" locomotor is un-piggybacked and is restored.

You can think of piggybacking as a form of "backing-up" where the game, essentially, backs-up the previous locomotor so that it can be restored later.

The original game code did not power on a locomotor when it is un-piggybacked, so I wrote code to do the power on, which is the code you see above.

How should I describe your bugfix and what is your signature?

NetsuNegi avatar Sep 25 '24 13:09 NetsuNegi

My... signature? You can just reference my username, which is tyuah8.

I explain the bug fix and why it works in my previous post. Basically the bug fix works by powering on locomotors when "piggybacking" ends (when we switch back to the piggybacked locomotor), and is needed because the Service Depot powered off the teleport locomotor.

You are free to mention my explanation as well as the reason for the fix and that is to get the Chrono Miner to work after using the Service Depot.

tyuah8 avatar Sep 25 '24 17:09 tyuah8

My... signature? You can just reference my username, which is tyuah8.

I explain the bug fix and why it works in my previous post. Basically the bug fix works by powering on locomotors when "piggybacking" ends (when we switch back to the piggybacked locomotor), and is needed because the Service Depot powered off the teleport locomotor.

You are free to mention my explanation as well as the reason for the fix and that is to get the Chrono Miner to work after using the Service Depot.

ok

NetsuNegi avatar Sep 26 '24 11:09 NetsuNegi

@NetsuNegi @tyuah8 Does this bugfix also allow using locomotors other than Jumpjet for magnetron weapon? For example Teleport locomotor in order to teleport enemy unit to oneself.

Not a requirement, just curious. Would be good to fix eventually.

Metadorius avatar Nov 11 '24 07:11 Metadorius

@NetsuNegi @tyuah8 Does this bugfix also allow using locomotors other than Jumpjet for magnetron weapon? For example Teleport locomotor in order to teleport enemy unit to oneself.

Not a requirement, just curious. Would be good to fix eventually.

No, this bugfix simply powers-on a locomotor when it is un-piggybacked and does not change the functionality of an IsLocomotor=yes warhead.

tyuah8 avatar Nov 11 '24 22:11 tyuah8