mirror of
https://github.com/electronicarts/CnC_Remastered_Collection.git
synced 2026-07-03 16:53:14 -04:00
September 16th patch update
DLL version incremented Beacon functionality added Support for loading screen match preview display Placeholder handling of new key-bindable mod commands
This commit is contained in:
+139
-19
@@ -396,6 +396,20 @@ void UnitClass::AI(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Clear the unload refinery if not haresting or entering a refinery.
|
||||
*/
|
||||
if (Class->IsToHarvest) {
|
||||
if (Mission != MISSION_HARVEST) {
|
||||
if (Mission != MISSION_ENTER ||
|
||||
!In_Radio_Contact() ||
|
||||
Contact_With_Whom()->What_Am_I() != RTTI_BUILDING ||
|
||||
*((BuildingClass*)Contact_With_Whom()) != STRUCT_REFINERY) {
|
||||
TiberiumUnloadRefinery = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Rocket launchers will reload every so often.
|
||||
*/
|
||||
@@ -1198,6 +1212,7 @@ UnitClass::UnitClass(UnitType classid, HousesType house) :
|
||||
Reload = 0;
|
||||
Ammo = Class->MaxAmmo;
|
||||
IsCloakable = Class->IsCloakable;
|
||||
TiberiumUnloadRefinery = NULL;
|
||||
if (Class->IsAnimating) Set_Rate(Options.Normalize_Delay(3));
|
||||
|
||||
/*
|
||||
@@ -2345,29 +2360,47 @@ bool UnitClass::Goto_Tiberium(void)
|
||||
int tiberium = 0;
|
||||
int besttiberium = 0;
|
||||
for (int x = -radius; x <= radius; x++) {
|
||||
|
||||
/*
|
||||
** Randomize the corners.
|
||||
*/
|
||||
int corner[2];
|
||||
int corners[4][2] = {
|
||||
{x, -radius},
|
||||
{x, +radius},
|
||||
{-radius, x},
|
||||
{+radius, x}
|
||||
};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int j = i + rand() / (RAND_MAX / (4 - i) + 1);
|
||||
memcpy(&corner, &corners[j], sizeof(corner));
|
||||
memcpy(&corners[j], &corners[i], sizeof(corner));
|
||||
memcpy(&corners[i], corner, sizeof(corner));
|
||||
}
|
||||
|
||||
cell = center;
|
||||
tiberium = Tiberium_Check(cell, x, -radius);
|
||||
tiberium = Tiberium_Check(cell, corners[0][0], corners[0][1]);
|
||||
if (tiberium > besttiberium) {
|
||||
bestcell = cell;
|
||||
besttiberium = tiberium;
|
||||
}
|
||||
|
||||
cell = center;
|
||||
tiberium = Tiberium_Check(cell, x, +radius);
|
||||
tiberium = Tiberium_Check(cell, corners[1][0], corners[1][1]);
|
||||
if (tiberium > besttiberium) {
|
||||
bestcell = cell;
|
||||
besttiberium = tiberium;
|
||||
}
|
||||
|
||||
cell = center;
|
||||
tiberium = Tiberium_Check(cell, -radius, x);
|
||||
tiberium = Tiberium_Check(cell, corners[2][0], corners[2][1]);
|
||||
if (tiberium > besttiberium) {
|
||||
bestcell = cell;
|
||||
besttiberium = tiberium;
|
||||
}
|
||||
|
||||
cell = center;
|
||||
tiberium = Tiberium_Check(cell, +radius, x);
|
||||
tiberium = Tiberium_Check(cell, corners[3][0], corners[3][1]);
|
||||
if (tiberium > besttiberium) {
|
||||
bestcell = cell;
|
||||
besttiberium = tiberium;
|
||||
@@ -2385,6 +2418,96 @@ bool UnitClass::Goto_Tiberium(void)
|
||||
}
|
||||
|
||||
|
||||
struct RefineryData
|
||||
{
|
||||
BuildingClass* Refinery;
|
||||
int Distance;
|
||||
int Harvesters;
|
||||
};
|
||||
|
||||
static bool operator==(const RefineryData& lhs, const RefineryData& rhs)
|
||||
{
|
||||
return lhs.Refinery == rhs.Refinery;
|
||||
}
|
||||
|
||||
static bool operator!=(const RefineryData& lhs, const RefineryData& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
static int _refinery_compare(const void * left, const void * right)
|
||||
{
|
||||
const RefineryData& lhs = *reinterpret_cast<const RefineryData*>(left);
|
||||
const RefineryData& rhs = *reinterpret_cast<const RefineryData*>(right);
|
||||
if (lhs.Distance < rhs.Distance) {
|
||||
return -1;
|
||||
} else if (rhs.Distance < lhs.Distance) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BuildingClass* UnitClass::Find_Best_Refinery(void) const
|
||||
{
|
||||
static DynamicVectorClass<RefineryData> _refineries;
|
||||
|
||||
_refineries.Clear();
|
||||
for (int i = 0; i < Buildings.Count(); ++i) {
|
||||
BuildingClass* refinery = Buildings.Ptr(i);
|
||||
if (refinery != NULL &&
|
||||
refinery->House == House &&
|
||||
!refinery->IsInLimbo &&
|
||||
*refinery == STRUCT_REFINERY) {
|
||||
_refineries.Add(RefineryData{ refinery, Distance(refinery), 0 });
|
||||
}
|
||||
}
|
||||
|
||||
// Base case for zero or one refineries.
|
||||
if (_refineries.Count() == 0) {
|
||||
return NULL;
|
||||
} else if (_refineries.Count() == 1) {
|
||||
return _refineries[0].Refinery;
|
||||
}
|
||||
|
||||
// Count harvesters going to each refinery as well as the total.
|
||||
int num_harvesters = 0;
|
||||
for (int i = 0; i < Units.Count(); ++i) {
|
||||
UnitClass* unit = Units.Ptr(i);
|
||||
if (unit->IsActive && unit->Class->IsToHarvest && unit->House == House) {
|
||||
BuildingClass* refinery = unit->Tiberium_Unload_Refinery();
|
||||
if (refinery != NULL) {
|
||||
int index = _refineries.ID(RefineryData{ refinery });
|
||||
assert(index >= 0);
|
||||
_refineries[index].Harvesters++;
|
||||
num_harvesters++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by distance (special case for 2 refineries as that's a single swap).
|
||||
if (_refineries.Count() == 2) {
|
||||
if (_refineries[0].Distance > _refineries[1].Distance) {
|
||||
RefineryData temp = _refineries[0];
|
||||
_refineries[0] = _refineries[1];
|
||||
_refineries[1] = temp;
|
||||
}
|
||||
} else {
|
||||
qsort(&_refineries[0], _refineries.Count(), sizeof(RefineryData), _refinery_compare);
|
||||
}
|
||||
|
||||
// Evenly distribute harvesters among refineries.
|
||||
int harvesters_per_refinery = (num_harvesters + _refineries.Count() - 1) / _refineries.Count();
|
||||
for (int i = 0; i < _refineries.Count(); ++i) {
|
||||
if (_refineries[i].Harvesters < harvesters_per_refinery) {
|
||||
return _refineries[i].Refinery;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back on closest refinery
|
||||
return _refineries[0].Refinery;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* UnitClass::Harvesting -- Harvests tiberium at the current location. *
|
||||
* *
|
||||
@@ -2677,7 +2800,10 @@ int UnitClass::Mission_Harvest(void)
|
||||
Assign_Target(TARGET_NONE);
|
||||
Status = FINDHOME;
|
||||
return(1);
|
||||
} else if (Goto_Tiberium()) {
|
||||
}
|
||||
|
||||
TiberiumUnloadRefinery = NULL;
|
||||
if (Goto_Tiberium()) {
|
||||
IsHarvesting = true;
|
||||
Set_Rate(2);
|
||||
Set_Stage(0);
|
||||
@@ -2739,21 +2865,14 @@ int UnitClass::Mission_Harvest(void)
|
||||
if (!Target_Legal(NavCom)) {
|
||||
|
||||
/*
|
||||
** Find nearby refinery and head to it?
|
||||
** Find nearby refinery and head to it.
|
||||
*/
|
||||
BuildingClass * nearest = Find_Docking_Bay(STRUCT_REFINERY, false);
|
||||
|
||||
/*
|
||||
** Since the refinery said it was ok to load, establish radio
|
||||
** contact with the refinery and then await docking orders.
|
||||
*/
|
||||
if (nearest && Transmit_Message(RADIO_HELLO, nearest) == RADIO_ROGER) {
|
||||
Status = HEADINGHOME;
|
||||
} else {
|
||||
ScenarioInit++;
|
||||
nearest = Find_Docking_Bay(STRUCT_REFINERY, false);
|
||||
ScenarioInit--;
|
||||
if (nearest) {
|
||||
BuildingClass * nearest = Find_Best_Refinery();
|
||||
if (nearest) {
|
||||
TiberiumUnloadRefinery = nearest;
|
||||
if (Transmit_Message(RADIO_HELLO, nearest) == RADIO_ROGER) {
|
||||
Status = HEADINGHOME;
|
||||
} else {
|
||||
Assign_Destination(::As_Target(nearest->Nearby_Location(this)));
|
||||
}
|
||||
}
|
||||
@@ -2770,6 +2889,7 @@ int UnitClass::Mission_Harvest(void)
|
||||
return(1);
|
||||
|
||||
case GOINGTOIDLE:
|
||||
TiberiumUnloadRefinery = NULL;
|
||||
Assign_Mission(MISSION_GUARD);
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user