Ares
|
#include <src/Ext/Building/Body.h>
Public Member Functions | |
bool | InfiltratedBy (HouseClass *Enterer) |
ExtData (const DWORD Canary, TT *const OwnerObject) | |
virtual | ~ExtData () |
virtual size_t | Size () const |
virtual void | InvalidatePointer (void *ptr) |
bool | RubbleYell (bool beingRepaired=false) |
This function switches the building into its Advanced Rubble state or back to normal. | |
void | KickOutOfRubble () |
Bumps all Technos that reside on a building's foundation out of the way. | |
bool | canTraverseTo (BuildingClass *targetBuilding) |
This function checks if occupants of the current building can, on principle, move on to the target building. | |
void | doTraverseTo (BuildingClass *targetBuilding) |
This function moves as many occupants as possible from the current to the target building. | |
bool | sameTrench (BuildingClass *targetBuilding) |
This function checks if the current and the target building are both of the same trench kind. | |
bool | isLinkable () |
Returns true if this is a structure that can be linked to other structures, like a wall, fence, or trench. This is used to quick-check if the game has to look for linkable buildings in the first place. | |
bool | canLinkTo (BuildingClass *targetBuilding) |
Checks if the current building can link to the given target building. | |
void | evalRaidStatus () |
Checks if the building is empty but still marked as raided, and returns the building to its previous owner, if so. | |
void | UpdateFirewall () |
void | ImmolateVictims () |
void | ImmolateVictim (ObjectClass *Victim) |
bool | ReverseEngineer (TechnoClass *Victim) |
Returns true if Victim wasn't buildable and now should be. | |
Public Attributes | |
HouseClass * | OwnerBeforeRaid |
Contains the house which owned this building prior to it being raided and turned over to the raiding party. | |
bool | isCurrentlyRaided |
Whether this building is currently occupied by someone not the actual owner of the structure. | |
bool | ignoreNextEVA |
This is used when returning raided buildings, to decide whether to play EVA announcements about building capture. | |
bool | FreeUnits_Done |
Prevent free units and aircraft to be created multiple times. Set when the free units have been granted. | |
bool | AboutToChronoshift |
This building is going to be shifted. It should not be attacked with temporal weapons now. Otherwise it would disappear. | |
cPrismForwarding | PrismForwarding |
std::set< TechnoClass * > | RegisteredJammers |
Set of Radar Jammers which have registered themselves to be in range of this building. (Related to issue #305) |
BuildingExt::ExtData::ExtData | ( | const DWORD | Canary, |
TT *const | OwnerObject | ||
) | [inline] |
: Extension<TT>(Canary, OwnerObject), OwnerBeforeRaid(NULL), isCurrentlyRaided(false), ignoreNextEVA(false), PrismForwarding(), FreeUnits_Done(false), AboutToChronoshift(false) { };
virtual BuildingExt::ExtData::~ExtData | ( | ) | [inline, virtual] |
{ BuildingTypeExt::cPrismForwarding::RemoveFromNetwork(this->AttachedToObject, true); }
bool BuildingExt::ExtData::canLinkTo | ( | BuildingClass * | targetBuilding | ) |
Checks if the current building can link to the given target building.
targetBuilding | the building to check for compatibility. |
{ BuildingClass* currentBuilding = this->AttachedToObject; // Different owners // and owners not allied if((currentBuilding->Owner != targetBuilding->Owner) && !currentBuilding->Owner->IsAlliedWith(targetBuilding->Owner)) { //<-- see thread 1424 return false; } BuildingTypeExt::ExtData* currentTypeExtData = BuildingTypeExt::ExtMap.Find(currentBuilding->Type); BuildingTypeExt::ExtData* targetTypeExtData = BuildingTypeExt::ExtMap.Find(targetBuilding->Type); // Firewalls if(currentTypeExtData->Firewall_Is && targetTypeExtData->Firewall_Is) { return true; } // Trenches if(this->sameTrench(targetBuilding)) { return true; } return false; }
bool BuildingExt::ExtData::canTraverseTo | ( | BuildingClass * | targetBuilding | ) |
This function checks if occupants of the current building can, on principle, move on to the target building.
Conditions checked are whether there are occupants in the current building, whether the target building is full, whether the current building even is a trench, and whether both buildings are of the same trench kind.
The current system assumes 1x1 sized trench parts; it will probably work in all cases where the 0,0 (top) cells of buildings touch (e.g. a 3x3 building next to a 1x3 building), but not when the 0,0 cells are further apart. This may be changed at a later point in time, if there is demand for it.
targetBuilding | a pointer to the target building. |
{ BuildingClass* currentBuilding = this->AttachedToObject; //BuildingTypeClass* currentBuildingType = game_cast<BuildingTypeClass *>(currentBuilding->GetTechnoType()); BuildingTypeClass* targetBuildingType = targetBuilding->Type; if((targetBuilding == currentBuilding) || (targetBuilding->Occupants.Count >= targetBuildingType->MaxNumberOccupants) || !currentBuilding->Occupants.Count || !targetBuildingType->CanBeOccupied) { // I'm a little if-clause short and stdout... // beat you to the punchline -- D // Can't traverse if there's no one to move, or the target is full, we can't actually occupy the target, // or if it's actually the same building return false; } BuildingTypeExt::ExtData* currentBuildingTypeExt = BuildingTypeExt::ExtMap.Find(currentBuilding->Type); BuildingTypeExt::ExtData* targetBuildingTypeExt = BuildingTypeExt::ExtMap.Find(targetBuilding->Type); if(this->sameTrench(targetBuilding)) { // if we've come here, there's room, there are people to move, and the buildings are trenches and of the same kind // the only questioning remaining is whether they are next to each other. // if the target building is more than 256 leptons away, it's not on a straight neighboring cell. return targetBuilding->Location.DistanceFrom(currentBuilding->Location) <= 256.0; } else { return false; // not the same trench kind or not a trench } }
void BuildingExt::ExtData::doTraverseTo | ( | BuildingClass * | targetBuilding | ) |
This function moves as many occupants as possible from the current to the target building.
This function will move occupants from the current building to the target building until either a) the target building is full, or b) the current building is empty.
targetBuilding | a pointer to the target building. |
{ BuildingClass* currentBuilding = this->AttachedToObject; BuildingTypeClass* targetBuildingType = targetBuilding->Type; // depending on Westwood's handling, this could explode when Size > 1 units are involved...but don't tell the users that while(currentBuilding->Occupants.Count && (targetBuilding->Occupants.Count < targetBuildingType->MaxNumberOccupants)) { targetBuilding->Occupants.AddItem(currentBuilding->Occupants.GetItem(0)); currentBuilding->Occupants.RemoveItem(0); // maybe switch Add/Remove if the game gets pissy about multiple of them walking around } this->evalRaidStatus(); // if the traversal emptied the current building, it'll have to be returned to its owner }
void BuildingExt::ExtData::evalRaidStatus | ( | ) |
Checks if the building is empty but still marked as raided, and returns the building to its previous owner, if so.
{ // if the building is still marked as raided, but unoccupied, return it to its previous owner if(this->isCurrentlyRaided && !this->AttachedToObject->Occupants.Count) { // Fix for #838: Only return the building to the previous owner if he hasn't been defeated if(!this->OwnerBeforeRaid->Defeated) { this->ignoreNextEVA = true; // #698 - used in BuildingClass_ChangeOwnership_TrenchEVA to override EVA announcement this->AttachedToObject->SetOwningHouse(this->OwnerBeforeRaid); } this->OwnerBeforeRaid = NULL; this->isCurrentlyRaided = false; } }
void BuildingExt::ExtData::ImmolateVictim | ( | ObjectClass * | Victim | ) |
{ BuildingClass *pThis = this->AttachedToObject; if(generic_cast<TechnoClass *>(Victim) && Victim != pThis && !Victim->InLimbo && Victim->IsAlive && Victim->Health) { CoordStruct XYZ; Victim->GetCoords(&XYZ); int Damage = Victim->Health; Victim->ReceiveDamage(&Damage, 0, RulesClass::Instance->C4Warhead/* todo */, 0, 1, 0, pThis->Owner); if(AnimTypeClass *FSAnim = AnimTypeClass::Find(Victim->IsInAir() ? "FSAIR" : "FSGRND")) { AnimClass * placeholder; GAME_ALLOC(AnimClass, placeholder, FSAnim, &XYZ); } } }
void BuildingExt::ExtData::ImmolateVictims | ( | ) |
{ CellClass *C = this->AttachedToObject->GetCell(); for(ObjectClass *O = C->GetContent(); O; O = O->NextObject) { this->ImmolateVictim(O); } }
bool BuildingExt::ExtData::InfiltratedBy | ( | HouseClass * | Enterer | ) |
{ BuildingClass *EnteredBuilding = this->AttachedToObject; BuildingTypeClass *EnteredType = EnteredBuilding->Type; HouseClass *Owner = EnteredBuilding->Owner; BuildingTypeExt::ExtData* pTypeExt = BuildingTypeExt::ExtMap.Find(EnteredBuilding->Type); HouseExt::ExtData* pEntererExt = HouseExt::ExtMap.Find(Enterer); if(!pTypeExt->InfiltrateCustom) { return false; } if(Owner == Enterer) { return true; } bool raiseEva = false; if(Enterer->ControlledByPlayer() || Owner->ControlledByPlayer()) { CellStruct xy; EnteredBuilding->GetMapCoords(&xy); if(RadarEventClass::Create(RADAREVENT_STRUCTUREINFILTRATED, xy)) { raiseEva = true; } } bool evaForOwner = Owner->ControlledByPlayer() && raiseEva; bool evaForEnterer = Enterer->ControlledByPlayer() && raiseEva; bool effectApplied = false; if(pTypeExt->ResetRadar.Get()) { Owner->ReshroudMap(); if(!Owner->SpySatActive && evaForOwner) { VoxClass::Play("EVA_RadarSabotaged"); } if(!Owner->SpySatActive && evaForEnterer) { VoxClass::Play("EVA_BuildingInfRadarSabotaged"); } effectApplied = true; } if(pTypeExt->PowerOutageDuration > 0) { Owner->CreatePowerOutage(pTypeExt->PowerOutageDuration); if(evaForOwner) { VoxClass::Play("EVA_PowerSabotaged"); } if(evaForEnterer) { VoxClass::Play("EVA_BuildingInfiltrated"); VoxClass::Play("EVA_EnemyBasePoweredDown"); } effectApplied = true; } if(pTypeExt->StolenTechIndex > -1) { pEntererExt->StolenTech.set(pTypeExt->StolenTechIndex); Enterer->ShouldRecheckTechTree = true; if(evaForOwner) { VoxClass::Play("EVA_TechnologyStolen"); } if(evaForEnterer) { VoxClass::Play("EVA_BuildingInfiltrated"); VoxClass::Play("EVA_NewTechnologyAcquired"); } effectApplied = true; } if(pTypeExt->UnReverseEngineer.Get()) { int idx = HouseClass::Array->FindItemIndex(&Owner); Debug::Log("Undoing all Reverse Engineering achieved by house %ls (#%d)\n", Owner->UIName, idx); if(idx != -1) { for(int i = 0; i < TechnoTypeClass::Array->Count; ++i) { TechnoTypeClass * Type = TechnoTypeClass::Array->GetItem(i); TechnoTypeExt::ExtData * TypeData = TechnoTypeExt::ExtMap.Find(Type); if(TypeData->ReversedByHouses.ValidIndex(idx)) { Debug::Log("Zeroing out RevEng of %s\n", Type->ID); TypeData->ReversedByHouses[idx] = false; } } Owner->ShouldRecheckTechTree = true; } if(evaForOwner) { VoxClass::Play("EVA_BuildingInfiltrated"); } if(evaForEnterer) { VoxClass::Play("EVA_BuildingInfiltrated"); } effectApplied = true; } if(pTypeExt->ResetSW.Get()) { bool somethingReset = false; int swIdx = EnteredType->SuperWeapon; if(swIdx != -1) { Owner->Supers.Items[swIdx]->Reset(); somethingReset = true; } swIdx = EnteredType->SuperWeapon2; if(swIdx != -1) { Owner->Supers.Items[swIdx]->Reset(); somethingReset = true; } for(int i = 0; i < EnteredType->Upgrades; ++i) { if(BuildingTypeClass *Upgrade = EnteredBuilding->Upgrades[i]) { swIdx = Upgrade->SuperWeapon; if(swIdx != -1) { Owner->Supers.Items[swIdx]->Reset(); somethingReset = true; } swIdx = Upgrade->SuperWeapon2; if(swIdx != -1) { Owner->Supers.Items[swIdx]->Reset(); somethingReset = true; } } } if(somethingReset) { if(evaForOwner || evaForEnterer) { VoxClass::Play("EVA_BuildingInfiltrated"); } effectApplied = true; } } int bounty = 0; int available = Owner->Available_Money(); if(pTypeExt->StolenMoneyAmount > 0) { bounty = pTypeExt->StolenMoneyAmount; } else if(pTypeExt->StolenMoneyPercentage > 0) { bounty = int(available * pTypeExt->StolenMoneyPercentage); } if(bounty > 0) { bounty = std::min(bounty, available); Owner->TakeMoney(bounty); Enterer->GiveMoney(bounty); if(evaForOwner) { VoxClass::Play("EVA_CashStolen"); } if(evaForEnterer) { VoxClass::Play("EVA_BuildingInfCashStolen"); } effectApplied = true; } if(pTypeExt->GainVeterancy.Get()) { bool promotionStolen = true; switch(EnteredType->Factory) { case UnitTypeClass::AbsID: Enterer->WarFactoryInfiltrated = true; break; case InfantryTypeClass::AbsID: Enterer->BarracksInfiltrated = true; break; // TODO: aircraft/building default: promotionStolen = false; } if(promotionStolen) { Enterer->ShouldRecheckTechTree = true; if(Enterer->ControlledByPlayer()) { MouseClass::Instance->SidebarNeedsRepaint(); } if(evaForOwner) { VoxClass::Play("EVA_TechnologyStolen"); } if(evaForEnterer) { VoxClass::Play("EVA_BuildingInfiltrated"); VoxClass::Play("EVA_NewTechnologyAcquired"); } effectApplied = true; } } /* RA1-Style Spying, as requested in issue #633 This sets the respective bit to inform the game that a particular house has spied this building. Knowing that, the game will reveal the current production in this building to the players who have spied it. In practice, this means: If a player who has spied a factory clicks on that factory, he will see the cameo of whatever is being built in the factory. Addition 04.03.10: People complained about it not being optional. Now it is. */ if(pTypeExt->RevealProduction.Get()) { EnteredBuilding->DisplayProductionTo.Add(Enterer); if(evaForOwner || evaForEnterer) { VoxClass::Play("EVA_BuildingInfiltrated"); } effectApplied = true; } if(pTypeExt->RevealRadar.Get()) { EnteredBuilding->DisplayProductionTo.Add(Enterer); BuildingExt::UpdateDisplayTo(EnteredBuilding); if(evaForOwner || evaForEnterer) { VoxClass::Play("EVA_BuildingInfiltrated"); } MapClass::Instance->sub_657CE0(); MapClass::Instance->RedrawSidebar(2); effectApplied = true; } if(effectApplied) { EnteredBuilding->SetLayer(Layer::Ground); } return true; }
virtual void BuildingExt::ExtData::InvalidatePointer | ( | void * | ptr | ) | [inline, virtual] |
Implements Extension< TT >.
{ AnnounceInvalidPointer(OwnerBeforeRaid, ptr); }
bool BuildingExt::ExtData::isLinkable | ( | ) |
Returns true if this is a structure that can be linked to other structures, like a wall, fence, or trench. This is used to quick-check if the game has to look for linkable buildings in the first place.
{ BuildingTypeExt::ExtData* typeExtData = BuildingTypeExt::ExtMap.Find(this->AttachedToObject->Type); return typeExtData->IsLinkable(); }
void BuildingExt::ExtData::KickOutOfRubble | ( | ) |
Bumps all Technos that reside on a building's foundation out of the way.
All units on the building's foundation are kicked out.
{ BuildingClass* pBld = this->AttachedToObject; if(BuildingTypeExt::ExtData *pData = BuildingTypeExt::ExtMap.Find(pBld->Type)) { // get the number of cells and a pointer to the cell data int length = 0, height = 0, width = 0; CellStruct *data = NULL; if(pData->IsCustom) { width = pData->CustomWidth; height = pData->CustomHeight; data = pData->CustomData; } else { // these are length constants derived from the fnd_* constants int fnd_widths[] = {1, 2, 1, 2, 2, 3, 3, 3, 4, 3, 1, 3, 4, 1, 1, 2, 2, 5, 4, 3, 6, 0}; int fnd_heights[] = {1, 1, 2, 2, 3, 2, 3, 5, 2, 3, 3, 1, 3, 4, 5, 6, 5, 3, 4, 4, 4, 0}; width = fnd_widths[pBld->Type->Foundation]; height = fnd_heights[pBld->Type->Foundation]; data = pBld->Type->FoundationData; } length = height * width; // iterate over all cells and remove all infantry DynamicVectorClass<TechnoClass*> *list = new DynamicVectorClass<TechnoClass*>(); DynamicVectorClass<bool> *sel = new DynamicVectorClass<bool>(); CellStruct location = MapClass::Instance->GetCellAt(&pBld->Location)->MapCoords; for(int i=0; i<length; ++i) { CellStruct pos = data[i]; if((pos.X != 0x7FFF) && (pos.Y != 0x7FFF)) { pos += location; // remove every techno that resides on this cell CellClass* cell = MapClass::Instance->GetCellAt(&pos); for(ObjectClass* pObj = cell->GetContent(); pObj; pObj = pObj->NextObject) { if(TechnoClass* pTech = generic_cast<FootClass*>(pObj)) { bool bSel = pTech->IsSelected; if(pTech->Remove()) { list->AddItem(pTech); sel->AddItem(bSel); } } } } else { // invalid cell. break; } } // this part kicks out all units we found in the rubble for(int i=0; i<list->Count; ++i) { TechnoClass* pTech = list->GetItem(i); pBld->KickOutUnit(pTech, &location); if(sel->GetItem(i)) { pTech->Select(); } } delete list; delete sel; } }
bool BuildingExt::ExtData::ReverseEngineer | ( | TechnoClass * | Victim | ) |
Returns true if Victim wasn't buildable and now should be.
{ BuildingTypeExt::ExtData *pReverseData = BuildingTypeExt::ExtMap.Find(this->AttachedToObject->Type); if(!pReverseData->ReverseEngineersVictims) { return false; } TechnoTypeClass * VictimType = Victim->GetTechnoType(); TechnoTypeExt::ExtData *pVictimData = TechnoTypeExt::ExtMap.Find(VictimType); if(!pVictimData->CanBeReversed) { return false; } HouseClass *Owner = this->AttachedToObject->Owner; int idx = HouseClass::Array->FindItemIndex(&Owner); if(pVictimData->ReversedByHouses.ValidIndex(idx)) { if(!pVictimData->ReversedByHouses[idx]) { bool WasBuildable = HouseExt::PrereqValidate(Owner, VictimType, false, true) == 1; pVictimData->ReversedByHouses[idx] = true; if(!WasBuildable) { bool IsBuildable = HouseExt::RequirementsMet(Owner, VictimType) != HouseExt::Forbidden; if(IsBuildable) { Owner->ShouldRecheckTechTree = true; return true; } } } } return false; }
bool BuildingExt::ExtData::RubbleYell | ( | bool | beingRepaired = false | ) |
This function switches the building into its Advanced Rubble state or back to normal.
If no respective target-state object exists in the ExtData so far, the function will create it. It'll check beforehand whether the necessary Rubble.Intact or Rubble.Destroyed are actually set on the type. If the necessary one is not set, it'll log a debug message and abort.
Rubble is set to full health on placing, since, no matter what we do in the backend, to the player, each pile of rubble is a new one. The reconstructed building, on the other hand, is set to 1% of it's health, since it was just no reconstructed, and not freshly built or repaired yet.
Lastly, the function will set the current building as the alternate state on the other state, to ensure that, if the other state gets triggered back, it is connected to this state. (e.g. when a building is turned into rubble, the normal state will set itself as the normal state of the rubble, so when the rubble is reconstructed, it switches back to the correct normal state.)
beingRepaired | if set to true, the function will turn the building back into its normal state. If false or unset, the building will be turned into rubble. |
{ BuildingClass* currentBuilding = this->AttachedToObject; BuildingTypeExt::ExtData* pTypeData = BuildingTypeExt::ExtMap.Find(currentBuilding->Type); BuildingClass* newState = NULL; currentBuilding->Remove(); // only takes it off the map currentBuilding->DestroyNthAnim(BuildingAnimSlot::All); if(beingRepaired) { if(!pTypeData->RubbleIntact) { Debug::Log("Warning! Advanced Rubble was supposed to be reconstructed but Ares could not obtain its normal state. \ Check if [%s]Rubble.Intact is set (correctly).\n", currentBuilding->Type->ID); return true; } newState = specific_cast<BuildingClass *>(pTypeData->RubbleIntact->CreateObject(currentBuilding->Owner)); newState->Health = static_cast<int>(std::max((newState->Type->Strength / 100), 1)); // see description above newState->IsAlive = true; // assuming this is in the sense of "is not destroyed" // Location should not be changed by removal if(!newState->Put(¤tBuilding->Location, currentBuilding->Facing)) { Debug::Log("Advanced Rubble: Failed to place normal state on map!\n"); GAME_DEALLOC(newState); return false; } // currentBuilding->UnInit(); DON'T DO THIS } else { // if we're not here to repair that thing, obviously, we're gonna crush it if(!pTypeData->RubbleDestroyed) { Debug::Log("Warning! Building was supposed to be turned into Advanced Rubble but Ares could not obtain its rubble state. \ Check if [%s]Rubble.Destroyed is set (correctly).\n", currentBuilding->Type->ID); return true; } newState = specific_cast<BuildingClass *>(pTypeData->RubbleDestroyed->CreateObject(currentBuilding->Owner)); // Location should not be changed by removal if(!newState->Put(¤tBuilding->Location, currentBuilding->Facing)) { Debug::Log("Advanced Rubble: Failed to place rubble state on map!\n"); GAME_DEALLOC(newState); } } return true; }
bool BuildingExt::ExtData::sameTrench | ( | BuildingClass * | targetBuilding | ) |
This function checks if the current and the target building are both of the same trench kind.
targetBuilding | a pointer to the target building. |
{ BuildingTypeExt::ExtData* currentTypeExtData = BuildingTypeExt::ExtMap.Find(this->AttachedToObject->Type); BuildingTypeExt::ExtData* targetTypeExtData = BuildingTypeExt::ExtMap.Find(targetBuilding->Type); return ((currentTypeExtData->IsTrench > -1) && (currentTypeExtData->IsTrench == targetTypeExtData->IsTrench)); }
virtual size_t BuildingExt::ExtData::Size | ( | ) | const [inline, virtual] |
Implements Extension< TT >.
{ return sizeof(*this); };
void BuildingExt::ExtData::UpdateFirewall | ( | ) |
{ BuildingClass *B = this->AttachedToObject; BuildingTypeClass *BT = B->Type; HouseClass *H = B->Owner; BuildingTypeExt::ExtData* pTypeData = BuildingTypeExt::ExtMap.Find(BT); if(!pTypeData->Firewall_Is) { return; } HouseExt::ExtData *pHouseData = HouseExt::ExtMap.Find(H); bool FS = pHouseData->FirewallActive; DWORD FWFrame = BuildingExt::GetFirewallFlags(B); if(FS) { FWFrame += 32; } if(B->FirestormWallFrame != FWFrame) { if(!pHouseData->FirewallRecalc) { pHouseData->FirewallRecalc = 1; } B->FirestormWallFrame = FWFrame; B->GetCell()->Setup(0xFFFFFFFF); B->SetLayer(Layer::Ground); // HACK - repaints properly } if(!FS) { return; } if(!(Unsorted::CurrentFrame % 7) && ScenarioClass::Instance->Random.RandomRanged(0, 15) == 1) { int corners = (FWFrame & 0xF); // 1111b if(AnimClass *IdleAnim = B->FirestormAnim) { GAME_DEALLOC(IdleAnim); B->FirestormAnim = 0; } if(corners != 5 && corners != 10) { // (0101b || 1010b) == part of a straight line CoordStruct XYZ; B->GetCoords(&XYZ); XYZ.X -= 768; XYZ.Y -= 768; if(AnimTypeClass *FSA = AnimTypeClass::Find("FSIDLE")) { GAME_ALLOC(AnimClass, B->FirestormAnim, FSA, &XYZ); } } } this->ImmolateVictims(); }
This building is going to be shifted. It should not be attacked with temporal weapons now. Otherwise it would disappear.
Prevent free units and aircraft to be created multiple times. Set when the free units have been granted.
This is used when returning raided buildings, to decide whether to play EVA announcements about building capture.
Whether this building is currently occupied by someone not the actual owner of the structure.
HouseClass* BuildingExt::ExtData::OwnerBeforeRaid |
Contains the house which owned this building prior to it being raided and turned over to the raiding party.
std::set<TechnoClass *> BuildingExt::ExtData::RegisteredJammers |
Set of Radar Jammers which have registered themselves to be in range of this building. (Related to issue #305)