August patch integration: Merge branch 'master' of https://github.com/electronicarts/CnC_Remastered_Collection

This commit is contained in:
Justin Marshall
2020-08-06 15:35:00 -07:00
33 changed files with 473 additions and 93 deletions
+2 -2
View File
@@ -359,7 +359,7 @@ static AnimTypeClass const LZSmoke(
72, // Loop start frame number. 72, // Loop start frame number.
91, // Ending frame of loop back. 91, // Ending frame of loop back.
-1, // Number of animation stages. -1, // Number of animation stages.
255, // Number of times the animation loops. 127, // Number of times the animation loops.
VOC_NONE, // Sound effect to play. VOC_NONE, // Sound effect to play.
ANIM_NONE ANIM_NONE
); );
@@ -1127,7 +1127,7 @@ static AnimTypeClass const OilFieldBurn(
33, // Loop start frame number. 33, // Loop start frame number.
99, // Ending frame of loop back. 99, // Ending frame of loop back.
66, // Number of animation stages. 66, // Number of animation stages.
65535, // Number of times the animation loops. 127, // Number of times the animation loops.
VOC_NONE, // Sound effect to play. VOC_NONE, // Sound effect to play.
ANIM_NONE ANIM_NONE
); );
+14 -5
View File
@@ -1955,9 +1955,17 @@ void AircraftClass::Enter_Idle_Mode(bool )
/* /*
** Normal aircraft try to find a good landing spot to rest. ** Normal aircraft try to find a good landing spot to rest.
*/ */
BuildingClass * building = Find_Docking_Bay(Class->Building, false); BuildingClass * building = NULL;
if (In_Radio_Contact() && Contact_With_Whom()->What_Am_I() == RTTI_BUILDING) {
building = (BuildingClass *)Contact_With_Whom();
} else {
building = Find_Docking_Bay(Class->Building, false);
if (Transmit_Message(RADIO_HELLO, building) != RADIO_ROGER) {
building = NULL;
}
}
Assign_Destination(TARGET_NONE); Assign_Destination(TARGET_NONE);
if (building != NULL && Transmit_Message(RADIO_HELLO, building) == RADIO_ROGER) { if (building != NULL) {
if (Class->IsFixedWing) { if (Class->IsFixedWing) {
Status = 0; //BG - reset the mission status to avoid landing on the ground next to the airstrip Status = 0; //BG - reset the mission status to avoid landing on the ground next to the airstrip
if (IsLanding) { if (IsLanding) {
@@ -2374,7 +2382,7 @@ ActionType AircraftClass::What_Action(CELL cell) const
ActionType action = FootClass::What_Action(cell); ActionType action = FootClass::What_Action(cell);
//using function for IsVisible so we have different results for different players - JAS 2019/09/30 //using function for IsVisible so we have different results for different players - JAS 2019/09/30
if (action == ACTION_MOVE && !Map[cell].Is_Visible(PlayerPtr)) { if ((action == ACTION_MOVE || action == ACTION_ATTACK) && !Map[cell].Is_Visible(PlayerPtr)) {
action = ACTION_NOMOVE; action = ACTION_NOMOVE;
} }
@@ -3075,7 +3083,7 @@ MoveType AircraftClass::Can_Enter_Cell(CELL cell, FacingType ) const
if (occupier == NULL || if (occupier == NULL ||
!occupier->Is_Techno() || !occupier->Is_Techno() ||
((TechnoClass *)occupier)->House->Is_Ally(House) || ((TechnoClass *)occupier)->House->Is_Ally(House) ||
(((TechnoClass *)occupier)->Cloak != CLOAKED && (!((TechnoClass *)occupier)->Is_Cloaked(this) &&
(ScenarioInit == 0 && (occupier->What_Am_I() != RTTI_BUILDING || !((BuildingClass*)occupier)->Class->IsInvisible)) ) (ScenarioInit == 0 && (occupier->What_Am_I() != RTTI_BUILDING || !((BuildingClass*)occupier)->Class->IsInvisible)) )
) { ) {
@@ -3135,9 +3143,10 @@ TARGET AircraftClass::Good_Fire_Location(TARGET target) const
for (int face = 0; face < 255; face += 16) { for (int face = 0; face < 255; face += 16) {
COORDINATE newcoord = Coord_Move(tcoord, (DirType)face, r); COORDINATE newcoord = Coord_Move(tcoord, (DirType)face, r);
CELL newcell = Coord_Cell(newcoord); CELL newcell = Coord_Cell(newcoord);
CELL actualcell = Coord_Cell(Coord_Sub(newcoord, XY_Coord(0, FLIGHT_LEVEL)));
//using function for IsVisible so we have different results for different players - JAS 2019/09/30 //using function for IsVisible so we have different results for different players - JAS 2019/09/30
if (Map.In_Radar(newcell) && (Session.Type != GAME_NORMAL || Map[newcell].Is_Visible(PlayerPtr)) && Cell_Seems_Ok(newcell, true)) { if (Map.In_Radar(actualcell) && (Session.Type != GAME_NORMAL || Map[newcell].Is_Visible(PlayerPtr)) && Cell_Seems_Ok(newcell, true)) {
int dist; int dist;
if (altcoord != 0) { if (altcoord != 0) {
dist = ::Distance(newcoord, altcoord); dist = ::Distance(newcoord, altcoord);
+7 -3
View File
@@ -578,7 +578,7 @@ IsTheaterShape = false;
AnimClass::Unlimbo(coord); AnimClass::Unlimbo(coord);
VisibleFlags = 0xffff; VisibleFlags = static_cast<unsigned int>(-1);
/* /*
** Drop zone smoke always reveals the map around itself. ** Drop zone smoke always reveals the map around itself.
@@ -817,10 +817,10 @@ void AnimClass::AI(void)
int damage = Accum; int damage = Accum;
Accum -= damage; Accum -= damage;
if (As_Object(xObject)->Take_Damage(damage, 0, WARHEAD_FIRE) == RESULT_DESTROYED) { if (As_Object(xObject)->Take_Damage(damage, 0, WARHEAD_FIRE) == RESULT_DESTROYED) {
delete this;
if (Target_Legal(VirtualAnimTarget)) { if (Target_Legal(VirtualAnimTarget)) {
delete As_Animation(VirtualAnimTarget); delete As_Animation(VirtualAnimTarget);
} }
delete this;
return; return;
} }
} }
@@ -1177,8 +1177,12 @@ void AnimClass::Detach(TARGET target, bool all)
assert(IsActive); assert(IsActive);
if (all) { if (all) {
if (VirtualAnimTarget && VirtualAnimTarget == target) { if (Target_Legal(VirtualAnimTarget) && VirtualAnimTarget == target) {
VirtualAnimTarget = TARGET_NONE; VirtualAnimTarget = TARGET_NONE;
if (IsInvisible) {
IsToDelete = true;
Mark(MARK_UP);
}
} }
if (xObject == target) { if (xObject == target) {
Map.Remove(this, In_Which_Layer()); Map.Remove(this, In_Which_Layer());
+19 -4
View File
@@ -173,7 +173,7 @@ RadioMessageType BuildingClass::Receive_Message(RadioClass * from, RadioMessageT
case RADIO_CAN_LOAD: case RADIO_CAN_LOAD:
TechnoClass::Receive_Message(from, message, param); TechnoClass::Receive_Message(from, message, param);
if (!House->Is_Ally(from)) return(RADIO_STATIC); if (!House->Is_Ally(from)) return(RADIO_STATIC);
if (Mission == MISSION_CONSTRUCTION || Mission == MISSION_DECONSTRUCTION || BState == BSTATE_CONSTRUCTION || (!ScenarioInit && In_Radio_Contact() && Contact_With_Whom() != from)) return(RADIO_NEGATIVE); if (Mission == MISSION_CONSTRUCTION || Mission == MISSION_DECONSTRUCTION || BState == BSTATE_CONSTRUCTION || (!ScenarioInit && Class->Type != STRUCT_REFINERY && In_Radio_Contact())) return(RADIO_NEGATIVE);
switch (Class->Type) { switch (Class->Type) {
case STRUCT_AIRSTRIP: case STRUCT_AIRSTRIP:
if (from->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass const *)from)->Class->IsFixedWing) { if (from->What_Am_I() == RTTI_AIRCRAFT && ((AircraftClass const *)from)->Class->IsFixedWing) {
@@ -200,7 +200,7 @@ RadioMessageType BuildingClass::Receive_Message(RadioClass * from, RadioMessageT
*((UnitClass *)from) == UNIT_HARVESTER && *((UnitClass *)from) == UNIT_HARVESTER &&
(ScenarioInit || !Is_Something_Attached())) { (ScenarioInit || !Is_Something_Attached())) {
return(RADIO_ROGER); return((Contact_With_Whom() != from) ? RADIO_ROGER : RADIO_NEGATIVE);
} }
break; break;
@@ -2588,13 +2588,21 @@ void BuildingClass::Grand_Opening(bool captured)
** to place it in a nearby location. ** to place it in a nearby location.
*/ */
if (!unit->Unlimbo(Cell_Coord(cell), DIR_W)) { if (!unit->Unlimbo(Cell_Coord(cell), DIR_W)) {
cell = unit->Nearby_Location(this); /*
** Check multiple times for clear locations.
*/
for (int i = 0; i < 10; i++) {
cell = unit->Nearby_Location(this, i);
if (unit->Unlimbo(Cell_Coord(cell), DIR_SW)) {
break;
}
}
/* /*
** If the harvester could still not be placed, then refund the money ** If the harvester could still not be placed, then refund the money
** to the owner and then bail. ** to the owner and then bail.
*/ */
if (!unit->Unlimbo(Cell_Coord(cell), DIR_SW)) { if (unit->IsInLimbo) {
House->Refund_Money(unit->Class->Cost_Of()); House->Refund_Money(unit->Class->Cost_Of());
delete unit; delete unit;
} }
@@ -3742,9 +3750,16 @@ int BuildingClass::Mission_Deconstruction(void)
} }
} }
// MBL 07.10.2020 - In 1v1, sometimes both players will hear this SFX, or neither player will hear it
// Making it so all players hear it positionally in the map; Per thread discussion in https://jaas.ea.com/browse/TDRA-7245
//
#if 0
if (House->IsPlayerControl) { if (House->IsPlayerControl) {
Sound_Effect(VOC_CASHTURN, Coord); Sound_Effect(VOC_CASHTURN, Coord);
} }
#else
Sound_Effect(VOC_CASHTURN, Coord);
#endif
/* /*
** Destroy all attached objects. ST - 4/24/2020 9:38PM ** Destroy all attached objects. ST - 4/24/2020 9:38PM
+11 -2
View File
@@ -2818,10 +2818,19 @@ void CellClass::Flag_Create(void)
{ {
if (!CTFFlag) { if (!CTFFlag) {
CTFFlag = new AnimClass(ANIM_FLAG, Cell_Coord()); CTFFlag = new AnimClass(ANIM_FLAG, Cell_Coord());
if (CTFFlag) { if (CTFFlag == NULL) {
CTFFlag->OwnerHouse = Owner; for (int i = 0; i < Anims.Count(); ++i) {
AnimClass* anim = Anims.Ptr(i);
if (*anim != ANIM_FLAG) {
delete anim;
break;
} }
} }
CTFFlag = new AnimClass(ANIM_FLAG, Cell_Coord());
}
assert(CTFFlag != NULL);
CTFFlag->OwnerHouse = Owner;
}
} }
+9
View File
@@ -3618,6 +3618,15 @@ typedef enum OptionControlType : char {
} OptionControlType; } OptionControlType;
/****************************************************************************
** Used to store firing data for a unit.
*/
typedef struct {
COORDINATE Center;
int Distance;
} FireDataType;
#define size_of(typ,id) sizeof(((typ*)0)->id) #define size_of(typ,id) sizeof(((typ*)0)->id)
+2 -2
View File
@@ -3122,9 +3122,9 @@ int DisplayClass::TacticalClass::Action(unsigned flags, KeyNumType & key)
object = Map.Close_Object(coord); object = Map.Close_Object(coord);
/* /*
** Special case check to ignore cloaked object if not owned by the player. ** Special case check to ignore cloaked object if not allied with the player.
*/ */
if (object != NULL && object->Is_Techno() && !((TechnoClass *)object)->IsOwnedByPlayer && (((TechnoClass *)object)->Cloak == CLOAKED || ((TechnoClass *)object)->Techno_Type_Class()->IsInvisible)) { if (object != NULL && object->Is_Techno() && ((TechnoClass *)object)->Is_Cloaked(PlayerPtr, true)) {
object = NULL; object = NULL;
} }
} }
+78 -4
View File
@@ -384,6 +384,8 @@ bool MPSuperWeaponDisable = false;
bool ShareAllyVisibility = true; bool ShareAllyVisibility = true;
bool UseGlyphXStartLocations = true; bool UseGlyphXStartLocations = true;
SpecialClass* SpecialBackup = NULL;
int GetRandSeed() int GetRandSeed()
{ {
@@ -670,6 +672,8 @@ extern "C" __declspec(dllexport) bool __cdecl CNC_Set_Multiplayer_Data(int scena
Special.IsEarlyWin = game_options.DestroyStructures; Special.IsEarlyWin = game_options.DestroyStructures;
Special.ModernBalance = game_options.ModernBalance;
/* /*
** Enable Counterstrike/Aftermath units ** Enable Counterstrike/Aftermath units
*/ */
@@ -714,6 +718,13 @@ extern "C" __declspec(dllexport) bool __cdecl CNC_Set_Multiplayer_Data(int scena
*/ */
Rule.IsSmartDefense = true; Rule.IsSmartDefense = true;
/*
** Backup special
*/
if (SpecialBackup != NULL) {
memcpy(SpecialBackup, &Special, sizeof(SpecialClass));
}
return true; return true;
} }
@@ -1538,6 +1549,13 @@ extern "C" __declspec(dllexport) bool __cdecl CNC_Advance_Instance(uint64 player
DLLExportClass::Set_Player_Context(DLLExportClass::GlyphxPlayerIDs[0]); DLLExportClass::Set_Player_Context(DLLExportClass::GlyphxPlayerIDs[0]);
} }
/*
** Restore special from backup
*/
if (SpecialBackup != NULL) {
memcpy(&Special, SpecialBackup, sizeof(SpecialClass));
}
#ifdef FIXIT_CSII // checked - ajw 9/28/98 #ifdef FIXIT_CSII // checked - ajw 9/28/98
TimeQuake = PendingTimeQuake; TimeQuake = PendingTimeQuake;
PendingTimeQuake = false; PendingTimeQuake = false;
@@ -1730,6 +1748,15 @@ extern "C" __declspec(dllexport) bool __cdecl CNC_Advance_Instance(uint64 player
//Sync_Delay(); //Sync_Delay();
//DLLExportClass::Set_Event_Callback(NULL); //DLLExportClass::Set_Event_Callback(NULL);
Color_Cycle(); Color_Cycle();
/*
** Don't respect GameActive. Game will end in multiplayer on win/loss
*/
if (GAME_TO_PLAY == GAME_GLYPHX_MULTIPLAYER) {
return true;
}
return(GameActive); return(GameActive);
} }
@@ -1776,6 +1803,12 @@ extern "C" __declspec(dllexport) bool __cdecl CNC_Save_Load(bool save, const cha
result = Load_Game(file_path_and_name); result = Load_Game(file_path_and_name);
// MBL 07.21.2020
if (result == false)
{
return false;
}
DLLExportClass::Set_Player_Context(DLLExportClass::GlyphxPlayerIDs[0], true); DLLExportClass::Set_Player_Context(DLLExportClass::GlyphxPlayerIDs[0], true);
Set_Logic_Page(SeenBuff); Set_Logic_Page(SeenBuff);
VisiblePage.Clear(); VisiblePage.Clear();
@@ -1995,6 +2028,11 @@ void DLLExportClass::Init(void)
CurrentLocalPlayerIndex = 0; CurrentLocalPlayerIndex = 0;
MessagesSent.clear(); MessagesSent.clear();
if (SpecialBackup == NULL) {
SpecialBackup = new SpecialClass;
}
memcpy(SpecialBackup, &Special, sizeof(SpecialClass));
} }
@@ -2011,6 +2049,9 @@ void DLLExportClass::Init(void)
**************************************************************************************************/ **************************************************************************************************/
void DLLExportClass::Shutdown(void) void DLLExportClass::Shutdown(void)
{ {
delete SpecialBackup;
SpecialBackup = NULL;
for (int i=0 ; i<ModSearchPaths.Count() ; i++) { for (int i=0 ; i<ModSearchPaths.Count() ; i++) {
delete [] ModSearchPaths[i]; delete [] ModSearchPaths[i];
} }
@@ -3117,6 +3158,7 @@ void DLL_Draw_Pip_Intercept(const ObjectClass* object, int pip)
void DLLExportClass::DLL_Draw_Intercept(int shape_number, int x, int y, int width, int height, int flags, const ObjectClass *object, DirType rotation, long scale, const char *shape_file_name, char override_owner) void DLLExportClass::DLL_Draw_Intercept(int shape_number, int x, int y, int width, int height, int flags, const ObjectClass *object, DirType rotation, long scale, const char *shape_file_name, char override_owner)
{ {
CNCObjectStruct& new_object = ObjectList->Objects[TotalObjectCount + CurrentDrawCount]; CNCObjectStruct& new_object = ObjectList->Objects[TotalObjectCount + CurrentDrawCount];
memset(&new_object, 0, sizeof(new_object));
Convert_Type(object, new_object); Convert_Type(object, new_object);
if (new_object.Type == UNKNOWN) { if (new_object.Type == UNKNOWN) {
return; return;
@@ -4259,6 +4301,8 @@ bool DLLExportClass::Get_Sidebar_State(uint64 player_id, unsigned char *buffer_i
return false; return false;
} }
memset(&sidebar_entry, 0, sizeof(sidebar_entry));
sidebar_entry.AssetName[0] = 0; sidebar_entry.AssetName[0] = 0;
sidebar_entry.Type = UNKNOWN; sidebar_entry.Type = UNKNOWN;
sidebar_entry.BuildableID = Map.Column[c].Buildables[b].BuildableID; sidebar_entry.BuildableID = Map.Column[c].Buildables[b].BuildableID;
@@ -4271,7 +4315,7 @@ bool DLLExportClass::Get_Sidebar_State(uint64 player_id, unsigned char *buffer_i
sidebar_entry.SuperWeaponType = SW_NONE; sidebar_entry.SuperWeaponType = SW_NONE;
if (tech) { if (tech) {
sidebar_entry.Cost = tech->Cost * PlayerPtr->CostBias; sidebar_entry.Cost = tech->Cost * PlayerPtr->CostBias; // MBL: If this gets modified, also modify below for skirmish and multiplayer
sidebar_entry.PowerProvided = 0; sidebar_entry.PowerProvided = 0;
sidebar_entry.BuildTime = tech->Time_To_Build(PlayerPtr->Class->House); // sidebar_entry.BuildTime = tech->Time_To_Build() / 60; sidebar_entry.BuildTime = tech->Time_To_Build(PlayerPtr->Class->House); // sidebar_entry.BuildTime = tech->Time_To_Build() / 60;
strncpy(sidebar_entry.AssetName, tech->IniName, CNC_OBJECT_ASSET_NAME_LENGTH); strncpy(sidebar_entry.AssetName, tech->IniName, CNC_OBJECT_ASSET_NAME_LENGTH);
@@ -4414,6 +4458,8 @@ bool DLLExportClass::Get_Sidebar_State(uint64 player_id, unsigned char *buffer_i
return false; return false;
} }
memset(&sidebar_entry, 0, sizeof(sidebar_entry));
sidebar_entry.AssetName[0] = 0; sidebar_entry.AssetName[0] = 0;
sidebar_entry.Type = UNKNOWN; sidebar_entry.Type = UNKNOWN;
sidebar_entry.BuildableID = context_sidebar->Column[c].Buildables[b].BuildableID; sidebar_entry.BuildableID = context_sidebar->Column[c].Buildables[b].BuildableID;
@@ -4426,7 +4472,13 @@ bool DLLExportClass::Get_Sidebar_State(uint64 player_id, unsigned char *buffer_i
sidebar_entry.SuperWeaponType = SW_NONE; sidebar_entry.SuperWeaponType = SW_NONE;
if (tech) { if (tech) {
sidebar_entry.Cost = tech->Cost;
// MBL 06.22.2020 - Updated to apply and difficulty abd/or faction price modifier; See https://jaas.ea.com/browse/TDRA-6864
// If this gets modified, also modify above for non-skirmish / non-multiplayer
//
// sidebar_entry.Cost = tech->Cost;
sidebar_entry.Cost = tech->Cost * PlayerPtr->CostBias;
sidebar_entry.PowerProvided = 0; sidebar_entry.PowerProvided = 0;
sidebar_entry.BuildTime = tech->Time_To_Build(PlayerPtr->Class->House); // sidebar_entry.BuildTime = tech->Time_To_Build() / 60; sidebar_entry.BuildTime = tech->Time_To_Build(PlayerPtr->Class->House); // sidebar_entry.BuildTime = tech->Time_To_Build() / 60;
strncpy(sidebar_entry.AssetName, tech->IniName, CNC_OBJECT_ASSET_NAME_LENGTH); strncpy(sidebar_entry.AssetName, tech->IniName, CNC_OBJECT_ASSET_NAME_LENGTH);
@@ -8345,10 +8397,16 @@ bool DLLExportClass::Save(Pipe & pipe)
pipe.Put(&Special, sizeof(Special)); pipe.Put(&Special, sizeof(Special));
/*
** Special case for MPSuperWeaponDisable - store negated value so it defaults to enabled
*/
bool not_allow_super_weapons = !MPSuperWeaponDisable;
pipe.Put(&not_allow_super_weapons, sizeof(not_allow_super_weapons));
/* /*
** Room for save game expansion ** Room for save game expansion
*/ */
unsigned char padding[4096]; unsigned char padding[4095];
memset(padding, 0, sizeof(padding)); memset(padding, 0, sizeof(padding));
pipe.Put(padding, sizeof(padding)); pipe.Put(padding, sizeof(padding));
@@ -8431,7 +8489,23 @@ bool DLLExportClass::Load(Straw & file)
return false; return false;
} }
unsigned char padding[4096]; /*
** Restore backup
*/
if (SpecialBackup != NULL) {
memcpy(SpecialBackup, &Special, sizeof(SpecialClass));
}
/*
** Special case for MPSuperWeaponDisable - store negated value so it defaults to enabled
*/
bool not_allow_super_weapons = false;
if (file.Get(&not_allow_super_weapons, sizeof(not_allow_super_weapons)) != sizeof(not_allow_super_weapons)) {
return false;
}
MPSuperWeaponDisable = !not_allow_super_weapons;
unsigned char padding[4095];
if (file.Get(padding, sizeof(padding)) != sizeof(padding)) { if (file.Get(padding, sizeof(padding)) != sizeof(padding)) {
return false; return false;
+2 -1
View File
@@ -732,7 +732,7 @@ struct CNCMultiplayerOptionsStruct {
int MPlayerCount; // # of human players in this game int MPlayerCount; // # of human players in this game
int MPlayerBases; // 1 = bases are on for this scenario int MPlayerBases; // 1 = bases are on for this scenario
int MPlayerCredits; // # credits everyone gets int MPlayerCredits; // # credits everyone gets
int MPlayerTiberium; // 1 = tiberium enabled for this scenario int MPlayerTiberium; // >0 = tiberium enabled for this scenario
int MPlayerGoodies; // 1 = goodies enabled for this scenario int MPlayerGoodies; // 1 = goodies enabled for this scenario
int MPlayerGhosts; // 1 = houses with no players will still play int MPlayerGhosts; // 1 = houses with no players will still play
int MPlayerSolo; // 1 = allows a single-player net game int MPlayerSolo; // 1 = allows a single-player net game
@@ -744,6 +744,7 @@ struct CNCMultiplayerOptionsStruct {
bool MPlayerAftermathUnits; bool MPlayerAftermathUnits;
bool CaptureTheFlag; bool CaptureTheFlag;
bool DestroyStructures; // New early win condition via destroying all a player's structures bool DestroyStructures; // New early win condition via destroying all a player's structures
bool ModernBalance;
}; };
+7 -1
View File
@@ -603,7 +603,7 @@ void EventClass::Execute(void)
//2019/09/19 JAS - Visibility needs to be determined per player //2019/09/19 JAS - Visibility needs to be determined per player
if (Data.Anim.Owner == HOUSE_NONE || Data.Anim.What != ANIM_MOVE_FLASH) if (Data.Anim.Owner == HOUSE_NONE || Data.Anim.What != ANIM_MOVE_FLASH)
{ {
anim->Set_Visible_Flags(0xffff); anim->Set_Visible_Flags(static_cast<unsigned int>(-1));
} }
else else
{ {
@@ -761,6 +761,12 @@ void EventClass::Execute(void)
techno->Assign_Target(TARGET_NONE); techno->Assign_Target(TARGET_NONE);
techno->Assign_Destination(Data.MegaMission.Target.As_TARGET()); techno->Assign_Destination(Data.MegaMission.Target.As_TARGET());
techno->ArchiveTarget = Data.MegaMission.Target.As_TARGET(); techno->ArchiveTarget = Data.MegaMission.Target.As_TARGET();
} else if (Data.MegaMission.Mission == MISSION_ENTER &&
object != NULL &&
object->What_Am_I() == RTTI_BUILDING &&
*((BuildingClass*)object) == STRUCT_REFINERY) {
techno->Transmit_Message(RADIO_HELLO, (BuildingClass*)object);
techno->Assign_Destination(TARGET_NONE);
} else { } else {
if (q && techno->Is_Foot()) { if (q && techno->Is_Foot()) {
((FootClass *)techno)->Queue_Navigation_List(Data.MegaMission.Destination.As_TARGET()); ((FootClass *)techno)->Queue_Navigation_List(Data.MegaMission.Destination.As_TARGET());
+12
View File
@@ -1741,8 +1741,20 @@ int FootClass::Mission_Enter(void)
** Since there is no potential object to enter, then abort this ** Since there is no potential object to enter, then abort this
** mission with some default standby mission. ** mission with some default standby mission.
*/ */
if (MissionQueue == MISSION_NONE) {
/*
** If this is a harvester, then return to harvesting.
** Set a hacky target so we know to skip to the proper state.
*/
if (What_Am_I() == RTTI_UNIT && ((UnitClass*)this)->Class->IsToHarvest) {
Assign_Mission(MISSION_HARVEST);
Assign_Target(As_Target());
Assign_Destination(TARGET_NONE);
} else {
Enter_Idle_Mode(); Enter_Idle_Mode();
} }
}
}
return(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2)); return(MissionControl[Mission].Normal_Delay() + Random_Pick(0, 2));
} }
+83 -9
View File
@@ -923,7 +923,7 @@ void HouseClass::AI(void)
** production and team creation as well. This is also true if the IQ is high enough to ** production and team creation as well. This is also true if the IQ is high enough to
** being base building. ** being base building.
*/ */
if (IsBaseBuilding || IQ >= Rule.IQProduction) { if (!IsHuman && (IsBaseBuilding || IQ >= Rule.IQProduction)) {
IsBaseBuilding = true; IsBaseBuilding = true;
IsStarted = true; IsStarted = true;
IsAlerted = true; IsAlerted = true;
@@ -959,6 +959,9 @@ void HouseClass::AI(void)
if (IsToDie && BorrowedTime == 0) { if (IsToDie && BorrowedTime == 0) {
IsToDie = false; IsToDie = false;
Blowup_All(); Blowup_All();
if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
MPlayer_Defeated();
}
} }
/* /*
@@ -1153,7 +1156,7 @@ void HouseClass::AI(void)
} }
#ifdef FIXIT_VERSION_3 // For endgame auto-sonar pulse. #ifdef FIXIT_VERSION_3 // For endgame auto-sonar pulse.
if( Scen.AutoSonarTimer == 0 ) if( (Session.Type != GAME_NORMAL || !IsHuman) && Scen.AutoSonarTimer == 0 )
{ {
// If house has nothing but subs left, do an automatic sonar pulse to reveal them. // If house has nothing but subs left, do an automatic sonar pulse to reveal them.
if( VQuantity[ VESSEL_SS ] > 0 ) // Includes count of VESSEL_MISSILESUBs. ajw if( VQuantity[ VESSEL_SS ] > 0 ) // Includes count of VESSEL_MISSILESUBs. ajw
@@ -1820,12 +1823,18 @@ void HouseClass::Attacked(BuildingClass* source)
{ {
assert(Houses.ID(this) == ID); assert(Houses.ID(this) == ID);
bool expired = SpeakAttackDelay == 0;
bool spoke = false;
#ifdef FIXIT_BASE_ANNOUNCE #ifdef FIXIT_BASE_ANNOUNCE
if (SpeakAttackDelay == 0 && ((Session.Type == GAME_NORMAL && IsPlayerControl) || PlayerPtr->Class->House == Class->House)) { // if (SpeakAttackDelay == 0 && ((Session.Type == GAME_NORMAL && IsPlayerControl) || PlayerPtr->Class->House == Class->House)) {
if (expired && ((Session.Type == GAME_NORMAL && IsPlayerControl) || PlayerPtr->Class->House == Class->House)) {
#else #else
if (SpeakAttackDelay == 0 && PlayerPtr->Class->House == Class->House) { // if (SpeakAttackDelay == 0 && PlayerPtr->Class->House == Class->House) {
if (expired && PlayerPtr->Class->House == Class->House) {
#endif #endif
Speak(VOX_BASE_UNDER_ATTACK, NULL, source ? source->Center_Coord() : 0); Speak(VOX_BASE_UNDER_ATTACK, NULL, source ? source->Center_Coord() : 0);
spoke = true;
// MBL 06.13.2020 - Timing change from 2 minute cooldown, per https://jaas.ea.com/browse/TDRA-6784 // MBL 06.13.2020 - Timing change from 2 minute cooldown, per https://jaas.ea.com/browse/TDRA-6784
// SpeakAttackDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay); // 2 minutes // SpeakAttackDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay); // 2 minutes
@@ -1840,6 +1849,22 @@ void HouseClass::Attacked(BuildingClass* source)
HouseTriggers[Class->House][index]->Spring(TEVENT_ATTACKED); HouseTriggers[Class->House][index]->Spring(TEVENT_ATTACKED);
} }
} }
// MBL 07.07.2020 - CNC Patch 3, fix for not working for all players in MP, per https://jaas.ea.com/browse/TDRA-7249
// Separated to here as did not want to change any logic around the HouseTriggers[] Spring events
//
if (expired == true && spoke == false)
{
if (Session.Type != GAME_NORMAL) // Multiplayer
{
Speak(VOX_BASE_UNDER_ATTACK, this);
spoke = true;
// SpeakAttackDelay = Options.Normalize_Delay(TICKS_PER_MINUTE * Rule.SpeakDelay); // 2 minutes
// SpeakAttackDelay = Options.Normalize_Delay(TICKS_PER_MINUTE/2); // 30 seconds as requested
SpeakAttackDelay = Options.Normalize_Delay( (TICKS_PER_MINUTE/2)+(TICKS_PER_SECOND*5) ); // Tweaked for accuracy
}
}
} }
@@ -3760,6 +3785,13 @@ void HouseClass::MPlayer_Defeated(void)
} }
} }
/*
** Remove any one-time superweapons the player might have.
*/
for (i = SPC_FIRST; i < SPC_COUNT; i++) {
SuperWeapon[i].Remove(true);
}
/* /*
** If this is me: ** If this is me:
** - Set MPlayerObiWan, so I can only send messages to all players, and ** - Set MPlayerObiWan, so I can only send messages to all players, and
@@ -4101,7 +4133,14 @@ void HouseClass::Blowup_All(void)
*/ */
count = 0; count = 0;
while (::Units.Ptr(i)==uptr && uptr->Strength) { while (::Units.Ptr(i)==uptr && uptr->Strength) {
damage = uptr->Strength;
// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840
// Likely due to damage biasing based on RA factions and/or difficulty settings
// Applying this to units (vehicles), ships, buildings, and infantry, too
//
// damage = uptr->Strength; // Original
damage = 0x7fff; // Copied from TD
uptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true); uptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);
count++; count++;
if (count > 5 && uptr->IsActive) { if (count > 5 && uptr->IsActive) {
@@ -4120,7 +4159,13 @@ void HouseClass::Blowup_All(void)
if (::Aircraft.Ptr(i)->House == this && !::Aircraft.Ptr(i)->IsInLimbo) { if (::Aircraft.Ptr(i)->House == this && !::Aircraft.Ptr(i)->IsInLimbo) {
AircraftClass * aptr = ::Aircraft.Ptr(i); AircraftClass * aptr = ::Aircraft.Ptr(i);
damage = aptr->Strength; // MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840
// Likely due to damage biasing based on RA factions and/or difficulty settings
// Applying this to units (vehicles), ships, buildings, and infantry, too
//
// damage = aptr->Strength; // Original
damage = 0x7fff; // Copied from TD
aptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true); aptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);
if (!aptr->IsActive) { if (!aptr->IsActive) {
i--; i--;
@@ -4135,7 +4180,13 @@ void HouseClass::Blowup_All(void)
if (::Vessels.Ptr(i)->House == this && !::Vessels.Ptr(i)->IsInLimbo) { if (::Vessels.Ptr(i)->House == this && !::Vessels.Ptr(i)->IsInLimbo) {
VesselClass * vptr = ::Vessels.Ptr(i); VesselClass * vptr = ::Vessels.Ptr(i);
damage = vptr->Strength; // MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840
// Likely due to damage biasing based on RA factions and/or difficulty settings
// Applying this to units (vehicles), ships, buildings, and infantry, too
//
// damage = vptr->Strength; // Original
damage = 0x7fff; // Copied from TD
vptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true); vptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);
if (!vptr->IsActive) { if (!vptr->IsActive) {
i--; i--;
@@ -4153,7 +4204,14 @@ void HouseClass::Blowup_All(void)
count = 0; count = 0;
while (Buildings.Ptr(i)==bptr && bptr->Strength) { while (Buildings.Ptr(i)==bptr && bptr->Strength) {
damage = bptr->Strength;
// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840
// Likely due to damage biasing based on RA factions and/or difficulty settings
// Applying this to units (vehicles), ships, buildings, and infantry, too
//
// damage = bptr->Strength; // Original
damage = 0x7fff; // Copied from TD
bptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true); bptr->Take_Damage(damage, 0, WARHEAD_HE, NULL, true);
count++; count++;
if (count > 5) { if (count > 5) {
@@ -4176,7 +4234,14 @@ void HouseClass::Blowup_All(void)
count = 0; count = 0;
while (Infantry.Ptr(i)==iptr && iptr->Strength) { while (Infantry.Ptr(i)==iptr && iptr->Strength) {
damage = iptr->Strength;
// MBL 06.22.2020 RA: Not all aircraft die in this case; See https://jaas.ea.com/browse/TDRA-6840
// Likely due to damage biasing based on RA factions and/or difficulty settings
// Applying this to units (vehicles), ships, buildings, and infantry, too
//
// damage = iptr->Strength; // Original
damage = 0x7fff; // Copied from TD
warhead = Random_Pick(WARHEAD_SA, WARHEAD_FIRE); warhead = Random_Pick(WARHEAD_SA, WARHEAD_FIRE);
iptr->Take_Damage(damage, 0, warhead, NULL, true); iptr->Take_Damage(damage, 0, warhead, NULL, true);
@@ -8015,6 +8080,13 @@ void HouseClass::Check_Pertinent_Structures(void)
return; return;
} }
// MBL 07.15.2020 - Prevention of recent issue with constant "player defeated logic" and message to client spamming
// Per https://jaas.ea.com/browse/TDRA-7433
//
if (IsDefeated) {
return;
}
bool any_good_buildings = false; bool any_good_buildings = false;
for (int index = 0; index < Buildings.Count(); index++) { for (int index = 0; index < Buildings.Count(); index++) {
@@ -8022,6 +8094,7 @@ void HouseClass::Check_Pertinent_Structures(void)
if (b && b->IsActive && b->House == this) { if (b && b->IsActive && b->House == this) {
if (!b->Class->IsWall && *b != STRUCT_APMINE && *b != STRUCT_AVMINE) { if (!b->Class->IsWall && *b != STRUCT_APMINE && *b != STRUCT_AVMINE) {
if (!Special.ModernBalance || (*b != STRUCT_SHIP_YARD && *b != STRUCT_FAKE_YARD && *b != STRUCT_SUB_PEN && *b != STRUCT_FAKE_PEN)) {
if (!b->IsInLimbo && b->Strength > 0) { if (!b->IsInLimbo && b->Strength > 0) {
any_good_buildings = true; any_good_buildings = true;
break; break;
@@ -8029,6 +8102,7 @@ void HouseClass::Check_Pertinent_Structures(void)
} }
} }
} }
}
if (!any_good_buildings) { if (!any_good_buildings) {
for (int index = 0; index < Units.Count(); index++) { for (int index = 0; index < Units.Count(); index++) {
+12 -2
View File
@@ -511,6 +511,9 @@ int InfantryClass::Shape_Number(WindowNumberType window) const
** The animation frame numbers may be different when rendering in legacy mode vs. exporting for render in GlyphX. ST - 9/5/2019 12:34PM ** The animation frame numbers may be different when rendering in legacy mode vs. exporting for render in GlyphX. ST - 9/5/2019 12:34PM
*/ */
const DoInfoStruct *do_controls = (window == WINDOW_VIRTUAL) ? Class->DoControlsVirtual : Class->DoControls; const DoInfoStruct *do_controls = (window == WINDOW_VIRTUAL) ? Class->DoControlsVirtual : Class->DoControls;
if (window != WINDOW_VIRTUAL && !IsOwnedByPlayer && *this == INFANTRY_SPY) {
do_controls = InfantryTypeClass::As_Reference(INFANTRY_E1).DoControls;
}
/* /*
** The infantry shape is always modulo the number of animation frames ** The infantry shape is always modulo the number of animation frames
@@ -698,7 +701,7 @@ void InfantryClass::Per_Cell_Process(PCPType why)
// If they're spying on a sub pen, give 'em a sonar pulse // If they're spying on a sub pen, give 'em a sonar pulse
if (build == STRUCT_SUB_PEN) { if (build == STRUCT_SUB_PEN) {
House->SuperWeapon[SPC_SONAR_PULSE].Enable(true, true, false); House->SuperWeapon[SPC_SONAR_PULSE].Enable(false, true, false);
// Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM // Add to Glyphx multiplayer sidebar. ST - 8/7/2019 10:13AM
if (Session.Type == GAME_GLYPHX_MULTIPLAYER) { if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
if (House->IsHuman) { if (House->IsHuman) {
@@ -1486,7 +1489,7 @@ MoveType InfantryClass::Can_Enter_Cell(CELL cell, FacingType ) const
** Cloaked enemy objects are not considered if this is a Find_Path() ** Cloaked enemy objects are not considered if this is a Find_Path()
** call. ** call.
*/ */
if (!obj->Is_Techno() || ((TechnoClass *)obj)->Cloak != CLOAKED) { if (!obj->Is_Techno() || !((TechnoClass *)obj)->Is_Cloaked(this)) {
/* /*
** Any non-allied blockage is considered impassible if the infantry ** Any non-allied blockage is considered impassible if the infantry
@@ -3964,6 +3967,13 @@ void InfantryClass::Movement_AI(void)
// if (IsTethered) Scatter(0, true); // if (IsTethered) Scatter(0, true);
} }
/*
** Scatter infantry off buildings in guard modes.
*/
if (!IsTethered && (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA) && MissionQueue == MISSION_NONE && Map[Coord].Cell_Building() != NULL) {
Scatter(0, true, true);
}
/* /*
** Double check to make sure it doesn't have a movement destination into a zone ** Double check to make sure it doesn't have a movement destination into a zone
** that it can't travel to. In such a case, abort the movement process by clearing ** that it can't travel to. In such a case, abort the movement process by clearing
+3
View File
@@ -286,6 +286,9 @@ bool Read_Scenario_INI_Write_INB( char *root, bool fresh)
UnitClass::Read_INI(buffer); UnitClass::Read_INI(buffer);
Call_Back(); Call_Back();
AircraftClass::Read_INI(buffer);
Call_Back();
VesselClass::Read_INI(buffer); VesselClass::Read_INI(buffer);
Call_Back(); Call_Back();
+10
View File
@@ -435,6 +435,16 @@ bool Init_Game(int , char * [])
ChronalVortex.Stop(); ChronalVortex.Stop();
ChronalVortex.Setup_Remap_Tables(Scen.Theater); ChronalVortex.Setup_Remap_Tables(Scen.Theater);
/*
** Clear out name overrides array
*/
#ifdef FIXIT_NAME_OVERRIDE
for (int index = 0; index < ARRAY_SIZE(NameOverride); index++) {
NameOverride[index] = NULL;
NameIDOverride[index] = 0;
}
#endif //FIXIT_NAME_OVERRIDE
return(true); return(true);
} }
+4 -2
View File
@@ -316,6 +316,7 @@ void LogicClass::AI(void)
*/ */
for (index = 0; index < Count(); index++) { for (index = 0; index < Count(); index++) {
ObjectClass * obj = (*this)[index]; ObjectClass * obj = (*this)[index];
int count = Count();
BStart(BENCH_AI); BStart(BENCH_AI);
obj->AI(); obj->AI();
@@ -354,8 +355,9 @@ void LogicClass::AI(void)
** If the object was destroyed in the process of performing its AI, then ** If the object was destroyed in the process of performing its AI, then
** adjust the index so that no object gets skipped. ** adjust the index so that no object gets skipped.
*/ */
if (obj != (*this)[index]) { int count_diff = Count() - count;
index--; if (count_diff < 0) {
index += count_diff;
} }
} }
HouseClass::Recalc_Attributes(); HouseClass::Recalc_Attributes();
+15 -5
View File
@@ -1026,6 +1026,16 @@ void MapClass::Logic(void)
** Tiberium cells that can grow or spread. ** Tiberium cells that can grow or spread.
*/ */
int subcount = MAP_CELL_TOTAL / (Rule.GrowthRate * TICKS_PER_MINUTE); int subcount = MAP_CELL_TOTAL / (Rule.GrowthRate * TICKS_PER_MINUTE);
/*
** Use the Tiberium setting as a multiplier on growth rate. ST - 7/1/2020 3:05PM
*/
if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
if (Session.Options.Tiberium > 1) {
subcount *= Session.Options.Tiberium;
}
}
subcount = max(subcount, 1); subcount = max(subcount, 1);
int index; int index;
for (index = TiberiumScan; index < MAP_CELL_TOTAL; index++) { for (index = TiberiumScan; index < MAP_CELL_TOTAL; index++) {
@@ -1416,11 +1426,11 @@ ObjectClass * MapClass::Close_Object(COORDINATE coord) const
while (o != NULL) { while (o != NULL) {
/* /*
** Special case check to ignore cloaked object if not owned by the player. ** Special case check to ignore cloaked object if not allied with the player.
*/ */
// Change for client/server multiplayer. ST - 8/7/2019 10:35AM // Change for client/server multiplayer. ST - 8/7/2019 10:35AM
//if (!o->Is_Techno() || ((TechnoClass *)o)->IsOwnedByPlayer || ((TechnoClass *)o)->Cloak != CLOAKED) { //if (!o->Is_Techno() || ((TechnoClass *)o)->IsOwnedByPlayer || ((TechnoClass *)o)->Cloak != CLOAKED) {
if (!o->Is_Techno() || ((TechnoClass *)o)->Is_Owned_By_Player() || ((TechnoClass *)o)->Cloak != CLOAKED) { if (!o->Is_Techno() || !((TechnoClass *)o)->Is_Cloaked(PlayerPtr)) {
int d=-1; int d=-1;
if (o->What_Am_I() == RTTI_BUILDING) { if (o->What_Am_I() == RTTI_BUILDING) {
d = Distance(coord, Cell_Coord(newcell)); d = Distance(coord, Cell_Coord(newcell));
@@ -1445,7 +1455,7 @@ ObjectClass * MapClass::Close_Object(COORDINATE coord) const
AircraftClass * aircraft = Aircraft.Ptr(index); AircraftClass * aircraft = Aircraft.Ptr(index);
if (aircraft->In_Which_Layer() != LAYER_GROUND) { if (aircraft->In_Which_Layer() != LAYER_GROUND) {
if (aircraft->Is_Owned_By_Player() || (aircraft->Cloak != CLOAKED)) { if (!aircraft->Is_Cloaked(PlayerPtr)) {
int d = Distance(coord, Coord_Add(aircraft->Center_Coord(), XY_Coord(0, -aircraft->Height))); int d = Distance(coord, Coord_Add(aircraft->Center_Coord(), XY_Coord(0, -aircraft->Height)));
if (d >= 0 && (!object || d < distance)) { if (d >= 0 && (!object || d < distance)) {
distance = d; distance = d;
@@ -1683,7 +1693,7 @@ int MapClass::Zone_Span(CELL cell, int zone, MZoneType check)
* HISTORY: * * HISTORY: *
* 10/05/1995 JLB : Created. * * 10/05/1995 JLB : Created. *
*=============================================================================================*/ *=============================================================================================*/
CELL MapClass::Nearby_Location(CELL cell, SpeedType speed, int zone, MZoneType check, bool checkflagged) const CELL MapClass::Nearby_Location(CELL cell, SpeedType speed, int zone, MZoneType check, bool checkflagged, int locationmod) const
{ {
CELL topten[10]; CELL topten[10];
int count = 0; int count = 0;
@@ -1767,7 +1777,7 @@ CELL MapClass::Nearby_Location(CELL cell, SpeedType speed, int zone, MZoneType c
} }
if (count > 0) { if (count > 0) {
return(topten[Frame % count]); return(topten[(Frame+locationmod) % count]);
} }
return(0); return(0);
} }
+1 -1
View File
@@ -61,7 +61,7 @@ class MapClass: public GScreenClass
CELL Pick_Random_Location(void) const; CELL Pick_Random_Location(void) const;
int Intact_Bridge_Count(void) const; int Intact_Bridge_Count(void) const;
bool Base_Region(CELL cell, HousesType & house, ZoneType & zone) const; bool Base_Region(CELL cell, HousesType & house, ZoneType & zone) const;
CELL Nearby_Location(CELL cell, SpeedType speed, int zone=-1, MZoneType check=MZONE_NORMAL, bool checkflagged=false) const; CELL Nearby_Location(CELL cell, SpeedType speed, int zone=-1, MZoneType check=MZONE_NORMAL, bool checkflagged=false, int locationmod=0) const;
ObjectClass * Close_Object(COORDINATE coord) const; ObjectClass * Close_Object(COORDINATE coord) const;
virtual void Detach(ObjectClass * ) {}; virtual void Detach(ObjectClass * ) {};
int Cell_Region(CELL cell); int Cell_Region(CELL cell);
+8
View File
@@ -632,6 +632,14 @@ COORDINATE ObjectClass::Sort_Y(void) const
* HISTORY: * * HISTORY: *
* 09/21/1995 JLB : Created. * * 09/21/1995 JLB : Created. *
*=============================================================================================*/ *=============================================================================================*/
FireDataType ObjectClass::Fire_Data(int which) const
{
assert(this != 0);
assert(IsActive);
return{Fire_Coord(which),0};
}
COORDINATE ObjectClass::Fire_Coord(int ) const COORDINATE ObjectClass::Fire_Coord(int ) const
{ {
assert(this != 0); assert(this != 0);
+1
View File
@@ -178,6 +178,7 @@ class ObjectClass : public AbstractClass
virtual COORDINATE Center_Coord(void) const; virtual COORDINATE Center_Coord(void) const;
virtual COORDINATE Render_Coord(void) const; virtual COORDINATE Render_Coord(void) const;
virtual COORDINATE Sort_Y(void) const; virtual COORDINATE Sort_Y(void) const;
virtual FireDataType Fire_Data(int which) const;
virtual COORDINATE Fire_Coord(int which) const; virtual COORDINATE Fire_Coord(int which) const;
virtual COORDINATE Exit_Coord(void) const; virtual COORDINATE Exit_Coord(void) const;
+2 -2
View File
@@ -255,7 +255,7 @@ bool RadarClass::Radar_Activate(int control)
case 0: case 0:
if (Map.IsSidebarActive) { if (Map.IsSidebarActive) {
if (IsRadarActive && !IsRadarDeactivating) { if (IsRadarActive && !IsRadarDeactivating) {
Sound_Effect(VOC_RADAR_OFF); // Sound_Effect(VOC_RADAR_OFF); // MBL 07.20.2020: These are never being sent to the client, so handled there; Disabling here for good measure.
IsRadarDeactivating = true; IsRadarDeactivating = true;
IsRadarActive = false; IsRadarActive = false;
if (IsRadarActivating == true) { if (IsRadarActivating == true) {
@@ -272,7 +272,7 @@ bool RadarClass::Radar_Activate(int control)
case 1: case 1:
if (Map.IsSidebarActive) { if (Map.IsSidebarActive) {
if (!IsRadarActivating && !IsRadarActive) { if (!IsRadarActivating && !IsRadarActive) {
Sound_Effect(VOC_RADAR_ON); // Sound_Effect(VOC_RADAR_ON); // MBL 07.20.2020: These are never being sent to the client, so handled there; Disabling here for good measure.
IsRadarActivating = true; IsRadarActivating = true;
if (IsRadarDeactivating == true) { if (IsRadarDeactivating == true) {
IsRadarDeactivating = false; IsRadarDeactivating = false;
+3
View File
@@ -2477,6 +2477,9 @@ bool Read_Scenario_INI(char * fname, bool )
UnitClass::Read_INI(ini); UnitClass::Read_INI(ini);
Call_Back(); Call_Back();
AircraftClass::Read_INI(ini);
Call_Back();
VesselClass::Read_INI(ini); VesselClass::Read_INI(ini);
Call_Back(); Call_Back();
+1
View File
@@ -82,6 +82,7 @@ void SpecialClass::Init(void)
UseMCVDeploy = false; UseMCVDeploy = false;
IsMCVDeploy = false; IsMCVDeploy = false;
IsEarlyWin = false; IsEarlyWin = false;
ModernBalance = false;
} }
+13 -1
View File
@@ -105,10 +105,22 @@ class SpecialClass
*/ */
unsigned IsEarlyWin:1; unsigned IsEarlyWin:1;
/*
** New modern balance setting.
*/
unsigned ModernBalance:1;
/* /*
** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load ** Some additional padding in case we need to add data to the class and maintain backwards compatibility for save/load
*/ */
unsigned char SaveLoadPadding[128]; // MBL 07.21.2020 - https://jaas.ea.com/browse/TDRA-7537
// Loading save files from Live and July Patch 3 Beta versions results in a crash
// Fixes issue from Change 738397 2020/07/17 14:06:03
//
// unsigned char SaveLoadPadding[128]; // Note: Never changed to 127 like TD did
//
// unsigned char SaveLoadPadding[124]; // Trying 124 like we did with TD - Failed
unsigned char SaveLoadPadding[128]; // Works with With last weeks saves (7/16/2020) and newest saves; Skyler says go with this.
}; };
+4
View File
@@ -769,6 +769,10 @@ void __cdecl Prog_End(const char *why, bool fatal)
*((int*)0) = 0; *((int*)0) = 0;
} }
if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
return;
}
Sound_End(); Sound_End();
if (WWMouse) { if (WWMouse) {
delete WWMouse; delete WWMouse;
+2 -2
View File
@@ -168,9 +168,9 @@ bool SuperClass::Enable(bool onetime, bool player, bool quiet)
* HISTORY: * * HISTORY: *
* 07/28/1995 JLB : Created. * * 07/28/1995 JLB : Created. *
*=============================================================================================*/ *=============================================================================================*/
bool SuperClass::Remove(void) bool SuperClass::Remove(bool forced)
{ {
if (IsPresent && !IsOneTime) { if (IsPresent && (!IsOneTime || forced)) {
IsReady = false; IsReady = false;
IsPresent = false; IsPresent = false;
return(true); return(true);
+1 -1
View File
@@ -47,7 +47,7 @@ class SuperClass {
bool Enable(bool onetime = false, bool player=false, bool quiet=false); bool Enable(bool onetime = false, bool player=false, bool quiet=false);
void Forced_Charge(bool player=false); void Forced_Charge(bool player=false);
bool AI(bool player=false); bool AI(bool player=false);
bool Remove(void); bool Remove(bool forced=false);
void Impatient_Click(void) const; void Impatient_Click(void) const;
int Anim_Stage(void) const; int Anim_Stage(void) const;
bool Discharged(bool player); bool Discharged(bool player);
+63 -22
View File
@@ -484,6 +484,25 @@ bool TechnoClass::Is_Allowed_To_Recloak(void) const
* HISTORY: * * HISTORY: *
* 07/29/1996 JLB : Created. * * 07/29/1996 JLB : Created. *
*=============================================================================================*/ *=============================================================================================*/
FireDataType TechnoClass::Fire_Data(int which) const
{
assert(IsActive);
TechnoTypeClass const * tclass = Techno_Type_Class();
int dist = 0;
if (which == 0) {
dist = tclass->PrimaryOffset;
} else {
dist = tclass->SecondaryOffset;
}
COORDINATE coord = Coord_Move(Center_Coord(), DIR_N, tclass->VerticalOffset + Height);
coord = Coord_Move(coord, DIR_E, tclass->HorizontalOffset);
return{coord,dist};
}
COORDINATE TechnoClass::Fire_Coord(int which) const COORDINATE TechnoClass::Fire_Coord(int which) const
{ {
assert(IsActive); assert(IsActive);
@@ -662,7 +681,7 @@ bool TechnoClass::Is_Visible_On_Radar(void) const
} }
} }
} }
if (!Techno_Type_Class()->IsInvisible && (Cloak != CLOAKED || House->Is_Ally(PlayerPtr))) { if (!Is_Cloaked(PlayerPtr, true)) {
return(true); return(true);
} }
return(false); return(false);
@@ -968,9 +987,14 @@ RadioMessageType TechnoClass::Receive_Message(RadioClass * from, RadioMessageTyp
/* /*
** If there is sufficient money to repair the unit one step, then do so. ** If there is sufficient money to repair the unit one step, then do so.
** Otherwise return with a "can't complete" radio response. ** Otherwise return with a "can't complete" radio response.
** Special case: in single-player campaigns, also try to use the repair pad house's money.
*/ */
if (House->Available_Money() >= cost) { HouseClass* house = House;
House->Spend_Money(cost); if (Session.Type == GAME_NORMAL && house->Available_Money() < cost) {
house = HouseClass::As_Pointer(from->Owner());
}
if (house != NULL && house->Available_Money() >= cost) {
house->Spend_Money(cost);
Strength += step; Strength += step;
/* /*
@@ -1083,7 +1107,7 @@ void TechnoClass::Draw_It(int x, int y, WindowNumberType window) const
int width, height; int width, height;
Class_Of().Dimensions(width, height); Class_Of().Dimensions(width, height);
const bool show_health_bar = (Strength > 0) && (Is_Selected_By_Player() || const bool show_health_bar = (Strength > 0) && !Is_Cloaked(PlayerPtr) && (Is_Selected_By_Player() ||
((Rule.HealthBarDisplayMode == RulesClass::HB_DAMAGED) && (Strength < Techno_Type_Class()->MaxStrength)) || ((Rule.HealthBarDisplayMode == RulesClass::HB_DAMAGED) && (Strength < Techno_Type_Class()->MaxStrength)) ||
(Rule.HealthBarDisplayMode == RulesClass::HB_ALWAYS)); (Rule.HealthBarDisplayMode == RulesClass::HB_ALWAYS));
@@ -1248,8 +1272,8 @@ bool TechnoClass::In_Range(TARGET target, int which, bool reciprocal_check) cons
if (building != NULL) { if (building != NULL) {
range += ((building->Class->Width() + building->Class->Height()) * (ICON_LEPTON_W / 4)); range += ((building->Class->Width() + building->Class->Height()) * (ICON_LEPTON_W / 4));
} }
FireDataType data = Fire_Data(which);
if (::Distance(Fire_Coord(which), As_Coord(target)) <= range) { if (MAX(0, ::Distance(data.Center, As_Coord(target)) - data.Distance) <= range) {
return(true); return(true);
} }
@@ -1304,8 +1328,8 @@ bool TechnoClass::In_Range(ObjectClass const * target, int which, bool reciproca
BuildingClass const * building = (BuildingClass const *)target; BuildingClass const * building = (BuildingClass const *)target;
range += ((building->Class->Width() + building->Class->Height()) * (ICON_LEPTON_W / 4)); range += ((building->Class->Width() + building->Class->Height()) * (ICON_LEPTON_W / 4));
} }
FireDataType data = Fire_Data(which);
if (::Distance(Fire_Coord(which), target->Center_Coord()) <= range) { if (MAX(0, ::Distance(data.Center, target->Center_Coord()) - data.Distance) <= range) {
return(true); return(true);
} }
@@ -1501,7 +1525,7 @@ bool TechnoClass::Evaluate_Object(ThreatType method, int mask, int range, Techno
/* /*
** If the object is cloaked, then it isn't a legal target. ** If the object is cloaked, then it isn't a legal target.
*/ */
if (object->Cloak == CLOAKED) { if (object->Is_Cloaked(this)) {
BEnd(BENCH_EVAL_OBJECT); BEnd(BENCH_EVAL_OBJECT);
return(false); return(false);
} }
@@ -1530,17 +1554,13 @@ bool TechnoClass::Evaluate_Object(ThreatType method, int mask, int range, Techno
** object is a friend. Unless we're a medic, of course. But then, ** object is a friend. Unless we're a medic, of course. But then,
** only consider it a target if it's injured. ** only consider it a target if it's injured.
*/ */
if (House->Is_Ally(object)) { bool is_ally = House->Is_Ally(object);
if (Combat_Damage() < 0) { bool is_medic = Combat_Damage() < 0;
if (object->Health_Ratio() == Rule.ConditionGreen) { bool green_health = object->Health_Ratio() == Rule.ConditionGreen;
if ((is_ally && (!is_medic || green_health)) || (!is_ally && is_medic)) {
BEnd(BENCH_EVAL_OBJECT); BEnd(BENCH_EVAL_OBJECT);
return(false); return(false);
} }
} else {
BEnd(BENCH_EVAL_OBJECT);
return(false);
}
}
/* /*
** If the object is further away than allowed, bail. ** If the object is further away than allowed, bail.
@@ -2011,6 +2031,27 @@ int TechnoClass::Evaluate_Just_Cell(CELL cell) const
} }
bool TechnoClass::Is_Cloaked(HousesType house, bool check_invisible) const
{
const bool is_invisible = check_invisible && Techno_Type_Class()->IsInvisible;
return !House->Is_Ally(house) && ((Cloak == CLOAKED) || is_invisible);
}
bool TechnoClass::Is_Cloaked(HouseClass const * house, bool check_invisible) const
{
const bool is_invisible = check_invisible && Techno_Type_Class()->IsInvisible;
return !House->Is_Ally(house) && ((Cloak == CLOAKED) || is_invisible);
}
bool TechnoClass::Is_Cloaked(ObjectClass const * object, bool check_invisible) const
{
const bool is_invisible = check_invisible && Techno_Type_Class()->IsInvisible;
return !House->Is_Ally(object) && ((Cloak == CLOAKED) || is_invisible);
}
/*********************************************************************************************** /***********************************************************************************************
* TechnoClass::Greatest_Threat -- Determines best target given search criteria. * * TechnoClass::Greatest_Threat -- Determines best target given search criteria. *
* * * *
@@ -2443,7 +2484,7 @@ void TechnoClass::AI(void)
** If for some strange reason, the computer is firing upon itself, then ** If for some strange reason, the computer is firing upon itself, then
** tell it not to. ** tell it not to.
*/ */
if (!House->IsHuman && As_Techno(TarCom) && As_Techno(TarCom)->House->Is_Ally(this)) { if (!House->IsHuman && As_Techno(TarCom) && As_Techno(TarCom)->House->Is_Ally(this) && Combat_Damage() >= 0) {
//#ifdef FIXIT_CSII // checked - ajw 9/28/98 (commented out) //#ifdef FIXIT_CSII // checked - ajw 9/28/98 (commented out)
//if(What_Am_I() == RTTI_INFANTRY && *(InfantryClass *)this==INFANTRY_GENERAL && Session.Type==GAME_NORMAL && House->Class->House==HOUSE_UKRAINE) { //if(What_Am_I() == RTTI_INFANTRY && *(InfantryClass *)this==INFANTRY_GENERAL && Session.Type==GAME_NORMAL && House->Class->House==HOUSE_UKRAINE) {
//} else //} else
@@ -2768,9 +2809,9 @@ FireErrorType TechnoClass::Can_Fire(TARGET target, int which) const
ObjectClass * object = As_Object(target); ObjectClass * object = As_Object(target);
/* /*
** If the object is completely cloaked, then you can't fire on it. ** If an enemy object is completely cloaked, then you can't fire on it.
*/ */
if (object != NULL && object->Is_Techno() && ((TechnoClass *)object)->Cloak == CLOAKED) { if (object != NULL && object->Is_Techno() && ((TechnoClass *)object)->Is_Cloaked(this)) {
return(FIRE_CANT); return(FIRE_CANT);
} }
@@ -4172,7 +4213,7 @@ void TechnoClass::Record_The_Kill(TechnoClass * source)
* 07/06/1995 JLB : Created. * * 07/06/1995 JLB : Created. *
* 09/28/1995 JLB : Uses map scan function. * * 09/28/1995 JLB : Uses map scan function. *
*=============================================================================================*/ *=============================================================================================*/
CELL TechnoClass::Nearby_Location(TechnoClass const * techno) const CELL TechnoClass::Nearby_Location(TechnoClass const * techno, int locationmod) const
{ {
assert(IsActive); assert(IsActive);
@@ -4188,7 +4229,7 @@ CELL TechnoClass::Nearby_Location(TechnoClass const * techno) const
cell = Coord_Cell(Center_Coord()); cell = Coord_Cell(Center_Coord());
} }
return(Map.Nearby_Location(cell, speed, Map[cell].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone)); return(Map.Nearby_Location(cell, speed, Map[cell].Zones[Techno_Type_Class()->MZone], Techno_Type_Class()->MZone, false, locationmod));
} }
+5 -1
View File
@@ -271,7 +271,7 @@ class TechnoClass : public RadioClass,
bool Is_Ready_To_Cloak(void) const; bool Is_Ready_To_Cloak(void) const;
virtual int How_Many_Survivors(void) const; virtual int How_Many_Survivors(void) const;
virtual DirType Turret_Facing(void) const {return(PrimaryFacing.Current());} virtual DirType Turret_Facing(void) const {return(PrimaryFacing.Current());}
CELL Nearby_Location(TechnoClass const * from=NULL) const; CELL Nearby_Location(TechnoClass const * from=NULL, int locationmod=0) const;
TechnoTypeClass * Techno_Type_Class(void) const {return((TechnoTypeClass *)&Class_Of());}; TechnoTypeClass * Techno_Type_Class(void) const {return((TechnoTypeClass *)&Class_Of());};
bool Is_Visible_On_Radar(void) const; bool Is_Visible_On_Radar(void) const;
int Anti_Air(void) const; int Anti_Air(void) const;
@@ -282,6 +282,7 @@ class TechnoClass : public RadioClass,
virtual ActionType What_Action(ObjectClass const * target) const; virtual ActionType What_Action(ObjectClass const * target) const;
virtual BuildingClass * Find_Docking_Bay(StructType b, bool friendly) const; virtual BuildingClass * Find_Docking_Bay(StructType b, bool friendly) const;
virtual CELL Find_Exit_Cell(TechnoClass const * techno) const; virtual CELL Find_Exit_Cell(TechnoClass const * techno) const;
virtual FireDataType Fire_Data(int) const;
virtual COORDINATE Fire_Coord(int which) const; virtual COORDINATE Fire_Coord(int which) const;
virtual DirType Desired_Load_Dir(ObjectClass * , CELL & moveto) const; virtual DirType Desired_Load_Dir(ObjectClass * , CELL & moveto) const;
virtual DirType Fire_Direction(void) const; virtual DirType Fire_Direction(void) const;
@@ -338,6 +339,9 @@ class TechnoClass : public RadioClass,
bool Evaluate_Object(ThreatType method, int mask, int range, TechnoClass const * object, int & value, int zone=-1) const; bool Evaluate_Object(ThreatType method, int mask, int range, TechnoClass const * object, int & value, int zone=-1) const;
int Evaluate_Just_Cell(CELL cell) const; int Evaluate_Just_Cell(CELL cell) const;
virtual bool Electric_Zap (COORDINATE target_coord, int which, WindowNumberType window, COORDINATE source_coord=0L, unsigned char * remap=NULL) const; virtual bool Electric_Zap (COORDINATE target_coord, int which, WindowNumberType window, COORDINATE source_coord=0L, unsigned char * remap=NULL) const;
bool Is_Cloaked(HousesType house, bool check_invisible=false) const;
bool Is_Cloaked(HouseClass const * house, bool check_invisible=false) const;
bool Is_Cloaked(ObjectClass const * object, bool check_invisible=false) const;
/* /*
** AI. ** AI.
+40 -9
View File
@@ -433,6 +433,13 @@ void UnitClass::AI(void)
*/ */
Rotation_AI(); Rotation_AI();
/*
** Scatter units off buildings in guard modes.
*/
if (!IsTethered && !IsFiring && !IsDriving && !IsRotating && (Mission == MISSION_GUARD || Mission == MISSION_GUARD_AREA) && MissionQueue == MISSION_NONE && Map[Coord].Cell_Building() != NULL) {
Scatter(0, true, true);
}
/* /*
** Delete this unit if it finds itself off the edge of the map and it is in ** Delete this unit if it finds itself off the edge of the map and it is in
** guard or other static mission mode. ** guard or other static mission mode.
@@ -1283,6 +1290,11 @@ void UnitClass::Player_Assign_Mission(MissionType mission, TARGET target, TARGET
if (mission == MISSION_HARVEST) { if (mission == MISSION_HARVEST) {
ArchiveTarget = TARGET_NONE; ArchiveTarget = TARGET_NONE;
} else if (mission == MISSION_ENTER) {
BuildingClass* building = As_Building(destination);
if (building != NULL && *building == STRUCT_REFINERY && building->In_Radio_Contact()) {
building->Transmit_Message(RADIO_OVER_OUT);
}
} }
DriveClass::Player_Assign_Mission(mission, target, destination); DriveClass::Player_Assign_Mission(mission, target, destination);
} }
@@ -1707,7 +1719,7 @@ void UnitClass::Per_Cell_Process(PCPType why)
} else { } else {
TechnoClass * contact = Contact_With_Whom(); TechnoClass * contact = Contact_With_Whom();
if (Transmit_Message(RADIO_UNLOADED) == RADIO_RUN_AWAY) { if (Transmit_Message(RADIO_UNLOADED) == RADIO_RUN_AWAY) {
if (*this == UNIT_HARVESTER && contact && contact->What_Am_I() == RTTI_BUILDING) { if (*this == UNIT_HARVESTER && contact && contact->What_Am_I() == RTTI_BUILDING && *((BuildingClass*)contact) != STRUCT_REPAIR) {
Assign_Mission(MISSION_HARVEST); Assign_Mission(MISSION_HARVEST);
} else if (!Target_Legal(NavCom)) { } else if (!Target_Legal(NavCom)) {
Scatter(0, true); Scatter(0, true);
@@ -2231,10 +2243,25 @@ int UnitClass::Tiberium_Check(CELL & center, int x, int y)
center = XY_Cell(Cell_X(center)+x, Cell_Y(center)+y); center = XY_Cell(Cell_X(center)+x, Cell_Y(center)+y);
if ((Session.Type != GAME_NORMAL || (!IsOwnedByPlayer || Map[center].IsMapped))) { if ((Session.Type != GAME_NORMAL || (!IsOwnedByPlayer || Map[center].Is_Mapped(PlayerPtr)))) {
if (Map[Coord].Zones[Class->MZone] != Map[center].Zones[Class->MZone]) return(0); if (Map[Coord].Zones[Class->MZone] != Map[center].Zones[Class->MZone]) return(0);
if (!Map[center].Cell_Techno() && Map[center].Land_Type() == LAND_TIBERIUM) { if (!Map[center].Cell_Techno() && Map[center].Land_Type() == LAND_TIBERIUM) {
return(Map[center].OverlayData); int value = 0;
switch (Map[center].Overlay) {
case OVERLAY_GOLD1:
case OVERLAY_GOLD2:
case OVERLAY_GOLD3:
case OVERLAY_GOLD4:
value = Rule.GoldValue;
break;
case OVERLAY_GEMS1:
case OVERLAY_GEMS2:
case OVERLAY_GEMS3:
case OVERLAY_GEMS4:
value = Rule.GemValue*4;
break;
}
return((Map[center].OverlayData+1)*value);
} }
} }
return(0); return(0);
@@ -2278,6 +2305,7 @@ bool UnitClass::Goto_Tiberium(int rad)
int tiberium = 0; int tiberium = 0;
int besttiberium = 0; int besttiberium = 0;
for (int x = -radius; x <= radius; x++) { for (int x = -radius; x <= radius; x++) {
cell = center;
tiberium = Tiberium_Check(cell, x, -radius); tiberium = Tiberium_Check(cell, x, -radius);
if (tiberium > besttiberium) { if (tiberium > besttiberium) {
bestcell = cell; bestcell = cell;
@@ -2862,10 +2890,10 @@ int UnitClass::Mission_Harvest(void)
*/ */
case LOOKING: case LOOKING:
/* /*
** When full of tiberium, just skip to finding a free refinery ** Slightly hacky; if TarCom is set then skip to finding home state.
** to unload at.
*/ */
if (Tiberium_Load() == 1) { if (Target_Legal(TarCom)) {
Assign_Target(TARGET_NONE);
Status = FINDHOME; Status = FINDHOME;
return(1); return(1);
} }
@@ -3282,7 +3310,7 @@ MoveType UnitClass::Can_Enter_Cell(CELL cell, FacingType ) const
** Cloaked enemy objects are not considered if this is a Find_Path() ** Cloaked enemy objects are not considered if this is a Find_Path()
** call. ** call.
*/ */
if (!obj->Is_Techno() || ((TechnoClass *)obj)->Cloak != CLOAKED) { if (!obj->Is_Techno() || !((TechnoClass *)obj)->Is_Cloaked(this)) {
/* /*
** If this unit can crush infantry, and there is an enemy infantry in the ** If this unit can crush infantry, and there is an enemy infantry in the
@@ -3560,14 +3588,17 @@ ActionType UnitClass::What_Action(ObjectClass const * object) const
/* /*
** Special return to friendly refinery action. ** Special return to friendly refinery action.
*/ */
if (Is_Owned_By_Player() && House->Class->House == object->Owner() && object->What_Am_I() == RTTI_BUILDING && ((UnitClass *)this)->Transmit_Message(RADIO_CAN_LOAD, (TechnoClass*)object) == RADIO_ROGER) { bool is_player_controlled = (Session.Type == GAME_NORMAL)
? (House->IsPlayerControl && object->Owner() != HOUSE_NONE && HouseClass::As_Pointer(object->Owner())->IsPlayerControl)
: (Is_Owned_By_Player() && House->Class->House == object->Owner());
if (is_player_controlled && object->What_Am_I() == RTTI_BUILDING && ((UnitClass *)this)->Transmit_Message(RADIO_CAN_LOAD, (TechnoClass*)object) == RADIO_ROGER) {
action = ACTION_ENTER; action = ACTION_ENTER;
} }
/* /*
** Special return to friendly repair factory action. ** Special return to friendly repair factory action.
*/ */
if (Is_Owned_By_Player() && House->Class->House == object->Owner() && action == ACTION_SELECT && object->What_Am_I() == RTTI_BUILDING) { if (is_player_controlled && action == ACTION_SELECT && object->What_Am_I() == RTTI_BUILDING) {
BuildingClass * building = (BuildingClass *)object; BuildingClass * building = (BuildingClass *)object;
if (building->Class->Type == STRUCT_REPAIR && ((UnitClass *)this)->Transmit_Message(RADIO_CAN_LOAD, building) == RADIO_ROGER && !building->In_Radio_Contact() && !building->Is_Something_Attached()) { if (building->Class->Type == STRUCT_REPAIR && ((UnitClass *)this)->Transmit_Message(RADIO_CAN_LOAD, building) == RADIO_ROGER && !building->In_Radio_Contact() && !building->Is_Something_Attached()) {
action = ACTION_MOVE; action = ACTION_MOVE;
+1 -1
View File
@@ -728,7 +728,7 @@ unsigned long VersionClass::Max_Version(void)
char const * Version_Name(void) { char const * Version_Name(void) {
// jmarshall // jmarshall
#define AF_BUILDNUMBER 0 // Patch number for allied force. #define AF_BUILDNUMBER 0 // Patch number for allied force.
#define EA_REMASTER_PATCH 2 // What version of the remaster source we are integrated with. #define EA_REMASTER_PATCH 3 // What version of the remaster source we are integrated with.
static char tmp[512]; static char tmp[512];
#ifdef _DEBUG #ifdef _DEBUG
+27 -1
View File
@@ -299,7 +299,7 @@ MoveType VesselClass::Can_Enter_Cell(CELL cell, FacingType ) const
} }
TechnoClass * techno = cellptr->Cell_Techno(); TechnoClass * techno = cellptr->Cell_Techno();
if (techno != NULL && techno->Cloak == CLOAKED && !House->Is_Ally(techno)) { if (techno != NULL && techno->Is_Cloaked(this)) {
return(MOVE_CLOAK); return(MOVE_CLOAK);
} }
@@ -1183,6 +1183,32 @@ Mono_Set_Cursor(0,0);
* HISTORY: * * HISTORY: *
* 05/13/1996 JLB : Created. * * 05/13/1996 JLB : Created. *
*=============================================================================================*/ *=============================================================================================*/
FireDataType VesselClass::Fire_Data(int which) const
{
assert(Vessels.ID(this) == ID);
assert(IsActive);
COORDINATE coord = Center_Coord();
if (*this == VESSEL_CA) {
if (IsSecondShot) {
coord = Coord_Move(coord, PrimaryFacing + DIR_S, 0x0100);
} else {
coord = Coord_Move(coord, PrimaryFacing, 0x0100);
}
coord = Coord_Move(coord, DIR_N, 0x0030);
return{coord,0x0040};
}
if (*this == VESSEL_PT) {
coord = Coord_Move(coord, PrimaryFacing, 0x0080);
coord = Coord_Move(coord, DIR_N, 0x0020);
return{coord,0x0010};
}
return(DriveClass::Fire_Data(which));
}
COORDINATE VesselClass::Fire_Coord(int which) const COORDINATE VesselClass::Fire_Coord(int which) const
{ {
assert(Vessels.ID(this) == ID); assert(Vessels.ID(this) == ID);
+1
View File
@@ -97,6 +97,7 @@ class VesselClass : public DriveClass
virtual int Mission_Unload(void); virtual int Mission_Unload(void);
void LST_Open_Door(void); void LST_Open_Door(void);
void LST_Close_Door(void); void LST_Close_Door(void);
virtual FireDataType Fire_Data(int) const;
virtual COORDINATE Fire_Coord(int which) const; virtual COORDINATE Fire_Coord(int which) const;
virtual MoveType Can_Enter_Cell(CELL cell, FacingType from=FACING_NONE) const; virtual MoveType Can_Enter_Cell(CELL cell, FacingType from=FACING_NONE) const;
virtual void Draw_It(int x, int y, WindowNumberType window) const; virtual void Draw_It(int x, int y, WindowNumberType window) const;