Ares
Public Member Functions | Public Attributes | Static Public Attributes

BuildingTypeExt::ExtData Class Reference

#include <src/Ext/BuildingType/Body.h>

Inheritance diagram for BuildingTypeExt::ExtData:
Extension< TT >

List of all members.

Public Member Functions

 ExtData (const DWORD Canary, TT *const OwnerObject)
virtual ~ExtData ()
virtual size_t Size () const
virtual void LoadFromINIFile (TT *pThis, CCINIClass *pINI)
virtual void Initialize (TT *pThis)
virtual void CompleteInitialization (TT *pThis)
virtual void InvalidatePointer (void *ptr)
bool IsLinkable ()
bool CanBeOccupiedBy (InfantryClass *whom)

Public Attributes

int Solid_Height
bool IsCustom
int CustomWidth
int CustomHeight
int OutlineLength
CellStruct * CustomData
CellStruct * OutlineData
DynamicVectorClass
< TechnoTypeClass * > 
Secret_Boons
bool Secret_RecalcOnCapture
bool Secret_Placed
bool Firewall_Is
double LightningRod_Modifier
double UCPassThrough
 How many percent of the shots pass through the building to the occupants? 0.0 = 0%, 1.0 = 100%; Defaults to 0.0.
double UCFatalRate
 Chance of an occupant getting killed instantly when a bullet passes through. 0.0 = 0%, 1.0 = 100%; Defaults to 0.0.
double UCDamageMultiplier
 How many percent of normal damage are applied if an occupant is hit when a bullet passes through. 0.0 = 0%, 1.0 = 100%; Defaults to 1.0.
bool BunkerRaidable
 Can this BuildingType be occupied by hostile forces despite being owned by a player, if empty?
signed int IsTrench
 Enables moving between segments - saves ID of a kind of trench.
BuildingTypeClass * RubbleIntact
 What BuildingType to turn into when reconstructed. (This is the normal building, set on rubble.)
BuildingTypeClass * RubbleDestroyed
 What BuildingType to turn into when destroyed. (This is the rubble, set on normal buildings.)
Valueable< bool > InfiltrateCustom
Valueable< bool > RevealProduction
Valueable< bool > ResetSW
Valueable< bool > ResetRadar
Valueable< bool > RevealRadar
Valueable< bool > GainVeterancy
Valueable< bool > UnReverseEngineer
Valueable< int > StolenTechIndex
Valueable< int > StolenMoneyAmount
Valueable< int > StolenMoneyPercentage
Valueable< int > PowerOutageDuration
ValueableVector
< InfantryTypeClass * > 
AllowedOccupiers
cPrismForwarding PrismForwarding
Valueable< bool > ReverseEngineersVictims

Static Public Attributes

static std::vector< std::string > trenchKinds
 Vector of strings associating known trench names with IsTrench IDs.

Constructor & Destructor Documentation

BuildingTypeExt::ExtData::ExtData ( const DWORD  Canary,
TT *const  OwnerObject 
) [inline]
virtual BuildingTypeExt::ExtData::~ExtData ( ) [inline, virtual]
                                   {
                        delete [] CustomData;
                        delete [] OutlineData;
                }

Member Function Documentation

bool BuildingTypeExt::ExtData::CanBeOccupiedBy ( InfantryClass *  whom)
                                                                {
        // if CanBeOccupiedBy isn't empty, we have to check if this soldier is allowed in
        return this->AllowedOccupiers.empty() || (this->AllowedOccupiers == whom->Type);
}
void BuildingTypeExt::ExtData::CompleteInitialization ( TT pThis) [virtual]
                                                                            {
        // enforce same foundations for rubble/intact building pairs
        if(this->RubbleDestroyed && !BuildingTypeExt::IsFoundationEqual(this->AttachedToObject, this->RubbleDestroyed)) {
                Debug::FatalErrorAndExit("BuildingType %s and its Rubble.Destroyed %s don't have the same foundation.", this->AttachedToObject->ID, this->RubbleDestroyed->ID);
        }
        if(this->RubbleIntact && !BuildingTypeExt::IsFoundationEqual(this->AttachedToObject, this->RubbleIntact)) {
                Debug::FatalErrorAndExit("BuildingType %s and its Rubble.Intact %s don't have the same foundation.", this->AttachedToObject->ID, this->RubbleIntact->ID);
        }
}
void BuildingTypeExt::ExtData::Initialize ( TT pThis) [virtual]
{
        if(pThis->SecretLab) {
                this->Secret_Boons.Clear();
                DynamicVectorClass<TechnoTypeClass *> *Options
                        = (DynamicVectorClass<TechnoTypeClass *> *)&RulesClass::Instance->SecretInfantry;
                for(int i = 0; i < Options->Count; ++i) {
                        this->Secret_Boons.AddItem(Options->GetItem(i));
                }

                Options = (DynamicVectorClass<TechnoTypeClass *> *)&RulesClass::Instance->SecretUnits;
                for(int i = 0; i < Options->Count; ++i) {
                        this->Secret_Boons.AddItem(Options->GetItem(i));
                }

                Options = (DynamicVectorClass<TechnoTypeClass *> *)&RulesClass::Instance->SecretBuildings;
                for(int i = 0; i < Options->Count; ++i) {
                        this->Secret_Boons.AddItem(Options->GetItem(i));
                }
        }
        this->PrismForwarding.Initialize(pThis);
}
virtual void BuildingTypeExt::ExtData::InvalidatePointer ( void *  ptr) [inline, virtual]

Implements Extension< TT >.

                                                          {
                        AnnounceInvalidPointer(RubbleIntact, ptr);
                        AnnounceInvalidPointer(RubbleDestroyed, ptr);
                }
bool BuildingTypeExt::ExtData::IsLinkable ( )
                                        {
        return this->Firewall_Is || (this->IsTrench > -1);
}
void BuildingTypeExt::ExtData::LoadFromINIFile ( TT pThis,
CCINIClass *  pINI 
) [virtual]
{
        char* pArtID = pThis->ImageFile;
        char* pID = pThis->ID;

        this->PrismForwarding.LoadFromINIFile(pThis, pINI);

        if(pThis->UnitRepair && pThis->Factory == abs_AircraftType) {
                Debug::FatalErrorAndExit(
                        "BuildingType [%s] has both UnitRepair=yes and Factory=AircraftType.\n"
                        "This combination causes Internal Errors and other unwanted behaviour.", pID);
        }

        this->Firewall_Is = pINI->ReadBool(pID, "Firestorm.Wall", this->Firewall_Is);

        CCINIClass* pArtINI = CCINIClass::INI_Art;
        this->Solid_Height = pArtINI->ReadInteger(pArtID, "SolidHeight", this->Solid_Height);

        if(this->IsCustom) {
                //Reset
                pThis->Foundation = FOUNDATION_CUSTOM;
                pThis->FoundationData = this->CustomData;
        } else if(pArtINI) {

                char str[0x80]="\0";

                if(pArtINI->ReadString(pArtID, "Foundation", "", str, 0x80) && !_strcmpi(str,"Custom")) {
                        //Custom Foundation!
                        this->IsCustom = true;
                        pThis->Foundation = FOUNDATION_CUSTOM;

                        //Load Width and Height
                        this->CustomWidth = pArtINI->ReadInteger(pArtID, "Foundation.X", 0);
                        this->CustomHeight = pArtINI->ReadInteger(pArtID, "Foundation.Y", 0);
                        this->OutlineLength = pArtINI->ReadInteger(pArtID, "FoundationOutline.Length", 0);

                        // at len < 10, things will end very badly for weapons factories
                        if(this->OutlineLength < 10) {
                                this->OutlineLength = 10;
                        }

                        //Allocate CellStruct array
                        if(this->CustomData) {
                                delete [] this->CustomData;
                        }

                        if(this->OutlineData) {
                                delete [] this->OutlineData;
                        }

                        CellStruct* pFoundationData = new CellStruct[this->CustomWidth * this->CustomHeight + 1];
                        CellStruct* pOutlineData = new CellStruct[this->OutlineLength + 1];

                        this->CustomData = pFoundationData;
                        this->OutlineData = pOutlineData;
                        pThis->FoundationData = pFoundationData;
                        pThis->FoundationOutside = pOutlineData;

                        //Load FoundationData
                        CellStruct* pCurrent = pFoundationData;
                        char key[0x20];

                        for(int i = 0; i < this->CustomWidth * this->CustomHeight; ++i) {
                                _snprintf(key, 32, "Foundation.%d", i);
                                if(pArtINI->ReadString(pArtID, key, "", str, 0x80)) {
                                        short x = 0, y = 0;
                                        sscanf(str, "%d,%d", &x, &y);
                                        pCurrent->X = x;
                                        pCurrent->Y = y;
                                        ++pCurrent;
                                } else {
                                        break;
                                }
                        }

                        //Set end vector
                        pCurrent->X = 0x7FFF;
                        pCurrent->Y = 0x7FFF;

                        pCurrent = pOutlineData;
                        for(int i = 0; i < this->OutlineLength; ++i) {
                                _snprintf(key, 32, "FoundationOutline.%d", i);
                                if(pArtINI->ReadString(pArtID, key, "", str, 0x80)) {
                                        short x = 0, y = 0;
                                        sscanf(str, "%d,%d", &x, &y);
                                        pCurrent->X = x;
                                        pCurrent->Y = y;
                                        ++pCurrent;
                                } else {
                                        //Set end vector
                                        // can't break, some stupid functions access fixed offsets without checking if that offset is within the valid range
                                        pCurrent->X = 0x7FFF;
                                        pCurrent->Y = 0x7FFF;
                                        ++pCurrent;
                                }
                        }

                        //Set end vector
                        pCurrent->X = 0x7FFF;
                        pCurrent->Y = 0x7FFF;
                }

        }

        if(pINI->ReadString(pID, "SecretLab.PossibleBoons", "", Ares::readBuffer, Ares::readLength)) {
                this->Secret_Boons.Clear();
                for(char *cur = strtok(Ares::readBuffer, ","); cur; cur = strtok(NULL, ",")) {
                        TechnoTypeClass *pTechno = TechnoTypeClass::Find(cur);
                        if(pTechno) {
                                this->Secret_Boons.AddItem(pTechno);
                        } else {
                                Debug::INIParseFailed(pID, "SecretLab.PossibleBoons", cur);
                        }
                }
        }

        this->Secret_RecalcOnCapture = pINI->ReadBool(pID, "SecretLab.GenerateOnCapture", this->Secret_RecalcOnCapture);

        // added on 11.11.09 for #221 and children (Trenches)
        this->UCPassThrough = pINI->ReadDouble(pID, "UC.PassThrough", this->UCPassThrough);
        this->UCFatalRate = pINI->ReadDouble(pID, "UC.FatalRate", this->UCFatalRate);
        this->UCDamageMultiplier = pINI->ReadDouble(pID, "UC.DamageMultiplier", this->UCDamageMultiplier);
        this->BunkerRaidable = pINI->ReadBool(pID, "Bunker.Raidable", this->BunkerRaidable);
        if(pINI->ReadString(pID, "IsTrench", "", Ares::readBuffer, Ares::readLength)) {
                /*  If the list of kinds is empty so far, just add this kind as the first one;
                        if there already are kinds in it, compare the current kind against the kinds in the list;
                        if it was found, assign that kind's ID to this type;
                        if it wasn't found, add this kind at the end of the list and assign the ID.

                        I originally thought of using a map here, but I figured the probability that the kinds list
                        grows so long that the search through all kinds takes up significant time is very low, and
                        vectors are far simpler to use in this situation.
                */
                if(trenchKinds.size()) {
                        signed int foundMatch = -1;
                        for(unsigned int i = 0; i < trenchKinds.size(); ++i) {
                                if(trenchKinds.at(i).compare(Ares::readBuffer) == 0) {
                                        foundMatch = i;
                                        break;
                                }
                        }

                        if(foundMatch > -1) {
                                this->IsTrench = foundMatch;
                        } else {
                                this->IsTrench = trenchKinds.size();
                                trenchKinds.push_back(Ares::readBuffer);
                        }

                } else {
                        this->IsTrench = 0;
                        trenchKinds.push_back(Ares::readBuffer);
                }
        }
        if(pINI->ReadString(pID, "Rubble.Intact", "", Ares::readBuffer, Ares::readLength)) {
                this->RubbleIntact = BuildingTypeClass::Find(Ares::readBuffer);
        }
        if(pINI->ReadString(pID, "Rubble.Destroyed", "", Ares::readBuffer, Ares::readLength)) {
                this->RubbleDestroyed = BuildingTypeClass::Find(Ares::readBuffer);
                this->RubbleDestroyed->Capturable = false;
                this->RubbleDestroyed->TogglePower = false;
                this->RubbleDestroyed->Unsellable = true;
                this->RubbleDestroyed->CanBeOccupied = false;
        }

        this->LightningRod_Modifier = pINI->ReadDouble(pID, "LightningRod.Modifier", this->LightningRod_Modifier);

//      this->LegacyRadarEffect = pINI->ReadBool(pID, "SpyEffect.LegacyRadar", this->LegacyRadarEffect);
//      this->DisplayProduction = pINI->ReadBool(pID, "SpyEffect.DisplayProduction", this->DisplayProduction);

        INI_EX exINI(pINI);
        this->InfiltrateCustom.Read(&exINI, pID, "SpyEffect.Custom");
        if(this->InfiltrateCustom) {
                this->RevealProduction.Read(&exINI, pID, "SpyEffect.RevealProduction");
                this->ResetSW.Read(&exINI, pID, "SpyEffect.ResetSuperweapons");
                this->ResetRadar.Read(&exINI, pID, "SpyEffect.ResetRadar");
                this->RevealRadar.Read(&exINI, pID, "SpyEffect.RevealRadar");
                this->GainVeterancy.Read(&exINI, pID, "SpyEffect.UnitVeterancy");
                this->StolenTechIndex.Read(&exINI, pID, "SpyEffect.StolenTechIndex");
                this->PowerOutageDuration.Read(&exINI, pID, "SpyEffect.PowerOutageDuration");
                this->StolenMoneyAmount.Read(&exINI, pID, "SpyEffect.StolenMoneyAmount");
                this->StolenMoneyPercentage.Read(&exINI, pID, "SpyEffect.StolenMoneyPercentage");
                this->UnReverseEngineer.Read(&exINI, pID, "SpyEffect.UndoReverseEngineer");
        }

        // #218 Specific Occupiers
        this->AllowedOccupiers.Read(&exINI, pID, "CanBeOccupiedBy");
        if(!this->AllowedOccupiers.empty()) {
                // having a specific occupier list implies that this building is supposed to be occupiable
                pThis->CanBeOccupied = true;
        }

        this->ReverseEngineersVictims.Read(&exINI, pID, "ReverseEngineersVictims");
}
virtual size_t BuildingTypeExt::ExtData::Size ( ) const [inline, virtual]

Implements Extension< TT >.

{ return sizeof(*this); };

Member Data Documentation

Can this BuildingType be occupied by hostile forces despite being owned by a player, if empty?

Enables moving between segments - saves ID of a kind of trench.

See also:
trenchKinds

What BuildingType to turn into when destroyed. (This is the rubble, set on normal buildings.)

What BuildingType to turn into when reconstructed. (This is the normal building, set on rubble.)

DynamicVectorClass<TechnoTypeClass *> BuildingTypeExt::ExtData::Secret_Boons
std::vector< std::string > BuildingTypeExt::ExtData::trenchKinds [static]

Vector of strings associating known trench names with IsTrench IDs.

See also:
IsTrench

How many percent of normal damage are applied if an occupant is hit when a bullet passes through. 0.0 = 0%, 1.0 = 100%; Defaults to 1.0.

Chance of an occupant getting killed instantly when a bullet passes through. 0.0 = 0%, 1.0 = 100%; Defaults to 0.0.

How many percent of the shots pass through the building to the occupants? 0.0 = 0%, 1.0 = 100%; Defaults to 0.0.


The documentation for this class was generated from the following files:
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines