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

Fixed infantry 'Boxing' Mechanic #45

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
38 changes: 31 additions & 7 deletions TIBERIANDAWN/INFANTRY.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ void InfantryClass::Draw_It(int x, int y, WindowNumberType window)

#ifdef BOXING
// BG hack to get him to face right when he's supposed to.
if (IsBoxing && BodyFacing<128) shapenum += 47;
if (IsBoxing && facing < Facing_To_32(DIR_S)) shapenum += 47;
#endif

/*
Expand Down Expand Up @@ -1047,6 +1047,29 @@ void InfantryClass::AI(void)
return;
}

/*
** Catch infantry that may be stuck in Boxing animations and get them out of it
*/
if (!IsBoxing)
{
switch (Doing)
{
case DO_FIGHT_READY:
case DO_ON_GUARD:
case DO_PUNCH:
case DO_KICK:
case DO_PUNCH_HIT1:
case DO_PUNCH_HIT2:
case DO_KICK_HIT1:
case DO_KICK_HIT2:
Do_Action(DO_READY_WEAPON, true);
break;

default:
break;
}
}

/*
** Act on new orders if the unit is at a good position to do so.
*/
Expand Down Expand Up @@ -1143,7 +1166,7 @@ void InfantryClass::AI(void)
if (Is_Target_Infantry(TarCom) && (Distance(TarCom)<=0x80) && (Coord_Y(Coord) == Coord_Y(object->Coord))) {

// Too close to shoot, so start hand-to-hand combat
if (Establish_Contact((TechnoClass *)object)) {
if (Transmit_Message(RADIO_HELLO, (TechnoClass *)object) == RADIO_ROGER) {
if (Transmit_Message(RADIO_PREPARE_TO_BOX) == RADIO_ROGER) {
IsBoxing = true;
Do_Action(DO_ON_GUARD,true);
Expand Down Expand Up @@ -1269,7 +1292,7 @@ void InfantryClass::AI(void)
/*
** Perform movement operations at this time.
*/
if (!IsFiring /*&& !IsBoxing*/) {
if (!IsFiring && !IsBoxing) {
if (!IsDriving) {

/*
Expand Down Expand Up @@ -2364,7 +2387,8 @@ BulletClass * InfantryClass::Fire_At(TARGET target, int which)
** Fighting done for some reason, so pick up gun
*/
IsBoxing = false;
Do_Action(DO_READY_WEAPON,true);
if (Strength) // Make sure we haven't died in the meantime
Do_Action(DO_READY_WEAPON,true);
}
} else {
#endif
Expand Down Expand Up @@ -2776,8 +2800,8 @@ RadioMessageType InfantryClass::Receive_Message(RadioClass * from, RadioMessageT
if (IsBoxing) break;
#endif
if (Contact_With_Whom() == from) {
Do_Action(DO_ON_GUARD, true);
Assign_Target(Contact_With_Whom()->As_Target());
Do_Action(DO_ON_GUARD, true);
return(RADIO_ROGER);
}
return(RADIO_NEGATIVE);
Expand All @@ -2786,15 +2810,15 @@ RadioMessageType InfantryClass::Receive_Message(RadioClass * from, RadioMessageT
** Just received a kick! Take some damage.
*/
case RADIO_KICK:
damage = Infantry_Kick_Damage[Random_Pick(0, (int)(sizeof(Infantry_Kick_Damage) / sizeof(Infantry_Kick_Damage[0])))];
damage = Infantry_Kick_Damage[Random_Pick(0, (int)(sizeof(Infantry_Kick_Damage) / sizeof(Infantry_Kick_Damage[0])) - 1)];
Copy link

Choose a reason for hiding this comment

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

A classic off-by-one error. I wonder how many of those invalid reads are in the code.
Maybe create a macro/inline template to properly access such arrays?

#define MAX_ARRAY_INDEX(array) (int)(sizeof(array) / sizeof(array[0])) - 1

I out of C++ for several years but I am sure an inline template function could make this even more secure.

Copy link
Author

Choose a reason for hiding this comment

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

Yea, that's what I would have done ideally if this was a more active codebase. I was trying to fix these issues while touching as little as possible so it would be straight-forward for others to integrate without conflicts.

Choose a reason for hiding this comment

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

A classic off-by-one error. I wonder how many of those invalid reads are in the code.
Maybe create a macro/inline template to properly access such arrays?

#define MAX_ARRAY_INDEX(array) (int)(sizeof(array) / sizeof(array[0])) - 1

I out of C++ for several years but I am sure an inline template function could make this even more secure.

You probably want to wrap that inside another pair of parentheses in case you ever want to use an operator with a higher priority after using this macro. It is a little bit nitpicky and I don't see a real use of this happening in this project, but I prefer to be extra cautious when using macros.

Instead of:
#define MAX_ARRAY_INDEX(array) (int)(sizeof(array) / sizeof(array[0])) - 1
Use:
#define MAX_ARRAY_INDEX(array) ((int)(sizeof(array) / sizeof(array[0])) - 1)

A situation like this could return undesired side-effects (imagine an array size of 5, thus max index 4):
int a = MAX_ARRAY_INDEX(array) * 2; The intended value of 'a' is 8.
Would be understood as:
int a = (int)(sizeof(array) / sizeof(array[0])) - 1 * 2; The actual value of 'a' is 3.

Copy link

Choose a reason for hiding this comment

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

Correct, my code was made up on the fly and I mentioned there is probably a more typesafe way in C++ to do that.

if (Take_Damage(damage, 0, WARHEAD_FOOT, this) == RESULT_DESTROYED) return(RADIO_STATIC);
return(RADIO_ROGER);

/*
** Just recieved a punch! Take some damage.
*/
case RADIO_PUNCH:
damage = Infantry_Punch_Damage[Random_Pick(0, (int)(sizeof(Infantry_Punch_Damage) / sizeof(Infantry_Punch_Damage[0])))];
damage = Infantry_Punch_Damage[Random_Pick(0, (int)(sizeof(Infantry_Punch_Damage) / sizeof(Infantry_Punch_Damage[0])) - 1)];
if (Take_Damage(damage, 0, WARHEAD_FIST, this) == RESULT_DESTROYED) return(RADIO_STATIC);
return(RADIO_ROGER);

Expand Down