/* ** Command & Conquer Generals Zero Hour(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ //////////////////////////////////////////////////////////////////////////////// // // // (c) 2001-2003 Electronic Arts Inc. // // // //////////////////////////////////////////////////////////////////////////////// // FILE: FlightDeckBehavior.h ///////////////////////////////////////////////////////////////////// // Author: Kris Morness, May 2003 // Desc: Handles aircraft movement and parking behavior for aircraft carriers. /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma once #ifndef __FLIGHT_DECK_BEHAVIOR_H #define __FLIGHT_DECK_BEHAVIOR_H // INCLUDES /////////////////////////////////////////////////////////////////////////////////////// #include "GameLogic/Module/BehaviorModule.h" #include "GameLogic/Module/DieModule.h" #include "GameLogic/Module/AIUpdate.h" #define MAX_RUNWAYS 2 //***NOTE: If you change this, make sure you update the parsing section! //And also do a search for MAX_RUNWAYS and evaluate any special case comments! enum { RUNWAY_START_BONE, RUNWAY_END_BONE, NUM_RUNWAY_BONES, }; struct RunwayDefinition { RunwayDefinition::RunwayDefinition() { m_catapultParticleSystem = NULL; } std::vector m_spacesBoneNames; std::vector m_taxiBoneNames; std::vector m_creationBoneNames; AsciiString m_takeoffBoneNames[ NUM_RUNWAY_BONES ]; AsciiString m_landingBoneNames[ NUM_RUNWAY_BONES ]; const ParticleSystemTemplate *m_catapultParticleSystem; }; //------------------------------------------------------------------------------------------------- class FlightDeckBehaviorModuleData : public AIUpdateModuleData { public: RunwayDefinition m_runwayInfo[ MAX_RUNWAYS ]; AsciiString m_thingTemplateName; Real m_healAmount; Real m_approachHeight; Real m_landingDeckHeightOffset; Int m_numRows; Int m_numCols; UnsignedInt m_cleanupFrames; UnsignedInt m_humanFollowFrames; UnsignedInt m_replacementFrames; UnsignedInt m_dockAnimationFrames; UnsignedInt m_launchWaveFrames; UnsignedInt m_launchRampFrames; UnsignedInt m_lowerRampFrames; UnsignedInt m_catapultFireFrames; FlightDeckBehaviorModuleData(); static void buildFieldParse( MultiIniFieldParse& p ); static void parseRunwayStrip( INI* ini, void *instance, void *store, const void* /*userData*/ ); }; //------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- class FlightDeckBehavior : public AIUpdateInterface, public ParkingPlaceBehaviorInterface, public DieModuleInterface, public ExitInterface { MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( FlightDeckBehavior, "FlightDeckBehavior" ) MAKE_STANDARD_MODULE_MACRO_WITH_MODULE_DATA( FlightDeckBehavior, FlightDeckBehaviorModuleData ) public: FlightDeckBehavior( Thing *thing, const ModuleData* moduleData ); // virtual destructor prototype provided by memory pool declaration static Int getInterfaceMask() { return UpdateModule::getInterfaceMask() | (MODULEINTERFACE_DIE); } // BehaviorModule virtual ParkingPlaceBehaviorInterface* getParkingPlaceBehaviorInterface() { return this; } virtual ExitInterface* getUpdateExitInterface() { return this; } virtual DieModuleInterface* getDie() { return this; } // ExitInterface virtual Bool isExitBusy() const {return FALSE;} ///< Contain style exiters are getting the ability to space out exits, so ask this before reserveDoor as a kind of no-commitment check. virtual ExitDoorType reserveDoorForExit( const ThingTemplate* objType, Object *specificObject ); virtual void exitObjectViaDoor( Object *newObj, ExitDoorType exitDoor ); virtual void unreserveDoorForExit( ExitDoorType exitDoor ); virtual void exitObjectByBudding( Object *newObj, Object *budHost ) { return; } virtual Bool getExitPosition( Coord3D& rallyPoint ) const { return FALSE; } virtual Bool getNaturalRallyPoint( Coord3D& rallyPoint, Bool offset = TRUE ) { return FALSE; } virtual void setRallyPoint( const Coord3D *pos ) {} virtual const Coord3D *getRallyPoint( void ) const { return NULL;} // UpdateModule virtual UpdateSleepTime update(); // DieModule virtual void onDie( const DamageInfo *damageInfo ); // ParkingPlaceBehaviorInterface virtual Bool shouldReserveDoorWhenQueued(const ThingTemplate* thing) const; virtual Bool hasAvailableSpaceFor(const ThingTemplate* thing) const; virtual Bool hasReservedSpace(ObjectID id) const; virtual Int getSpaceIndex( ObjectID id ) const; virtual Bool reserveSpace(ObjectID id, Real parkingOffset, PPInfo* info); virtual void releaseSpace(ObjectID id); virtual Bool reserveRunway(ObjectID id, Bool forLanding); virtual void releaseRunway(ObjectID id); virtual void calcPPInfo( ObjectID id, PPInfo *info ); virtual Int getRunwayCount() const { return m_runways.size(); } virtual ObjectID getRunwayReservation( Int r, RunwayReservationType type ); virtual void transferRunwayReservationToNextInLineForTakeoff(ObjectID id); virtual Real getApproachHeight() const { return getFlightDeckBehaviorModuleData()->m_approachHeight; } virtual Real getLandingDeckHeightOffset() const { return getFlightDeckBehaviorModuleData()->m_landingDeckHeightOffset; } virtual void setHealee(Object* healee, Bool add); virtual void killAllParkedUnits(); virtual void defectAllParkedUnits(Team* newTeam, UnsignedInt detectionTime); virtual Bool calcBestParkingAssignment( ObjectID id, Coord3D *pos, Int *oldIndex = NULL, Int *newIndex = NULL ); // AIUpdateInterface virtual void aiDoCommand(const AICommandParms* parms); virtual const std::vector* getTaxiLocations( ObjectID id ) const; virtual const std::vector* getCreationLocations( ObjectID id ) const; private: Bool isAbleToGiveUpParkingSpace( Object *jet ); Bool isAbleToMoveForward( const Object &jet ) const; Bool isInPositionToTakeoff( const Object &jet ) const; void validateAssignments(); void propagateOrdersToPlanes(); void propagateOrderToSpecificPlane( Object *jet ); Bool hasTakeoffOrders(); struct FlightDeckInfo { Coord3D m_prep; Real m_orientation; Int m_runway; ObjectID m_objectInSpace; FlightDeckInfo() { m_prep.zero(); m_orientation = 0; m_runway = 0; m_objectInSpace = INVALID_ID; } }; struct RunwayInfo { Coord3D m_start; Matrix3D m_startTransform; Coord3D m_end; Coord3D m_landingStart; Coord3D m_landingEnd; std::vector m_taxi; std::vector m_creation; Real m_startOrient; ObjectID m_inUseByForTakeoff; ObjectID m_inUseByForLanding; }; struct HealingInfo { ObjectID m_gettingHealedID; UnsignedInt m_healStartFrame; }; void buildInfo( Bool createUnits = TRUE); void purgeDead(); void resetWakeFrame(); FlightDeckInfo* findPPI(ObjectID id); FlightDeckInfo* findEmptyPPI(); const ThingTemplate *m_thingTemplate; std::vector m_spaces; std::vector m_runways; std::list m_healing; // note, this list can vary in size, and be larger than the parking space count UnsignedInt m_nextHealFrame; UnsignedInt m_nextCleanupFrame; UnsignedInt m_startedProductionFrame; UnsignedInt m_nextAllowedProductionFrame; UnsignedInt m_nextLaunchWaveFrame[ MAX_RUNWAYS ]; UnsignedInt m_rampUpFrame[ MAX_RUNWAYS ]; //The frame the ramp has completed raising. UnsignedInt m_catapultSystemFrame[ MAX_RUNWAYS ]; //The frame the catapult effect created. UnsignedInt m_lowerRampFrame[ MAX_RUNWAYS ]; //The frame the ramp begins to lower. ObjectID m_designatedTarget; AICommandType m_designatedCommand; Coord3D m_designatedPosition; Bool m_gotInfo; Bool m_rampUp[ MAX_RUNWAYS ]; }; #endif // __FLIGHT_DECK_BEHAVIOR_H