Ares
|
#include <src/Misc/SWTypes/ParaDrop.h>
Public Member Functions | |
SW_ParaDrop () | |
virtual | ~SW_ParaDrop () |
virtual const char * | GetTypeString () |
virtual void | LoadFromINI (SWTypeExt::ExtData *pData, SuperWeaponTypeClass *pSW, CCINIClass *pINI) |
virtual void | Initialize (SWTypeExt::ExtData *pData, SuperWeaponTypeClass *pSW) |
virtual bool | Launch (SuperClass *pThis, CellStruct *pCoords, byte IsPlayer) |
virtual bool | HandlesType (int type) |
bool | SendParadrop (SuperClass *pThis, CellClass *pCell) |
SW_ParaDrop::SW_ParaDrop | ( | ) | [inline] |
: NewSWType() { };
virtual SW_ParaDrop::~SW_ParaDrop | ( | ) | [inline, virtual] |
{ };
virtual const char* SW_ParaDrop::GetTypeString | ( | ) | [inline, virtual] |
Reimplemented from NewSWType.
{ return NULL; }
bool SW_ParaDrop::HandlesType | ( | int | type | ) | [virtual] |
Reimplemented from NewSWType.
{
return (type == SuperWeaponType::ParaDrop) || (type == SuperWeaponType::AmerParaDrop);
}
void SW_ParaDrop::Initialize | ( | SWTypeExt::ExtData * | pData, |
SuperWeaponTypeClass * | pSW | ||
) | [virtual] |
Reimplemented from NewSWType.
{ // default for american paradrop if(pSW->Type == SuperWeaponType::AmerParaDrop) { // the American paradrop will be the same for every country, // thus we use the SW's default here. ParadropPlane* pPlane = new ParadropPlane(); pData->ParaDropPlanes.AddItem(pPlane); pData->ParaDrop[NULL].AddItem(pPlane); for(int i = 0; i < RulesClass::Instance->AmerParaDropInf.Count; ++i) { pPlane->pTypes.AddItem((RulesClass::Instance->AmerParaDropInf.GetItem(i))); } for(int i = 0; i < RulesClass::Instance->AmerParaDropNum.Count; ++i) { pPlane->pNum.AddItem(RulesClass::Instance->AmerParaDropNum.GetItem(i)); } } pData->SW_RadarEvent = false; pData->EVA_Ready = VoxClass::FindIndex("EVA_ReinforcementsReady"); pData->SW_AITargetingType = SuperWeaponAITargetingMode::ParaDrop; pData->SW_Cursor = MouseCursor::First[MouseCursorType::ParaDrop]; }
bool SW_ParaDrop::Launch | ( | SuperClass * | pThis, |
CellStruct * | pCoords, | ||
byte | IsPlayer | ||
) | [virtual] |
Implements NewSWType.
{ if(pThis->IsCharged) { CellClass *pTarget = MapClass::Instance->GetCellAt(pCoords); // find the nearest cell the paradrop troopers can land on if(pTarget != MapClass::InvalidCell()) { if(pTarget->Tile_Is_Water()) { int a2 = 0; int a14 = 0; CellStruct *nearest = MapClass::Instance->Pathfinding_Find(&a2, pCoords, 0, -1, 0, 0, 1, 1, 0, 0, 0, 1, &a14, 0, 0); if(*nearest != SuperClass::DefaultCoords) { if(CellClass *pTemp = MapClass::Instance->GetCellAt(nearest)) { if(pTemp != MapClass::InvalidCell()) { if(!pTemp->Tile_Is_Water()) { pTarget = pTemp; } } } } } } // all set. send in the planes. return this->SendParadrop(pThis, pTarget); } return false; }
void SW_ParaDrop::LoadFromINI | ( | SWTypeExt::ExtData * | pData, |
SuperWeaponTypeClass * | pSW, | ||
CCINIClass * | pINI | ||
) | [virtual] |
Reimplemented from NewSWType.
{ 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(Plane + 1, &plane[6], 10); } // construct the full tag name base char base[0x40], key[0x40]; _snprintf(base, 0x40, "%s%s", pID, plane); // parse the plane contents _snprintf(key, 0x40, "%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(key, 0x40, "%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(); for(char* p = strtok(Ares::readBuffer, Ares::readDelims); p && *p; p = strtok(NULL, Ares::readDelims)) { 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(key, 0x40, "%s.Num", base); if(pINI->ReadString(section, key, "", Ares::readBuffer, Ares::readLength)) { pPlane->pNum.Clear(); for(char* p = strtok(Ares::readBuffer, Ares::readDelims); p && *p; p = strtok(NULL, Ares::readDelims)) { 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(key, 0x40, "%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]); } }
bool SW_ParaDrop::SendParadrop | ( | SuperClass * | pThis, |
CellClass * | pCell | ||
) |
{ // sanity if(!pThis || !pCell) { return false; } SuperWeaponTypeClass *pSW = pThis->Type; SWTypeExt::ExtData *pData = SWTypeExt::ExtMap.Find(pSW); HouseClass *pHouse = pThis->Owner; // these are fallback values if the SW doesn't define them AircraftTypeClass* pFallbackPlane = NULL; TypeList<TechnoTypeClass*> *pFallbackTypes = NULL; TypeList<int> *pFallbackNum = NULL; // get the paradrop list without creating a new value auto GetParadropPlanes = [pData](AbstractTypeClass* pKey) -> DynamicVectorClass<ParadropPlane*>* { if(pData->ParaDrop.find(pKey) == pData->ParaDrop.end()) { return NULL; } return &pData->ParaDrop[pKey]; }; // use paradrop lists from house, side and default DynamicVectorClass<ParadropPlane*>* drops[3]; drops[0] = GetParadropPlanes(pHouse->Type); drops[1] = GetParadropPlanes(SideClass::Array->GetItem(pHouse->Type->SideIndex)); drops[2] = GetParadropPlanes(NULL); // how many planes shall we launch? int count = 0; for(int i=0; i<3; ++i) { if(drops[i]) { count = drops[i]->Count; break; } } // assemble each plane and its contents for(int i=0; i<count; ++i) { // i = index of plane TypeList<TechnoTypeClass*> *pParaDrop = NULL; TypeList<int> *pParaDropNum = NULL; AircraftTypeClass* pParaDropPlane = NULL; // try the planes in order of precedence: // * country, explicit plane // * side, explicit plane // * default, explict plane // * country, default plane // * side, default plane // * default, default plane // * fill gaps with data from house/side/rules for(int j=1; j>=0; --j) { // factor 1 or 0: "plane * j" => "plane" or "0" (default) for(int k=0; k<3; ++k) { // index in the "drops" array // only do something if there is data missing if(!(pParaDrop && pParaDropNum && pParaDropPlane)) { // get the country/side-specific plane list DynamicVectorClass<ParadropPlane*> *planes = drops[k]; if(!planes) { continue; } // get the plane at specified index int index = i * j; if(planes->ValidIndex(index)) { if(ParadropPlane* pPlane = planes->GetItem(index)) { // get the contents, if not already set if(!pParaDrop || !pParaDropNum) { if((pPlane->pTypes.Count != 0) && (pPlane->pNum.Count != 0)) { pParaDrop = &pPlane->pTypes; pParaDropNum = &pPlane->pNum; } } // get the airplane, if it isn't set already if(!pParaDropPlane) { if(AircraftTypeClass* pTAircraft = pPlane->pAircraft) { pParaDropPlane = pTAircraft; } } } } } } } // fallback for types and nums if(!pParaDrop || !pParaDropNum) { if(!pFallbackTypes || !pFallbackNum) { if(HouseTypeExt::ExtData *pExt = HouseTypeExt::ExtMap.Find(pHouse->Type)) { pExt->GetParadropContent(&pFallbackTypes, &pFallbackNum); } } pParaDrop = pFallbackTypes; pParaDropNum = pFallbackNum; } // house fallback for the plane if(!pParaDropPlane) { if(!pFallbackPlane) { if(HouseTypeExt::ExtData *pExt = HouseTypeExt::ExtMap.Find(pHouse->Type)) { pFallbackPlane = pExt->GetParadropPlane(); } } pParaDropPlane = pFallbackPlane; } // finally, send the plane if(pParaDrop && pParaDropNum && pParaDropPlane) { Ares::SendPDPlane( pHouse, pCell, pParaDropPlane, pParaDrop, pParaDropNum); } } return true; }