コード例 #1
0
ファイル: Body.cpp プロジェクト: Gluk-v48/Ares
void HouseExt::ExtData::SetFirestormState(bool Active) {
	HouseClass *pHouse = this->AttachedToObject;
	HouseExt::ExtData* pData = HouseExt::ExtMap.Find(pHouse);

	if(pData->FirewallActive == Active) {
		return;
	}

	pData->FirewallActive = Active;
	UpdateAnyFirestormActive();

	DynamicVectorClass<CellStruct> AffectedCoords;

	for(int i = 0; i < pHouse->Buildings.Count; ++i) {
		BuildingClass *B = pHouse->Buildings[i];
		BuildingTypeExt::ExtData *pBuildTypeData = BuildingTypeExt::ExtMap.Find(B->Type);
		if(pBuildTypeData->Firewall_Is) {
			BuildingExt::ExtData * pBldData = BuildingExt::ExtMap.Find(B);
			pBldData->UpdateFirewall();
			CellStruct temp = B->GetMapCoords();
			AffectedCoords.AddItem(temp);
		}
	}

	MapClass::Instance->Update_Pathfinding_1();
	MapClass::Instance->Update_Pathfinding_2(&AffectedCoords);
};
コード例 #2
0
ファイル: Body.cpp プロジェクト: Ares-Developers/Ares
void HouseExt::ExtData::SetFirestormState(bool const active) {
	auto const pHouse = this->OwnerObject();
	auto const pData = HouseExt::ExtMap.Find(pHouse);

	if(pData->FirewallActive == active) {
		return;
	}

	pData->FirewallActive = active;
	UpdateAnyFirestormActive(active);

	DynamicVectorClass<CellStruct> AffectedCoords;

	for(auto const& pBld : pHouse->Buildings) {
		auto const pTypeData = BuildingTypeExt::ExtMap.Find(pBld->Type);
		if(pTypeData->Firewall_Is) {
			auto const pExt = BuildingExt::ExtMap.Find(pBld);
			pExt->UpdateFirewall();
			auto const temp = pBld->GetMapCoords();
			AffectedCoords.AddItem(temp);
		}
	}

	MapClass::Instance->Update_Pathfinding_1();
	MapClass::Instance->Update_Pathfinding_2(AffectedCoords);
};
コード例 #3
0
static void ParseList(DynamicVectorClass<T> &List, CCINIClass * pINI, const char *section, const char *key) {
	if(pINI->ReadString(section, key, Ares::readDefval, Ares::readBuffer)) {
		List.Clear();

		char* context = nullptr;
		for(char *cur = strtok_s(Ares::readBuffer, Ares::readDelims, &context); cur; cur = strtok_s(nullptr, Ares::readDelims, &context)) {
			T buffer = T();
			if(Parser<T>::TryParse(cur, &buffer)) {
				List.AddItem(buffer);
			} else if(!std::is_pointer<T>() || !INIClass::IsBlank(cur)) {
				Debug::INIParseFailed(section, key, cur);
			}
		}
	}
};
コード例 #4
0
ファイル: ChronoWarp.cpp プロジェクト: Ares-Developers/Ares
bool SW_ChronoWarp::Activate(SuperClass* pThis, const CellStruct &Coords, bool IsPlayer)
{
    // get the previous super weapon
    SuperClass* pSource = nullptr;
    if(HouseExt::ExtData *pExt = HouseExt::ExtMap.Find(pThis->Owner)) {
        pSource = pThis->Owner->Supers.GetItemOrDefault(pExt->SWLastIndex);
    }

    // use source super weapon properties
    if(pSource && (pSource->Type->Type == SuperWeaponType::ChronoSphere)) {
        if(SWTypeExt::ExtData *pData = SWTypeExt::ExtMap.Find(pSource->Type)) {
            Debug::Log("[ChronoWarp::Launch] Launching %s with %s as source.\n", pThis->Type->ID, pSource->Type->ID);

            // add radar events for source and target
            if(pData->SW_RadarEvent) {
                RadarEventClass::Create(RadarEventType::SuperweaponActivated, pSource->ChronoMapCoords);
                RadarEventClass::Create(RadarEventType::SuperweaponActivated, Coords);
            }

            // cell and coords calculations
            CellClass *pCellSource = MapClass::Instance->GetCellAt(pSource->ChronoMapCoords);
            CellClass *pCellTarget = MapClass::Instance->GetCellAt(Coords);

            CoordStruct coordsSource = pCellSource->GetCoordsWithBridge();
            coordsSource.Z += pData->SW_AnimHeight;

            CoordStruct coordsTarget = pCellTarget->GetCoordsWithBridge();
            coordsTarget.Z += pData->SW_AnimHeight;

            // Update animations
            SWTypeExt::ClearChronoAnim(pThis);

            if(auto pAnimType = pData->Chronosphere_BlastSrc.Get(RulesClass::Instance->ChronoBlast)) {
                GameCreate<AnimClass>(pAnimType, coordsSource);
            }
            if(auto pAnimType = pData->Chronosphere_BlastDest.Get(RulesClass::Instance->ChronoBlastDest)) {
                GameCreate<AnimClass>(pAnimType, coordsTarget);
            }

            DynamicVectorClass<ChronoWarpStateMachine::ChronoWarpContainer> RegisteredBuildings;

            auto Chronoport = [&](TechnoClass* pTechno) -> bool {
                // is this thing affected at all?
                if(!pData->IsHouseAffected(pThis->Owner, pTechno->Owner)) {
                    return true;
                }

                if(!pData->IsTechnoAffected(pTechno)) {
                    return true;
                }

                TechnoTypeClass *pType = pTechno->GetTechnoType();
                TechnoTypeExt::ExtData *pExt = TechnoTypeExt::ExtMap.Find(pType);

                // can this techno be chronoshifted?
                if(!pExt->Chronoshift_Allow) {
                    return true;
                }

                // differentiate between buildings and vehicle-type buildings
                bool IsVehicle = false;
                if(BuildingClass* pBld = specific_cast<BuildingClass*>(pTechno)) {
                    // always ignore bridge repair huts
                    if(pBld->Type->BridgeRepairHut) {
                        return true;
                    }

                    // use "smart" detection of vehicular building types?
                    if(pData->Chronosphere_ReconsiderBuildings) {
                        IsVehicle = pExt->Chronoshift_IsVehicle;
                    }

                    // always let undeployers pass if all undeployers are affected
                    if(!pData->Chronosphere_AffectUndeployable || !pBld->Type->UndeploysInto) {
                        // we don't handle buildings and this is a real one
                        if(!IsVehicle && !pData->Chronosphere_AffectBuildings) {
                            return true;
                        }

                        // this is a vehicle in disguise and we don't handle them
                        if(IsVehicle && !(pData->SW_AffectsTarget & SuperWeaponTarget::Unit)) {
                            return true;
                        }
                    } else {
                        // force vehicle placement rules
                        IsVehicle = true;
                    }
                }

                // some quick exclusion criteria
                if(pTechno->IsImmobilized || pTechno->IsInAir()
                        || pTechno->IsBeingWarpedOut() || pTechno->IsWarpingIn()) {
                    return true;
                }

                // unwarpable unit
                if(!pType->Warpable && !pData->Chronosphere_AffectUnwarpable) {
                    return true;
                }

                // iron curtained units
                if(pTechno->IsIronCurtained() && !pData->Chronosphere_AffectIronCurtain) {
                    return true;
                }

                // if this is a newly produced unit that still is in its
                // weapons factory, this skips it.
                if(pTechno->WhatAmI() == AbstractType::Unit) {
                    TechnoClass* pLink = pTechno->GetNthLink(0);
                    if(pLink) {
                        if(BuildingClass* pLinkBld = specific_cast<BuildingClass*>(pLink)) {
                            if(pLinkBld->Type->WeaponsFactory) {
                                if(MapClass::Instance->GetCellAt(pTechno->Location)->GetBuilding() == pLinkBld) {
                                    return true;
                                }
                            }
                        }
                    }
                }

                // behind this point, the units are affected.

                // organics are destroyed as long as they aren't teleporters
                if(pType->Organic && pData->Chronosphere_KillOrganic) {
                    if(!pType->Teleporter || pData->Chronosphere_KillTeleporters) {
                        int strength = pType->Strength;
                        pTechno->ReceiveDamage(&strength, 0,
                                               RulesClass::Instance->C4Warhead, nullptr, true, false, pSource->Owner);
                        return true;
                    }
                }

                // remove squids. terror drones stay inside.
                if(FootClass *pFoot = generic_cast<FootClass*>(pTechno)) {
                    if(FootClass *pSquid = pFoot->ParasiteEatingMe) {
                        if(pType->Naval) {
                            if(ParasiteClass *pSquidParasite = pSquid->ParasiteImUsing) {
                                pSquidParasite->SuppressionTimer.Start(500);
                                pSquidParasite->ExitUnit();
                            }
                        }
                    }
                }

                // disconnect bunker and contents
                if(pTechno->BunkerLinkedItem) {
                    if(BuildingClass *pBunkerLink = specific_cast<BuildingClass*>(pTechno->BunkerLinkedItem)) {
                        // unit will be destroyed or chronoported. in every case the bunker will be empty.
                        pBunkerLink->ClearBunker();
                    } else if(BuildingClass *pBunker = specific_cast<BuildingClass*>(pTechno)) {
                        // the bunker leaves...
                        pBunker->UnloadBunker();
                        pBunker->EmptyBunker();
                    }
                }

                // building specific preparations
                if(BuildingClass* pBld = specific_cast<BuildingClass*>(pTechno)) {
                    // tell all linked units to get off
                    pBld->SendToEachLink(rc_0D);
                    pBld->SendToEachLink(rc_Exit);

                    // destroy the building light source
                    if(pBld->LightSource) {
                        pBld->LightSource->Deactivate();
                        GameDelete(pBld->LightSource);
                        pBld->LightSource = nullptr;
                    }

                    // shut down cloak generation
                    if(pBld->Type->CloakGenerator && pBld->CloakRadius) {
                        pBld->HasCloakingData = -1;
                        pBld->NeedsRedraw = true;
                        pBld->CloakRadius = 1;
                        pBld->UpdateCloak();
                    }
                }

                // get the cells and coordinates
                CoordStruct coordsUnitSource = pTechno->GetCoords();
                CoordStruct coordsUnitTarget = coordsUnitSource;
                CellStruct cellUnitTarget = pTechno->GetCell()->MapCoords - pSource->ChronoMapCoords + Coords;
                CellClass* pCellUnitTarget = MapClass::Instance->GetCellAt(cellUnitTarget);

                // move the unit to the new position
                coordsUnitTarget.X += (Coords.X - pSource->ChronoMapCoords.X) * 256;
                coordsUnitTarget.Y += (Coords.Y - pSource->ChronoMapCoords.Y) * 256;
                coordsUnitTarget = pCellUnitTarget->FixHeight(coordsUnitTarget);

                if(FootClass *pFoot = generic_cast<FootClass*>(pTechno)) {
                    // clean up the unit's current cell
                    pFoot->Locomotor->Mark_All_Occupation_Bits(0);
                    pFoot->Locomotor->Force_Track(-1, coordsUnitSource);
                    pFoot->MarkAllOccupationBits(coordsUnitSource);
                    pFoot->FrozenStill = true;

                    // piggyback the original locomotor onto a new teleport locomotor and
                    // use that for the next move order.
                    LocomotionClass::ChangeLocomotorTo(pFoot, LocomotionClass::CLSIDs::Teleport);

                    // order unit to move to target location
                    pFoot->IsImmobilized = true;
                    pFoot->ChronoDestCoords = coordsUnitTarget;
                    pFoot->SendToEachLink(rc_Exit);
                    pFoot->ChronoWarpedByHouse = pThis->Owner;
                    pFoot->SetDestination(pCellUnitTarget, true);
                } else if (BuildingClass *pBld = specific_cast<BuildingClass*>(pTechno)) {
                    // begin the building chronoshift
                    pBld->BecomeUntargetable();
                    for(int i = 0; i<BulletClass::Array->Count; ++i) {
                        BulletClass* pBullet = BulletClass::Array->GetItem(i);
                        if(pBullet->Target == pBld) {
                            pBullet->LoseTarget();
                        }
                    }

                    // the buidling counts as warped until it reappears
                    pBld->BeingWarpedOut = true;
                    pBld->Owner->RecheckTechTree = true;
                    pBld->Owner->RecheckPower = true;
                    pBld->DisableTemporal();
                    pBld->UpdatePlacement(PlacementType::Redraw);

                    BuildingExt::ExtData* pBldExt = BuildingExt::ExtMap.Find(pBld);
                    pBldExt->AboutToChronoshift = true;

                    // register for chronoshift
                    ChronoWarpStateMachine::ChronoWarpContainer Container(pBld, cellUnitTarget, pBld->Location, IsVehicle);
                    RegisteredBuildings.AddItem(Container);
                }

                return true;
            };

            // collect every techno in this range only once. apply the Chronosphere.
            auto range = pData->GetRange();
            Helpers::Alex::DistinctCollector<TechnoClass*> items;
            Helpers::Alex::for_each_in_rect_or_range<TechnoClass>(pSource->ChronoMapCoords, range.WidthOrRange, range.Height, std::ref(items));
            items.for_each(Chronoport);

            if(RegisteredBuildings.Count) {
                this->newStateMachine(RulesClass::Instance->ChronoDelay + 1, Coords, pSource, this, &RegisteredBuildings);
            }

            return true;
        }
    } else {
        // idiots at work.
        Debug::Log("ChronoWarp typed super weapon triggered as standalone. Use ChronoSphere instead.\n");
    }

    return false;
}
コード例 #5
0
ファイル: ChronoWarp.cpp プロジェクト: Ares-Developers/Ares
void ChronoWarpStateMachine::Update()
{
    int passed = this->TimePassed();

    if(passed == 1) {
        // redraw all buildings
        for(int i=0; i<this->Buildings.Count; ++i) {
            ChronoWarpContainer& Container = this->Buildings.Items[i];
            if(Container.pBld) {
                Container.pBld->UpdatePlacement(PlacementType::Redraw);
            }
        }
    } else if(passed == this->Duration - 1) {
        // copy the array so items can't get invalidated
        DynamicVectorClass<ChronoWarpContainer> buildings;
        for(int i=0; i<this->Buildings.Count; ++i) {
            buildings.AddItem(this->Buildings.GetItem(i));
        }
        this->Buildings.Clear();

        // remove all buildings from the map at once
        for(int i=0; i<buildings.Count; ++i) {
            ChronoWarpContainer& Container = buildings.Items[i];
            Container.pBld->Remove();
            Container.pBld->ActuallyPlacedOnMap = false;
        }

        // bring back all buildings
        for(int i=0; i<buildings.Count; ++i) {
            ChronoWarpContainer& Container = buildings.Items[i];
            if(BuildingClass* pBld = Container.pBld) {

                if(!pBld->TemporalTargetingMe) {
                    // use some logic to place this unit on some other
                    // cell if the target cell is occupied. this emulates
                    // the behavior of other units.
                    bool success = false;
                    int count = CellSpread::NumCells(10);
                    int idx = 0;
                    do {
                        CellStruct cellNew = CellSpread::GetCell(idx) + Container.target;
                        CellClass* pNewCell = MapClass::Instance->GetCellAt(cellNew);
                        CoordStruct coordsNew = pNewCell->GetCoordsWithBridge();

                        if(pBld->Type->CanCreateHere(&cellNew, 0)) {
                            if(pBld->Put(coordsNew, Direction::North)) {
                                success = true;
                                break;
                            }
                        }
                        ++idx;
                    } while(Container.isVehicle && (idx<count));

                    if(!success) {
                        // put it back where it was
                        ++Unsorted::IKnowWhatImDoing;
                        pBld->Put(Container.origin, Direction::North);
                        pBld->Place(false);
                        --Unsorted::IKnowWhatImDoing;
                    }

                    // chronoshift ends
                    pBld->BeingWarpedOut = false;
                    pBld->Owner->RecheckPower = true;
                    pBld->Owner->RecheckTechTree = true;
                    pBld->EnableTemporal();
                    pBld->UpdatePlacement(PlacementType::Redraw);

                    BuildingExt::ExtData* pBldExt = BuildingExt::ExtMap.Find(pBld);
                    pBldExt->AboutToChronoshift = false;

                    if(!success) {
                        if(SWTypeExt::ExtData *pExt = SWTypeExt::ExtMap.Find(this->Super->Type)) {
                            // destroy (buildings only if they are supposed to)
                            if(Container.isVehicle || pExt->Chronosphere_BlowUnplaceable) {
                                int damage = pBld->Type->Strength;
                                pBld->ReceiveDamage(&damage, 0,
                                                    RulesClass::Instance->C4Warhead, nullptr, true, true, this->Super->Owner);
                            }
                        }
                    }
                }
            }
        }
    } else if(passed == this->Duration) {
        Super->Owner->RecheckPower = true;
        Super->Owner->RecheckTechTree = true;
        Super->Owner->RecheckRadar = true;
    }
}
コード例 #6
0
ファイル: ParaDrop.cpp プロジェクト: Fahroni/Ares
/*
	Every house can have several planes defined. If a plane is not defined by a
	house, this falls back to the side's planes defined for this SW. If that
	fails also it falls back to this SW's default paradrop. If that also fails,
	the paradrop defined by the house is used.

	\param pHouse The owner of this super weapon.
	\param pCell The paradrop target cell.
	
	\author AlexB
	\date 2010-07-19
*/
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;
}