Skip to content

Commit

Permalink
add feature for aircraft in Q-attack-move-loop to remember their nav …
Browse files Browse the repository at this point in the history
…queue and return to it after reloading, bugfix for fixed-wing aircraft flying off the map if given a Q-attack-move-loop with only 1 detination in the loop.
  • Loading branch information
ChthonVII committed Aug 28, 2021
1 parent 45f0d3b commit d99cd25
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 1 deletion.
1 change: 1 addition & 0 deletions Mod Data RA/CCDATA/DEFAULT.CFEPATCHREDUX_RA.INI
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ATTACK_MOVE=1
CHRONOTANK_ATTACK_MOVE=1
QMOVE_LOOPS=1
AIR_QMOVE=1
AIR_QAML_RECALL=1
TANYA_GUARD=1
SAFE_SABOTAGE=1
SMARTER_AIRCRAFT=1
Expand Down
26 changes: 25 additions & 1 deletion REDALERT/AIRCRAFT.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,11 @@ AircraftClass::AircraftClass(AircraftType classid, HousesType house) :

// Chthon CFE Note: Initialize mod stuff here
TargetRecheckCounter = 0;

HasMemorizedNavQueue = false;
for (int index = 0; index < ARRAY_SIZE(MemorizedNavQueue); index++) {
MemorizedNavQueue[index] = TARGET_NONE;
}

}


Expand Down Expand Up @@ -945,6 +949,19 @@ void AircraftClass::AI(void)
}
}

// Chthon CFE Note: If we have a memorized nav list and our ammo is reloaded, then reload the nav list and take off
if ( HasMemorizedNavQueue &&
(Techno_Type_Class()->PrimaryWeapon != NULL) &&
!Class->PrimaryWeapon->IsCamera &&
(Class->MaxAmmo > 0) &&
(Ammo == Class->MaxAmmo) &&
(Height == 0) &&
!IsLanding &&
!IsTakingOff
){
Recall_Navigation_List();
}


/*
** A Mission change can always occur if the aircraft is landed or flying.
Expand Down Expand Up @@ -1756,6 +1773,7 @@ int AircraftClass::Mission_Move(void)

// Attack Move rework by ChthonVII -- If "smarter aircraft" mode is also enabled, don't attack move if you don't have any ammo to start with
if (AttackMove && ActiveCFEPatchConfig.EnableSmarterAircraft && !IsALoaner && !Ammo){
//Memorize_Navigation_List();
ResetAttackMove();
Clear_Navigation_List();
Enter_Idle_Mode();
Expand Down Expand Up @@ -1788,6 +1806,7 @@ int AircraftClass::Mission_Move(void)
// Make q-moves work
if (Target_Legal(NavQueue[0])){
if (AttackMove && !Ammo){
//Memorize_Navigation_List();
Clear_Navigation_List();
}
else {
Expand Down Expand Up @@ -1888,6 +1907,7 @@ int AircraftClass::Mission_Move(void)
case VALIDATE_LZ:
// Attack Move rework by ChthonVII -- If "smarter aircraft" mode is also enabled, don't attack move if you don't have any ammo to start with
if (AttackMove && ActiveCFEPatchConfig.EnableSmarterAircraft && !IsALoaner && !Ammo){
//Memorize_Navigation_List();
ResetAttackMove();
Clear_Navigation_List();
Enter_Idle_Mode();
Expand Down Expand Up @@ -1941,6 +1961,7 @@ int AircraftClass::Mission_Move(void)
// Make q-moves work
if (Target_Legal(NavQueue[0])){
if (AttackMove && !Ammo){
//Memorize_Navigation_List();
Clear_Navigation_List();
} else {
Assign_Destination(TARGET_NONE);
Expand Down Expand Up @@ -2047,6 +2068,7 @@ void AircraftClass::Enter_Idle_Mode(bool )
return;
}
else {
Memorize_Navigation_List();
ResetAttackMove();
Clear_Navigation_List();
}
Expand Down Expand Up @@ -2439,6 +2461,7 @@ void AircraftClass::Player_Assign_Mission(MissionType mission, TARGET target, TA
}
}

//Clear_Memorized_Navigation_List(); // move this to event.cpp so it follows the queue

Queue_Mission(TargetClass(this), mission, target, destination);
}
Expand Down Expand Up @@ -4677,3 +4700,4 @@ bool AircraftClass::DoSmarterRunAway(){
return false;

}

2 changes: 2 additions & 0 deletions REDALERT/AIRCRAFT.H
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ class AircraftClass : public FootClass, public FlyClass
// Chthon CFE Note: logic for exiting repair bay
bool DoSmarterRunAway();


public:

/*
Expand Down Expand Up @@ -252,6 +253,7 @@ class AircraftClass : public FootClass, public FlyClass
// Chthon CFE Note: Counter for helicopters to recheck target's location
public:
unsigned short int TargetRecheckCounter;

private:

/*
Expand Down
1 change: 1 addition & 0 deletions REDALERT/CFEUTIL.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ void Populate_CFE_Patch_Config_From_INI(const INIClass& ini)
GetSetting(ActiveCFEPatchConfig.EnableChronoTankAttackMove , "FEATURES", "CHRONOTANK_ATTACK_MOVE");
GetSetting(ActiveCFEPatchConfig.EnableQMoveLoops , "FEATURES", "QMOVE_LOOPS");
GetSetting(ActiveCFEPatchConfig.EnableAirQMove , "FEATURES", "AIR_QMOVE");
GetSetting(ActiveCFEPatchConfig.EnableAirQAMLRecall , "FEATURES", "AIR_QAML_RECALL");
GetSetting(ActiveCFEPatchConfig.EnableTanyaGuard , "FEATURES", "TANYA_GUARD");
GetSetting(ActiveCFEPatchConfig.EnableSafeSabotage , "FEATURES", "SAFE_SABOTAGE");
GetSetting(ActiveCFEPatchConfig.EnableSmarterAircraft , "FEATURES", "SMARTER_AIRCRAFT");
Expand Down
5 changes: 5 additions & 0 deletions REDALERT/EVENT.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,11 @@ void EventClass::Execute(void)
techno->Assign_Destination(Data.MegaMission.Destination.As_TARGET());
}
}

// always clear the memorized nav list when receiving a new order from the player
if (techno->Is_Foot()) {
((FootClass *)techno)->Clear_Memorized_Navigation_List();
}

//
// Special case for ship repairing: If the assigned mission is to
Expand Down
1 change: 1 addition & 0 deletions REDALERT/EXTERNS.H
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ struct CFEPatchConfig
bool EnableChronoTankAttackMove = false;
bool EnableQMoveLoops = false;
bool EnableAirQMove = false;
bool EnableAirQAMLRecall = false;
bool EnableTanyaGuard = false;
bool EnableSafeSabotage = false;
bool EnableSmarterAircraft = false;
Expand Down
112 changes: 112 additions & 0 deletions REDALERT/FOOT.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -2160,6 +2160,28 @@ void FootClass::Detach(TARGET target, bool all)
NavQueueOriginalHead = TARGET_NONE;
}

// copy/pasta to remove from the memorized Nav queue as well
loop_count = 0;
for (int index = 0; index < ARRAY_SIZE(MemorizedNavQueue); index++) {
if (MemorizedNavQueue[index] == target) {
MemorizedNavQueue[index] = TARGET_NONE;
if (index < ARRAY_SIZE(MemorizedNavQueue)-1) {
memmove(&MemorizedNavQueue[index], &MemorizedNavQueue[index+1], ((ARRAY_SIZE(MemorizedNavQueue)-index)-1) * sizeof(MemorizedNavQueue[0]));
MemorizedNavQueue[ARRAY_SIZE(MemorizedNavQueue)-1] = TARGET_NONE;
index--;
}
}
/*
** Extra safety check
*/
loop_count++;
if (loop_count > ARRAY_SIZE(MemorizedNavQueue)) {
break;
}
}



/*
** If targeting the specified object and this unit is obviously heading
** toward the target to get within range, then abort the path.
Expand Down Expand Up @@ -2444,6 +2466,10 @@ void FootClass::Handle_Navigation_List(void)
IsNavQueueLoop = false;
NavQueueOriginalHead = TARGET_NONE;
//CFE_Debug_Printf("unit %i breaking out of loop mode", this);
// the only way we can get here is double Q-clicking a destination, then not adding anything to the nav queue before the unit arrives there.
// So the destination we just popped will be our current location.
// So trash the destination to avoid issuing a move order with nowhere to go (really fuxxors fixed-wing planes)
Assign_Destination(TARGET_NONE);
}
// otherwise stick whatever we just popped onto the back of the queue
else {
Expand Down Expand Up @@ -3008,3 +3034,89 @@ BuildingClass* FootClass::Find_Docking_Bay(StructType b, bool friendly) const
}
return as_best ? as_best : direct_best;
}


// save the navigation list so it can be restored later
void FootClass::Memorize_Navigation_List(){

// just return if we aren't doing a Q-attack-move-loop, since that's the only context we want this
if ( !ActiveCFEPatchConfig.EnableAirQAMLRecall ||
!AttackMove ||
!IsNavQueueLoop ||
!Target_Legal(NavQueue[0]) ||
!Target_Legal(NavQueue[1])
){
return;
}

// save the list (we're assuming both lists are the same size; don't change that!)
memcpy(&MemorizedNavQueue[0], &NavQueue[0], sizeof(MemorizedNavQueue));

// set a flag
HasMemorizedNavQueue = true;

// roll the list around until the original head is at the front of the list
while (MemorizedNavQueue[0] != NavQueueOriginalHead){
TARGET target = MemorizedNavQueue[0];
memmove(&MemorizedNavQueue[0], &MemorizedNavQueue[1], sizeof(MemorizedNavQueue)-sizeof(MemorizedNavQueue[0]));
MemorizedNavQueue[ARRAY_SIZE(MemorizedNavQueue)-1] = TARGET_NONE;
for (int index = 0; index < ARRAY_SIZE(MemorizedNavQueue); index++) {
if (MemorizedNavQueue[index] == TARGET_NONE) {
MemorizedNavQueue[index] = target;
break;
}
}
}

return;
}

// copies memorized nav list back and restarts Q-attack-move-loop
void FootClass::Recall_Navigation_List(){

// restore attack-move
AttackMove = true;
RememberedNavCom = MemorizedNavQueue[0];

// restore loop
IsNavQueueLoop = true;
NavQueueOriginalHead = MemorizedNavQueue[0];

// copy the list (we're assuming both lists are the same size; don't change that!)
memcpy(&NavQueue[0], &MemorizedNavQueue[0], sizeof(NavQueue));

// advance the list one step to put the current destination in the back
TARGET target = NavQueue[0];
memmove(&NavQueue[0], &NavQueue[1], sizeof(NavQueue)-sizeof(NavQueue[0]));
NavQueue[ARRAY_SIZE(NavQueue)-1] = TARGET_NONE;
for (int index = 0; index < ARRAY_SIZE(NavQueue); index++) {
if (NavQueue[index] == TARGET_NONE) {
NavQueue[index] = target;
break;
}
}

// clear the old list & flag
Clear_Memorized_Navigation_List();

// start moving
Assign_Target(TARGET_NONE);
Assign_Destination(RememberedNavCom);
Assign_Mission(MISSION_MOVE);

return;
}

void FootClass::Clear_Memorized_Navigation_List(){

// clear the old list
for (int index = 0; index < ARRAY_SIZE(MemorizedNavQueue); index++) {
MemorizedNavQueue[index] = TARGET_NONE;
}

// clear the flag
HasMemorizedNavQueue = false;

return;
}

11 changes: 11 additions & 0 deletions REDALERT/FOOT.H
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,11 @@ class FootClass : public TechnoClass
// Chthon CFE Note: make this public too
int Passable_Cell(CELL cell, FacingType face, int threat, MoveType threshhold) const;

// Chthon CFE Note: Memorize and recall nav list (presently only used by aircraft)
void Memorize_Navigation_List();
void Recall_Navigation_List();
void Clear_Memorized_Navigation_List();

private:
PathType * Find_Path(CELL dest, FacingType *final_moves, int maxlen, MoveType threshhold);
//int Find_Path_AStar(PathType* const resultPath, const CELL source, CELL dest, const int maxLen, const MoveType threshhold, const int threat) const;
Expand All @@ -392,6 +397,12 @@ class FootClass : public TechnoClass
public:
TARGET NavQueueOriginalHead;
unsigned char SkipNavQueueUpdate; // could make this a bitfield if we need more space someday

// Stuff for memorizing nav list
// This won't fit in the available padding, so we're just going to have to break savegame compatibility
bool HasMemorizedNavQueue;
TARGET MemorizedNavQueue[10];

private:

/*
Expand Down

0 comments on commit d99cd25

Please sign in to comment.