Skip to content

Commit

Permalink
Merged in Root-Core/cncremastered (pull request electronicarts#3)
Browse files Browse the repository at this point in the history
Updated Red Alert port to 06f73fb
  • Loading branch information
Root-Core authored and cfehunter committed Jun 15, 2020
2 parents df2eeca + 06bcc97 commit 201b2ff
Show file tree
Hide file tree
Showing 21 changed files with 520 additions and 51 deletions.
1 change: 1 addition & 0 deletions Mod Data/CCDATA/DEFAULT.CFEPATCH.INI
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ BUILDING_GAP=2
QUEUE_JUMP_CUTOFF=3
TIB_GROWTH_SCALE=1
WALL_BUILD_LENGTH=5
BUILDING_GAP_OFFSET=0
1 change: 1 addition & 0 deletions Mod Data/CCDATA/DEFAULT.CFEPATCH_RA.INI
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ INSTANT_CAPTURE=1
QUEUE_JUMP_CUTOFF=3
ORE_GROWTH_SCALE=1
WALL_BUILD_LENGTH=5
BUILDING_GAP_OFFSET=0
2 changes: 1 addition & 1 deletion REDALERT/AIRCRAFT.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -2449,7 +2449,7 @@ int AircraftClass::Mission_Attack(void)
** Double check target and validate the attack zone.
*/
case VALIDATE_AZ:
if (!Target_Legal(TarCom)) {
if (!Target_Legal(TarCom) || !Ammo) {
Status = RETURN_TO_BASE;
} else {
Status = PICK_ATTACK_LOCATION;
Expand Down
54 changes: 38 additions & 16 deletions REDALERT/BUILDING.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -433,15 +433,8 @@ RadioMessageType BuildingClass::Receive_Message(RadioClass * from, RadioMessageT
}
TechnoClass::Receive_Message(from, message, param);

//Either tell the unit to move to the rally point, or have it run away
if (Can_Have_Rally_Point() && Target_Legal(RallyPoint)) {
SpeedType speed = from->Is_Techno() ? ((TechnoClass const*)from)->Techno_Type_Class()->Speed : SPEED_TRACK;

from->Set_Mission(MISSION_MOVE);
static_cast<FootClass*>(from)->Assign_Destination(Target_For_Rally_Point(speed));
return RADIO_ROGER;
}

//Rally the unit
Rally_Unit(static_cast<FootClass&>(*from));
return(RADIO_ROGER);

default:
Expand Down Expand Up @@ -904,7 +897,7 @@ bool BuildingClass::Unlimbo_Wall(COORDINATE coord)
const OverlayTypeClass& oclass = OverlayTypeClass::As_Reference(otype);
if (Create_Overlay_At(oclass, placecell))
{
if (ActiveCFEPatchConfig.WallBuildLength > 1)
if (CFE_Patch_Should_Extend_Walls())
{
/* cfehunter 12/06/2020
* Walk through every cardinal direction and run the same scanning logic as the build cursor
Expand Down Expand Up @@ -2113,11 +2106,7 @@ int BuildingClass::Exit_Object(TechnoClass * base)
ScenarioInit++;
cell = Find_Exit_Cell(base);
if (cell != 0 && base->Unlimbo(Cell_Coord(cell), Direction(Cell_Coord(cell)))) {
if (Can_Have_Rally_Point() && RallyPoint) {
base->Set_Mission(MISSION_MOVE);
base->Assign_Destination(Target_For_Rally_Point(base->Techno_Type_Class()->Speed));
}
else {
if (!Rally_Unit(static_cast<FootClass&>(*base))) {
base->Assign_Mission(MISSION_GUARD);
}
ScenarioInit--;
Expand Down Expand Up @@ -4383,6 +4372,10 @@ int BuildingClass::Mission_Repair(void)
** The repair step resulted in a completely repaired unit.
*/
case RADIO_ALL_DONE:
if (!Rally_Unit(static_cast<FootClass&>(*Contact_With_Whom()))) {
Transmit_Message(RADIO_RUN_AWAY);
Transmit_Message(RADIO_OVER_OUT);
}

// MBL 04.27.2020: Make only audible to the correct player
// if (IsOwnedByPlayer) Speak(VOX_UNIT_REPAIRED);
Expand Down Expand Up @@ -6186,4 +6179,33 @@ unsigned BuildingClass::Spied_By() const
}

return spiedby;
}
}

/***********************************************************************************************
* BuildingClass::Rally_Unit -- Order a unit to the buildings rally point *
* *
* This routine will attempt to order a unit to move the the buildings rally point. *
* If the building has a rally point, and the unit should be rallyed. *
* *
* INPUT: unit - unit to rally *
* *
* OUTPUT: true if successful *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 14/06/2020 cfehunter : Created. *
*=============================================================================================*/
bool BuildingClass::Rally_Unit(FootClass& unit)
{
if (Can_Have_Rally_Point() && CFE_Patch_Unit_Should_Rally(unit) && Target_Legal(RallyPoint))
{
//SpeedType speed = from->Is_Techno() ? ((TechnoClass const*)from)->Techno_Type_Class()->Speed : SPEED_TRACK;
const TARGET rallyTarget = Target_For_Rally_Point(unit.Techno_Type_Class()->Speed);

//Make sure units dont rally to themselves. Only a problem for repair/reload pads
long move_target = (long)(unit.As_Target() != rallyTarget ? rallyTarget : ::As_Target(Nearby_Location()));
return Target_Legal(move_target) && Transmit_Message(RADIO_MOVE_HERE, move_target, &unit) == RADIO_ROGER;
}
return false;
}
3 changes: 2 additions & 1 deletion REDALERT/BUILDING.H
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,10 @@ class BuildingClass : public TechnoClass

virtual unsigned Spied_By() const;

bool Can_Have_Rally_Point() const;
bool Can_Have_Rally_Point(void) const;
virtual void Set_Unselected_By_Player(HouseClass* player = nullptr) override;

bool Rally_Unit(FootClass& unit);
private:
void Drop_Debris(TARGET source = TARGET_NONE);
void Player_Set_Rally_Point(TARGET target);
Expand Down
15 changes: 15 additions & 0 deletions REDALERT/CFEDEBUG.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include <cstdio>
#include "FUNCTION.H"

//Prints to steamapps\common\CnCRemastered\log\CnCDLL_Log_16000.txt
template <typename... ARGS>
void CFE_Debug_Printf(const char* const format, const ARGS&... args) {
const int bufferSize = snprintf(nullptr, 0, format, args...);
char* printed = (char*)malloc(bufferSize + 1);
snprintf(printed, bufferSize + 1, format, args...);

GlyphX_Debug_Print(printed);
delete printed;
}
29 changes: 29 additions & 0 deletions REDALERT/CFEPATCHQUERY.CPP
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "FUNCTION.H"

extern bool DLL_Export_Get_Input_Key_State(KeyNumType key);

bool CFE_Patch_Is_Wall(const ObjectTypeClass& object)
{
return object.What_Am_I() == RTTI_BUILDINGTYPE && static_cast<const BuildingTypeClass&>(object).IsWall;
}

bool CFE_Patch_Can_Have_Rally_Point(const ObjectClass& object)
{
return object.What_Am_I() == RTTI_BUILDING && static_cast<const BuildingClass&>(object).Can_Have_Rally_Point();
}

bool CFE_Patch_Should_Extend_Walls()
{
return ActiveCFEPatchConfig.WallBuildLength > 1 && !DLL_Export_Get_Input_Key_State(KN_LCTRL);
}

bool CFE_Patch_Unit_Should_Rally(const FootClass& object)
{
switch (object.What_Am_I())
{
case RTTI_UNIT:
return !static_cast<const UnitClass&>(object).Class->IsToHarvest;
default:
return true;
}
}
149 changes: 149 additions & 0 deletions REDALERT/CFEUTIL.CPP
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#define WIN32_LEAN_AND_MEAN
#include <algorithm>
#include <Windows.h>
#include <ShlObj.h>
#include <string>

#include "FUNCTION.H"
#include "INI.H"
#include "RANGEWRAPPER.H"

std::string Get_User_Mod_Dir()
{
std::string dirPath;
char documentsPath[1024];
HRESULT result = SHGetFolderPathA(NULL, CSIDL_MYDOCUMENTS, NULL, NULL, documentsPath);
if (SUCCEEDED(result))
{
dirPath = documentsPath;
dirPath += "\\CnCRemastered\\Mods\\Red_Alert";
}
return dirPath;
}

bool Load_INI_File(INIClass& ini, const char* path)
{
CCFileClass file(path);
if (file.Is_Available())
{
ini.Clear();
return ini.Load(file);
}
return false;
}

void Populate_CFE_Patch_Config_From_INI(const INIClass& ini)
{
static constexpr int InvalidSetting = std::numeric_limits<int>::lowest();
const auto GetSetting = [&ini](auto& target, const char* section, const char* entry)
{
const int value = ini.Get_Int(section, entry, InvalidSetting);
if (value != InvalidSetting)
target = value;
};



//cfehunter 12/06/2020 It's really starting to get to the point where I should make feature flags
//Features
GetSetting(ActiveCFEPatchConfig.EnableASPathing, "FEATURES", "ASTAR_PATHING");
GetSetting(ActiveCFEPatchConfig.EnableOOMRepair, "FEATURES", "OOM_REPAIR");
GetSetting(ActiveCFEPatchConfig.EnableRallyPoints, "FEATURES", "RALLY_POINTS");
GetSetting(ActiveCFEPatchConfig.EnableHarvyQueueJump, "FEATURES", "HARVY_QUEUE_JUMP");
GetSetting(ActiveCFEPatchConfig.EnableInstantCapture, "FEATURES", "INSTANT_CAPTURE");

//Settings
GetSetting(ActiveCFEPatchConfig.HarvyQueueJumpCutoff, "SETTINGS", "QUEUE_JUMP_CUTOFF");
GetSetting(ActiveCFEPatchConfig.OreGrowthScale, "SETTINGS", "ORE_GROWTH_SCALE");
GetSetting(ActiveCFEPatchConfig.WallBuildLength, "SETTINGS", "WALL_BUILD_LENGTH");
GetSetting(ActiveCFEPatchConfig.BuildingGapOffset, "SETTINGS", "BUILDING_GAP_OFFSET");

//Clamp Wall Length between 1 (build at all) and 10 (buffer limits)
ActiveCFEPatchConfig.WallBuildLength = (std::max)(1, (std::min)(ActiveCFEPatchConfig.WallBuildLength, 10));
}

bool Create_CFE_Patch_Directory(const char* path)
{
const int directory_result = SHCreateDirectoryExA(NULL, path, NULL);
return directory_result == ERROR_SUCCESS || directory_result == ERROR_ALREADY_EXISTS;
}

bool Reconcile_Config_With_Default(const INIClass& default, INIClass& config)
{
bool changed = false;
using KVPair = std::pair<const char*, const char*>;
for (const char* section : default)
{
for (KVPair entry : make_iterator_range(default.section_begin(section), default.section_end(section)))
{
if (!config.Is_Present(section, entry.first))
{
config.Put_String(section, entry.first, entry.second);
changed = true;
}
}
}

return changed;
}

//cfehunter 12/06/2020 I really miss std::filesystem
void Initialise_CFE_Patch_Config()
{
static constexpr const char* DefaultININame = "DEFAULT.CFEPATCH_RA.INI";

const std::string ini_dir = Get_User_Mod_Dir() + "\\CFEPatch";
const std::string ini_path = ini_dir + "\\CFEPATCH_RA.INI";

INIClass default_ini;
Load_INI_File(default_ini, DefaultININame);



//Initialise from the default config
Populate_CFE_Patch_Config_From_INI(default_ini);

//Overwrite settings from the user config
INIClass user_ini;
if (Load_INI_File(user_ini, ini_path.c_str()))
{
Populate_CFE_Patch_Config_From_INI(user_ini);

//Add any missing settings
if (Reconcile_Config_With_Default(default_ini, user_ini))
{
//Create the target directory
if (Create_CFE_Patch_Directory(ini_dir.c_str()))
{
//Write the modified ini to a temp file
const std::string write_path = ini_path + ".temp";
if (FILE* target_file = fopen(write_path.c_str(), "w"))
{
fclose(target_file);

//If it was written successfully, overwrite the existing config
CCFileClass write_file(write_path.c_str());
if (user_ini.Save(write_file))
{
write_file.Close();
CopyFileA(write_path.c_str(), ini_path.c_str(), FALSE);
}
}
}
}
}
else
{
//Clone the default
CCFileClass defaultConfig(DefaultININame);
if (defaultConfig.Is_Available())
{
//Create directories and clone the default config
if (Create_CFE_Patch_Directory(ini_dir.c_str()))
{
//Copy the default ini to the user directory so they can modify it later
CopyFileA(defaultConfig.File_Name(), ini_path.c_str(), TRUE);
}
}
}
}
12 changes: 7 additions & 5 deletions REDALERT/DISPLAY.CPP
Original file line number Diff line number Diff line change
Expand Up @@ -5155,13 +5155,12 @@ ActionType Best_Object_Action(CELL cell)
*=============================================================================================*/
void DisplayClass::Update_Placement_Cursor()
{
if (ActiveCFEPatchConfig.WallBuildLength > 1 && In_Radar(ZoneCell))
const BuildingTypeClass* const placement_building = PendingObject && PendingObject->What_Am_I() == RTTI_BUILDINGTYPE ? static_cast<const BuildingTypeClass*>(PendingObject) : nullptr;
if (placement_building && placement_building->IsWall)
{
const BuildingTypeClass* const placementBuilding = PendingObject && PendingObject->What_Am_I() == RTTI_BUILDINGTYPE ? static_cast<const BuildingTypeClass*>(PendingObject) : nullptr;

if (placementBuilding && placementBuilding->IsWall)
if (CFE_Patch_Should_Extend_Walls() && In_Radar(ZoneCell))
{
const OverlayType wallOverlay = placementBuilding->Overlay_Type();
const OverlayType wallOverlay = placement_building->Overlay_Type();

static short offsetlist[50];
static constexpr int MaxOffsets = sizeof(offsetlist) / sizeof(offsetlist[0]) - 1;
Expand All @@ -5186,5 +5185,8 @@ void DisplayClass::Update_Placement_Cursor()
offsetlist[offsetslength] = REFRESH_EOL;
Set_Cursor_Shape(offsetlist);
}
else if (CursorSize[1] != REFRESH_EOL) {
Set_Cursor_Shape(placement_building->Occupy_List(true));
}
}
}
1 change: 1 addition & 0 deletions REDALERT/EXTERNS.H
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ struct CFEPatchConfig
int HarvyQueueJumpCutoff = 3;
int OreGrowthScale = 1;
int WallBuildLength = 5;
int BuildingGapOffset = 0;
};

extern CFEPatchConfig ActiveCFEPatchConfig;
Expand Down
Loading

0 comments on commit 201b2ff

Please sign in to comment.