void SWTypeExt::ExtData::LoadFromRulesFile(SuperWeaponTypeClass *pThis, CCINIClass *pINI) { const char * section = pThis->get_ID(); if(!pINI->GetSection(section)) { return; } INI_EX exINI(pINI); if(exINI.ReadString(section, "Action") && !_strcmpi(exINI.value(), "Custom")) { pThis->Action = SW_YES_CURSOR; } if(exINI.ReadString(section, "Type")) { int customType = NewSWType::FindIndex(exINI.value()); if(customType > -1) { pThis->Type = customType; } } // find a NewSWType that handles this original one. if(this->IsOriginalType()) { this->HandledByNewSWType = NewSWType::FindHandler(pThis->Type); } // if this is handled by a NewSWType, initialize it. if(auto pNewSWType = this->GetNewSWType()) { pThis->Action = SW_YES_CURSOR; pNewSWType->Initialize(this, pThis); } this->LastAction = pThis->Action; }
// this should load everything that TypeData is not dependant on // i.e. InfantryElectrocuted= can go here since nothing refers to it // but [GenericPrerequisites] have to go earlier because they're used in parsing TypeData void RulesExt::ExtData::LoadAfterTypeData(RulesClass *pThis, CCINIClass *pINI) { RulesExt::ExtData *pData = RulesExt::Global(); if (!pData) { return; } INI_EX exINI(pINI); pData->ElectricDeath.Read(exINI, "AudioVisual", "InfantryElectrocuted"); pData->DecloakSound.Read(exINI, "AudioVisual", "DecloakSound"); pData->CloakHeight.Read(exINI, "General", "CloakHeight"); for (int i = 0; i < WeaponTypeClass::Array->Count; ++i) { WeaponTypeClass::Array->GetItem(i)->LoadFromINI(pINI); } pData->EngineerDamage = pINI->ReadDouble("General", "EngineerDamage", pData->EngineerDamage); pData->EngineerAlwaysCaptureTech = pINI->ReadBool("General", "EngineerAlwaysCaptureTech", pData->EngineerAlwaysCaptureTech); pData->EngineerDamageCursor.Read(exINI, "General", "EngineerDamageCursor"); pData->HunterSeekerBuildings.Read(exINI, "SpecialWeapons", "HSBuilding"); pData->HunterSeekerDetonateProximity.Read(exINI, "General", "HunterSeekerDetonateProximity"); pData->HunterSeekerDescendProximity.Read(exINI, "General", "HunterSeekerDescendProximity"); pData->HunterSeekerAscentSpeed.Read(exINI, "General", "HunterSeekerAscentSpeed"); pData->HunterSeekerDescentSpeed.Read(exINI, "General", "HunterSeekerDescentSpeed"); pData->HunterSeekerEmergeSpeed.Read(exINI, "General", "HunterSeekerEmergeSpeed"); pData->DropPodTrailer.Read(exINI, "General", "DropPodTrailer"); pData->DropPodTypes.Read(exINI, "General", "DropPodTypes"); pData->DropPodMinimum.Read(exINI, "General", "DropPodMinimum"); pData->DropPodMaximum.Read(exINI, "General", "DropPodMaximum"); }
void SW_LightningStorm::LoadFromINI(SWTypeExt::ExtData *pData, SuperWeaponTypeClass *pSW, CCINIClass *pINI) { const char * section = pSW->ID; if(!pINI->GetSection(section)) { return; } INI_EX exINI(pINI); pData->Weather_Duration.Read(exINI, section, "Lightning.Duration"); pData->Weather_RadarOutage.Read(exINI, section, "Lightning.RadarOutage"); pData->Weather_HitDelay.Read(exINI, section, "Lightning.HitDelay"); pData->Weather_ScatterDelay.Read(exINI, section, "Lightning.ScatterDelay"); pData->Weather_ScatterCount.Read(exINI, section, "Lightning.ScatterCount"); pData->Weather_Separation.Read(exINI, section, "Lightning.Separation"); pData->Weather_PrintText.Read(exINI, section, "Lightning.PrintText"); pData->Weather_IgnoreLightningRod.Read(exINI, section, "Lightning.IgnoreLightningRod"); pData->Weather_DebrisMin.Read(exINI, section, "Lightning.DebrisMin"); pData->Weather_DebrisMax.Read(exINI, section, "Lightning.DebrisMax"); pData->Weather_CloudHeight.Read(exINI, section, "Lightning.CloudHeight"); pData->Weather_BoltExplosion.Read(exINI, section, "Lightning.BoltExplosion"); pData->Weather_RadarOutageAffects.Read(exINI, section, "Lightning.RadarOutageAffects"); pData->Weather_Clouds.Read(exINI, section, "Lightning.Clouds"); pData->Weather_Bolts.Read(exINI, section, "Lightning.Bolts"); pData->Weather_Debris.Read(exINI, section, "Lightning.Debris"); pData->Weather_Sounds.Read(exINI, section, "Lightning.Sounds"); }
void HouseExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) { auto const pThis = this->OwnerObject(); auto const* const pSection = pThis->PlainName; INI_EX exINI(pINI); this->Degrades.Read(exINI, pSection, "Degrades"); }
void RadType::LoadFromINI(CCINIClass *pINI) { const char *section = this->Name; INI_EX exINI(pINI); this->WH.Read(exINI, section, "Warhead"); this->Color.Read(exINI, section, "Color"); this->Duration_Multiple.Read(exINI, section, "DurationMultiple"); this->Application_Delay.Read(exINI, section, "ApplicationDelay"); this->Level_Max.Read(exINI, section, "LevelMax"); this->Level_Delay.Read(exINI, section, "LevelDelay"); this->Light_Delay.Read(exINI, section, "LightDelay"); this->Level_Factor.Read(exINI, section, "LevelFactor"); this->Light_Factor.Read(exINI, section, "LightFactor"); this->Tint_Factor.Read(exINI, section, "TintFactor"); }
void RulesExt::ExtData::LoadBeforeTypeData(RulesClass *pThis, CCINIClass *pINI) { const char* section = "WeaponTypes"; const char* sectionGeneral = "General"; const char* sectionCombatDamage = "CombatDamage"; const char* sectionAV = "AudioVisual"; int len = pINI->GetKeyCount(section); for (int i = 0; i < len; ++i) { const char *key = pINI->GetKeyName(section, i); if (pINI->ReadString(section, key, "", Ares::readBuffer, Ares::readLength)) { WeaponTypeClass::FindOrAllocate(Ares::readBuffer); } } RulesExt::ExtData *pData = RulesExt::Global(); if (!pData) { return; } INI_EX exINI(pINI); pData->CanMakeStuffUp.Read(exINI, sectionGeneral, "CanMakeStuffUp"); pData->Tiberium_DamageEnabled.Read(exINI, sectionGeneral, "TiberiumDamageEnabled"); pData->Tiberium_HealEnabled.Read(exINI, sectionGeneral, "TiberiumHealEnabled"); pData->Tiberium_ExplosiveWarhead.Read(exINI, sectionCombatDamage, "TiberiumExplosiveWarhead"); pData->OverlayExplodeThreshold.Read(exINI, sectionGeneral, "OverlayExplodeThreshold"); pData->EnemyInsignia.Read(exINI, sectionGeneral, "EnemyInsignia"); pData->ReturnStructures.Read(exINI, sectionGeneral, "ReturnStructures"); pData->TypeSelectUseDeploy.Read(exINI, sectionGeneral, "TypeSelectUseDeploy"); pData->TeamRetaliate.Read(exINI, sectionGeneral, "TeamRetaliate"); pData->DeactivateDim_Powered.Read(exINI, sectionAV, "DeactivateDimPowered"); pData->DeactivateDim_EMP.Read(exINI, sectionAV, "DeactivateDimEMP"); pData->DeactivateDim_Operator.Read(exINI, sectionAV, "DeactivateDimOperator"); pData->AutoRepelAI.Read(exINI, sectionCombatDamage, "AutoRepel"); pData->AutoRepelPlayer.Read(exINI, sectionCombatDamage, "PlayerAutoRepel"); }
void SW_HunterSeeker::LoadFromINI(SWTypeExt::ExtData *pData, SuperWeaponTypeClass *pSW, CCINIClass *pINI) { const char * section = pSW->ID; if(!pINI->GetSection(section)) { return; } INI_EX exINI(pINI); pData->HunterSeeker_Type.Read(exINI, section, "HunterSeeker.Type"); pData->HunterSeeker_RandomOnly.Read(exINI, section, "HunterSeeker.RandomOnly"); pData->HunterSeeker_Buildings.Read(exINI, section, "HunterSeeker.Buildings"); // hardcoded pSW->Action = Action::None; pData->SW_RadarEvent = false; }
void SW_EMPulse::LoadFromINI(SWTypeExt::ExtData* pData, SuperWeaponTypeClass* pSW, CCINIClass* pINI) { const char* section = pSW->get_ID(); if(!pINI->GetSection(section)) { return; } INI_EX exINI(pINI); pData->EMPulse_Linked.Read(exINI, section, "EMPulse.Linked"); pData->EMPulse_TargetSelf.Read(exINI, section, "EMPulse.TargetSelf"); pData->EMPulse_PulseDelay.Read(exINI, section, "EMPulse.PulseDelay"); pData->EMPulse_PulseBall.Read(exINI, section, "EMPulse.PulseBall"); pData->EMPulse_Cannons.Read(exINI, section, "EMPulse.Cannons"); pSW->Action = pData->EMPulse_TargetSelf ? Action::None : Actions::SuperWeaponAllowed; }
void SW_PsychicDominator::LoadFromINI(SWTypeExt::ExtData *pData, SuperWeaponTypeClass *pSW, CCINIClass *pINI) { const char * section = pSW->ID; if(!pINI->GetSection(section)) { return; } INI_EX exINI(pINI); pData->Dominator_FirstAnimHeight.Read(exINI, section, "Dominator.FirstAnimHeight"); pData->Dominator_SecondAnimHeight.Read(exINI, section, "Dominator.SecondAnimHeight"); pData->Dominator_FirstAnim.Read(exINI, section, "Dominator.FirstAnim"); pData->Dominator_SecondAnim.Read(exINI, section, "Dominator.SecondAnim"); pData->Dominator_ControlAnim.Read(exINI, section, "Dominator.ControlAnim"); pData->Dominator_FireAtPercentage.Read(exINI, section, "Dominator.FireAtPercentage"); pData->Dominator_Capture.Read(exINI, section, "Dominator.Capture"); pData->Dominator_Ripple.Read(exINI, section, "Dominator.Ripple"); pData->Dominator_CaptureMindControlled.Read(exINI, section, "Dominator.CaptureMindControlled"); pData->Dominator_CapturePermaMindControlled.Read(exINI, section, "Dominator.CapturePermaMindControlled"); pData->Dominator_CaptureImmuneToPsionics.Read(exINI, section, "Dominator.CaptureImmuneToPsionics"); pData->Dominator_PermanentCapture.Read(exINI, section, "Dominator.PermanentCapture"); }
void SWTypeExt::ExtData::LoadFromINIFile(SuperWeaponTypeClass *pThis, CCINIClass *pINI) { const char * section = pThis->get_ID(); if(!pINI->GetSection(section)) { return; } INI_EX exINI(pINI); // read general properties this->EVA_Ready.Read(exINI, section, "EVA.Ready"); this->EVA_Activated.Read(exINI, section, "EVA.Activated"); this->EVA_Detected.Read(exINI, section, "EVA.Detected"); this->EVA_Impatient.Read(exINI, section, "EVA.Impatient"); this->EVA_InsufficientFunds.Read(exINI, section, "EVA.InsufficientFunds"); this->EVA_SelectTarget.Read(exINI, section, "EVA.SelectTarget"); this->SW_FireToShroud.Read(exINI, section, "SW.FireIntoShroud"); this->SW_AutoFire.Read(exINI, section, "SW.AutoFire"); this->SW_ManualFire.Read(exINI, section, "SW.ManualFire"); this->SW_RadarEvent.Read(exINI, section, "SW.CreateRadarEvent"); this->SW_ShowCameo.Read(exINI, section, "SW.ShowCameo"); this->SW_Unstoppable.Read(exINI, section, "SW.Unstoppable"); this->Money_Amount.Read(exINI, section, "Money.Amount"); this->Money_DrainAmount.Read(exINI, section, "Money.DrainAmount"); this->Money_DrainDelay.Read(exINI, section, "Money.DrainDelay"); this->SW_Sound.Read(exINI, section, "SW.Sound"); this->SW_ActivationSound.Read(exINI, section, "SW.ActivationSound"); this->SW_Anim.Read(exINI, section, "SW.Animation"); this->SW_AnimHeight.Read(exINI, section, "SW.AnimationHeight"); this->SW_AnimVisibility.Read(exINI, section, "SW.AnimationVisibility"); this->SW_AffectsHouse.Read(exINI, section, "SW.AffectsHouse"); this->SW_AITargetingType.Read(exINI, section, "SW.AITargeting"); this->SW_AffectsTarget.Read(exINI, section, "SW.AffectsTarget"); this->SW_RequiresTarget.Read(exINI, section, "SW.RequiresTarget"); this->SW_RequiresHouse.Read(exINI, section, "SW.RequiresHouse"); this->SW_Deferment.Read(exINI, section, "SW.Deferment"); this->SW_ChargeToDrainRatio.Read(exINI, section, "SW.ChargeToDrainRatio"); this->SW_Cursor.Read(exINI, section, "Cursor"); this->SW_NoCursor.Read(exINI, section, "NoCursor"); this->SW_Warhead.Read(exINI, section, "SW.Warhead"); this->SW_Damage.Read(exINI, section, "SW.Damage"); if(pINI->ReadString(section, "SW.Range", Ares::readDefval, Ares::readBuffer, Ares::readLength)) { char* context = nullptr; char* p = strtok_s(Ares::readBuffer, Ares::readDelims, &context); if(p && *p) { this->SW_Range.WidthOrRange = (float)atof(p); this->SW_Range.Height = -1; p = strtok_s(nullptr, Ares::readDelims, &context); if(p && *p) { this->SW_Range.Height = atoi(p); } } } // lighting this->Lighting_Enabled.Read(exINI, section, "Light.Enabled"); this->Lighting_Ambient.Read(exINI, section, "Light.Ambient"); this->Lighting_Red.Read(exINI, section, "Light.Red"); this->Lighting_Green.Read(exINI, section, "Light.Green"); this->Lighting_Blue.Read(exINI, section, "Light.Blue"); // messages and their properties this->Message_FirerColor.Read(exINI, section, "Message.FirerColor"); if(pINI->ReadString(section, "Message.Color", Ares::readDefval, Ares::readBuffer, Ares::readLength)) { this->Message_ColorScheme = ColorScheme::FindIndex(Ares::readBuffer); if(this->Message_ColorScheme < 0) { Debug::INIParseFailed(section, "Message.Color", Ares::readBuffer, "Expected a valid color scheme name."); } } this->Message_Detected.Read(exINI, section, "Message.Detected"); this->Message_Ready.Read(exINI, section, "Message.Ready"); this->Message_Launch.Read(exINI, section, "Message.Launch"); this->Message_Activate.Read(exINI, section, "Message.Activate"); this->Message_Abort.Read(exINI, section, "Message.Abort"); this->Message_InsufficientFunds.Read(exINI, section, "Message.InsufficientFunds"); this->Text_Preparing.Read(exINI, section, "Text.Preparing"); this->Text_Ready.Read(exINI, section, "Text.Ready"); this->Text_Hold.Read(exINI, section, "Text.Hold"); this->Text_Charging.Read(exINI, section, "Text.Charging"); this->Text_Active.Read(exINI, section, "Text.Active"); // the fallback is handled in the PreDependent SW's code if(pINI->ReadString(section, "SW.PostDependent", Ares::readDefval, Ares::readBuffer, Ares::readLength)) { AresCRT::strCopy(this->SW_PostDependent, Ares::readBuffer); } // initialize the NewSWType that handles this SWType. if(auto pNewSWType = this->GetNewSWType()) { pThis->Action = this->LastAction; pNewSWType->LoadFromINI(this, pThis, pINI); this->LastAction = pThis->Action; // whatever the user does, we take care of the stupid tags. // there is no need to have them not hardcoded. SuperWeaponFlags::Value flags = pNewSWType->Flags(); pThis->PreClick = ((flags & SuperWeaponFlags::PreClick) != 0); pThis->PostClick = ((flags & SuperWeaponFlags::PostClick) != 0); pThis->PreDependent = -1; } this->CameoPal.LoadFromINI(pINI, pThis->ID, "SidebarPalette"); this->SidebarPCX.Read(pINI, pThis->ID, "SidebarPCX"); }
void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* pINI) { auto pThis = this->OwnerObject(); const char * section = pThis->ID; INI_EX exINI(pINI); if(!pINI->GetSection(section)) { return; } // writing custom verses parser just because if(pINI->ReadString(section, "Verses", "", Ares::readBuffer, Ares::readLength)) { int idx = 0; char* context = nullptr; for(char *cur = strtok_s(Ares::readBuffer, ",", &context); cur; cur = strtok_s(nullptr, ",", &context)) { this->Verses[idx].Parse(cur); ++idx; if(idx > 10) { break; } } } ArmorType::LoadForWarhead(pINI, pThis); if(pThis->MindControl) { this->MindControl_Permanent = pINI->ReadBool(section, "MindControl.Permanent", this->MindControl_Permanent); } this->EMP_Duration = pINI->ReadInteger(section, "EMP.Duration", this->EMP_Duration); this->EMP_Cap = pINI->ReadInteger(section, "EMP.Cap", this->EMP_Cap); this->IC_Duration = pINI->ReadInteger(section, "IronCurtain.Duration", this->IC_Duration); this->IC_Cap = pINI->ReadInteger(section, "IronCurtain.Cap", this->IC_Cap); if(pThis->Temporal) { this->Temporal_WarpAway.Read(exINI, section, "Temporal.WarpAway"); } this->DeployedDamage = pINI->ReadDouble(section, "Damage.Deployed", this->DeployedDamage); this->Ripple_Radius = pINI->ReadInteger(section, "Ripple.Radius", this->Ripple_Radius); this->AffectsEnemies = pINI->ReadBool(section, "AffectsEnemies", this->AffectsEnemies); this->InfDeathAnim.Read(exINI, section, "InfDeathAnim"); this->PreImpactAnim.Read(exINI, section, "PreImpactAnim"); this->KillDriver = pINI->ReadBool(section, "KillDriver", this->KillDriver); this->KillDriver_KillBelowPercent.Read(exINI, section, "KillDriver.KillBelowPercent"); this->Malicious.Read(exINI, section, "Malicious"); this->PreventScatter.Read(exINI, section, "PreventScatter"); this->CellSpread_MaxAffect.Read(exINI, section, "CellSpread.MaxAffect"); this->AttachedEffect.Read(exINI); };
void BuildingTypeExt::cPrismForwarding::LoadFromINIFile(BuildingTypeClass *pThis, CCINIClass* pINI) { const char * pID = pThis->ID; if(pINI->ReadString(pID, "PrismForwarding", "", Ares::readBuffer, Ares::readLength)) { if((_strcmpi(Ares::readBuffer, "yes") == 0) || (_strcmpi(Ares::readBuffer, "true") == 0)) { this->Enabled = YES; } else if(_strcmpi(Ares::readBuffer, "forward") == 0) { this->Enabled = FORWARD; } else if(_strcmpi(Ares::readBuffer, "attack") == 0) { this->Enabled = ATTACK; } else if((_strcmpi(Ares::readBuffer, "no") == 0) || (_strcmpi(Ares::readBuffer, "false"))== 0) { this->Enabled = NO; } } if (this->Enabled != NO) { INI_EX exINI(pINI); this->Targets.Read(exINI, pID, "PrismForwarding.Targets"); this->MaxFeeds.Read(exINI, pID, "PrismForwarding.MaxFeeds"); this->MaxChainLength.Read(exINI, pID, "PrismForwarding.MaxChainLength"); this->MaxNetworkSize.Read(exINI, pID, "PrismForwarding.MaxNetworkSize"); this->SupportModifier.Read(exINI, pID, "PrismForwarding.SupportModifier"); this->DamageAdd.Read(exINI, pID, "PrismForwarding.DamageAdd"); this->ToAllies.Read(exINI, pID, "PrismForwarding.ToAllies"); this->MyHeight.Read(exINI, pID, "PrismForwarding.MyHeight"); this->BreakSupport.Read(exINI, pID, "PrismForwarding.BreakSupport"); this->Intensity.Read(exINI, pID, "PrismForwarding.Intensity"); int ChargeDelay = pINI->ReadInteger(pID, "PrismForwarding.ChargeDelay", this->ChargeDelay); if (ChargeDelay >= 1) { this->ChargeDelay.Set(ChargeDelay); } else { Debug::Log("[Developer Error] %s has an invalid PrismForwarding.ChargeDelay (%d), overriding to 1.\n", pThis->ID, ChargeDelay); } auto SuperWH = RulesClass::Instance->C4Warhead; if(!SuperWH) { SuperWH = WarheadTypeClass::Find("Super"); } if(pINI->ReadString(pID, "PrismForwarding.SupportWeapon", "", Ares::readBuffer, Ares::readLength)) { if (WeaponTypeClass *cWeapon = WeaponTypeClass::FindOrAllocate(Ares::readBuffer)) { int idxWeapon = this->GetUnusedWeaponSlot(pThis, 0); //rookie weapons if (idxWeapon == -1) { Debug::FatalErrorAndExit( "BuildingType [%s] is a Prism Tower however there are no free\n" "weapon slots to assign the support weapon to.", pThis->ID); } this->SupportWeaponIndex = idxWeapon; if(!cWeapon->Warhead) { cWeapon->Warhead = SuperWH; } cWeapon->NeverUse = true; //the modder shouldn't be expected to have to set this CoordStruct supportFLH; pThis->set_Weapon(idxWeapon, cWeapon); //now get the FLH supportFLH = pThis->get_WeaponFLH(13); //AlternateFLH0 if (supportFLH.X == 0 && supportFLH.Y == 0 && supportFLH.Z == 0) { //assuming that, for Prism Towers, this means the FLH was not set. supportFLH = pThis->get_WeaponFLH(0); //Primary } pThis->set_WeaponFLH(idxWeapon, supportFLH); } } if(pINI->ReadString(pID, "PrismForwarding.EliteSupportWeapon", "", Ares::readBuffer, Ares::readLength)) { if (WeaponTypeClass *cWeapon = WeaponTypeClass::FindOrAllocate(Ares::readBuffer)) { int idxWeapon = this->GetUnusedWeaponSlot(pThis, 1); //elite weapons if (idxWeapon == -1) { Debug::FatalErrorAndExit( "BuildingType [%s] is a Prism Tower however there are no free\n" "weapon slots to assign the elite support weapon to.", pThis->ID); } this->EliteSupportWeaponIndex = idxWeapon; if(!cWeapon->Warhead) { cWeapon->Warhead = SuperWH; } cWeapon->NeverUse = true; //the modder shouldn't be expected to have to set this CoordStruct supportFLH; pThis->set_EliteWeapon(idxWeapon, cWeapon); //now get the FLH supportFLH = pThis->get_WeaponFLH(14); //AlternateFLH1 if (supportFLH.X == 0 && supportFLH.Y == 0 && supportFLH.Z == 0) { //assuming that, for Prism Towers, this means the FLH was not set. supportFLH = pThis->get_EliteWeaponFLH(0); //ElitePrimary } pThis->set_EliteWeaponFLH(idxWeapon, supportFLH); } } } }
void HouseTypeExt::ExtData::LoadFromINIFile(HouseTypeClass *pThis, CCINIClass *pINI) { char* pID = pThis->ID; if(!this->SettingsInherited && *pThis->ParentCountry && _strcmpi(pThis->ParentCountry, pThis->ID)) { this->InheritSettings(pThis); } if (!this->Powerplants.Count) { const char * section = "General"; const char * key = NULL; switch (pThis->SideIndex) { case 0: key = "GDIPowerPlant"; break; case 1: key = "NodRegularPower"; break; case 2: key = "ThirdPowerPlant"; break; } if(key) { if (pINI->ReadString(section, key, "", Ares::readBuffer, Ares::readLength)) { if (BuildingTypeClass *pBld = BuildingTypeClass::Find(Ares::readBuffer)) { this->Powerplants.AddItem(pBld); } else { Debug::INIParseFailed(section, key, Ares::readBuffer); } } } } if (pINI->ReadString(pID, "AI.PowerPlants", "", Ares::readBuffer, Ares::readLength)) { this->Powerplants.Clear(); char* context = nullptr; for (char *bld = strtok_s(Ares::readBuffer, Ares::readDelims, &context); bld; bld = strtok_s(nullptr, Ares::readDelims, &context)) { if (BuildingTypeClass *pBld = BuildingTypeClass::Find(bld)) { this->Powerplants.AddItem(pBld); } else { Debug::INIParseFailed(pID, "AI.PowerPlants", bld); } } } INI_EX exINI(pINI); this->Parachute_Anim.Parse(&exINI, pID, "Parachute.Anim"); this->ParaDropPlane.Read(&exINI, pID, "ParaDrop.Aircraft"); char* p = NULL; if(pINI->ReadString(pID, "ParaDrop.Types", "", Ares::readBuffer, Ares::readLength)) { this->ParaDrop.Clear(); char* context = nullptr; for(p = strtok_s(Ares::readBuffer, Ares::readDelims, &context); p && *p; p = strtok_s(nullptr, Ares::readDelims, &context)) { TechnoTypeClass* pTT = UnitTypeClass::Find(p); if(!pTT) { pTT = InfantryTypeClass::Find(p); } if(pTT) { this->ParaDrop.AddItem(pTT); } else { Debug::INIParseFailed(pID, "ParaDrop.Types", p); } } } if(pINI->ReadString(pID, "ParaDrop.Num", "", Ares::readBuffer, Ares::readLength)) { this->ParaDropNum.Clear(); char* context = nullptr; for(p = strtok_s(Ares::readBuffer, Ares::readDelims, &context); p && *p; p = strtok_s(nullptr, Ares::readDelims, &context)) { this->ParaDropNum.AddItem(atoi(p)); } } if(pINI->ReadString(pID, "LoadScreenText.Color", "", Ares::readBuffer, 0x80)) { if(ColorScheme* CS = ColorScheme::Find(Ares::readBuffer)) { this->LoadTextColor = CS; } } this->RandomSelectionWeight = pINI->ReadInteger(pID, "RandomSelectionWeight", this->RandomSelectionWeight); this->CountryListIndex = pINI->ReadInteger(pID, "ListIndex", this->CountryListIndex); this->VeteranBuildings.Read(&exINI, pID, "VeteranBuildings"); }
void HouseTypeExt::ExtData::LoadFromRulesFile(HouseTypeClass *pThis, CCINIClass *pINI) { char* pID = pThis->ID; this->InitializeConstants(pThis); // ppShp is optional. if not set, only PCX is supported auto ReadShpOrPcxImage = [&](const char* key, char* pBuffer, size_t cbBuffer, SHPStruct** ppShp) { // read the key and convert it to lower case if(pINI->ReadString(pID, key, pBuffer, Ares::readBuffer, Ares::readLength)) { AresCRT::strCopy(pBuffer, Ares::readBuffer, cbBuffer); _strlwr_s(pBuffer, cbBuffer); // parse the value if(INIClass::IsBlank(pBuffer)) { // explicitly set to no image if(ppShp) { *ppShp = nullptr; } pBuffer[0] = 0; } else if(!ppShp || strstr(pBuffer, ".pcx")) { // clear shp and load pcx if(ppShp) { *ppShp = nullptr; } if(!PCX::Instance->LoadFile(pBuffer)) { // log error and clear invalid name Debug::INIParseFailed(pID, key, pBuffer); pBuffer[0] = 0; } } else if(ppShp) { // allowed to load as shp *ppShp = FileSystem::LoadSHPFile(pBuffer); if(!*ppShp) { // log error and clear invalid name Debug::INIParseFailed(pID, key, pBuffer); pBuffer[0] = 0; } } else { // disallowed file type Debug::INIParseFailed(pID, key, pBuffer, "File type not allowed."); } } }; ReadShpOrPcxImage("File.Flag", this->FlagFile, 0x20, nullptr); ReadShpOrPcxImage("File.ObserverFlag", this->ObserverFlag, 0x20, &this->ObserverFlagSHP); ReadShpOrPcxImage("File.ObserverBackground", this->ObserverBackground, 0x20, &this->ObserverBackgroundSHP); if (pINI->ReadString(pID, "File.LoadScreen", "", Ares::readBuffer, Ares::readLength)) { AresCRT::strCopy(this->LSFile, Ares::readBuffer, 0x20); } if (pINI->ReadString(pID, "File.LoadScreenPAL", "", Ares::readBuffer, Ares::readLength)) { AresCRT::strCopy(this->LSPALFile, Ares::readBuffer, 0x20); } if (pINI->ReadString(pID, "File.Taunt", "", Ares::readBuffer, Ares::readLength)) { AresCRT::strCopy(this->TauntFile, Ares::readBuffer, 0x20); } if (pINI->ReadString(pID, "LoadScreenText.Name", "", Ares::readBuffer, Ares::readLength)) { AresCRT::strCopy(this->LSName, Ares::readBuffer, 0x20); } if (pINI->ReadString(pID, "LoadScreenText.SpecialName", "", Ares::readBuffer, Ares::readLength)) { AresCRT::strCopy(this->LSSpecialName, Ares::readBuffer, 0x20); } if (pINI->ReadString(pID, "LoadScreenText.Brief", "", Ares::readBuffer, Ares::readLength)) { AresCRT::strCopy(this->LSBrief, Ares::readBuffer, 0x20); } if (pINI->ReadString(pID, "MenuText.Status", "", Ares::readBuffer, Ares::readLength)) { AresCRT::strCopy(this->StatusText, Ares::readBuffer, 0x20); } INI_EX exINI(pINI); this->ObserverFlagYuriPAL.Read(&exINI, pID, "File.ObserverFlagAltPalette"); }
void SW_ParaDrop::LoadFromINI( SWTypeExt::ExtData *pData, SuperWeaponTypeClass *pSW, CCINIClass *pINI) { const char * section = pSW->ID; if(!pINI->GetSection(section)) { return; } INI_EX exINI(pINI); char base[0x40]; auto CreateParaDropBase = [](char* pID, char* pBuffer) { // put a string like "Paradrop.Americans" into the buffer if(pBuffer) { AresCRT::strCopy(pBuffer, "ParaDrop", 9); if(pID && strlen(pID)) { AresCRT::strCopy(&pBuffer[8], ".", 2); AresCRT::strCopy(&pBuffer[9], pID, 0x18); } } }; auto ParseParaDrop = [&](char* pID, int Plane) -> ParadropPlane* { ParadropPlane* pPlane = NULL; // create the plane part of this request. this will be // an empty string for the first plane for this is the default. char plane[0x10] = ""; if(Plane) { AresCRT::strCopy(plane, ".Plane", 0x10); _itoa_s(Plane + 1, &plane[6], 10, 10); } // construct the full tag name base char base[0x40], key[0x40]; _snprintf_s(base, 0x3F, "%s%s", pID, plane); // parse the plane contents _snprintf_s(key, 0x3F, "%s.Aircraft", base); if(pINI->ReadString(section, key, "", Ares::readBuffer, Ares::readLength)) { if(AircraftTypeClass* pTAircraft = AircraftTypeClass::Find(Ares::readBuffer)) { pPlane = new ParadropPlane(); pPlane->pAircraft = pTAircraft; } else { Debug::INIParseFailed(section, key, Ares::readBuffer); } } // a list of UnitTypes and InfantryTypes _snprintf_s(key, 0x3F, "%s.Types", base); if(pINI->ReadString(section, key, "", Ares::readBuffer, Ares::readLength)) { // create new plane if there is none yet if(!pPlane) { pPlane = new ParadropPlane(); } // parse the types pPlane->pTypes.Clear(); char* context = nullptr; for(char* p = strtok_s(Ares::readBuffer, Ares::readDelims, &context); p && *p; p = strtok_s(nullptr, Ares::readDelims, &context)) { TechnoTypeClass* pTT = UnitTypeClass::Find(p); if(!pTT) { pTT = InfantryTypeClass::Find(p); } if(pTT) { pPlane->pTypes.AddItem(pTT); } else { Debug::INIParseFailed(section, key, p); } } } // don't parse nums if there are no types if(!pPlane || !pPlane->pTypes.Count) { return pPlane; } // the number how many times each item is created _snprintf_s(key, 0x3F, "%s.Num", base); if(pINI->ReadString(section, key, "", Ares::readBuffer, Ares::readLength)) { pPlane->pNum.Clear(); char* context = nullptr; for(char* p = strtok_s(Ares::readBuffer, Ares::readDelims, &context); p && *p; p = strtok_s(nullptr, Ares::readDelims, &context)) { pPlane->pNum.AddItem(atoi(p)); } } return pPlane; }; auto GetParadropPlane = [&](char *pID, int defCount, DynamicVectorClass<ParadropPlane*>* ret) { // get the number of planes for this house or side char key[0x40]; _snprintf_s(key, 0x3F, "%s.Count", pID); int count = pINI->ReadInteger(section, key, defCount); // parse every plane ret->SetCapacity(count, NULL); for(int i=0; i<count; ++i) { if(i>=ret->Count) { ret->AddItem(NULL); } ParadropPlane* pPlane = ParseParaDrop(base, i); if(pPlane) { pData->ParaDropPlanes.AddItem(pPlane); ret->Items[i] = pPlane; } } }; // now load the paradrops // 0: default // 1 to n: n sides // n+1 to n+m+1: m countries // default CreateParaDropBase(NULL, base); GetParadropPlane(base, 1, &pData->ParaDrop[NULL]); // put all sides into the hash table for(int i=0; i<SideClass::Array->Count; ++i) { SideClass *pSide = SideClass::Array->GetItem(i); CreateParaDropBase(pSide->ID, base); GetParadropPlane(base, pData->ParaDrop[NULL].Count, &pData->ParaDrop[pSide]); } // put all countries into the hash table for(int i=0; i<HouseTypeClass::Array->Count; ++i) { HouseTypeClass *pTHouse = HouseTypeClass::Array->GetItem(i); CreateParaDropBase(pTHouse->ID, base); GetParadropPlane(base, pData->ParaDrop[SideClass::Array->GetItem(pTHouse->SideIndex)].Count, &pData->ParaDrop[pTHouse]); } }