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:
PG-SteveT
2020-09-16 10:03:04 -07:00
parent e37e174be1
commit fd05be35c1
68 changed files with 1313 additions and 267 deletions
+139 -19
View File
@@ -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;