sources » HouseClass » CanBuildHowMany
/*
* returns:
* 1 - can build more
* 0 - cannot build any more
* -1 - special case
*/
signed int HouseClass::CanBuildHowMany(TechnoTypeClass *item, bool BypassExtras, bool IncludeQueued) {
if(BypassExtras) {
goto extras_done;
}
if(item->Unbuildable) { // always set to false
return 0;
}
for(int i = 0; i < item->PrerequisiteOverride.Length; ++i) {
if(this->CurrentlyOwnedBuildingTypes.GetItemCount(item->PrerequisiteOverride[i]) > 0) {
goto prereqs_done;
}
}
for(int i = 0; i < this->OwnedSecretLabs.Length; ++i) {
if(this->OwnedSecretLabs[i]->GetSecretProduction() == item) {
goto prereqs_done;
}
}
if(item->TechLevel == -1) {
return 0;
}
if(item->RequiresStolenAlliedTech && !this->HasStolenAlliedTech) {
return 0;
}
if(item->RequiresStolenSovietTech && !this->HasStolenSovietTech) {
return 0;
}
if(item->RequiresStolenThirdTech && !this->HasStolenThirdTech) {
return 0;
}
if(item->RequiredHouses != -1) {
if(!((1 << this->Country->IndexInArray) & item->RequiredHouses)) {
return 0;
}
}
if(item->ForbiddenHouses != -1) {
if((1 << this->Country->IndexInArray) & item->ForbiddenHouses) {
return 0;
}
}
if(!GameOptions.SWAllowed && item->WhatAmI() == IS_BUILDINGTYPE) {
BuildingTypeClass *Type = (BuildingTypeClass*)item;
if(item->SuperWeapon != -1) { // SW2 is ignored...
if(!Rules->BuildTech.Includes(item) && vec_SuperWeaponTypes[item->SuperWeapon]->DisableableFromShell)) {
return 0;
}
}
}
if(item->TechLevel > this->TechLevel) {
return 0;
}
if(!this->ControlledByHuman && !this->ControlledByPlayer) {
return 1; // AI cheater!
}
:
// fun, part 1 - prerequisite list
for(int i = 0; i < item->Prerequisite.Length; ++i) {
// this is magic - non-negative prereqIdx stands for indices in [BuildingTypes], negative for generics
int prereqIdx = item->Prerequisite[i];
bool prereqMet = 0;
switch(prereqIdx) {
case PREREQ_POWER:
for(int j = 0; j < Rules->PrerequisitePower.Length; ++j) {
if(this->CurrentlyOwnedBuildingTypes.GetItemCount(Rules->PrerequisitePower[j]) > 0) {
prereqMet = 1;
break;
}
}
break;
case PREREQ_BARRACKS:
for(int j = 0; j < Rules->PrerequisiteBarracks.Length; ++j) {
if(this->CurrentlyOwnedBuildingTypes.GetItemCount(Rules->PrerequisiteBarracks[j]) > 0) {
prereqMet = 1;
break;
}
}
break;
case PREREQ_FACTORY:
for(int j = 0; j < Rules->PrerequisiteFactory.Length; ++j) {
if(this->CurrentlyOwnedBuildingTypes.GetItemCount(Rules->PrerequisiteFactory[j]) > 0) {
prereqMet = 1;
break;
}
}
break;
case PREREQ_RADAR:
for(int j = 0; j < Rules->PrerequisiteRadar.Length; ++j) {
if(this->CurrentlyOwnedBuildingTypes.GetItemCount(Rules->PrerequisiteRadar[j]) > 0) {
prereqMet = 1;
break;
}
}
break;
case PREREQ_TECH:
for(int j = 0; j < Rules->PrerequisiteTech.Length; ++j) {
if(this->CurrentlyOwnedBuildingTypes.GetItemCount(Rules->PrerequisiteTech[j]) > 0) {
prereqMet = 1;
break;
}
}
break;
case PREREQ_PROC:
for(int j = 0; j < Rules->PrerequisiteProc.Length; ++j) {
if(this->CurrentlyOwnedBuildingTypes.GetItemCount(Rules->PrerequisiteProc[j]) > 0) {
prereqMet = 1;
break;
}
}
if(this->CurrentlyOwnedVehicleTypes.GetItemCount(Rules->PrerequisiteProcAlternate) > 0) {
prereqMet = 1;
}
break;
default:
BuildingTypeClass *prereqTest = vec_BuildingTypes[prereqIdx];
if(prereqTest->PowersUpBuilding) {
for(int j = this->OwnedBuildings.Length - 1; j; --j) {
BuildingClass *bld = this->OwnedBuildings[j];
if(!bld->NotOnMap && bld->PowerOn
&& bld->GetCurrentMission != MISSION_SELLING && bld->QueuedMission != MISSION_SELLING)
{
for(int k = 0; k < 3; ++k) {
if(bld->Upgrades[k] == item) {
prereqMet = 1;
break;
}
}
break; // !!! what this does is break the loop after checking just the most recently placed building
}
}
} else {
if(this->CurrentlyOwnedBuildingTypes.GetItemCount(prereqTest) > 0) {
prereqMet = 1;
}
}
} // end of switch(PrereqIdx)
if(!prereqMet) {
return 0;
}
} // end of prereq loop
prereqs_done:
// fun, part 2 - BuildLimit
CounterClass *counter;
switch(item->WhatAmI()) {
case IS_VEHICLE:
if(item->BuildLimit <= 0) {
return this->TotalOwnedVehicleTypes->GetItemCount(item) < abs(item->BuildLimit) ? 1 : 0; // just 1
} else if(this->CurrentlyOwnedVehicleTypes->GetItemCount(item) < item->BuildLimit) {
return 1;
} else { // owned == limit
if(!IncludeQueued) {
return -1;
}
for(int j = 0; j < vec_Factories.Length; ++j) {
FactoryClass *Fact = vec_Factories[j];
if(Fact->Owner != this) {
continue;
}
if(Fact->GetProduct()->GetTechnoType() == item) {
return Fact ? 1 : -1; // don't look at me, I didn't write this... if Fact is a valid pointer
}
}
return -1;
}
case IS_INFANTRY:
if(item->BuildLimit <= 0 && this->TotalOwnedInfantryTypes->GetItemCount(item) >= abs(item->BuildLimit)) {
return 0;
} else {
InfantryTypeClass *infT = (InfantryTypeClass *)item;
int count = this->CurrentlyOwnedInfantryTypes->GetItemCount(item);
if(infT->VehicleThief) {
for(int j = 0; j < vec_Units.Length; ++j) {
UnitClass *v = vec_Units[j];
if(v->OwnerHouse == this && v->HijackedByInfantry == infT) {
++count;
}
}
}
if(count < item->BuildLimit) {
return 1;
}
if(!IncludeQueued) {
return -1;
}
for(int j = 0; j < vec_Factories.Length; ++j) {
FactoryClass *Fact = vec_Factories[j];
if(Fact->Owner != this) {
continue;
}
if(Fact->GetProduct()->GetTechnoType() == item) {
return Fact ? 1 : -1; // don't look at me, I didn't write this... if Fact is a valid pointer
}
}
return -1;
}
case IS_AIRCRAFT:
if(item->BuildLimit <= 0) {
return this->TotalOwnedAircraftTypes->GetItemCount(item) < abs(item->BuildLimit) ? 1 : 0; // just 1
} else if(this->CurrentlyOwnedAircraftTypes->GetItemCount(item) < item->BuildLimit) {
return 1;
} else { // owned == limit
if(!IncludeQueued) {
return -1;
}
for(int j = 0; j < vec_Factories.Length; ++j) {
FactoryClass *Fact = vec_Factories[j];
if(Fact->Owner != this) {
continue;
}
if(Fact->GetProduct()->GetTechnoType() == item) {
return Fact ? 1 : -1; // don't look at me, I didn't write this... if Fact is a valid pointer
}
}
return -1;
}
case IS_BUILDING:
if(item->BuildLimit <= 0) {
return this->TotalOwnedBuildingTypes->GetItemCount(item) < abs(item->BuildLimit) ? 1 : 0; // just 1
} else if(this->CurrentlyOwnedBuildingTypes->GetItemCount(item) < item->BuildLimit) {
return 1;
} else { // owned == limit
if(!IncludeQueued) {
return -1;
}
for(int j = 0; j < vec_Factories.Length; ++j) {
FactoryClass *Fact = vec_Factories[j];
if(Fact->Owner != this) {
continue;
}
if(Fact->GetProduct()->GetTechnoType() == item) {
return Fact ? 1 : -1; // don't look at me, I didn't write this... if Fact is a valid pointer
}
}
return -1;
}
default:
return 1;
}
}