diff --git a/tiberiandawn/bdata.cpp b/tiberiandawn/bdata.cpp index 1ec6301e..ad3626f3 100644 --- a/tiberiandawn/bdata.cpp +++ b/tiberiandawn/bdata.cpp @@ -4535,7 +4535,7 @@ int BuildingTypeClass::Full_Name(void) const if (::Scenario == 3 && Type == STRUCT_MISSION) { return (TXT_PRISON); } - if (!IsNominal || Special.IsNamed || IsWall || Debug_Map || Type == STRUCT_V23 || Type == STRUCT_V30 + if (!IsNominal || Rule.IsNamed || IsWall || Debug_Map || Type == STRUCT_V23 || Type == STRUCT_V30 || Type == STRUCT_MISSION || Type == STRUCT_BIO_LAB) { return (TechnoTypeClass::Full_Name()); } @@ -4567,7 +4567,7 @@ int BuildingTypeClass::Raw_Cost(void) const int BuildingTypeClass::Cost_Of(void) const { - if (Special.IsSeparate && Type == STRUCT_HELIPAD) { + if (Rule.IsSeparate && Type == STRUCT_HELIPAD) { return (Raw_Cost()); } diff --git a/tiberiandawn/building.cpp b/tiberiandawn/building.cpp index 3007356c..515142ea 100644 --- a/tiberiandawn/building.cpp +++ b/tiberiandawn/building.cpp @@ -924,7 +924,7 @@ void BuildingClass::AI(void) ** the loop. */ if (Fetch_Stage() == ctrl->Start + ctrl->Count - 1 - || (Special.IsMCVDeploy && *this == STRUCT_CONST && Mission == MISSION_DECONSTRUCTION + || (Is_MCV_Deploy() && *this == STRUCT_CONST && Mission == MISSION_DECONSTRUCTION && Fetch_Stage() == (42 - 19))) { IsReadyToCommence = true; } @@ -1672,7 +1672,7 @@ ResultType BuildingClass::Take_Damage(int& damage, int distance, WarheadType war if (*this != STRUCT_SAM && !House->Is_Ally(source) && Class->Primary != WEAPON_NONE && (!Target_Legal(TarCom) || !In_Range(TarCom))) { - if (source->What_Am_I() != RTTI_AIRCRAFT && (!House->IsHuman || Special.IsSmartDefense)) { + if (source->What_Am_I() != RTTI_AIRCRAFT && (!House->IsHuman || Rule.IsSmartDefense)) { Assign_Target(source->As_Target()); } else { @@ -3160,7 +3160,7 @@ ActionType BuildingClass::What_Action(CELL cell) const Validate(); ActionType action = TechnoClass::What_Action(cell); - if (action == ACTION_MOVE && (*this != STRUCT_CONST || !Special.IsMCVDeploy)) { + if (action == ACTION_MOVE && (*this != STRUCT_CONST || !Is_MCV_Deploy())) { action = ACTION_NONE; } @@ -4079,7 +4079,7 @@ int BuildingClass::Mission_Deconstruction(void) ** members leaving is equal to the unrecovered cost of the building ** divided by 100 (the typical cost of a minigunner infantryman). */ - if (!Target_Legal(ArchiveTarget) || !Special.IsMCVDeploy || *this != STRUCT_CONST) { + if (!Target_Legal(ArchiveTarget) || !Is_MCV_Deploy() || *this != STRUCT_CONST) { int divisor = 200; if (IsCaptured) divisor *= 2; @@ -4169,7 +4169,7 @@ int BuildingClass::Mission_Deconstruction(void) ** Construction yards that deconstruct, really just revert back ** to an MCV. */ - if (Target_Legal(ArchiveTarget) && Special.IsMCVDeploy && *this == STRUCT_CONST && House->IsHuman) { + if (Target_Legal(ArchiveTarget) && Is_MCV_Deploy() && *this == STRUCT_CONST && House->IsHuman) { ScenarioInit++; UnitClass* unit = new UnitClass(UNIT_MCV, House->Class->House); ScenarioInit--; @@ -4495,10 +4495,10 @@ int BuildingClass::Mission_Harvest(void) /* ** Force any bib squaters to scatter. */ - bool old = Special.IsScatter; - Special.IsScatter = true; + bool old = Rule.IsScatter; + Rule.IsScatter = true; Map[Adjacent_Cell(Coord_Cell(Center_Coord()), DIR_SW)].Incoming(0, true); - Special.IsScatter = old; + Rule.IsScatter = old; FootClass* techno = Attached_Object(); if (techno) { @@ -5444,7 +5444,7 @@ CELL BuildingClass::Find_Exit_Cell(TechnoClass const* techno) const bool BuildingClass::Can_Player_Move(void) const { Validate(); - return (*this == STRUCT_CONST && (Mission == MISSION_GUARD) && Special.IsMCVDeploy); + return (*this == STRUCT_CONST && (Mission == MISSION_GUARD) && Is_MCV_Deploy()); } /*********************************************************************************************** diff --git a/tiberiandawn/cell.cpp b/tiberiandawn/cell.cpp index 4883146d..57b099d0 100644 --- a/tiberiandawn/cell.cpp +++ b/tiberiandawn/cell.cpp @@ -1803,7 +1803,7 @@ void CellClass::Incoming(COORDINATE threat, bool forced, bool nokidding) /* ** Special check to make sure that friendly units never scatter. */ - if (nokidding || Special.IsScatter || (object->Is_Techno() && !((TechnoClass*)object)->House->IsHuman)) { + if (nokidding || Rule.IsScatter || (object->Is_Techno() && !((TechnoClass*)object)->House->IsHuman)) { if (object->What_Am_I() == RTTI_INFANTRY) { object->Scatter(threat, forced, nokidding); } else { diff --git a/tiberiandawn/dllinterface.cpp b/tiberiandawn/dllinterface.cpp index e310e751..6dace22e 100644 --- a/tiberiandawn/dllinterface.cpp +++ b/tiberiandawn/dllinterface.cpp @@ -724,14 +724,11 @@ extern "C" __declspec(dllexport) bool __cdecl CNC_Set_Multiplayer_Data(int scena MPlayerSolo = game_options.MPlayerSolo; // 1 = allows a single-player net game MPlayerUnitCount = game_options.MPlayerUnitCount; // # units for non-base multiplayer scenarios - Special.IsMCVDeploy = game_options.IsMCVDeploy; Special.IsVisceroids = game_options.SpawnVisceroids; Special.IsCaptureTheFlag = game_options.CaptureTheFlag; Special.IsEarlyWin = game_options.DestroyStructures; Special.ModernBalance = game_options.ModernBalance; - Rule.AllowSuperWeapons = game_options.EnableSuperweapons; // Are superweapons available - if (MPlayerTiberium) { Special.IsTGrowth = 1; Special.IsTSpread = 1; @@ -740,6 +737,11 @@ extern "C" __declspec(dllexport) bool __cdecl CNC_Set_Multiplayer_Data(int scena Special.IsTSpread = 0; } + Special.IsMCVDeploy = game_options.IsMCVDeploy; + Special.UseMCVDeploy = true; + + Rule.AllowSuperWeapons = game_options.EnableSuperweapons; // Are superweapons available + Scenario = scenario_index; MPlayerCount = 0; diff --git a/tiberiandawn/drive.cpp b/tiberiandawn/drive.cpp index 49227d19..4c40b7d2 100644 --- a/tiberiandawn/drive.cpp +++ b/tiberiandawn/drive.cpp @@ -239,7 +239,7 @@ void DriveClass::Overrun_Square(CELL cell, bool threaten) /* ** Scattering is controlled by the game difficulty level. */ - if (((GameToPlay == GAME_NORMAL && PlayerPtr->Difficulty == DIFF_HARD) || Special.IsScatter + if (((GameToPlay == GAME_NORMAL && PlayerPtr->Difficulty == DIFF_HARD) || Rule.IsScatter || Scenario > 8) && !(GameToPlay == GAME_NORMAL && PlayerPtr->Difficulty == DIFF_EASY)) { cellptr->Incoming(0, true); @@ -708,10 +708,10 @@ bool DriveClass::While_Moving(void) case MOVE_TEMP: if (*this == UNIT_HARVESTER || !House->IsHuman) { - bool old = Special.IsScatter; - Special.IsScatter = true; + bool old = Rule.IsScatter; + Rule.IsScatter = true; Map[Coord_Cell(c)].Incoming(0, true); - Special.IsScatter = old; + Rule.IsScatter = old; } break; } @@ -975,10 +975,10 @@ bool DriveClass::Start_Of_Move(void) CellClass* cellptr = &Map[cell]; TechnoClass* blockage = cellptr->Cell_Techno(); if (blockage && House->Is_Ally(blockage)) { - bool old = Special.IsScatter; - Special.IsScatter = true; + bool old = Rule.IsScatter; + Rule.IsScatter = true; cellptr->Incoming(0, true); - Special.IsScatter = old; + Rule.IsScatter = old; } } } @@ -1009,10 +1009,10 @@ bool DriveClass::Start_Of_Move(void) CellClass* cellptr = &Map[cell]; TechnoClass* blockage = cellptr->Cell_Techno(); if (blockage && House->Is_Ally(blockage)) { - bool old = Special.IsScatter; - Special.IsScatter = true; + bool old = Rule.IsScatter; + Rule.IsScatter = true; cellptr->Incoming(0, true); - Special.IsScatter = old; + Rule.IsScatter = old; } } } @@ -1079,10 +1079,10 @@ bool DriveClass::Start_Of_Move(void) ** get out of the way. */ if (cando == MOVE_TEMP) { - bool old = Special.IsScatter; - Special.IsScatter = true; + bool old = Rule.IsScatter; + Rule.IsScatter = true; Map[destcell].Incoming(0, true); - Special.IsScatter = old; + Rule.IsScatter = old; } /* @@ -1210,10 +1210,10 @@ bool DriveClass::Start_Of_Move(void) ** get out of the way. */ if (cando == MOVE_TEMP) { - bool old = Special.IsScatter; - Special.IsScatter = true; + bool old = Rule.IsScatter; + Rule.IsScatter = true; Map[destcell].Incoming(0, true); - Special.IsScatter = old; + Rule.IsScatter = old; } /* diff --git a/tiberiandawn/foot.cpp b/tiberiandawn/foot.cpp index e3e75038..8e5da0c1 100644 --- a/tiberiandawn/foot.cpp +++ b/tiberiandawn/foot.cpp @@ -1175,7 +1175,7 @@ ResultType FootClass::Take_Damage(int& damage, int distance, WarheadType warhead && (source->What_Am_I() != RTTI_AIRCRAFT || BulletTypeClass::As_Reference(Weapons[Techno_Type_Class()->Primary].Fires).IsAntiAircraft) && (!Target_Legal(TarCom) - || ((!House->IsHuman || Special.IsSmartDefense) && (!tweap || !In_Range(TarCom)))) + || ((!House->IsHuman || Rule.IsSmartDefense) && (!tweap || !In_Range(TarCom)))) && // !Target_Legal(NavCom) && (Mission == MISSION_AMBUSH || Mission == MISSION_GUARD || Mission == MISSION_RESCUE @@ -1208,7 +1208,7 @@ ResultType FootClass::Take_Damage(int& damage, int distance, WarheadType warhead ** Simple retaliation cannot occur because the source of the damage ** is too far away. If scatter logic is enabled, then scatter now. */ - if (Special.IsScatter) { + if (Rule.IsScatter) { Scatter(0, true); } } @@ -1218,7 +1218,7 @@ ResultType FootClass::Take_Damage(int& damage, int distance, WarheadType warhead /* ** If this object isn't doing anything important, then scatter. */ - if (!IsDriving && !Target_Legal(TarCom) && !Target_Legal(NavCom) && Special.IsScatter + if (!IsDriving && !Target_Legal(TarCom) && !Target_Legal(NavCom) && Rule.IsScatter && What_Am_I() != RTTI_AIRCRAFT) { Scatter(0, true); } diff --git a/tiberiandawn/idata.cpp b/tiberiandawn/idata.cpp index a48a2f3d..1de498c8 100644 --- a/tiberiandawn/idata.cpp +++ b/tiberiandawn/idata.cpp @@ -2002,7 +2002,7 @@ BuildingClass* InfantryTypeClass::Who_Can_Build_Me(bool intheory, bool legal, Ho *=============================================================================================*/ int InfantryTypeClass::Full_Name(void) const { - if (Debug_Map || !IsNominal || Special.IsNamed || Type == INFANTRY_C10 || Type == INFANTRY_DELPHI + if (Debug_Map || !IsNominal || Rule.IsNamed || Type == INFANTRY_C10 || Type == INFANTRY_DELPHI || Type == INFANTRY_MOEBIUS) { return (TechnoTypeClass::Full_Name()); } diff --git a/tiberiandawn/infantry.cpp b/tiberiandawn/infantry.cpp index 2cc00baa..2401b1a2 100644 --- a/tiberiandawn/infantry.cpp +++ b/tiberiandawn/infantry.cpp @@ -716,7 +716,7 @@ void InfantryClass::Per_Cell_Process(bool center) if (center && Mission == MISSION_SABOTAGE) { BuildingClass* building = cellptr->Cell_Building(); if (building && building->As_Target() == NavCom) { - int temp = Special.IsScatter; + int temp = Rule.IsScatter; building->IsGoingToBlow = true; building->Clicked_As_Target(PlayerPtr->Class->House, @@ -724,12 +724,12 @@ void InfantryClass::Per_Cell_Process(bool center) building->Clicked_As_Target(building->Owner(), 20); building->CountDown.Set(20); building->WhomToRepay = As_Target(); - Special.IsScatter = true; + Rule.IsScatter = true; NavCom = TARGET_NONE; Do_Uncloak(); Arm = Rearm_Delay(true); Scatter(building->Center_Coord(), true); // RUN AWAY! - Special.IsScatter = temp; + Rule.IsScatter = temp; return; } } @@ -2102,7 +2102,7 @@ void InfantryClass::Scatter(COORDINATE threat, bool forced, bool nokidding) ** For human players, don't scatter the infantry, if the special ** flag has not been enabled that allows infantry scatter. */ - if (!Special.IsScatter && !nokidding && House->IsHuman && !forced && !Team) + if (!Rule.IsScatter && !nokidding && House->IsHuman && !forced && !Team) return; if (forced || Class->IsFraidyCat /*|| !(Random_Pick(1, 4) == 1)*/) { diff --git a/tiberiandawn/map.cpp b/tiberiandawn/map.cpp index 497173d9..bc022bf1 100644 --- a/tiberiandawn/map.cpp +++ b/tiberiandawn/map.cpp @@ -1369,7 +1369,7 @@ void MapClass::Logic(void) /* ** Bail early if there is no allowed growth or spread of Tiberium. */ - if (!Special.IsTGrowth && !Special.IsTSpread) + if (!Rule.IsTGrowth && !Rule.IsTSpread) return; /* @@ -1384,7 +1384,7 @@ void MapClass::Logic(void) cell = (MAP_CELL_TOTAL - 1) - index; CellClass* ptr = &(*this)[cell]; - if (Special.IsTGrowth && ptr->Land_Type() == LAND_TIBERIUM && ptr->OverlayData < 11) { + if (Rule.IsTGrowth && ptr->Land_Type() == LAND_TIBERIUM && ptr->OverlayData < 11) { if (TiberiumGrowthCount < sizeof(TiberiumGrowth) / sizeof(TiberiumGrowth[0])) { TiberiumGrowth[TiberiumGrowthCount++] = cell; } else { @@ -1396,7 +1396,7 @@ void MapClass::Logic(void) ** Heavy Tiberium growth can spread. */ TerrainClass* terrain = ptr->Cell_Terrain(); - if (Special.IsTSpread && (ptr->Land_Type() == LAND_TIBERIUM && ptr->OverlayData > 6) + if (Rule.IsTSpread && (ptr->Land_Type() == LAND_TIBERIUM && ptr->OverlayData > 6) || (terrain && terrain->Class->IsTiberiumSpawn)) { int tries = 1; diff --git a/tiberiandawn/netdlg.cpp b/tiberiandawn/netdlg.cpp index 3c025a62..8809078d 100644 --- a/tiberiandawn/netdlg.cpp +++ b/tiberiandawn/netdlg.cpp @@ -4406,6 +4406,7 @@ static int Net_Fake_New_Dialog(void) ........................................................................*/ Special.IsTGrowth = MPlayerTiberium; Special.IsTSpread = MPlayerTiberium; + Rule.IsTSpread = Special.IsTSpread; transmit = 0; /*........................................................................ diff --git a/tiberiandawn/options.cpp b/tiberiandawn/options.cpp index 07d58f92..4cdd30d5 100644 --- a/tiberiandawn/options.cpp +++ b/tiberiandawn/options.cpp @@ -681,14 +681,6 @@ void OptionsClass::Load_Settings(void) char workbuf[128]; - /* - ** Check for and possible enable true object names. - */ - ini.Get_String(OPTIONS, "TrueNames", "", workbuf, sizeof(workbuf)); - if (Obfuscate(workbuf) == PARM_TRUENAME) { - Special.IsNamed = true; - } - /* ** Enable 6 player games if special flag is detected. */ @@ -705,22 +697,6 @@ void OptionsClass::Load_Settings(void) Special.IsThreePoint = true; } - /* - ** Allow purchase of the helipad separately from the helicopter. - */ - ini.Get_String(OPTIONS, "Helipad", "", workbuf, sizeof(workbuf)); - if (Obfuscate(workbuf) == PARM_HELIPAD) { - Special.IsSeparate = true; - } - - /* - ** Allow the MCV to undeploy rather than sell. - */ - ini.Get_String(OPTIONS, "MCV", "", workbuf, sizeof(workbuf)); - if (Obfuscate(workbuf) == PARM_MCV) { - Special.IsMCVDeploy = true; - } - /* ** Allow disabling of building bibs so that tigher building packing can occur. */ @@ -729,14 +705,6 @@ void OptionsClass::Load_Settings(void) Special.IsRoad = true; } - /* - ** Allow targeting of trees without having to hold down the shift key. - */ - ini.Get_String(OPTIONS, "TreeTarget", "", workbuf, sizeof(workbuf)); - if (Obfuscate(workbuf) == PARM_TREETARGET) { - Special.IsTreeTarget = true; - } - /* ** Allow infantry to fire while moving. Attacker gets advantage with this flag. */ @@ -753,17 +721,6 @@ void OptionsClass::Load_Settings(void) Special.IsVariation = true; } - /* - ** Smarter self defense logic. Tanks will try to run over adjacent infantry. Buildings - ** will automatically return fire if they are fired upon. Infantry will run from an - ** incoming explosive (grenade or napalm) or damage that can't be directly addressed. - */ - ini.Get_String(OPTIONS, "CombatIQ", "", workbuf, sizeof(workbuf)); - if (Obfuscate(workbuf) == PARM_IQ) { - Special.IsSmartDefense = true; - Special.IsScatter = true; - } - /* ** Enable the infantry squish marks when run over by a vehicle. */ diff --git a/tiberiandawn/rules.cpp b/tiberiandawn/rules.cpp index f1a4ef45..3ca8b76c 100644 --- a/tiberiandawn/rules.cpp +++ b/tiberiandawn/rules.cpp @@ -123,6 +123,14 @@ RulesClass::RulesClass(void) , IsComputerParanoid(false) , IsCompEasyBonus(false) , IsFineDifficulty(false) + , IsMCVDeploy(false) + , IsSeparate(false) + , IsTreeTarget(false) + , IsTGrowth(true) + , IsTSpread(true) + , IsNamed(false) + , IsSmartDefense(false) + , IsScatter(false) , AllowSuperWeapons(true) { #ifndef REMASTER_BUILD @@ -253,6 +261,7 @@ static void Difficulty_Put(CCINIClass& ini, DifficultyClass& diff, char const* s *=============================================================================================*/ bool RulesClass::Process(CCINIClass& ini) { + General(ini); AI(ini); IQ(ini); Difficulty(ini); @@ -276,6 +285,7 @@ bool RulesClass::Process(CCINIClass& ini) *=============================================================================================*/ bool RulesClass::Export(CCINIClass& ini) { + Export_General(ini); Export_AI(ini); Export_IQ(ini); Export_Difficulty(ini); @@ -283,6 +293,76 @@ bool RulesClass::Export(CCINIClass& ini) return (true); } +/*********************************************************************************************** + * RulesClass::General -- Process the general main game rules. * + * * + * This fetches the control constants uses for regular game processing. Any game behavior * + * controlling values that don't properly fit in any of the other catagories will be * + * stored here. * + * * + * INPUT: ini -- Reference to the database to fetch the values from. * + * * + * OUTPUT: bool; Was the general section found and processed? * + * * + * WARNINGS: none * + * * + * HISTORY: * + * 08/08/1996 JLB : Created. * + *=============================================================================================*/ +bool RulesClass::General(CCINIClass& ini) +{ + static char const* const GENERAL = "General"; + + if (ini.Is_Present(GENERAL)) { + IsFineDifficulty = ini.Get_Bool(GENERAL, "FineDiffControl", IsFineDifficulty); + IsScatter = ini.Get_Bool(GENERAL, "PlayerScatter", IsScatter); + IsSmartDefense = ini.Get_Bool(GENERAL, "PlayerReturnFire", IsSmartDefense); + IsNamed = ini.Get_Bool(GENERAL, "NamedCivilians", IsNamed); + IsTGrowth = ini.Get_Bool(GENERAL, "TiberiumGrows", IsTGrowth); + IsTSpread = ini.Get_Bool(GENERAL, "TiberiumSpreads", IsTSpread); + IsTreeTarget = ini.Get_Bool(GENERAL, "TreeTargeting", IsTreeTarget); + IsSeparate = ini.Get_Bool(GENERAL, "SeparateAircraft", IsSeparate); + IsMCVDeploy = ini.Get_Bool(GENERAL, "MCVUndeploy", IsMCVDeploy); + + return (true); + } + + return (false); +} + +/*********************************************************************************************** + * RulesClass::General -- Process the general main game rules. * + * * + * This fetches the control constants uses for regular game processing. Any game behavior * + * controlling values that don't properly fit in any of the other catagories will be * + * stored here. * + * * + * INPUT: ini -- Reference to the database to fetch the values from. * + * * + * OUTPUT: bool; Was the general section found and processed? * + * * + * WARNINGS: none * + * * + * HISTORY: * + * 08/08/1996 JLB : Created. * + *=============================================================================================*/ +bool RulesClass::Export_General(CCINIClass& ini) +{ + static char const GENERAL[] = "General"; + + ini.Put_Bool(GENERAL, "FineDiffControl", IsFineDifficulty); + ini.Put_Bool(GENERAL, "PlayerScatter", IsScatter); + ini.Put_Bool(GENERAL, "PlayerReturnFire", IsSmartDefense); + ini.Put_Bool(GENERAL, "NamedCivilians", IsNamed); + ini.Put_Bool(GENERAL, "TiberiumGrows", IsTGrowth); + ini.Put_Bool(GENERAL, "TiberiumSpreads", IsTSpread); + ini.Put_Bool(GENERAL, "TreeTargeting", IsTreeTarget); + ini.Put_Bool(GENERAL, "SeparateAircraft", IsSeparate); + ini.Put_Bool(GENERAL, "MCVUndeploy", IsMCVDeploy); + + return (true); +} + /*********************************************************************************************** * RulesClass::AI -- Processes the AI control constants from the database. * * * @@ -497,4 +577,24 @@ bool RulesClass::Export_Difficulty(CCINIClass& ini) Difficulty_Put(ini, Diff[DIFF_HARD], "Difficult"); #endif return (true); +} + +/*********************************************************************************************** + * Is_MCV_Deploy -- Check if MCV can be deployed. * + * * + * This routine is used to check if the Construction Yard can revert back into an MCV. * + * It allows the special variables to override anything set by the rules. * + * * + * INPUT: none * + * * + * OUTPUT: bool; Can the Construction Yard revert back into an MCV. * + * * + * WARNINGS: none * + * * + * HISTORY: * + * 10/24/2019 SKY : Created. * + *=============================================================================================*/ +bool Is_MCV_Deploy() +{ + return Special.UseMCVDeploy ? Special.IsMCVDeploy : Rule.IsMCVDeploy; } \ No newline at end of file diff --git a/tiberiandawn/rules.h b/tiberiandawn/rules.h index c9b8cc53..2c0d7b17 100644 --- a/tiberiandawn/rules.h +++ b/tiberiandawn/rules.h @@ -66,10 +66,12 @@ class RulesClass RulesClass(void); bool Process(CCINIClass& file); + bool General(CCINIClass& ini); bool AI(CCINIClass& ini); bool IQ(CCINIClass& ini); bool Difficulty(CCINIClass& ini); bool Export(CCINIClass& file); + bool Export_General(CCINIClass& ini); bool Export_AI(CCINIClass& ini); bool Export_IQ(CCINIClass& ini); bool Export_Difficulty(CCINIClass& ini); @@ -283,6 +285,50 @@ class RulesClass */ bool IsFineDifficulty; + /* + ** If this flag is true, then the construction yard can undeploy back into an MCV. + */ + bool IsMCVDeploy; + + /* + ** Can the helipad (and airfield) be purchased separately from the associated + ** aircraft. + */ + bool IsSeparate; + + /* + ** Give target cursor for trees? Doing this will make targetting of trees easier. + */ + bool IsTreeTarget; + + /* + ** If Tiberium is allowed to grow, then this flag will be true. + */ + bool IsTGrowth; + + /* + ** If Tiberium is allowed to spread, then this flag will be true. + */ + bool IsTSpread; + + /* + ** Should civilan buildings and civilians display their true name rather than + ** the generic "Civilian Building" and "Civilain"? + */ + bool IsNamed; + + /* + ** Should the player controlled buildings and units automatically return fire when + ** fired upon? + */ + bool IsSmartDefense; + + /* + ** Should player controlled units try to scatter more easily in order to + ** avoid damage or threats? + */ + bool IsScatter; + /* ** Are superweapons allowed? */ @@ -295,4 +341,6 @@ class RulesClass DifficultyClass Diff[DIFF_COUNT]; }; +bool Is_MCV_Deploy(); + #endif diff --git a/tiberiandawn/special.cpp b/tiberiandawn/special.cpp index d75e44cc..a6b1c71c 100644 --- a/tiberiandawn/special.cpp +++ b/tiberiandawn/special.cpp @@ -79,11 +79,11 @@ void Special_Dialog(void) bool value = false; switch (_options[index].Description) { case TXT_SEPARATE_HELIPAD: - value = Special.IsSeparate; + value = Rule.IsSeparate; break; case TXT_SHOW_NAMES: - value = Special.IsNamed; + value = Rule.IsNamed; break; case TXT_DEFENDER_ADVANTAGE: @@ -95,15 +95,15 @@ void Special_Dialog(void) break; case TXT_TREE_TARGET: - value = Special.IsTreeTarget; + value = Rule.IsTreeTarget; break; case TXT_MCV_DEPLOY: - value = Special.IsMCVDeploy; + value = Rule.IsMCVDeploy; break; case TXT_SMART_DEFENCE: - value = Special.IsSmartDefense; + value = Rule.IsSmartDefense; break; case TXT_THREE_POINT: @@ -127,7 +127,7 @@ void Special_Dialog(void) break; case TXT_SCATTER: - value = Special.IsScatter; + value = Rule.IsScatter; break; } diff --git a/tiberiandawn/special.h b/tiberiandawn/special.h index 957ecd3e..0a9d8b35 100644 --- a/tiberiandawn/special.h +++ b/tiberiandawn/special.h @@ -52,6 +52,7 @@ class SpecialClass IsJuvenile = false; IsSmartDefense = false; IsTreeTarget = false; + UseMCVDeploy = false; IsMCVDeploy = false; IsVisceroids = false; IsMonoEnabled = false; @@ -147,6 +148,7 @@ class SpecialClass /* ** If this flag is true, then the construction yard can undeploy back into an MCV. */ + unsigned UseMCVDeploy : 1; unsigned IsMCVDeploy : 1; /* diff --git a/tiberiandawn/techno.cpp b/tiberiandawn/techno.cpp index 4601ea13..eabb3111 100644 --- a/tiberiandawn/techno.cpp +++ b/tiberiandawn/techno.cpp @@ -2630,9 +2630,9 @@ ActionType TechnoClass::What_Action(ObjectClass* object) const // Changed for multiplayer. ST - 3/13/2019 5:52PM if (Is_Owned_By_Player() && (ctrldown || !House->Is_Ally(object)) && (ctrldown || object->Class_Of().IsLegalTarget - || (Special.IsTreeTarget && object->What_Am_I() == RTTI_TERRAIN))) { + || (Rule.IsTreeTarget && object->What_Am_I() == RTTI_TERRAIN))) { // if (IsOwnedByPlayer && (ctrldown || !House->Is_Ally(object)) && (ctrldown || - // object->Class_Of().IsLegalTarget || (Special.IsTreeTarget && object->What_Am_I() == RTTI_TERRAIN))) { + // object->Class_Of().IsLegalTarget || (Rule.IsTreeTarget && object->What_Am_I() == RTTI_TERRAIN))) { if (Can_Player_Move() || In_Range(object, 0)) { // Check for anti-air capability if (object->What_Am_I() != RTTI_AIRCRAFT) { diff --git a/tiberiandawn/unit.cpp b/tiberiandawn/unit.cpp index c0bf8db3..b0e92d3c 100644 --- a/tiberiandawn/unit.cpp +++ b/tiberiandawn/unit.cpp @@ -994,7 +994,7 @@ ResultType UnitClass::Take_Damage(int& damage, int distance, WarheadType warhead ** Try to crush anyone that fires on this unit if possible. The harvester ** typically is the only one that will qualify here. */ - if (!Team && source && !IsTethered && !House->Is_Ally(source) && (!House->IsHuman || Special.IsSmartDefense)) { + if (!Team && source && !IsTethered && !House->Is_Ally(source) && (!House->IsHuman || Rule.IsSmartDefense)) { /* ** Try to crush the attacker if it can be crushed by this unit and this unit is